找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
广告投放联系QQ68610888广告投放联系QQ68610888
广告投放联系QQ68610888广告投放联系QQ68610888
查看: 2612|回复: 2

【原创】使用外部存储实现OpenWrt扩容

[复制链接]
发表于 2025-2-13 19:23 | 显示全部楼层 |阅读模式
本帖最后由 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)重启

至此,相关工作就结束了。

## 总结

此方法的缺点是剩余空间无法体现在软件包管理界面中,只能在概览界面中看到使用情况。

软件包管理:


概览:




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
发表于 2025-2-13 20:33 来自手机 | 显示全部楼层
对 X86 squashfs 固件,最省心的方法
先扩容固件,再写入硬盘

对 ARM 和 MIPS,还是老老实实按步骤扩容
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

发表于 2025-2-13 22:47 | 显示全部楼层
本帖最后由 regedit110 于 2025-2-13 22:49 编辑

厉害
使用了一种全新的扩容方式,可以多一种选择。从提出想法、到论证、再测试、最终给出可行方法,谢谢

只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

欢迎大家光临恩山无线论坛上一条 /2 下一条

有疑问请添加管理员QQ86788181|手机版|小黑屋|Archiver|恩山无线论坛(常州市恩山计算机开发有限公司版权所有) ( 苏ICP备05084872号 )

GMT+8, 2026-8-24 00:15

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

| 江苏省互联网有害信息举报中心 举报信箱:js12377 | @jischina.com.cn 举报电话:025-88802724 本站不良内容举报信箱:68610888@qq.com 电话:13506125623

快速回复 返回顶部 返回列表