首页 > *nix技术, 文件系统 > Xfs文件系统磁盘布局之十四:目录文件数据结构

Xfs文件系统磁盘布局之十四:目录文件数据结构

2012年1月9日 发表评论 阅读评论 2,646 次浏览

对于目录类型的文件来说,其文件内容就是该目录下管理的所有文件(也即是子目录、普通文件等等)的信息(比如文件名、inode号等),随着目录文件内容的多少不同,存放的方式也不同,本篇就先介绍最简单的存放方式,称为简短方式(Shortform Directories)。前面说过,目录文件对应inode的data fork最大可有156个字节,利用这些磁盘空间也是可以存放一些信息的,简短方式就是直接把目录文件下的子文件相关信息存放在该目录文件对应inode的这156个字节空间内。

typedef struct xfs_dir2_sf_hdr {
	__uint8_t		count;		/* count of entries */
	__uint8_t		i8count;	/* count of 8-byte inode #s */
	xfs_dir2_inou_t		parent;		/* parent dir inode number */
} __arch_pack xfs_dir2_sf_hdr_t;

typedef union {
	xfs_dir2_ino8_t	i8;
	xfs_dir2_ino4_t	i4;
} xfs_dir2_inou_t;

typedef	struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;

typedef struct xfs_dir2_sf_entry {
	__uint8_t		namelen;	/* actual name length */
	xfs_dir2_sf_off_t	offset;		/* saved offset */
	__uint8_t		name[1];	/* name, variable size */
	xfs_dir2_inou_t		inumber;	/* inode number, var. offset */
} __arch_pack xfs_dir2_sf_entry_t; 

typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t;

Xfs在使用简短方式存储子文件信息时会采用尽可能的方法压缩这些子文件信息,以便在156字节空间里存储最大容量的项目:
1,只存储子文件的文件名(包括文件名长度以及文件名字符串)、inode号、offset偏移(为了迭代调用readdir函数而设定的字段,但其具体含义以及怎么被readdir函数使用,目前尚未搞清楚)。
2,代表当前目录的“.”没有存储,因为就是当前inode本身;代表父目录的“..”直接存放在头结构体xfs_dir2_sf_hdr_t的parent字段内。
3,为了尽量节省每个项目占用的字节数,代表inode号的项目字段inumber为union类型,既可以是8字节,又可以是4字节。当所有子文件的inode号都可以用4字节完整表示时,项目的字段inumber就用4字节字段足以,此时整个项目数记录在头结构体xfs_dir2_sf_hdr_t的count字段内,与此相对的i8count字段值为0;只要有一个子文件的inode号需要用8字节才能完整表示,此时每个项目的字段inumber就要都占用8字节(因为无法知道具体哪个项目的inumber字段需要8字节,所以此时想节省空间也没有办法,只能全部占用8字节),整个项目数记录在头结构体xfs_dir2_sf_hdr_t的i8count字段内,与此相对的count字段值为0;
简短方式比较简单,看一个实例:

[root@localhost loop]# ls
inode.256  inode.256.img  xfs  xfs.img
[root@localhost loop]# mount /dev/loop0 inode.256
[root@localhost loop]# cd !$
cd inode.256
[root@localhost inode.256]# ls
bigfile  lib64  linux-2.6.36  shortform  t1
[root@localhost inode.256]# cd shortform/
[root@localhost shortform]# ls -lai
total 32
   149 drwxr-xr-x 5 root root    82 Jan  9 09:54 .
   128 drwxr-xr-x 5 root root    76 Jan  9 09:52 ..
   157 -rw-r--r-- 1 root root     0 Jan  9 09:53 empty
338976 drwxr-xr-x 2 root root     6 Jan  9 09:53 gdb
   160 -rw-r--r-- 1 root root 27596 Jan  9 09:54 history
132448 drwxr-xr-x 2 root root     6 Jan  9 09:52 linux-2.6.30
393347 drwxr-xr-x 2 root root     6 Jan  9 09:54 study
   155 -rw-r--r-- 1 root root     5 Jan  9 09:53 t1
[root@localhost shortform]# cd ../../
[root@localhost loop]# umount inode.256
[root@localhost loop]# /home/lenky/xfs/xfsprogs/db/xfs_db /dev/loop0
xfs_db> inode 149
xfs_db> p
core.magic = 0x494e
core.mode = 040755
core.version = 1
core.format = 1 (local)
core.nlinkv1 = 5
core.uid = 0
core.gid = 0
core.flushiter = 11
core.atime.sec = Mon Jan  9 09:54:30 2012
core.atime.nsec = 536999855
core.mtime.sec = Mon Jan  9 09:54:27 2012
core.mtime.nsec = 823999851
core.ctime.sec = Mon Jan  9 09:54:27 2012
core.ctime.nsec = 823999851
core.size = 82
core.nblocks = 0
core.extsize = 0
core.nextents = 0
core.naextents = 0
core.forkoff = 0
core.aformat = 2 (extents)
core.dmevmask = 0
core.dmstate = 0
core.newrtbm = 0
core.prealloc = 0
core.realtime = 0
core.immutable = 0
core.append = 0
core.sync = 0
core.noatime = 0
core.nodump = 0
core.rtinherit = 0
core.projinherit = 0
core.nosymlinks = 0
core.extsz = 0
core.extszinherit = 0
core.nodefrag = 0
core.filestream = 0
core.gen = 5
next_unlinked = null
u.sfdir2.hdr.count = 6
u.sfdir2.hdr.i8count = 0
u.sfdir2.hdr.parent.i4 = 128
u.sfdir2.list[0].namelen = 12
u.sfdir2.list[0].offset = 0x30
u.sfdir2.list[0].name = "linux-2.6.30"
u.sfdir2.list[0].inumber.i4 = 132448
u.sfdir2.list[1].namelen = 3
u.sfdir2.list[1].offset = 0x48
u.sfdir2.list[1].name = "gdb"
u.sfdir2.list[1].inumber.i4 = 338976
u.sfdir2.list[2].namelen = 2
u.sfdir2.list[2].offset = 0x58
u.sfdir2.list[2].name = "t1"
u.sfdir2.list[2].inumber.i4 = 155
u.sfdir2.list[3].namelen = 5
u.sfdir2.list[3].offset = 0x68
u.sfdir2.list[3].name = "empty"
u.sfdir2.list[3].inumber.i4 = 157
u.sfdir2.list[4].namelen = 7
u.sfdir2.list[4].offset = 0x78
u.sfdir2.list[4].name = "history"
u.sfdir2.list[4].inumber.i4 = 160
u.sfdir2.list[5].namelen = 5
u.sfdir2.list[5].offset = 0x90
u.sfdir2.list[5].name = "study"
u.sfdir2.list[5].inumber.i4 = 393347
xfs_db> q
[root@localhost loop]#  hexdump -C -s 38144 -n 256 /dev/loop0
00009500  49 4e 41 ed 01 01 00 05  00 00 00 00 00 00 00 00  |INA.............|
00009510  00 00 00 05 00 00 00 00  00 00 00 00 00 00 00 0b  |................|
00009520  4f 0a ff a6 20 01 f7 af  4f 0a ff a3 31 1d 3d 6b  |O... ...O...1.=k|
00009530  4f 0a ff a3 31 1d 3d 6b  00 00 00 00 00 00 00 52  |O...1.=k.......R|
00009540  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00009550  00 00 00 02 00 00 00 00  00 00 00 00 00 00 00 05  |................|
00009560  ff ff ff ff 06 00 00 00  00 80 0c 00 30 6c 69 6e  |............0lin|
00009570  75 78 2d 32 2e 36 2e 33  30 00 02 05 60 03 00 48  |ux-2.6.30...`..H|
00009580  67 64 62 00 05 2c 20 02  00 58 74 31 00 00 00 9b  |gdb.., ..Xt1....|
00009590  05 00 68 65 6d 70 74 79  00 00 00 9d 07 00 78 68  |..hempty......xh|
000095a0  69 73 74 6f 72 79 00 00  00 a0 05 00 90 73 74 75  |istory.......stu|
000095b0  64 79 00 06 00 83 00 00  00 00 00 00 00 00 00 00  |dy..............|
000095c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00009600
[root@localhost loop]# 

当我们删除一个子文件时,如果这个子文件对应的项目不是最后一个,那么接在后面的项目必须要前移,这些都是很容易想到的事情,因为如果不前移,那么按照头结构体里的count或i8count字段而遍历后续“数组”找到的项目就不对了。

转载请保留地址:http://www.lenky.info/archives/2012/01/848http://lenky.info/?p=848


备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。

  1. lenky
    2012年10月6日16:37 | #1

    @肚腩照明月
    额,我一下子也都记不得了,你把整个文档连起来看一下,应该是149*256?

  2. 肚腩照明月
    2012年10月6日13:31 | #2

    hexdump -C -s 38144 -n 256 /dev/loop0
    你好,请问下38144这个是如何得到的。

  1. 本文目前尚无任何 trackbacks 和 pingbacks.