首页 > *nix技术, 文件系统 > Xfs文件系统磁盘布局之十二:普通文件数据结构(extents)

Xfs文件系统磁盘布局之十二:普通文件数据结构(extents)

2012年1月6日 发表评论 阅读评论 6,610 次浏览

对于普通文件来说,文件内容可以以“extents”或者“btree”两种方式存放,前一篇已经讲过这两种方式所存放数据的大致格式,下面详细描述;
先看“extents”,“extents”是将存放文件实际数据的block块号以数组的形式存放在inode核心数据之后,当然,不仅仅只是块号那么简单,假设称其中的每一个数组元素为一个“extent”,那么,一个“extent”具体就是如下四个信息:
1,这一部分文件内容对应到文件整体内容中的逻辑起始地址(也以block块为单位)。
2,存放这一部分文件内容的起始block块号。
3,有多少块block用来存放这一部分文件内容。
4,该“extent”的状态标记。
一个文件可能由多个“extent”组成,于是此时就由多个“extent”形成“extents”数组,有多少“extent”记录在inode核心数据对应的结构体xfs_dinode的di_nextents字段内。一个“extent”对应的数据结构是xfs_bmbt_rec,它看上去很简单:

typedef struct xfs_bmbt_rec {
	__be64			l0, l1;
} xfs_bmbt_rec_t;

这是在磁盘上对应的数据结构,占128bit,大端字节序,而在实际Xfs操作代码里,为了更方便的获取上面提到的四个信息,所以其对应的数据结构是xfs_bmbt_irec:

/*
 * Incore version of above.
 */
typedef struct xfs_bmbt_irec
{
	xfs_fileoff_t	br_startoff;	/* starting file offset */
	xfs_fsblock_t	br_startblock;	/* starting block number */
	xfs_filblks_t	br_blockcount;	/* number of blocks */
	xfs_exntst_t	br_state;	/* extent state */
} xfs_bmbt_irec_t;

很明显,xfs_bmbt_irec是xfs_bmbt_rec的扩展形式,那么这个结构体如何对应呢?在文件include/xfs_bmp_btree.h头文件里已有详细说明:

/*
 * Bmap btree record and extent descriptor.
 *  l0:63 is an extent flag (value 1 indicates non-normal).
 *  l0:9-62 are startoff.
 *  l0:0-8 and l1:21-63 are startblock.
 *  l1:0-20 are blockcount.
 */
#define BMBT_EXNTFLAG_BITLEN	1
#define BMBT_STARTOFF_BITLEN	54
#define BMBT_STARTBLOCK_BITLEN	52
#define BMBT_BLOCKCOUNT_BITLEN	21

看一个实例,根据实例数据来分析:

[root@localhost loop]# /home/lenky/xfs/xfsprogs/db/xfs_db /dev/loop0
xfs_db> inode 132
xfs_db> p
core.magic = 0x494e
core.mode = 0100644
core.version = 1
core.format = 2 (extents)
...
core.size = 21465
core.nblocks = 6
core.extsize = 0
core.nextents = 2
...
next_unlinked = null
u.bmx[0-1] = [startoff,startblock,blockcount,extentflag] 0:[0,12,1,0] 1:[1,25,5,0]
xfs_db> q
[root@localhost loop]# hexdump -C -s 33792 -n 256 /dev/loop0
00008400  49 4e 81 a4 01 02 00 01  00 00 00 00 00 00 00 00  |IN..............|
00008410  00 00 00 01 00 00 00 00  00 00 00 00 00 00 00 07  |................|
00008420  4f 06 f3 9e 09 b7 2f 49  4f 06 f4 5e 08 0b ef 70  |O...../IO..^...p|
00008430  4f 06 f4 5e 08 0b ef 70  00 00 00 00 00 00 53 d9  |O..^...p......S.|
00008440  00 00 00 00 00 00 00 06  00 00 00 00 00 00 00 02  |................|
00008450  00 00 00 02 00 00 00 00  00 00 00 00 00 00 00 02  |................|
00008460  ff ff ff ff 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00008470  01 80 00 01 00 00 00 00  00 00 02 00 00 00 00 00  |................|
00008480  03 20 00 05 00 00 00 00  00 00 00 00 00 00 00 00  |. ..............|
00008490  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00008500
[root@localhost loop]# 

磁盘extents数据为:
00008460 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 |…………….|
00008470 01 80 00 01 00 00 00 00 00 00 02 00 00 00 00 00 |…………….|
00008480 03 20 00 05
即是:
(la.0):00 00 00 00 00 00 00 00 (la.1): 00 00 00 00 01 80 00 01
(lb.0):00 00 00 00 00 00 02 00 (lb.1): 00 00 00 00 03 20 00 05
解压缩后的数据:
u.bmx[0-1] = [startoff,startblock,blockcount,extentflag] 0:[0,12,1,0] 1:[1,25,5,0]
1,la.0:63和lb.0:63都为0。
2,la.0:9-62为0,而lb.0:9-62为1(看最末的2,二进制即为0010,注意这个蓝色的0要排除,因为它是lb.0:8,所以lb.0:9-62的结果为1)。
3,la.0:0-8和la.1:21-63组合为:0 00 00 00 00 00 01 8,最后的18的二进制表示为0001 1000,同样注意这个蓝色的0要排除,因为它是la.0:20,所以最后有效位值为1100,即12。与此类似,lb.0:0-8和lb.1:21-63组合为:2 00 00 00 00 00 03 2,第一位16进制数2属于lb.0:0-8的第8bit为0,最后的32的二进制表示为0011 0010,同样排除蓝色的0,因为它是lb.0:20,所以最后有效位值为11001,即25。
4,la.1:0-20为1,而lb.1:0-20为5。
也许全部展开可以一目了然(以lb,[1,25,5,0]为例,其中颜色显示:startoffstartblockblockcountextentflag):
127-96: 00000000 00000000 00000000 00000000
  95-64: 00000000 00000000 00000010 00000000
  63-32: 00000000 00000000 00000000 00000000
    31-0: 00000011 00100000 00000000 00000101
另外,0:[0,12,1,0] 1:[1,25,5,0]的具体含义表示这个文件由两个extent存放实际数据,第一个extent的起始block块号为12,长度为1;而第二个extent的起始block块号为25,长度为5,即占用25、26、27、28、29这五块block,它对应的文件的逻辑起始地址为4096(因为startoff=1),对比看看:

xfs_db> fsblock 25
xfs_db> type text
xfs_db> p
000:  70 74 6f 72 20 2a 2f 0a 09 69 6e 74 20 20 20 20  ptor.....int....
010:  20 20 20 20 20 20 20 20 20 72 74 66 64 3b 20 20  .........rtfd...
020:  20 20 20 20 20 20 20 20 20 2f 2a 20 72 65 61 6c  ............real
030:  74 69 6d 65 20 73 75 62 76 6f 6c 75 6d 65 20 66  time.subvolume.f
040:  69 6c 65 20 64 65 73 63 72 69 70 74 6f 72 20 2a  ile.descriptor..
050:  2f 0a 7d 20 6c 69 62 78 66 73 5f 69 6e 69 74 5f  ....libxfs.init.
060:  74 3b 0a 0a 23 64 65 66 69 6e 65 20 4c 49 42 58  t....define.LIBX
070:  46 53 5f 45 58 49 54 5f 4f 4e 5f 46 41 49 4c 55  FS.EXIT.ON.FAILU
080:  52 45 09 30 78 30 30 30 31 09 2f 2a 20 65 78 69  RE.0x0001....exi
090:  74 20 74 68 65 20 70 72 6f 67 72 61 6d 20 69 66  t.the.program.if
0a0:  20 61 20 63 61 6c 6c 20 66 61 69 6c 73 20 2a 2f  .a.call.fails...
0b0:  0a 23 64 65 66 69 6e 65 20 4c 49 42 58 46 53 5f  ..define.LIBXFS.
0c0:  49 53 52 45 41 44 4f 4e 4c 59 09 30 78 30 30 30  ISREADONLY.0x000
0d0:  32 09 2f 2a 20 64 69 73 61 6c 6c 6f 77 20 61 6c  2....disallow.al
0e0:  6c 20 6d 6f 75 6e 74 65 64 20 66 69 6c 65 73 79  l.mounted.filesy
0f0:  73 74 65 6d 73 20 2a 2f 0a 23 64 65 66 69 6e 65  stems.....define
100:  20 4c 49 42 58 46 53 5f 49 53 49 4e 41 43 54 49  .LIBXFS.ISINACTI
110:  56 45 09 30 78 30 30 30 34 09 2f 2a 20 61 6c 6c  VE.0x0004....all
120:  6f 77 20 6d 6f 75 6e 74 65 64 20 6f 6e 6c 79 20  ow.mounted.only.
130:  69 66 20 6d 6f 75 6e 74 65 64 20 72 6f 20 2a 2f  if.mounted.ro...
140:  0a 23 64 65 66 69 6e 65 20 4c 49 42 58 46 53 5f  ..define.LIBXFS.
150:  44 41 4e 47 45 52 4f 55 53 4c 59 09 30 78 30 30  DANGEROUSLY.0x00
160:  30 38 09 2f 2a 20 72 65 70 61 69 72 69 6e 67 20  08....repairing.
170:  61 20 64 65 76 69 63 65 20 6d 6f 75 6e 74 65 64  a.device.mounted
180:  20 72 6f 20 20 20 20 2a 2f 0a 23 64 65 66 69 6e  .ro........defin
190:  65 20 4c 49 42 58 46 53 5f 45 58 43 4c 55 53 49  e.LIBXFS.EXCLUSI
1a0:  56 45 4c 59 09 30 78 30 30 31 30 09 2f 2a 20 64  VELY.0x0010....d
1b0:  69 73 61 6c 6c 6f 77 20 6f 74 68 65 72 20 61 63  isallow.other.ac
1c0:  63 65 73 73 65 73 20 28 4f 5f 45 58 43 4c 29 20  cesses..O.EXCL..
...
[root@localhost loop]# mount /dev/loop0 inode.256
[root@localhost loop]# cd inode.256
[root@localhost inode.256]# ls -lai
total 76
     128 drwxr-xr-x 2 root root    56 Jan  6 08:14 .
32800854 drwxr-xr-x 4 root root  4096 Jan  6 07:11 ..
     133 -rw-r--r-- 1 root root 21465 Jan  6 08:17 lenky.xfs
     132 -rw-r--r-- 1 root root 21465 Jan  6 08:17 lenky.xfs.bk
     131 -rw-r--r-- 1 root root 21416 Jan  6 07:15 libxfs.h
[root@localhost inode.256]# hexdump -C -s 4096 -n 256 lenky.xfs.bk 
00001000  70 74 6f 72 20 2a 2f 0a  09 69 6e 74 20 20 20 20  |ptor */..int    |
00001010  20 20 20 20 20 20 20 20  20 72 74 66 64 3b 20 20  |         rtfd;  |
00001020  20 20 20 20 20 20 20 20  20 2f 2a 20 72 65 61 6c  |         /* real|
00001030  74 69 6d 65 20 73 75 62  76 6f 6c 75 6d 65 20 66  |time subvolume f|
00001040  69 6c 65 20 64 65 73 63  72 69 70 74 6f 72 20 2a  |ile descriptor *|
00001050  2f 0a 7d 20 6c 69 62 78  66 73 5f 69 6e 69 74 5f  |/.} libxfs_init_|
00001060  74 3b 0a 0a 23 64 65 66  69 6e 65 20 4c 49 42 58  |t;..#define LIBX|
00001070  46 53 5f 45 58 49 54 5f  4f 4e 5f 46 41 49 4c 55  |FS_EXIT_ON_FAILU|
00001080  52 45 09 30 78 30 30 30  31 09 2f 2a 20 65 78 69  |RE.0x0001./* exi|
00001090  74 20 74 68 65 20 70 72  6f 67 72 61 6d 20 69 66  |t the program if|
000010a0  20 61 20 63 61 6c 6c 20  66 61 69 6c 73 20 2a 2f  | a call fails */|
000010b0  0a 23 64 65 66 69 6e 65  20 4c 49 42 58 46 53 5f  |.#define LIBXFS_|
000010c0  49 53 52 45 41 44 4f 4e  4c 59 09 30 78 30 30 30  |ISREADONLY.0x000|
000010d0  32 09 2f 2a 20 64 69 73  61 6c 6c 6f 77 20 61 6c  |2./* disallow al|
000010e0  6c 20 6d 6f 75 6e 74 65  64 20 66 69 6c 65 73 79  |l mounted filesy|
000010f0  73 74 65 6d 73 20 2a 2f  0a 23 64 65 66 69 6e 65  |stems */.#define|
00001100
[root@localhost inode.256]# 

一个inode最大大小为256个字节,除去inode核心数据100个字节,假设该文件没有扩展属性,那么最多可以有(256-100)*8/128=9.75个“extent”,即数组“extents”最多只能有9个元素,当文件增大到一定程度,这些“extent”无法以数组的形式存放时,就会以B+tree的形式组织起来,这将是下一篇文章的内容。最后,看一个图:

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


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

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

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