btrfs système de files fin offset (taille de l'image)

J'ai un système de files btrfs d'environ 7G dans un file image 10G img.btrfs (je l'ai img.btrfs utilisant btrfs fi resize -3G /mnt ). Comment puis-je find la taille totale (offset de fin d'octet) du système de files, de sorte que je puisse réduire la taille de l'image? C'est à dire find $SIZE pour

 truncate -s $SIZE img.btrfs 

Un mécanisme qui s'applique à tout autre système de files à l'intérieur d'un file image serait un plus.

REMARQUE : une chose qui fonctionne est:

 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 

c'est-à-dire rétrécir les btrfs, réduire l'image d'un peu less (en laissant un overhead 1M), puis augmenter les btrfs au maximum offert par l'image rétrécie.

De façon gênante, le btrfs filesystem show une valeur approximative si la taille n'est pas un multiple de 1 Mo. Il nécessite également un périphérique de boucle, le btrfs filesystem show img.btrfs ne fonctionne pas (à partir de jessie Debian). Je ne peux pas find une autre sous-command btrfs qui aiderait.

Mais le file img.btrfs renvoie utilement la taille désirée.

 $ tronquer -s 16684k /tmp/img.btrfs
 $ /sbin/mkfs.btrfs /tmp/img.btrfs
 PETIT VOLUME: forçage de métadonnées / groupes de données mixtes
 Btrfs v3.17
 Voir http://btrfs.wiki.kernel.org pour plus d'informations.

 Activer la fonction incompat 'mixed-bg': groupes de blocs de données et de métadonnées mixtes
 Activation de la fonction incompat 'extref': augmentation de la limite du lien fixe par file à 65536
 Création d'un bloc de données / métadonnées de taille 1703936
 a échoué à ouvrir / dev / btrfs-control en ignorant l'logging du périphérique: Autorisation refusée
 fs créé label (null) sur /tmp/img.btrfs
         taille de noeud 4096 taille de champ 4096 taille de segment 4096 taille 16.29MiB
 $ tronquer -s 32m /tmp/img.btrfs
 $ file /tmp/img.btrfs
 /tmp/img.btrfs: Système de files BTRFS secteursize 4096, nodesize 4096, taille 4096, UUID = 61297945-d399-4fdc-ba9f-750ef9f9dfdb, 28672/17084416 octets utilisés, 1 périphériques

Il lit directement la valeur little-endian à 8 octets à l'offset 0x10070. Si vous ne souhaitez pas parsingr la sortie du file , vous pouvez l'extraire. L'extrait POSIX suivant fait le travail¹:

 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 en 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 fonctionne pour d'autres types de filesystems, mais cela n'aide pas beaucoup pour les scripts car la sortie n'est pas standardisée. Je ne peux pas penser à un utilitaire générique avec une interface standard pour tous les filesystems courants, peut-être un outil de virtualisation ou de médecine légale.

¹ Exercice: pourquoi est-ce une utilisation utile du cat ?

Les deux btrfs filesystem show et l' btrfs filesystem usage vous donne la taille de l'appareil, en Mebibytes , Gibibytes, ou d'autres puissances de 2. Vous pouvez simplement passer cela pour truncate avec le suffixe M ou G etc car elles sont également en puissance de 2 (n'utilisez pas le suffixe MB GB!). Par exemple, sur une image 1G réduite de 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 

Il ne devrait pas y avoir de blocs utilisés au-delà de cette taille.