Como calcular o tamanho correto de uma imagem do sistema de arquivos do dispositivo de loopback para o debootstrap?

3

Estou usando o debootstrap para criar um rootfs para um dispositivo que desejo gravar em um arquivo de imagem. Para calcular o tamanho necessário dos meus rootfs, eu faço o seguinte:

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

Como você pode ver, estou deixando 50 MB de preenchimento além do que o dd calcula que preciso.

Eu então crio o dispositivo de loopback, cria uma tabela de partição e um sistema de arquivos:

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

Parece que parted tenta fazer algum alinhamento de setor (?), já que a partição não ocupa todo o disco virtual, mas perto o suficiente.

Eu, então, montei a nova partição e comecei a escrever arquivos. Mas então eu fiquei sem espaço em disco perto do fim!

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

Eu suspeito que isso é algum problema de conversão de tamanho de bloco ou talvez diferença entre MiB e MB? Porque até um certo tamanho de imagem, parece que tenho espaço suficiente com os 50MB de preenchimento. (Eu quero algum espaço livre na imagem por padrão, mas não muito). O tamanho da imagem não está desativado por um fator-de-dois, então há alguma fluência ou sobrecarga que é ampliada o tamanho da imagem fica maior e não tenho certeza de onde ela está vindo.

Para o contexto, aqui está o último que eu fiz e que não se encaixa:

# du -sb build/rootfs
489889774   build/rootfs

Ok, 489MB / 1024 ** 2 + 50MB = tamanho de imagem de 517MB. Então dd se parecia com:

# 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

Confirmado em disco, parece um pouco maior:

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

A partição é semelhante a:

# 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

e sistema de arquivos montado:

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

Então, talvez haja sobrecarga no sistema de arquivos ext4, possivelmente para superblocos / journal / etc? Como posso explicar isso no meu cálculo de tamanho?

EDITAR:

Olhando para a sobrecarga do ext4, como esta pergunta do ServerFault .

Veja também as opções do mkfs.ext4 como -m (reservado) e vários registros de diário e opções de inode. Em geral, se eu sei que há uma sobrecarga de 5% vindo do sistema de arquivos, posso fatorar isso facilmente.

EDIT # 2:

Pensando que du pode estar subnotificando os requisitos reais de tamanho do disco (por exemplo, um arquivo de 10 bytes ainda ocupa um bloco de 4k, certo?) Tentei algumas outras opções:

# 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

Além disso, a página manp para -b observa que é um alias para --apparent-size , que pode ser menor que "uso real do disco". Então, isso pode ser (mais) de onde minha matemática estava errada.

    
por thom_nic 22.03.2017 / 19:26

2 respostas

4

Possivelmente, a solução mais simples é sobrecarregar o espaço inicialmente, copiar todos os arquivos e usar resize2fs -M para reduzir o tamanho ao mínimo que esse utilitário pode gerenciar. Aqui está um exemplo:

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

Alguns trechos da saída de um diretório de exemplo:

+ 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
    
por 22.03.2017 / 20:55
0

Para o registro, eu mudei meu código original para usar du -sm , o que parece ter resolvido o meu problema. Eu acho que o cerne do problema foi o fato de que -sb é um alias para --apparent-size .

Além disso, saber que o ext4 exige, digamos, 5% de sobrecarga, torna fácil o fator de inclusão no cálculo, mas não acho que foi o problema real em questão, pois estava falhando ao escrever como superusuário.

    
por 31.03.2017 / 15:16