如何计算用于 debootstrap 的环回设备文件系统映像的正确大小?

如何计算用于 debootstrap 的环回设备文件系统映像的正确大小?

我正在使用 debootstrap 为我想要写入图像文件的设备创建 rootfs。为了计算 rootfs 所需的大小,我执行以下操作:

local SIZE_NEEDED=$(du -sb $CHROOT_DIR|awk '{print $1}')
SIZE_NEEDED=$(($SIZE_NEEDED / 1048576 + 50)) # in MB + 50 MB space
dd if=/dev/zero of=$ROOTFS_IMAGE bs=1M count=$SIZE_NEEDED

正如你所看到的,我留下了 50MB 的填充,超出了dd我计算出的需要。

然后我创建环回设备,创建分区表和文件系统:

LO_DEVICE=$(losetup --show -f $ROOTFS_IMAGE)
parted $LO_DEVICE mktable msdos mkpart primary ext4 0% 100%
partprobe $LO_DEVICE
local LO_ROOTFS_PARTITION="${LO_DEVICE}p1"
mkfs.ext4 -O ^64bit $LO_ROOTFS_PARTITION

它似乎parted尝试进行一些扇区对齐(?),因为分区没有完全占据整个虚拟磁盘,但足够接近。

然后我安装新分区并开始写入文件。但后来我在快结束时用完了磁盘空间!

mount $LO_ROOTFS_PARTITION $LO_MOUNT_POINT
cp -rp $CHROOT_DIR/* $LO_MOUNT_POINT

.....
cp: cannot create directory '/root/buildimage/rootfs_mount/var': No space left on device

我怀疑这是一些块大小转换问题或者可能是 MiB 和 MB 之间的差异?因为达到一定的图像尺寸,我似乎有足够的空间和 50MB 的填充。 (我想一些默认情况下图像中的可用空间,但不是很多。)图像大小不会相差两倍,因此随着图像大小变大,一些蠕变或开销会被放大,我不确定在哪里它来自。

对于上下文,这是我所做的最后一个不合适的:

# du -sb build/rootfs
489889774   build/rootfs

好的,489MB/1024**2 + 50MB = 517MB 图像大小。所以dd看起来像:

# dd if=/dev/zero of=build/rootfs.img size=1M count=517
517+0 records in
517+0 records out
542113792 bytes (542 MB, 517 MiB) copied, 2.02757 s, 267 MB/s

在磁盘上确认它看起来稍大一些:

# du -sb build/rootfs.img
542113792   build/rootfs.img

分区看起来像:

# parted /dev/loop0 print
Model: Loopback device (loopback)
Disk /dev/loop0: 542MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End    Size   Type     File system  Flags
 1      1049kB  542MB  541MB  primary  ext4

并安装文件系统:

# df -h /dev/loop0p1
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0p1    492M  482M     0 100% /root/buildimage/build/rootfs_mount

那么 ext4 文件系统中可能存在超级块/日志/等开销吗?我如何在尺寸计算中考虑这一点?

编辑:

研究 ext4 开销,例如这个服务器故障问题

也在调查mkfs.ext4 选项例如-m(保留)以及各种日志记录和 inode 选项。一般来说,如果我知道文件系统有 5% 的开销,我就可以很容易地将其考虑在内。

编辑#2:

我认为这du可能会低估实际的磁盘大小要求(例如 10 字节文件仍然占用 4k 块,对吧?)我尝试了其他一些选项:

# du -sb build/rootfs        # This is what I was using
489889774   build/rootfs

# du -sm build/rootfs        # bigger
527 build/rootfs

# du -sk build/rootfs        # bigger-est
539088  build/rootfs

此外,手册页-b指出,它是一个别名--apparent-size,可以小于“实际磁盘使用量”。所以这可能是我的数学错误的(大部分)地方。

答案1

最简单的解决方案可能是最初大量过度配置空间,复制所有文件,然后使用resize2fs -M该实用程序将大小减少到可以管理的最小值。这是一个例子:

dir=/home/meuh/some/dir
rm -f /tmp/image
size=$(du -sb $dir/ | awk '{print $1*2}')
truncate -s $size /tmp/image
mkfs.ext4 -m 0 -O ^64bit /tmp/image
sudo mount /tmp/image /mnt/loop
sudo chown $USER /mnt/loop
rsync -a $dir/ /mnt/loop
sync
df /mnt/loop
sudo umount /mnt/loop
e2fsck -f /tmp/image 
resize2fs -M /tmp/image 
newsize=$(e2fsck -n /tmp/image | awk -F/ '/blocks$/{print $NF*1024}')
truncate -s $newsize /tmp/image
sudo mount /tmp/image /mnt/loop
df /mnt/loop
diff -r $dir/ /mnt/loop
sudo umount /mnt/loop

示例目录输出的一些摘录:

+ size=13354874
Creating filesystem with 13040 1k blocks and 3264 inodes
+ df /mnt/loop
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop1         11599  7124      4215  63% /mnt/loop
+ resize2fs -M /tmp/image
Resizing the filesystem on /tmp/image to 8832 (1k) blocks.
+ newsize=9043968
+ truncate -s 9043968 /tmp/image
+ df /mnt/loop
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop1          7391  7124        91  99% /mnt/loop

答案2

作为记录,我已经更改了我的原始代码du -sm,这似乎已经解决了我的问题。我认为问题的关键在于它-sb是 的别名--apparent-size

此外,知道 ext4 需要,比如说 5% 的开销,就可以很容易地将其纳入计算中,但我认为这不是当前的实际问题,因为它在以超级用户身份写入时失败了。

相关内容