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

ご覧のとおり、私がdd計算したものよりも50MB以上のパディングが残っています。

次に、ループバックデバイスを作成し、パーティションテーブルとファイルシステムを作成します。

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程度のパディングが確保されたようです。 (私の考えでは一部デフォルトでは、イメージには使用可能なスペースがありますが、それほど多くはありません。 )画像サイズは2倍に変わらないので、画像サイズが大きくなるほど、わずかなクリープやオーバーヘッドが増幅されます。これがどこから来るのかよくわかりません。

文脈上、これは私が最後に不適切な行動をしたことです:

# 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%のオーバーヘッドが必要であることを知っていれば、それを計算に含めることは簡単ですが、スーパーユーザーで書くときに失敗するので、これが実際の問題ではないと思います。

関連情報