Dimensionando uma imagem de disco / sistema de arquivos para armazenar exatamente um determinado conjunto de arquivos com espaço livre próximo de zero

2

Eu preciso construir, em código adequado para scripting / make / automation, uma imagem de disco (duas partições, um sistema de arquivos FAT e um sistema de arquivos ext4, para inicializar o UEFI / Syslinux USB Linux [instalador do SO], que nunca será modificado produção) de um tamanho que mantém exatamente (ou muito próximo de) um conjunto de arquivos de tamanho arbitrário. Em outras palavras, dado um conjunto de arquivos construídos, preciso saber como gerar imagens do sistema de arquivos FAT e ext4 e a imagem de disco que é particionada para mantê-los, que têm tamanhos computados para resultar tão próximos de zero quanto ter. Não há problema em errar ao lado de uma pequena sala extra, mas não há problema em falhar quando alguém adiciona N + 1 bytes ao arquivo daqui a dois anos. Isso precisa ser adequado para um makefile, ou seja, tentativa e erro não o reduzem (embora eu suponha que, se o pior acontecesse, uma solução iterativa com um limite poderia funcionar). Isso é algo como uma imagem ISO-9660 (que costumava estar em um projeto anterior, mas o Syslinux não suporta imagens ISO-9660 no UEFI).

Estou criando os arquivos usando dd (para alocar a imagem de disco), parted , dd (para alocar o sistema de arquivos FAT), mkfs.vfat , dd (para o ext4), mkfs.ext4 , kpartx (para mapear as partições), dd (para gravar a partição FAT), dd (para gravar a partição ext4) e, finalmente, dd para gravar a imagem do disco em um USB para inicializar no hardware real.

Minha idéia atual é usar du para determinar quanto espaço os arquivos ocupam no disco de compilação, depois adicionar alguma margem para sobrecarga adicional do sistema de arquivos e da partição e margem de erro. Portanto, preciso saber as contagens de blocos para cada uma das dd que receberam as saídas du .

Outra opção é construir uma imagem grande de tamanho fixo, gravar os arquivos e redimensionar o FAT, o ext4 e as partições para o tamanho mínimo. Os sistemas de arquivos ext4 podem ser encolhidos e eu vejo que os sistemas de arquivos FAT podem ser encolhidos. Mas então você ainda tem o problema de calcular quanto diminuir. Perguntar se alguém fez isso antes teve algumas ideias concretas (ou código de exemplo).

    
por eewanco 04.10.2016 / 21:25

1 resposta

0

Acabei usando uma combinação de fatores fudge e uma abordagem iterativa (como fail-safe). Isso não precisa ser tão complicado quanto eu imaginava. Acontece que, por enquanto, pouca falsificação era necessária para o FAT, mas uma enorme quantidade de falsificação negativa era necessária para ext; com um fator de fudge zero para ext4, eu tinha muito espaço livre (mais de 21M). Eu converti para ext2 (que precisa de um diário fedorento ?!), aumentei o tamanho do meu bloco e contei cuidadosamente os inodes que eu precisava, e obtive ainda mais megabytes de espaço livre. Eu suponho que eu poderia ter obtido o "tamanho real" de du e trabalhado a partir daí, mas imaginei que contar a sobrecarga, mesmo que fossem sistemas de arquivos diferentes, seria uma aproximação mais próxima.

# Estimated filesystem overhead, in 512-byte blocks
FS_ESP_FUDGE=256 
FS_ISO_FUDGE=-80000 # Wow!
FS_FUDGE_INCR=1024
...
read ESP_RSIZE d < <(du --summarize --block-size=512 $ESP)
read ISO_RSIZE d < <(du --summarize --block-size=512 $ISO)

success=false
until $success; do 
    let ESP_SIZE=ESP_RSIZE+FS_ESP_FUDGE
    let ISO_SIZE=ISO_RSIZE+FS_ISO_FUDGE
    let ESP_START=2048
    let IMG_SIZE=ESP_SIZE+ISO_SIZE+ESP_START
    let ESP_END=ESP_START+ESP_SIZE-1
    let ISO_START=ESP_END+1

    success=true
...
    sudo /sbin/mkfs.vfat /dev/mapper/$p1 -F 16 \
        || error_exit "mkfs.vfat failed" 5
    # -N: Count the inodes (all files, plus . and .. for each directory,
    # which I can't get "find" to include).  
    sudo /sbin/mke2fs -b 4096 -N $(( $(find $ISO | wc -l ) + 2 * $(find $ISO -type d | wc -l))) -m 0 -q /dev/mapper/$p2 \
        || error_exit "mke2fs failed" 6
...
    if ! tar -C $ESP -c --exclude-vcs --exclude-backups . | \
        sudo tar -C mnt/esp -x; then
        {
            read
            read fs onek used avail use rest
        } < <(df mnt/esp)
        # Are we out of disk space? If not, bail, else increase margin, retry
        [[ $onek -ne $used || $avail -ne 0 || $use != "100%" ]] && \
            error_exit "esp tar failed" 9
        let FS_ESP_FUDGE=FS_ESP_FUDGE+FS_FUDGE_INCR
        success=false
    fi
    if ! tar -C $ISO -c --exclude-vcs --exclude-backups . | \
        sudo tar -C mnt/iso --owner=root --group=root -x ; then
        {
            read
            read fs onek used avail use rest
        } < <(df mnt/iso)
        # Are we out of disk space? If not, bail, else increase margin, retry
        [[ $onek -ne $used || $avail -ne 0 || $use != "100%" ]] && \
            error_exit "iso tar failed" 10
        let FS_ISO_FUDGE=FS_ISO_FUDGE+FS_FUDGE_INCR
        success=false
    fi
    $success || echo "Whoops, I guessed too small; please adjust fudge factor.  Retrying ..."
...
done
    
por 05.10.2016 / 23:01