如何使用其inode找出文件的LBA范围?


9

在回答这个标题为“ U&L”的问题时,如何使用什么命令查看文件系统中文件的开始和结束块?,我试图弄清楚是否可以使用文件的inode来确定文件的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

我觉得可能是替代方法躲在工具filefragstatdebugfs,和tune2fs,但逗弄它是躲避我。

谁能想到替代方案?


到目前为止,我的一些研究可能对那些勇于尝试回答这一问题的人有用。

文件片段

我怀疑您可以使用该工具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

索引节点

我怀疑可能存在的另一种可能的方法是直接使用文件的inode信息,或者通过一些复杂的数学来使用这些信息,而这些数学却很少在互连网上记录。

首先,我们找出文件的索引节点。我们就可以利用这样做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

有了inode信息,我们现在可以使用工具打开该文件所在的文件系统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

现在我们有了上面的扩展信息,这是我迷路而又不知道如何进行的地方。

参考文献

Answers:


5

filefragdebugfs以文件系统块数表示的报告偏移量。

要获得以512字节为单位的偏移量,需要乘以512字节为单位的块大小。在ext4 FS上,块大小通常为4k,因此您需要乘以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依赖于FIBMAP ioctl,后者在可使用的块设备上受到限制,而较新的版本则使用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或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

您可以从实际的块设备获得它:

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

因此,如果我对您的理解正确,如果filefrag -b512 -v ..说“ physical_offset:211787168..211795719”,这些等同于LBA吗?这似乎与hdparm --fibmap211787168..211795719的文件相同。如果我放下-b512 -v并使用def。1024,然后尝试换乘。通过8,26473396⋅8..26474464⋅8,我得到211787168..211795712,它接近但有点偏离。我在想第二个值应该是(26474465⋅8)-1 = 211795719,但不确定为什么。
slm

关于如何从debugfs中以512个单位获取块的任何想法?
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是什么?为此,我们需要认识到我们的inode可以放入单个块中,因此其结束范围与开始范围相同。要计算最终的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

我们再次比赛。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.