最近有遇到对镜像文件(.img)进行扩容的需求,踩了一些坑,在此记录一下。
背景是要在仿真器上跑一个在挂载额外disk.img的全系统测试,需要用到很大的数据。但是一开始用的磁盘镜像空间不够大,所以需要扩容然后才够放下数据。
一种类似的场景是,在虚拟机上启动,挂载某个disk.img作为linux启动之后的rootfs,disk.img内有自己的分区表和文件系统。
这种需求不能仅仅只扩大外部host的img文件,而是要剥洋葱。
具体从外到内有三个层次步骤:
- 扩大hostFS内的disk.img文件容量
- 扩大disk.img内使用的分区容量
- 扩大disk.img内guestFS的容量
hostFS的文件容量
这一层是最直观也最好理解的一层。因为容量不够肯定先想到扩大手里的disk.img文件本身。
操作之前要对disk.img进行备份
现成的工具有qemu-img
和dd
:
qemu-img resize --preallocation=full disk.img +18G
# or
dd if=/dev/zero of=disk.img seek=2GiB count=18GiB
--preallocation
在支持sparse file的文件系统下是必须的,比如ext2,3,4。否则扩容后的disk.img由于增加的容量是被认为empty的,从而不会实际占据空间。当在虚拟机或者仿真器中挂载时,扩容出来的空间依然不可用。具体可以参考Wikipedia:Sparse file。
目前个人认为这是由于仿真器和虚拟机对img的操作,并不经过外部的hostFS,从而没办法完成对sparse的支持。
第二种方法,直接通过dd往disk.img后面写入无用的0,从而扩大文件大小。seek
表示在写入of文件时要跳过前多少比特,一般需要指定为原disk.img大小,以免破坏原有内容。count
表示将多少大小的if内容复制到of中。具体可以参考dd man。
需要注意的是seek
可以接收以B结尾的具体大小,也可以接收以obs
大小的block个数。
例如obs=1M seek=1024
就是1GiB大小。count
同样可以接收两种,后者以ibs
作为block的大小。ibs
和obs
默认都是512比特,也可以用bs
统一设置。
disk.img的分区容量
这一层就是常见的分区操作了,但是在玩虚拟机和仿真器的时候很容易忽略。
先将disk.img挂载到loop设备上,然后就可以操作分区表。
(root) losetup -P /dev/loopX disk.img
加上-P
是为了直接扫出分区表,然后可以直接刷新出已有分区。
之后就是对想要扩容的分区操作。现成的工具太多了,例如parted和gparted。
guestFS的容量
这一层是洋葱最里层,就是要告诉guestFS扩容了,有新空间可以用了。
这里以ext3为例,需要用到e2fsck
和resize2fs
(root) e2fsck -f /dev/loopXpY
(root) resize2fs /dev/loopXpT 20G
e2fsck
先检查guestFS,然后报一个section使用情况。resize2fs扩大guestFS的使用容量。
至此,disk.img在仿真器里可以使用的容量成功从2GiB扩大到20GiB。
《布朗神父第十一季》欧美剧高清在线免费观看:https://www.jgz518.com/xingkong/3287.html
果果爱你