本人使用的设备及版本为:EdgeRouter X v1.10.11。
我的设备是er-x。考虑到网上说,erx的flash大概只能用3年,个人感觉是nand flash的频繁擦写问题,导致flash坏掉,设备无法再正常使用。讨论附图如下:
(原始链接)
决定研究一下,如何保护"路由器NAND闪存里频繁读写"问题
计划的nand flash保护方案如下:
- 静默跑几天(假设2天),然后登陆设备,通过这条命令获取这2天系统修改的文件
find /root.dev -mtime -2
- 将这些文件的所在目录进行tmpfs格式mount,方法如下:
- 在tmp目录下新建一个文件夹,因为tmp目录是tmpfs格式的,不会占用磁盘空间;
- 拷贝这些文件所在目录(注意保持文件所有者和权限)到这个tmpfs文件夹;
- 将这个tmpfs目录直接mount到文件所在目录;
- 再静默跑几天(假设2天),然后登陆设备,再查找这2天系统修改的文件
- 如此反复,直至所有相关文件都转义到tmpfs下
- 编写脚本或程序,并实现开机自启;关机时自动将修改写入flash进行保存,确保下次开机不丢失。
方案原理:
将易变的数据,使用tmpfs方式挂载掉,这样设备在运行过程中的频繁磁盘写动作,变成了内存条里的数据的改写,从而保护了nand flash不会被频繁刷写。
最后,设备关机时,还是需要将数据写入flash进行保存的。因为在内存中的数据,断电就会强制被丢失。写回磁盘后,才能确保数据不被丢失。
优化之后,就没有了设备在运行过程中的频繁flash擦写动作,有效保护了nand flash。
实施方法:
- 部分脚本的sed需要调整为自研的sed2程序,因为sed用的mv,mount后是不能用mv命令进行覆写文件的。(sed2是一个脚本,源码参看附件中的sed2文件)
- 编写mount工具。(源码参看附件中的tmp-mount_src,对应二进制程序在附件中的tmp-mount_bin目录下)
- 经实践积累,需要mount掉的文件清单(即mount工具的配置文件)
# 将频繁变动的文件转为tmpfs来mount /etc/ubnt/last_time /etc/hosts /var/lib/logrotate/status /home/nat/.ssh/authorized_keys /config/dhcpd.leases /var/lib/ntp # 2022-9-7新添加 /etc/dnsmasq.conf /etc/cron.hourly/dnsmasq-cron /config/dnsmasq-dhcp.leases /var/cache/ddclient /etc/ppp # 2022-11-18新添加 /etc/resolv.conf /etc/resolv.conf.tmp /etc/resolv.conf.pppd-backup # 2022-12-11新添加 /home/ubnt/.lesshst /root/.lesshst
- 系统开机自动mount掉上述文件,关机时再自动写回上述文件到磁盘。工具已含umount功能(但仅写回单个文件,写回文件夹太复杂就暂不实现了)。
- 安装配置工具,让其开机自动执行mount,关机也能自动执行umount。(源码参看附件中的install.sh)
可能的缺陷:
- 强制断电的话没有umount,就没有拷贝文件的内容回去了。经过实际测试,断电并没有对系统有什么影响,还是能正常使用。
目前的机器现状(作记录,仅供参考)
查看dmesg信息如下(2022-09-11):
root@ubnt:/var/log# dmesg
UBI: attaching mtd7 to ubi0
UBI: scanning is finished
UBI: attached mtd7 (name "RootFS", size 247 MiB) to ubi0
UBI: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
UBI: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
UBI: VID header offset: 2048 (aligned 2048), data offset: 4096
UBI: good PEBs: 1982, bad PEBs: 0, corrupted PEBs: 0
UBI: user volume: 1, internal volumes: 1, max. volumes count: 128
UBI: max/mean erase counter: 16/7, WL threshold: 4096, image sequence number: 1473513539
UBI: available PEBs: 0, total reserved PEBs: 1982, PEBs reserved for bad PEB handling: 40
UBI: background thread "ubi_bgt0d" started, PID 54
UBIFS: background thread "ubifs_bgt0_0" started, PID 55
UBIFS: mounted UBI device 0, volume 0, name "troot"
UBIFS: LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
UBIFS: FS size: 244428800 bytes (233 MiB, 1925 LEBs), journal size 12189696 bytes (11 MiB, 96 LEBs)
UBIFS: reserved for root: 4952683 bytes (4836 KiB)
UBIFS: media format: w4/r0 (latest is w4/r0), UUID D4683CBE-27A0-4D67-BB9C-0BD4293353B8, small LPT model
VFS: Mounted root (aufs filesystem) on device 0:12.
devtmpfs: mounted
max/mean erase counter: 16/7
的含义:最大单个块的擦除次数为16次,平均每个块的擦除次数为7次。
下面分析其中几条其他的主要信息(分析的数据是从其他博文拷贝的,不是依据上面的打印数据来的):
# 在 mtddata 原始分区初始化 ubi 卷
Info: init ubi volumes on mtddata raw partition
# 将mtd20附加到ubi0...
UBI: attaching mtd20 to ubi0
# 将mtd20附加到ubi0 完成
UBI: attached mtd20 (name "mtddata", size 30 MiB) to ubi0
# PEB 128KB, LEB 124KB
UBI: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
# 最小最大I/O读写单元:2048/2048, subpage 2048, 就是2KB
UBI: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
# VID header偏移量2KB,用于对齐,数据偏移量4KB
UBI: VID header offset: 2048 (aligned 2048), data offset: 4096
# 240 pebs正常,无坏块
UBI: good PEBs: 240, bad PEBs: 0, corrupted PEBs: 0
# 剩余可用3 PEBs, 总保留 237 PEBs(已用或保留),用于坏块处理的保留PEBs 20(本文讨论重点)
UBI: available PEBs: 3, total reserved PEBs: 237, PEBs reserved for bad PEB handling: 20
# UBI 设备号0,共240 LEBs(29.1MB),剩余可用3 LEBs,每个LEB大小为124KB
UBI device number 0, total 240 LEBs (30474240 bytes, 29.1 MiB), available 3 LEBs (380928 bytes, 372.0 KiB), LEB size 126976 bytes
(124.0 KiB)
# 成功在mtddata附加ubi设备
Info: attach ubi device on mtddata success!
从log中可以知晓很多关键信息,UBI挂载的分区名称为mtddata,对应mtd20; PEB 128KB, LEB 124KB; ubi0共240 LEBs/PEBs, 剩余可以3 LEBs/PEBs, 无坏块; 用于坏块处理的保留部分为20 PEBs。
执行
sudo ubinfo -a
信息如下(2022-09-11):ubnt@ubnt:/var/log$ sudo ubinfo -a
UBI version: 1
Count of UBI devices: 1
UBI control device major/minor: 10:60
Present UBI devices: ubi0
ubi0
Volumes count: 1
Logical eraseblock size: 126976 bytes, 124.0 KiB
Total amount of logical eraseblocks: 1982 (251666432 bytes, 240.0 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes 128
Count of bad physical eraseblocks: 0
Count of reserved physical eraseblocks: 40
Current maximum erase counter value: 16
Minimum input/output unit size: 2048 bytes
Character device major/minor: 254:0
Present volumes: 0
Volume ID: 0 (on ubi0)
Type: dynamic
Alignment: 1
Size: 1938 LEBs (246079488 bytes, 234.7 MiB)
State: OK
Name: troot
Character device major/minor: 254:1
ubi的工具集,保存在/usr/sbin/目录下:
工具 | 作用 |
---|---|
ubinfo | 提供ubi设备和卷的信息 |
ubiattach | 链接MTD设备到UBI并且创建相应的UBI设备 |
ubidetach | ubiattach相反的操作,将MTD设备从UBI设备上去链接 |
ubimkvol | 从UBI设备上创建UBI卷 |
ubirmvol | 从UBI设备上删除UBI卷 |
ubiblock | 管理UBI卷上的block |
ubiupdatevol | 更新卷,例如OTA直接更新某个分区镜像 |
ubicrc32 | 使用与ubi相同的基数计算文件的crc32 |
ubinize | 制作UBI镜像 |
ubiformat | 格式化空的Flash设备,擦除Flash,保存擦除计数,写入UBI镜像到Flash |
mtdinfo | 报告从系统中找到的UBI设备的信息 |
NAND的物理性质决定了其每个块都有擦除寿命的限制,SLC约10W次,MLC约5000次,TLC约1000次
未能分析出ubnt的颗粒,感觉非常可能就是TLC,甚至以下,毕竟是比较老型号的设备了。
源码附件:
https://download.csdn.net/download/whgjjim/87399944
参考链接:
MTD中的nand驱动初步分析_shexujia的博客-CSDN博客; Linux MTD下获取Nand flash各个参数的过程的详细解析 - 程序员大本营