[fs] linux如何获知文件在分区上对应的块
概述
在包括 Linux ext 系列在内的 inode 文件系统中,文件自身的数据保存在磁盘分区数据块中,并由 inode 索 引。在某些情况下,我们需要知道一个文件在磁盘分区中是由第几个数据块开始的;本文即是介绍其方法。
使用debugfs和stat命令
对于获得文件详细信息,通常使用 stat 命令;但可以发现其中并没有数据块信息,如下图-1 所示:
这时我们需要使用 debugfs 来获得更为详尽的信息。
首先,在此文件所在分区中启动 debugfs。然后,再使用 stat 命令。详细步骤参见图-2:
- 使用 lsblk 命令确认当前分区信息。我们要查看的文件在/dev/sda5 分区上。
- 在这个分区上打开 debugfs。
- 使用 stat 命令,我们可以得到结果,如图-3 所示。
- 使用 q 退出 debugfs。
在 debugfs 中的 stat 命令结果,如下图-3 所示:
可以看到除了刚刚 stat 得到的普通结果外,“(0):31758604”为数据块信息,其含义是:此文件第 0 块数据块为 31758604。
使用FIBMAP ioctl
写一个程序,使用 FIBMAP ioctl 获知某个数据块是第几块。如代码 ff.c 所示:
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd = 0;
int i = 0;
int block = 0;
int blocksize = 0;
int bcount = 0;
struct stat st;
assert(NULL != argv[1]);
assert(fd = open(argv[1], O_RDONLY));
assert(0 == ioctl(fd, FIGETBSZ, &blocksize));
assert(!fstat(fd, &st));
bcount = (st.st_size + blocksize - 1) / blocksize;
printf("File: %s Size: %ld Blocks: %d Blocksize: %d\n",
argv[1], st.st_size, bcount, blocksize);
for (i = 0; i < bcount; i++) {
block = i;
if (ioctl(fd, FIBMAP, &block))
printf("FIBMAP ioctl failed - errno: %s\n", strerror(errno));
printf("%3d %10d\n", i, block);
}
close(fd);
return 0;
}
运行结果如下图-4 所示:
可知这与 debugfs 中使用 stat 命令得到的结果一致。
参考信息
https://serverfault.com/questions/29886/how-do-i-list-a-files-data-blocks-on-linux
https://lists.debian.org/debian-mips/2002/04/msg00059.html
END
Aningsk
2020-03-24
Written on March 24, 2020