Comment puis-je trouver la plage d'un fichier de LBA en utilisant son inode?

9

En répondant à cette question U&L intitulée: Quelle commande dois-je utiliser pour voir le bloc de début et de fin d'un fichier dans le système de fichiers? , J'ai essayé de déterminer s'il était possible de déterminer le LBA d'un fichier en utilisant son inode.

Ma réponse a déterminé que je pouvais utiliser hdparmcomme une méthode pour trouver des LBA:

$ sudo hdparm --fibmap afile 

afile:
 filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Mais j'étais curieux de savoir s'il existait une méthode utilisant l'inode d'un fichier pour obtenir également les LBA; sans utiliser hdparm.

Je pense qu'il pourrait y avoir d' autres méthodes qui se cachent dans les outils filefrag, stat, debugfset tune2fsmais taquine dehors me éludant.

Quelqu'un peut-il penser à des alternatives?


Voici quelques-unes de mes recherches jusqu'à présent qui pourraient être utiles à ceux qui ont le courage de tenter de répondre à cette question.

filefrag

Je soupçonne que vous pourriez utiliser l'outil filefragpour le faire, en utilisant spécifiquement les résultats de son -ecommutateur, peut-être en effectuant plusieurs calculs pour y arriver que je ne connais pas très bien.

exemple de sortie

$ filefrag -e afile
Filesystem type is: ef53
File size of afile is 20 (1 block of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       0:   35304898..  35304898:      1:             eof
afile: 1 extent found

inodes

Une autre méthode potentielle que je soupçonne pourrait avoir un potentiel consiste à utiliser les informations d'inode d'un fichier, soit directement, soit par le biais de calculs complexes mal documentés sur les interwebs.

Exemple

Nous découvrons d'abord l'inode du fichier. Nous pouvons le faire en utilisant la statcommande ou ls -i.

stat

$ stat afile 
  File: ‘afile’
  Size: 20          Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d    Inode: 6560281     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/    saml)   Gid: ( 1000/    saml)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2013-12-27 18:40:12.788333778 -0500
Modify: 2013-12-27 18:40:23.103333073 -0500
Change: 2013-12-27 18:44:03.697317989 -0500
 Birth: -

ls -i

$ ls -i 
6560281 afile

Avec les informations inode à la main, nous pouvons maintenant ouvrir le système de fichiers ce fichier se trouve sur l' utilisation de l'outil, debugfs.

REMARQUE: pour déterminer le système de fichiers sur lequel réside un fichier, vous pouvez utiliser la commande df <filename>.

Maintenant, si nous exécutons debugfset exécutons la commande, stat <inode #>nous pouvons obtenir une liste des extensions qui contiennent les données de ce fichier.

$ sudo debugfs -R "stat <6560281>" /dev/mapper/fedora_greeneggs-home
debugfs 1.42.7 (21-Jan-2013)
Inode: 6560281   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 1999478298    Version: 0x00000000:00000001
User:  1000   Group:  1000   Size: 20
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x52be10c3:a640e994 -- Fri Dec 27 18:44:03 2013
 atime: 0x52be0fdc:bbf41348 -- Fri Dec 27 18:40:12 2013
 mtime: 0x52be0fe7:18a2f344 -- Fri Dec 27 18:40:23 2013
crtime: 0x52be0dd8:64394b00 -- Fri Dec 27 18:31:36 2013
Size of extra inode fields: 28
Extended attributes stored in inode body: 
  selinux = "unconfined_u:object_r:user_home_t:s0\000" (37)
EXTENTS:
(0):35304898

Maintenant, nous avons les informations ci-dessus, et c'est là que je me perds et je ne sais pas comment procéder.

Références

slm
la source

Réponses:

5

filefraget debugfsrapport du décalage exprimé en nombre de blocs du système de fichiers.

Pour obtenir le décalage en nombre d'unités de 512 octets, vous devez multiplier par la taille du bloc en unités de 512 octets. Sur ext4 FS, la taille des blocs est souvent de 4k, vous devez donc multiplier par 8.

Avec filefrag, vous pouvez également utiliser une -b 512option pour obtenir le décalage en unités de 512 octets.

Vous pouvez obtenir la taille de bloc avec la statscommande in debugfsou avec GNU stat:

stat -fc%s /mount/point

(ou tout fichier de ce système de fichiers).

Notez qu'il hdparms'agit d'un utilitaire de disque dur, il essaiera de donner le décalage dans le disque par opposition au périphérique de bloc sur lequel le système de fichiers est monté (en supposant que le périphérique de bloc réside sur le disque d'une manière ou d'une autre). Cela ne fonctionne que de cette façon pour les partitions (en ajoutant le contenu de /sys/class/block/the-block-device/startl'offset réel) et les périphériques md RAID 1, mais pas d'autres types de périphériques de bloc éventuellement sauvegardés sur disque comme les périphériques de mappage de périphériques, d'autres niveaux RAID, les périphériques dmraid, loop, nbd. .. Notez également que les anciennes versions de hdparmreposaient sur l'ioctl FIBMAP qui est limité dans quel périphérique de bloc il peut être utilisé, tandis que les versions plus récentes utilisent FIEMAP comme filefrag.

Ainsi, par exemple, si vous avez un ext2système de fichiers /dev/sda1.

# hdparm --fibmap /file/in/there
/file/in/there:
 filesystem blocksize 1024, begins at LBA 2048; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0     109766     109767          2

Vous pouvez obtenir ces deux secteurs (mais notez que le fichier n'en utilise probablement qu'une partie):

dd skip=109766 count=2 if=/dev/sda # not /dev/sda1

Avec filefragou debugfs.

# filefrag -v /file/in/there
Filesystem type is: ef53
Filesystem cylinder groups is approximately 12
File size of /file/in/there is 87 (1 block, blocksize 1024)
 ext logical physical expected length flags
   0       0    53859               1 merged,eof

Vous l'obtenez à partir du périphérique bloc réel:

dd bs=1024 skip=53859 count=1 if=/dev/sda1
Stéphane Chazelas
la source
Donc, si je vous comprends bien, si filefrag -b512 -v ..dit "offset_physique: 211787168 .. 211795719", cela équivaudrait aux LBA? Cela semble fonctionner avec le même fichier avec hdparm --fibmap211787168..211795719. Si je laisse tomber le -b512 -vet utilise le def. 1024, et essayez de mult. par 8, 26473396⋅8..26474464⋅8, je reçois 211787168..211795712, qui est proche mais un peu décalé. Je pense que la 2e valeur devrait être (26474465⋅8) -1 = 211795719, je ne sais pas pourquoi.
slm
Des réflexions sur la façon d'obtenir les blocs en 512 unités à partir de debugfs?
slm
J'ai fini par faire les calculs pour convertir des extensions en LBA en utilisant les mêmes calculs ci-dessus.
slm
2

Il s'avère que la conversion d'étendues en LBA est en fait assez simple une fois que vous comprenez d'où viennent les chiffres. La réponse de @StephaneChazelas était essentielle pour acquérir cette compréhension.

Sortie debugfs d'origine

En utilisant l'exemple suivant qui a été mentionné dans la question.

$ sudo debugfs -R "stat <6560281>" /dev/mapper/fedora_greeneggs-home
debugfs 1.42.7 (21-Jan-2013)
Inode: 6560281   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 1999478298    Version: 0x00000000:00000001
User:  1000   Group:  1000   Size: 20
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x52be10c3:a640e994 -- Fri Dec 27 18:44:03 2013
 atime: 0x52be0fdc:bbf41348 -- Fri Dec 27 18:40:12 2013
 mtime: 0x52be0fe7:18a2f344 -- Fri Dec 27 18:40:23 2013
crtime: 0x52be0dd8:64394b00 -- Fri Dec 27 18:31:36 2013
Size of extra inode fields: 28
Extended attributes stored in inode body: 
  selinux = "unconfined_u:object_r:user_home_t:s0\000" (37)
EXTENTS:
(0):35304898

Avec les informations d'étendue, nous pouvons effectuer les calculs suivants. Mais nous avons besoin d'une information supplémentaire. Taille de bloc du système de fichiers sous-jacent. Vous pouvez utiliser cette commande pour l'obtenir.

Taille de bloc

$ sudo tune2fs -l /dev/mapper/fedora_greeneggs-home | grep "Block size"
Block size:               4096

Conversion d'extensions en LBA

Ainsi, la transformation clé à reconnaître ici est que les LBA sont en unités de 512 octets et la debugfscommande ci-dessus qui a signalé le nombre d'extensions, indique que dans les blocs de 4096 octets.

Donc, 4096/512 = 8. Nous devons donc multiplier les extensions par 8 pour les convertir en valeurs LBA.

Ainsi, les calculs suivants nous donneront notre LBA de début:

$ calc -d
; 35304898 * 8
    282439184
; 

Alors, quelle est notre fin LBA? Pour obtenir cela, nous devons reconnaître que notre inode tient à l'intérieur d'un seul bloc de sorte que son étendue de fin est la même que son étendue de début. Pour calculer le LBA final, nous pouvons utiliser cette équation.

ending LBA = ( (extent + 1) * 8 ) - 1

Donc, effectuer ce calcul:

$ calc -d
; ( (35304898 + 1) * 8 ) - 1
    282439191

Confirmer les résultats

En regardant la hdparmsortie d' origine :

 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Nous voyons que les choses correspondent.

Un autre exemple

Juste pour vous assurer que nous avons raison, voici un fichier plus gros comme deuxième exemple.

$ ls -i util-linux-2.19.tar.bz2 
6559005 util-linux-2.19.tar.bz2

Voici l'étendue de l'inode.

$ sudo debugfs -R "stat <6559005>" /dev/mapper/fedora_greeneggs-home
...
EXTENTS:
(0-1068):26473396-26474464

Maintenant, nous faisons des conversions d'étendues en LBA.

$ calc -d
; 26473396*8
    211787168
; (26474464+1)*8 - 1
    211795719

Et nous confirmons.

$ sudo hdparm --fibmap util-linux-2.19.tar.bz2 
...
 byte_offset  begin_LBA    end_LBA    sectors
           0  211787168  211795719       8552

Et nous correspondons à nouveau.

slm
la source