linux 文件系统扩展属性 xattr
扩展属性(Extended Attributes,简称xattr)支持给文件添加用户自定义的额外属性(Key-value的键值对)
setfattr -n user.testattr -v abc test #设置test文件user.testattr属性为"abc" getfattr -n user.testattr test # 读取test文件的user.testattr属性 setfattr -x user.testattr test # 删除test文件的user.testattr属性 attr -lq test # 列举test文件的属性
Btrfs Design
Btrees Introduction
在btrfs(B-tree File System) 文件系统中,所有的 metadata 都由 BTree 管理。
文件系统由树木森林构造,superblock指向构成文件系统的所有B树:
- FS Tree:管理文件相关的元数据,如 inode,dir 等;
- Chunk tree:管理磁盘设备,每一个磁盘设备都在 Chunk Tree 中有一个 item ;
- Extent Tree:管理磁盘空间分配,btrfs 每分配一段磁盘空间,便将该磁盘空间的信息插入到 Extent tree。通过查询 Extent Tree得到空闲的磁盘空间信息;
- Checksum Tree:保存数据块的校验和。
Btree Data structure
以FS Tree为例:
结点分为内部结点和叶子结点
内部结点只用于查找,不存储数据,仅仅持有[key,block-pointer]对。
叶子结点持有[item,data]键值对。叶子结点分为header
、item
数组和data
数组两个部分。item
由头向尾生长,data
由尾向头生长。根据item
中的offset
和size
字段可以找到其对应的data
。item
中的key
标识一个唯一的item
。
文件系统由object构成(文件、目录等),每个object有自己的64bitobject_id
。每个object可以有若干不同类型的item
,item
的key
由三部分构成:object_id
、type
标识item
的类型,offset
标识item
在object中的偏移量。
文件object:
item |
功能 |
Key type |
Key offset |
Inode item |
inode |
BTRFS_INODE_ITEM_KEY |
0 |
extent data item |
存储文件数据 |
BTRFS_EXTENT_DATA_KEY |
该数据块在文件中的offset |
... |
目录object:
item |
功能 |
Key type |
Key offset |
Inode item |
inode |
BTRFS_INODE_ITEM_KEY |
0 |
dir item |
根据文件名查找文件的 |
BTRFS_DIR_ITEM_KEY |
64 bit filename hash |
index item |
文件遍历 |
BTRFS_DIR_INDEX_KEY |
Inode Sequence number |
Xattr item |
扩展属性 |
BTRFS_XATTR_ITEM_KEY |
64 bit filename hash |
... |
btrfs xattr支持
Btrfs将扩展属性以Xattr item形式维护,存储在目录的items中,类似于一个目录项,复用dir item数据结构。
Struct btrfs_disk_key |
transid |
data_len |
name_len |
type |
name |
data |
obj_id | BTRFS_XATTR_ITEM_KEY | hash("test") |
3 |
13 |
BTRFS_FT_XATTR |
"user.testattr" |
"abc" |
btrfs_setxattr
、btrfs_getxattr
、btrfs_removexattr
、btrfs_listxattr
分别对应设置扩展属性、读取扩展属性、删除扩展属性、列举扩展属性。
以btrfs_setxattr
为例:
btrfs_insert_xattr_item 插入xattr item:
leaf = path->nodes[0]; btrfs_cpu_key_to_disk(&disk_key, &location); // write key btrfs_set_dir_item_key(leaf, dir_item, &disk_key); btrfs_set_dir_type(leaf, dir_item, BTRFS_FT_XATTR); btrfs_set_dir_name_len(leaf, dir_item, name_len); // write name_len btrfs_set_dir_transid(leaf, dir_item, trans->transid); btrfs_set_dir_data_len(leaf, dir_item, data_len); // write data_len name_ptr = (unsigned long)(dir_item + 1); data_ptr = (unsigned long)((char *)name_ptr + name_len); write_extent_buffer(leaf, name, name_ptr, name_len); // write name of xattr write_extent_buffer(leaf, data, data_ptr, data_len); // write data of xattr btrfs_mark_buffer_dirty(path->nodes[0]);
btrfs_match_dir_item_name 匹配dir_item是否有要找的xattr
//walks through all the entries in a dir item and finds one for a specific name leaf = path->nodes[0]; dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); total_len = btrfs_item_size_nr(leaf, path->slots[0]); while (cur < total_len) { this_len = sizeof(*dir_item) + btrfs_dir_name_len(leaf, dir_item) + btrfs_dir_data_len(leaf, dir_item); name_ptr = (unsigned long)(dir_item + 1); if (btrfs_dir_name_len(leaf, dir_item) == name_len && memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) // find matched xattr return dir_item; cur += this_len; dir_item = (struct btrfs_dir_item *)((char *)dir_item + this_len); }
参考
btrfs.wiki.kernel.org/Btrfs_design
btrfs.wiki.kernel.org/Data_Structures.html
btrfs.wiki.kernel.org/On-disk_Format.html
btrfs.wiki.kernel.org/Trees.html
Filesystem Btree-BTRFS extent-CSDN