Wie kann ich mithilfe des Inodes den LBA-Bereich einer Datei ermitteln?

9

Bei der Beantwortung dieser U & L-Frage mit dem Titel: Mit welchem ​​Befehl kann ich den Start- und Endblock einer Datei im Dateisystem anzeigen? Ich habe versucht herauszufinden, ob es möglich ist, den LBA einer Datei mithilfe des Inodes zu bestimmen.

Meine Antwort ergab, dass ich hdparmals eine Methode zum Auffinden von LBAs verwenden könnte:

$ 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

Aber ich war neugierig, ob es eine Methode gibt, die den Inode einer Datei verwendet, um auch die LBAs zu erhalten. ohne zu benutzen hdparm.

Ich denke , es könnte alternative Methoden sein in den Werkzeugen versteckt filefrag, stat, debugfs, und , tune2fsaber es Herausarbeitung ist eluding ich.

Kann sich jemand Alternativen vorstellen?


Hier sind einige meiner bisherigen Forschungen, die für diejenigen nützlich sein könnten, die mutig genug sind, dies zu beantworten.

filefrag

Ich vermute, Sie könnten das Tool verwenden, filefragum dies zu tun, insbesondere anhand der Ergebnisse des -eWechsels, indem Sie möglicherweise mehrere Berechnungen durchführen, um dorthin zu gelangen, mit denen ich nicht so vertraut bin.

Beispielausgabe

$ 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

Eine andere mögliche Methode, von der ich vermute, dass sie Potenzial hat, besteht darin, die Inode-Informationen einer Datei entweder direkt oder durch eine komplexe Mathematik zu verwenden, die in den Interwebs schlecht dokumentiert ist.

Beispiel

Zuerst finden wir den Inode der Datei heraus. Wir können dies entweder mit dem statBefehl oder tun 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

Mit den vorliegenden Inode-Informationen können wir nun das Dateisystem öffnen, in dem sich diese Datei befindet, indem wir das Tool verwenden debugfs.

HINWEIS: Um das Dateisystem zu bestimmen, in dem sich eine Datei befindet, können Sie den Befehl verwenden df <filename>.

Wenn wir nun debugfsden Befehl ausführen stat <inode #>, können wir eine Liste der Speicherbereiche abrufen, die die Daten dieser Datei enthalten.

$ 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

Jetzt haben wir die oben genannten Informationen, und hier verliere ich mich und weiß nicht, wie ich vorgehen soll.

Verweise

slm
quelle

Antworten:

5

filefragund debugfsBerichtsoffset ausgedrückt in Anzahl der Dateisystemblöcke.

Um den Versatz in Anzahl von 512-Byte-Einheiten zu erhalten, müssen Sie mit der Größe des Blocks in 512-Byte-Einheiten multiplizieren. Bei ext4 FS beträgt die Blockgröße häufig 4 KB, daher müssen Sie mit 8 multiplizieren.

Mit filefragkönnen Sie auch eine -b 512Option verwenden, um den Offset in 512-Byte-Einheiten abzurufen.

Sie können die Blockgröße mit dem statsBefehl in debugfsoder mit GNU stat abrufen:

stat -fc%s /mount/point

(oder eine beliebige Datei in diesem Dateisystem).

Beachten Sie, dass hdparmes sich um ein Festplatten-Dienstprogramm handelt, das versucht, den Offset innerhalb der Festplatte im Gegensatz zu dem Blockgerät anzugeben, auf dem das Dateisystem bereitgestellt ist (vorausgesetzt, das Blockgerät befindet sich irgendwie auf der Festplatte). Dies funktioniert nur für Partitionen (durch Hinzufügen des Inhalts /sys/class/block/the-block-device/startzum tatsächlichen Offset) und md RAID 1-Geräte, jedoch nicht für andere möglicherweise festplattengestützte Blockgerätetypen wie Geräte-Mapper-Geräte, andere RAID-Levels, dmraid-Geräte, Schleifen, nbd. .. Beachten Sie auch, dass ältere Versionen von hdparmFIBMAP ioctl verwendet werden, das in dem Blockgerät, auf dem es verwendet werden kann, begrenzt ist, während neuere Versionen FIEMAP wie verwenden filefrag.

Zum Beispiel, wenn Sie ein ext2Dateisystem aktiviert haben /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

Sie können diese beiden Sektoren erhalten (beachten Sie jedoch, dass die Datei wahrscheinlich nur einen Teil davon verwendet):

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

Während mit filefragoder 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

Sie erhalten es vom eigentlichen Blockgerät:

dd bs=1024 skip=53859 count=1 if=/dev/sda1
Stéphane Chazelas
quelle
Wenn ich Sie also richtig verstehe und filefrag -b512 -v .."Physical_offset: 211787168 .. 211795719" sagt, würden diese den LBAs entsprechen? Dies scheint mit der gleichen Datei zu leben hdparm --fibmap, 211787168..211795719. Wenn ich das fallen -b512 -vlasse und das def benutze. 1024 und versuchen, mult. von 8, 26473396⋅8..26474464⋅8 erhalte ich 211787168..211795712, was nah ist, aber ein bisschen abweicht. Ich denke, der 2. Wert sollte (26474465⋅8) -1 = 211795719 sein, nicht sicher warum.
slm
Irgendwelche Gedanken darüber, wie man die Blöcke in 512 Einheiten von Debugfs bekommt?
slm
Am Ende habe ich die Berechnungen durchgeführt, um von Extents in LBAs zu konvertieren, wobei ich dieselbe Mathematik wie oben verwendet habe.
slm
2

Es stellt sich heraus, dass die Konvertierung von Extents in LBAs ziemlich einfach ist, wenn Sie erst einmal verstanden haben, woher die Zahlen stammen. Die Antwort von @StephaneChazelas war entscheidend, um dieses Verständnis zu erlangen.

Ursprüngliche Debugfs-Ausgabe

Verwenden Sie das folgende Beispiel, das in der Frage erwähnt wurde.

$ 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

Mit den Extents-Informationen können wir die folgenden Berechnungen durchführen. Wir brauchen aber noch eine zusätzliche Information. Die Blockgröße des zugrunde liegenden Dateisystems. Sie können diesen Befehl verwenden, um ihn abzurufen.

Block Größe

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

Konvertieren von Extents in LBAs

Die hier zu erkennende Schlüsseltransformation ist also, dass LBAs in 512-Byte-Einheiten vorliegen und der obige debugfsBefehl, der die Anzahl der Extents angibt, dies in 4096-Byte-Blöcken meldet.

Also, 4096/512 = 8. Wir müssen also die Extents mit 8 multiplizieren, um sie in LBA-Werte umzuwandeln.

Die folgende Mathematik gibt uns also unseren ersten LBA:

$ calc -d
; 35304898 * 8
    282439184
; 

Also, was ist unser Ende LBA? Um dies zu erreichen, müssen wir erkennen, dass unser Inode in einen einzelnen Block passt, sodass seine Endausdehnung mit seiner Anfangsausdehnung übereinstimmt. Um die End-LBA zu berechnen, können wir diese Gleichung verwenden.

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

Führen Sie also diese Berechnung durch:

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

Ergebnisse bestätigen

Betrachten Sie die Originalausgabe hdparm:

 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Wir sehen, dass die Dinge zusammenpassen.

Ein anderes Beispiel

Nur um sicherzugehen, dass wir hier richtig sind, ist hier eine größere Datei als zweites Beispiel.

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

Hier sind die Ausmaße der Inode.

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

Jetzt führen wir Konvertierungen von Extents in LBAs durch.

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

Und wir bestätigen.

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

Und wir passen wieder zusammen.

slm
quelle