我需要将一个包含文件(特别是 Linux chroot)的目录写入一个带有 LVM 映像的文件。任务的背景很愚蠢,但我想了解现在发生了什么。我计算目录的大小du
:
# du -s --block-size=1 chroot
3762733056 chroot
我将它四舍五入并创建一个足够大的文件来包含它:
# fallocate -l 4294967296 image.lvm
# ls -lah
drwxr-xr-x 23 root root 4.0K мая 27 20:59 chroot
-rw-r--r-- 1 root root 4.0G мая 28 09:59 image.lvm
我将文件挂载(抱歉,不确定术语是否正确)作为循环设备并在其上创建一个 LVM 分区。我会使用 ext4 fs,我知道 ext4 为 root 保留 5% 的空间(我可以调整它)和 inode 表的一些空间,所以我创建了一个比我的实际目录大 10% 左右的分区(4139006362 字节)并将其四舍五入,使其成为 512 的倍数(4139006464 字节)以满足 LVM 需求:
# losetup -f --show image.lvm
/dev/loop0
# pvcreate /dev/loop0
Physical volume "/dev/loop0" successfully created.
# vgcreate IMAGE /dev/loop0
Volume group "IMAGE" successfully created
# lvcreate --size 4139006464B -n CHROOT IMAGE
Rounding up size to full physical extent <3.86 GiB
Logical volume "CHROOT" created.
然后我在这个 LV 上创建一个 ext4 文件系统:
# mkfs.ext4 /dev/IMAGE/CHROOT
mke2fs 1.45.6 (20-Mar-2020)
Discarding device blocks: done
Creating filesystem with 1010688 4k blocks and 252960 inodes
Filesystem UUID: fb3775ff-8380-4f97-920d-6092ae0cd454
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
# mount /dev/IMAGE/CHROOT mnt
# df --block-size=1 mnt
Filesystem 1B-blocks Used Available Use% Mounted on
/dev/mapper/IMAGE-CHROOT 4007591936 16179200 3767648256 1% /mnt
虽然 3767648256 大于我从中得到的 3762733056 ,但du
我仍然将其调高一个档次:
# tune2fs -m 0 /dev/IMAGE/CHROOT
tune2fs 1.45.6 (20-Mar-2020)
Setting reserved blocks percentage to 0% (0 blocks)
# df --block-size=1 mnt
Filesystem 1B-blocks Used Available Use% Mounted on
/dev/mapper/IMAGE-CHROOT 4007591936 16179200 3974635520 1% /mnt
到目前为止一切顺利,让我们向它写入一些数据:
# cp -a chroot/. mnt/
...
cp: cannot create regular file 'mnt/./usr/portage/profiles/hardened/linux/powerpc/ppc64/32bit-userland/use.mask': No space left on device
砰。让我们看看df
显示了什么:
# df --block-size=1 mnt
Filesystem 1B-blocks Used Available Use% Mounted on
/dev/mapper/IMAGE-CHROOT 4007591936 3587997696 402817024 90% /mnt
所以实际上有可用的空间。在谷歌搜索了一下之后,我发现你的分区上的 inode 可能会用完,这看起来和我的情况一模一样:
# df -i mnt
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/IMAGE-CHROOT 248K 248K 0 100% /mnt
现在,问题!我可以轻松地使用更大的文件大小,创建 1.5 倍大的分区,在那里写我的文件,它会工作的。但是作为一个想要保留空间的迂腐开发人员:我如何准确计算要写入目录需要多少字节和 inode?我也相当肯定我--block-size=1
在路上的某个地方也搞砸了。
“为什么选择 LVM”上下文:它用于其快照功能。所以基本上其他脚本从所说的 4G chroot 创建一个 20G 快照,在这个快照中做一些事情,然后删除它,保持 chroot 的原始内容不变。所以基本文件系统可能被认为是只读的。“简单”愚蠢的 docker 容器早在 Docker 之前就发明了,不能轻易地用 Docker 本身或其 overlayfs 替换。
mkfs.ext4
为您提供了三个有趣的选项(有关详细信息,请参见手册页)。-i bytes-per-inode
-I inode-size
-N number-of-inodes
使用这些的组合,您可以精确地塑造文件系统。如果您确信您永远不需要创建任何其他文件或将文件系统安装为只读,那么理论上您可以提供
-N ${number-of-entities}
.请记住,目录也将采用 inode:
您可以获得使用
find
或类似的实体的计数,记住也要计算目录!(即:不要使用-type f
or-not -type d
)。现在您也知道(或可以指定)inode 大小,您可以更准确地确定需要分配多少空间,并且可以避免在未使用的 inode 上“浪费”空间。
如果您使用只读文件系统,那么另一种选择可能是查看 squashfs 而不是 ext4,它将专门根据输入文件分配一个连续(和压缩)块......而不是创建一个您希望的容器足够大并填充它。
除非你真的在追求 LVM 的某些东西,否则你可以轻松摆脱它,如上所示(我建议不要也使用它)。您可能喜欢/想要一个 MBR,这取决于您将如何部署映像。