Как я могу узнать диапазон файлов LBA, используя его инод?

9

При ответе на этот вопрос U & L под названием: Какую команду я использую, чтобы увидеть начальный и конечный блок файла в файловой системе? Я попытался выяснить, возможно ли определить LBA файла, используя его индекс.

Мой ответ определил, что я мог бы использовать hdparmкак один метод для нахождения 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

Но мне было любопытно, был ли какой-нибудь метод, использующий индекс файла, чтобы также получить LBA; без использования hdparm.

Я думаю , что может быть альтернативные методы , скрывающиеся в инструментах filefrag, stat, debugfsи , tune2fsно дразнить его ускользает меня.

Кто-нибудь может придумать альтернативы?


Вот некоторые из моих исследований, которые могут быть полезны тем, кто достаточно смел, чтобы попытаться ответить на этот вопрос.

filefrag

Я подозреваю, что вы могли бы использовать инструмент, filefragчтобы сделать это, в частности, используя результаты его -eпереключения, возможно, выполнив несколько вычислений, чтобы добраться туда, с которыми я не очень знаком.

образец вывода

$ 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

иноды

Еще один потенциальный метод, который, как я подозреваю, может иметь потенциал, - это использовать информацию об индексах файла, либо напрямую, либо с помощью сложной математики, которая плохо документирована во внутренних сетях.

пример

Сначала мы узнаем инод файла. Мы можем сделать это, используя statкоманду или ls -i.

стат

$ 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

С информацией инода в руке, теперь мы можем открыть файловую систему этот файл находится по использованию инструмента debugfs.

ПРИМЕЧАНИЕ. Для определения файловой системы, в которой находится файл, вы можете использовать команду df <filename>.

Теперь, если мы запустим debugfsи запустим команду, stat <inode #>мы можем получить список экстентов, которые содержат данные этого файла.

$ 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

Теперь у нас есть информация о экстентах выше, и вот тут я теряюсь и не знаю, как действовать дальше.

Ссылки

SLM
источник

Ответы:

5

filefragи debugfsсмещение отчета, выраженное в количестве блоков файловой системы.

Чтобы получить смещение в количестве 512 байт, вам необходимо умножить размер блока в 512 байт. На ext4 FS размер блока часто составляет 4 КБ, поэтому вам нужно умножить на 8.

С помощью filefragвы также можете использовать -b 512опцию для получения смещения в 512 байт.

Вы можете получить размер блока с помощью statsкоманды debugfsили с помощью GNU stat:

stat -fc%s /mount/point

(или любой файл в этой файловой системе).

Обратите внимание, что hdparmэто утилита для жесткого диска, она будет пытаться задать смещение на диске, а не блочное устройство, на котором монтируется файловая система (при условии, что блочное устройство каким-то образом находится на диске). Это работает только для разделов (путем добавления содержимого /sys/class/block/the-block-device/startк фактическому смещению) и устройств md RAID 1, но не для других типов блочных устройств с поддержкой диска, таких как устройства отображения устройств, другие уровни RAID, устройства dmraid, loop, nbd. Также обратите внимание, что более старые версии hdparmполагались на ioctl FIBMAP, который ограничен в том, на каком блочном устройстве он может использоваться, в то время как более новые версии используют FIEMAP как filefrag.

Так, например, если у вас есть ext2файловая система /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

Вы можете получить эти два сектора (но обратите внимание, что файл, вероятно, использует только его часть):

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

Хотя с filefragили отладки.

# 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

Вы получаете это от фактического блочного устройства:

dd bs=1024 skip=53859 count=1 if=/dev/sda1
Стефан Шазелас
источник
Так что, если я правильно вас понимаю, если вы filefrag -b512 -v ..скажете "physical_offset: 211787168 .. 211795719", это будет равно LBA? Похоже, что это джайв с тем же файлом с hdparm --fibmap, 211787168..211795719. Если я уроню -b512 -vи использую def. 1024, и попытка мульт. на 8, 26473396⋅8..26474464⋅8, я получаю 211787168..211795712, что близко, но немного не так. Я думаю, что 2-е значение должно быть (26474465⋅8) -1 = 211795719, хотя не знаю почему.
SLM
Любые мысли о том, как получить блоки в 512 единиц от debugfs?
SLM
В итоге я выполнил вычисления для преобразования из экстентов в LBA, используя ту же самую математику выше.
SLM
2

Оказывается, что преобразование из экстентов в LBA на самом деле довольно просто, если вы понимаете, откуда приходят цифры. Ответ @StephaneChazelas имел решающее значение для достижения этого понимания.

Исходный вывод debugfs

Используя следующий пример, который был упомянут в вопросе.

$ 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

С информацией о экстентах мы можем сделать следующие вычисления. Но нам нужен еще один кусок информации. Размер блока базовой файловой системы. Вы можете использовать эту команду, чтобы получить ее.

Размер блока

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

Преобразование из экстентов в LBA

Таким образом, ключевое преобразование, которое нужно распознать, заключается в том, что LBA находятся в 512-байтовых единицах, а вышеприведенная debugfsкоманда, которая сообщила о количестве экстентов, сообщает об этом в 4096-байтовых блоках.

Итак, 4096/512 = 8. Поэтому нам нужно умножить экстенты на 8, чтобы преобразовать их в значения LBA.

Таким образом, следующая математика даст нам начало LBA:

$ calc -d
; 35304898 * 8
    282439184
; 

Так каков наш финал LBA? Чтобы получить это, мы должны признать, что наш инод помещается внутри одного блока, поэтому его конечный экстент совпадает с его начальным экстентом. Для расчета конечного LBA мы можем использовать это уравнение.

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

Итак, выполняя этот расчет:

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

Подтверждение результатов

Глядя на оригинальный hdparmвывод:

 byte_offset  begin_LBA    end_LBA    sectors
           0  282439184  282439191          8

Мы видим, что все совпадает.

Другой пример

Просто чтобы убедиться, что мы здесь, вот большой файл в качестве второго примера.

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

Вот экстенты inode.

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

Теперь мы делаем преобразования из экстентов в LBA.

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

И мы подтверждаем.

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

И мы снова подходим.

SLM
источник