¿Cómo puedo encontrar el rango de un archivo de LBA usando su inodo?

9

Al responder esta pregunta de U&L titulada: ¿Qué comando utilizo para ver el bloque de inicio y finalización de un archivo en el sistema de archivos? , Traté de averiguar si era posible determinar el LBA de un archivo usando su inodo.

Mi respuesta determinó que podría usar hdparmcomo un método para encontrar 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

Pero tenía curiosidad si había algún método que usara el inodo de un archivo para obtener también los LBA; sin utilizar hdparm.

Creo que puede haber métodos alternativos que se esconden en las herramientas filefrag, stat, debugfs, y tune2fsaunque las burlas hacia fuera me está eludiendo.

¿Alguien puede pensar en alternativas?


Aquí hay algunas de mis investigaciones hasta el momento que podrían ser útiles para aquellos lo suficientemente valientes como para intentar responder esto.

filefrag

Sospecho que podría usar la herramienta filefragpara hacerlo, específicamente usando los resultados de su -ecambio, tal vez realizando varios cálculos para llegar allí con los que no estoy tan familiarizado.

salida de muestra

$ 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

Otro método potencial que sospecho que podría tener potencial es utilizar la información de inodo de un archivo, ya sea directamente o a través de algunas matemáticas complejas que están mal documentadas en las redes.

Ejemplo

Primero descubrimos el inodo del archivo. Podemos hacer esto usando el statcomando o 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

Con la información de i-nodo en la mano, ahora podemos abrir el sistema de archivos Este archivo reside en el uso de la herramienta, debugfs.

NOTA: Para determinar el sistema de archivos en el que reside un archivo, puede usar el comando df <filename>.

Ahora, si ejecutamos debugfsy ejecutamos el comando stat <inode #>, podemos obtener una lista de extensiones que contienen los datos de este archivo.

$ 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

Ahora tenemos la información de extensión anterior, y aquí es donde me pierdo y no sé cómo proceder.

Referencias

slm
fuente

Respuestas:

5

filefrage debugfsinformar el desplazamiento expresado en número de bloques del sistema de archivos.

Para obtener el desplazamiento en el número de unidades de 512 bytes, debe multiplicar por el tamaño del bloque en unidades de 512 bytes. En ext4 FS, el tamaño del bloque es a menudo 4k, por lo que debe multiplicar por 8.

Con filefrag, también puede usar una -b 512opción para obtener el desplazamiento en unidades de 512 bytes.

Puede obtener el tamaño de bloque con el statscomando debugfs, o con GNU stat:

stat -fc%s /mount/point

(o cualquier archivo en ese sistema de archivos).

Tenga en cuenta que hdparmes una utilidad de disco duro, intentará proporcionar el desplazamiento dentro del disco en lugar del dispositivo de bloque en el que está montado el sistema de archivos (suponiendo que el dispositivo de bloque resida de alguna manera en el disco). Solo funciona de esa manera para particiones (agregando el contenido del /sys/class/block/the-block-device/startdesplazamiento real) y dispositivos md RAID 1, pero no otros tipos de dispositivos de bloque posiblemente respaldados por disco como dispositivos mapeadores de dispositivos, otros niveles RAID, dispositivos dmraid, loop, nbd. .. También tenga en cuenta que las versiones anteriores de hdparmconfiaban en el ioctl FIBMAP, que está limitado en qué dispositivo de bloque se puede usar, mientras que las versiones más nuevas usan FIEMAP como filefrag.

Entonces, por ejemplo, si tiene un ext2sistema de archivos encendido /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

Puede obtener esos dos sectores (pero tenga en cuenta que el archivo probablemente usa solo una parte de él):

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

Mientras que 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 obtienes del dispositivo de bloqueo real:

dd bs=1024 skip=53859 count=1 if=/dev/sda1
Stéphane Chazelas
fuente
Entonces, si te entiendo correctamente, si filefrag -b512 -v ..dice "physical_offset: 211787168 .. 211795719", ¿esto equivaldría a los LBA? Esto parece coincidir con el mismo archivo con hdparm --fibmap211787168..211795719. Si dejo caer -b512 -vy uso el def. 1024, e intento de mult. a las 8, 26473396⋅8..26474464⋅8, obtengo 211787168..211795712, que está cerca pero un poco fuera de lugar. Estoy pensando que el segundo valor debería ser (26474465⋅8) -1 = 211795719, aunque no estoy seguro de por qué.
slm
¿Alguna idea sobre cómo obtener los bloques en 512 unidades de debugfs?
slm
Terminé haciendo los cálculos para convertir de extensiones a LBA usando las mismas matemáticas anteriores.
slm
2

Resulta que la conversión de extensiones a LBA es bastante sencilla una vez que entiendes de dónde provienen los números. La respuesta de @StephaneChazelas fue crítica para obtener esta comprensión.

Salida de depuración original

Usando el siguiente ejemplo que se mencionó en la pregunta.

$ 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 la información de extensión podemos hacer los siguientes cálculos. Pero necesitamos una información adicional. El tamaño de bloque del sistema de archivos subyacente. Puede usar este comando para obtenerlo.

Tamaño de bloque

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

Conversión de extensiones a LBA

Entonces, la transformación clave para reconocer aquí es que los LBA están en unidades de 512 bytes y el debugfscomando anterior que informó el número de extensiones, informa que en bloques de 4096 bytes.

Entonces, 4096/512 = 8. Entonces, necesitamos multiplicar las extensiones por 8 para convertirlas a valores LBA.

Entonces las siguientes matemáticas nos darán nuestro LBA inicial:

$ calc -d
; 35304898 * 8
    282439184
; 

Entonces, ¿cuál es nuestro LBA final? Para lograrlo, debemos reconocer que nuestro inodo cabe dentro de un solo bloque, por lo que su extensión final es la misma que su extensión inicial. Para calcular el LBA final podemos usar esta ecuación.

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

Entonces realizando este cálculo:

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

Confirmando los resultados

Mirando la hdparmsalida original :

 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Vemos que las cosas coinciden.

Otro ejemplo

Solo para asegurarnos de que tenemos razón, aquí hay un archivo más grande como un segundo ejemplo.

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

Aquí están las extensiones del inodo.

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

Ahora hacemos conversiones de extensiones a LBA.

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

Y lo confirmamos.

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

Y volvemos a unir.

slm
fuente