Come posso scoprire l'intervallo di un file di LBA usando il suo inode?


9

Mentre rispondo a questa domanda di U&L intitolata: Quale comando devo usare per vedere il blocco iniziale e finale di un file nel file system? , Ho provato a capire se era possibile determinare l'LBA di un file usando il suo inode.

La mia risposta ha stabilito che potrei usare hdparmcome metodo per trovare gli 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

Ma ero curioso di sapere se c'era un metodo che utilizzava l'inode di un file per ottenere anche gli LBA; senza usare hdparm.

Penso che ci potrebbero essere i metodi alternativi che si nascondono negli strumenti filefrag, stat, debugfs, e tune2fs, ma prendere in giro fuori mi sta sfuggendo.

Qualcuno può pensare ad alternative?


Ecco alcune delle mie ricerche finora che potrebbero essere utili a chi è abbastanza coraggioso da tentare di rispondere a questa domanda.

filefrag

Ho il sospetto che tu possa usare lo strumento filefragper farlo, in particolare usando i risultati dal suo -einterruttore, forse eseguendo diversi calcoli per arrivarci che non ho familiarità.

uscita campione

$ 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

inode

Un altro potenziale metodo che sospetto possa avere è quello di utilizzare le informazioni sull'inode di un file, direttamente o attraverso una matematica complessa che è scarsamente documentata sugli interwebs.

Esempio

Per prima cosa scopriamo l'inode del file. Possiamo farlo usando il statcomando o ls -i.

statistica

$ 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

Con le informazioni inode in mano, possiamo ora aprire il file system Il file si trova su come utilizzare lo strumento, debugfs.

NOTA: per determinare il filesystem su cui risiede un file è possibile utilizzare il comando df <filename>.

Ora se eseguiamo debugfsed eseguiamo il comando stat <inode #>possiamo ottenere un elenco di estensioni che contengono i dati di questo file.

$ 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

Ora abbiamo le informazioni sulle estensioni sopra, ed è qui che mi perdo e non so come procedere.

Riferimenti

Risposte:


5

filefrage debugfsriporta l'offset espresso in numero di blocchi del filesystem.

Per ottenere l'offset nel numero di unità da 512 byte, è necessario moltiplicare per la dimensione del blocco in unità da 512 byte. Su ext4 FS, la dimensione del blocco è spesso 4k, quindi è necessario moltiplicare per 8.

Con filefrag, è anche possibile utilizzare -b 512un'opzione per ottenere l'offset in unità da 512 byte.

Puoi ottenere la dimensione del blocco con il statscomando in debugfs, o con GNU stat:

stat -fc%s /mount/point

(o qualsiasi file in quel file system).

Si noti che hdparmè un'utilità del disco rigido, proverà a fornire l'offset all'interno del disco rispetto al dispositivo a blocchi su cui è montato il file system (supponendo che il dispositivo a blocchi risieda in qualche modo sul disco). Funziona in questo modo solo per le partizioni (aggiungendo il contenuto /sys/class/block/the-block-device/startall'offset effettivo) e i dispositivi RAID 1 md, ma non altri tipi di dispositivi a blocchi supportati da disco come dispositivi di mappatura dei dispositivi, altri livelli RAID, dispositivi di paura, loop, nbd. .. Si noti inoltre che le versioni precedenti di si hdparmbasavano sullo ioctl FIBMAP che è limitato in quale dispositivo a blocchi può essere utilizzato, mentre le versioni più recenti usano FIEMAP come filefrag.

Ad esempio, se hai un ext2filesystem acceso /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

Puoi ottenere quei due settori (ma nota che probabilmente il file ne usa solo una parte):

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

Mentre con filefrago 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

Lo ottieni dal dispositivo a blocchi reale:

dd bs=1024 skip=53859 count=1 if=/dev/sda1

Quindi, se ti capisco correttamente, se filefrag -b512 -v ..dice "physical_offset: 211787168 .. 211795719" questi equivarrebbero agli LBA? Questo sembra funzionare con lo stesso file con hdparm --fibmap, 211787168..211795719. Se lascio cadere -b512 -ve uso il def. 1024 e provare a mult. per 8, 26473396⋅8..26474464⋅8, ottengo 211787168..211795712, che è vicino ma un po 'fuori. Sto pensando che il secondo valore dovrebbe essere (26474465⋅8) -1 = 211795719, non so perché.
slm

Qualche idea su come ottenere i blocchi in 512 unità dal debug?
slm

Ho finito per fare i calcoli per convertire da estensioni a LBA usando la stessa matematica sopra.
slm

2

Risulta che convertire da estensioni a LBA è in realtà abbastanza semplice una volta capito da dove provengono i numeri. La risposta di @StephaneChazelas è stata fondamentale per ottenere questa comprensione.

Output originale di debug

Usando il seguente esempio menzionato nella domanda.

$ 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

Con le informazioni sulle estensioni possiamo fare i seguenti calcoli. Ma abbiamo bisogno di un'informazione aggiuntiva. La dimensione del blocco del filesystem sottostante. È possibile utilizzare questo comando per ottenerlo.

Misura del blocco

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

Conversione da estensioni a LBA

Quindi la trasformazione chiave da riconoscere qui è che gli LBA sono in unità da 512 byte e il debugfscomando sopra che ha riportato il numero di estensioni, lo sta segnalando in blocchi da 4096 byte.

Quindi, 4096/512 = 8. Quindi dobbiamo moltiplicare le estensioni per 8 per convertirle in valori LBA.

Quindi la seguente matematica ci darà il nostro LBA iniziale:

$ calc -d
; 35304898 * 8
    282439184
; 

Quindi qual è la nostra LBA finale? Per ottenere ciò, dobbiamo riconoscere che il nostro inode si inserisce in un singolo blocco, quindi la sua estensione finale è la stessa della sua estensione iniziale. Per calcolare l'LBA finale possiamo usare questa equazione.

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

Quindi eseguendo questo calcolo:

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

Confermando i risultati

Guardando l' hdparmoutput originale :

 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Vediamo che le cose corrispondono.

Un altro esempio

Solo per essere sicuri che abbiamo ragione, ecco un file più grande come secondo esempio.

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

Ecco le estensioni dell'inode.

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

Ora facciamo conversioni da estensioni a LBA.

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

E confermiamo

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

E ci abbiniamo di nuovo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.