btrfs deslocamento final do sistema de arquivos (tamanho da imagem)

5

Eu tenho um sistema de arquivos btrfs de cerca de 7G em um arquivo de imagem de 10G img.btrfs (eu o reduzi usando btrfs fi resize -3G /mnt ). Como posso encontrar o tamanho total (offset de byte final) do sistema de arquivos, para que eu possa reduzir o tamanho da imagem? Ou seja descubra $SIZE para

truncate -s $SIZE img.btrfs

Um mecanismo que se aplica a qualquer outro sistema de arquivos dentro de um arquivo de imagem seria uma vantagem.

NOTA : uma coisa que faz funcionar é:

INITIAL=$(stat -c %s img.btrfs)
mount img.btrfs /mnt
btrfs fi resize -$NBYTES /mnt
umount /mnt
truncate -s $((INITIAL - NBYTES + 1024*1024)) img.btrfs
mount /img.btrfs /mnt
btrfs fi resize max /mnt

i.e. encolha os btrfs, reduza a imagem um pouco menos (deixando uma sobrecarga de 1M), depois aumente o btrfs até o máximo permitido pela imagem encolhida.

    
por Anul 19.06.2015 / 20:18

2 respostas

5

Irritante, btrfs filesystem show retorna um valor aproximado se o tamanho não for um múltiplo de 1MB. Também requer um dispositivo de loop, btrfs filesystem show img.btrfs não funciona (como no Debian jessie). Não consigo encontrar outro subcomando btrfs que ajude.

Mas file img.btrfs de forma útil retorna o tamanho desejado.

$ truncate -s 16684k /tmp/img.btrfs
$ /sbin/mkfs.btrfs /tmp/img.btrfs
SMALL VOLUME: forcing mixed metadata/data groups
Btrfs v3.17
See http://btrfs.wiki.kernel.org for more information.

Turning ON incompat feature 'mixed-bg': mixed data and metadata block groups
Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
Created a data/metadata chunk of size 1703936
failed to open /dev/btrfs-control skipping device registration: Permission denied
fs created label (null) on /tmp/img.btrfs
        nodesize 4096 leafsize 4096 sectorsize 4096 size 16.29MiB
$ truncate -s 32m /tmp/img.btrfs
$ file /tmp/img.btrfs
/tmp/img.btrfs: BTRFS Filesystem sectorsize 4096, nodesize 4096, leafsize 4096, UUID=61297945-d399-4fdc-ba9f-750ef9f9dfdb, 28672/17084416 bytes used, 1 devices

Ele lê diretamente o valor little-endian de 8 bytes no deslocamento 0x10070. Se você não quiser analisar a saída de file , poderá extraí-lo. O seguinte trecho POSIX faz o job¹:

size_hex=$(cat /tmp/img.btrfs | dd ibs=8 skip=8206 count=1 2>/dev/null | od -tx8 -An | tr abcdef ABCDEF | tr -dc 0-9ABCDEF)
[ ${#size_hex} -eq 16 ] &&
{ echo "ibase=16; $size_hex"; } | bc

ou em Perl:

</tmp/btrfs.img perl -e 'seek(STDIN, 0x10070, 0) or sysread(STDIN, $_, 0x10070) == 0x10070 or die "seek"; sysread(STDIN, $_, 8) == 8 or die "read"; print unpack("Q<", $_), "\n"'

file funciona para alguns outros tipos de sistema de arquivos, mas isso não ajuda muito em scripts porque a saída não é padronizada. Não consigo pensar em um utilitário genérico com uma interface padrão para todos os sistemas de arquivos comuns, talvez alguma ferramenta de virtualização ou análise forense.

¹ Exercício: por que isso é um uso útil de cat ?

    
por 22.06.2015 / 16:58
1

Tanto btrfs filesystem show quanto btrfs filesystem usage fornecem o tamanho do dispositivo, em Mebibytes , Gibibytes, ou outros poderes de 2. Você pode passar isso para truncate com o sufixo M ou G etc como estes também estão em potências de 2 (não use sufixo MB GB!). Por exemplo, em uma imagem de 1G reduzida em 10M:

sudo btrfs fi show /mnt
 devid    1 size 1014.00MiB used 12.00MiB path /dev/loop0
sudo btrfs fi usage /mnt
 Device size:                1014.00MiB

SIZE=1014M # not MB!
truncate -s $SIZE img.btrfs

Não deve haver blocos usados além desse tamanho.

    
por 22.06.2015 / 18:38