在回答标题为:我使用什么命令查看文件系统中文件的开始和结束块的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
Run Code Online (Sandbox Code Playgroud)
但我很好奇是否有某种方法使用文件的 inode 来获取 LBA;不使用hdparm.
我认为可能有其他方法隐藏在工具filefrag, stat, 中debugfs,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
Run Code Online (Sandbox Code Playgroud)
我怀疑可能有潜力的另一种潜在方法是直接使用文件的 inode 信息,或者通过一些在互联网上记录不佳的复杂数学。
例子
首先我们找出文件的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: -
Run Code Online (Sandbox Code Playgroud)
ls -i
$ ls -i
6560281 afile
Run Code Online (Sandbox Code Playgroud)
有了 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
Run Code Online (Sandbox Code Playgroud)
现在我们有了上面的范围信息,这就是我迷路的地方,不知道如何继续。
filefrag并debugfs报告以文件系统块数表示的偏移量。
要获得以 512 字节为单位的偏移量,您需要乘以以 512 字节为单位的块大小。在 ext4 FS 上,块大小通常为 4k,因此需要乘以 8。
使用filefrag,您还可以使用-b 512选项以 512 字节为单位获取偏移量。
您可以使用 中的stats命令debugfs或 GNU stat获取块大小:
stat -fc%s /mount/point
Run Code Online (Sandbox Code Playgroud)
(或该文件系统中的任何文件)。
请注意,这hdparm是一个硬盘实用程序,它将尝试提供磁盘内的偏移量,而不是安装文件系统的块设备(假设块设备确实以某种方式驻留在磁盘上)。它仅适用于分区(通过将 的内容添加/sys/class/block/the-block-device/start到实际偏移量)和 md RAID 1 设备,但不适用于其他可能的磁盘支持的块设备类型,如设备映射器设备、其他 RAID 级别、dmraid 设备、循环、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
Run Code Online (Sandbox Code Playgroud)
您可以获得这两个扇区(但请注意,该文件可能仅使用其中的一部分):
dd skip=109766 count=2 if=/dev/sda # not /dev/sda1
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
你从实际的块设备中得到它:
dd bs=1024 skip=53859 count=1 if=/dev/sda1
Run Code Online (Sandbox Code Playgroud)
事实证明,一旦您了解了数字的来源,从范围转换为 LBA 实际上相当简单。@StephaneChazelas 的回答对于获得这种理解至关重要。
使用问题中提到的以下示例。
$ 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
Run Code Online (Sandbox Code Playgroud)
利用范围信息,我们可以进行以下计算。但我们还需要一条额外的信息。底层文件系统的块大小。您可以使用此命令来获取它。
$ sudo tune2fs -l /dev/mapper/fedora_greeneggs-home | grep "Block size"
Block size: 4096
Run Code Online (Sandbox Code Playgroud)
因此,这里要认识到的关键转换是 LBA 以 512 字节为单位,而上面debugfs报告范围数的命令是以 4096 字节块为单位报告的。
因此,4096/512 = 8。因此我们需要将范围乘以 8 将它们转换为 LBA 值。
因此,下面的数学计算将给出我们的初始 LBA:
$ calc -d
; 35304898 * 8
282439184
;
Run Code Online (Sandbox Code Playgroud)
那么我们的最终 LBA 是什么?为此,我们需要认识到我们的索引节点适合单个块,因此其结束范围与其开始范围相同。为了计算最终的 LBA,我们可以使用这个方程。
ending LBA = ( (extent + 1) * 8 ) - 1
Run Code Online (Sandbox Code Playgroud)
因此执行这个计算:
$ calc -d
; ( (35304898 + 1) * 8 ) - 1
282439191
Run Code Online (Sandbox Code Playgroud)
查看原始hdparm输出:
byte_offset begin_LBA end_LBA sectors
0 282439184 282439191 8
Run Code Online (Sandbox Code Playgroud)
我们看到事情是匹配的。
只是为了确保我们这里有一个更大的文件作为第二个示例。
$ ls -i util-linux-2.19.tar.bz2
6559005 util-linux-2.19.tar.bz2
Run Code Online (Sandbox Code Playgroud)
这是索引节点的范围。
$ sudo debugfs -R "stat <6559005>" /dev/mapper/fedora_greeneggs-home
...
EXTENTS:
(0-1068):26473396-26474464
Run Code Online (Sandbox Code Playgroud)
现在我们进行从范围到 LBA 的转换。
$ calc -d
; 26473396*8
211787168
; (26474464+1)*8 - 1
211795719
Run Code Online (Sandbox Code Playgroud)
我们确认了。
$ sudo hdparm --fibmap util-linux-2.19.tar.bz2
...
byte_offset begin_LBA end_LBA sectors
0 211787168 211795719 8552
Run Code Online (Sandbox Code Playgroud)
我们再次匹配。