|
|
本帖最后由 Timandes 于 2025-2-13 19:23 编辑
## 简介
在使用squashfs格式的固件过程中,小容量存储会因为安装的软件包累计而出现存储空间告急。这时候不可避免地需要启用外部存储来满足日益增长的功能需求。
目前常见的OpenWrt扩容方案是完全舍弃固件内的rootfs_data分区,在将数据复制到外部存储后,将外部存储的新分区直接以透明挂载的方式挂载到根分区。这样做,虽然可以解决存储需求,但是浪费了原本的rootfs_data分区,且不具有灵活性。
下面(基于x86/64架构的squashfs包)介绍一种局部透明挂载方式,力求可以以最少的代价实现OpenWrt扩容。
## 现状
默认状态下,标注有squashfs格式的固件挂载情况如下:
```shell
df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 5.8M 5.8M 0 100% /rom
tmpfs 115.1M 1.2M 114.0M 1% /tmp
/dev/loop0 86.6M 3.2M 76.6M 4% /overlay
overlayfs:/overlay 86.6M 3.2M 76.6M 4% /
/dev/sda1 16.0M 6.2M 9.7M 39% /boot
/dev/sda1 16.0M 6.2M 9.7M 39% /boot
tmpfs 512.0K 0 512.0K 0% /dev
```
其/proc/mounts文件内容如下:
```shell
cat /proc/mounts
/dev/root /rom squashfs ro,relatime,errors=continue 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
cgroup2 /sys/fs/cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate 0 0
tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0
/dev/loop0 /overlay ext4 rw,noatime 0 0
overlayfs:/overlay / overlay rw,noatime,lowerdir=/,upperdir=/overlay/upper,workdir=/overlay/work,xino=off 0 0
/dev/sda1 /boot vfat rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 0
tmpfs /dev tmpfs rw,nosuid,noexec,noatime,size=512k,mode=755 0 0
devpts /dev/pts devpts rw,nosuid,noexec,noatime,mode=600,ptmxmode=000 0 0
debugfs /sys/kernel/debug debugfs rw,nosuid,nodev,noexec,noatime 0 0
bpffs /sys/fs/bpf bpf rw,nosuid,nodev,noexec,noatime,mode=700 0 0
```
其中的/rom挂载到了根分区,而/overlay透明挂载到了根分区作为对写入数据的差异存储分区。
## 方案及模拟实施
### 方案
OpenWrt使用过程中的容量占用大户一般是软件包,而软件包的默认安装路径是/usr。因此,我们初步考虑将外部存储中的分区直接透明挂载到/usr目录。
根据透明挂载的原理(只保留差异变更),我们其实没有必要提前复制/usr目录下的文件到外部存储的新分区中。这样,就可以实现几乎无损的空间复用(除非做了软件包升级)。
另外,由于并未复制/etc目录,所有的配置不会在挂载外部存储后被还原。
### 模拟实施
*此处省略了外部存储的分区、格式化过程,其目标分区假定为/dev/sdb1。*
1)挂载分区到指定目录
透明挂载的源和目标都必须是文件系统中的目录,因此需要提前挂载设备到文件系统中:
```shell
mkdir /mnt/sdb1
mount -t ext4 /dev/sdb1 -o 'rw,noatime' /mnt/sdb1
```
2)准备透明挂载的差异文件存储目录
```shell
mkdir /mnt/sdb1/upper
mkdir /mnt/sdb1/work
```
这两个目录不存在时,透明挂载会失败。
3)透明挂载/usr目录
```shell
mount -t overlay overlayfs:/mnt/sdb1 -o 'rw,noatime,lowerdir=/usr,upperdir=/mnt/sdb1/upper,workdir=/mnt/sdb1/work,xino=off' /usr
```
### 效果验证
1)挂载后的结构
```shell
df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 5.8M 5.8M 0 100% /rom
tmpfs 115.1M 1.2M 114.0M 1% /tmp
/dev/loop0 86.6M 3.2M 76.6M 4% /overlay
overlayfs:/overlay 86.6M 3.2M 76.6M 4% /
/dev/sda1 16.0M 6.2M 9.7M 39% /boot
tmpfs 512.0K 0 512.0K 0% /dev
/dev/sdb1 988.4M 288.0K 921.0M 0% /mnt/sdb1
overlayfs:/mnt/sdb1 988.4M 288.0K 921.0M 0% /usr
```
2)创建文件
```shell
cd /usr
touch 1.txt
ls -l
```
这时候可以看到1.txt文件存在。
3)重启再看
```shell
cd /usr
ls -l
```
此时由于外部存储的挂载都失效了,因此看不到1.txt文件。
4)再次挂载
参考前述步骤完成两个挂载后,又可以看到1.txt文件了。
## 最终步骤
1)安装bind-mount软件包
以便启用/etc/config/fstab文件。
2)配置新分区的挂载
使用uci命令:
```shell
uci add fstab mount # =cfg054d77
uci set fstab.@mount[-1].enabled='1'
uci set fstab.@mount[-1].uuid='2b2a1bc7-5e1f-4d04-b542-c7dd00058b02'
uci set fstab.@mount[-1].target='/mnt/sdb1'
uci set fstab.@mount[-1].fstype='ext4'
uci set fstab.@mount[-1].options='rw,noatime'
uci commit
```
需要注意其中的uuid必须时/dev/sdb1这个分区的ID,具体查询方法略。
3)编写启动脚本透明挂载
*暂不清楚bind-mount如何进行透明挂载,也许根本就不支持。*
创建/etc/init.d/custom_overlay文件(脚本名称可以自己改):
```shell
vim /etc/init.d/custom_overlay
```
填入如下内容:
```shell
#!/bin/sh /etc/rc.common
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2013-2020 OpenWrt.org
START=12
boot() {
/bin/mount -t overlay overlayfs:/mnt/sdb1 -o 'rw,noatime,lowerdir=/usr,upperdir=/mnt/sdb1/upper,workdir=/mnt/sdb1/work,xino=off' /usr
}
start() {
return 0
}
restart() {
return 0
}
stop() {
/bin/umount /usr
}
```
尽量在/etc/init.d/fstab后马上启动这个脚本,如果其顺序号不是11,那么就需要修改脚本中的12为fstab脚本的“序号+1”,下同。
4)给脚本赋权:
```shell
chmod +x /etc/init.d/custom_overlay
```
5)软连接到/etc/rc.d
```shell
cd /etc/rc.d
ln -s ../init.d/custom_overlay S12custom_overlay
```
需要注意这里的S12前缀,需要和脚本中的`START=`后面的数字一致。
6)重启
至此,相关工作就结束了。
## 总结
此方法的缺点是剩余空间无法体现在软件包管理界面中,只能在概览界面中看到使用情况。
软件包管理:
概览:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|