Btrfsファイルシステムにおける拡張属性xattrの実装詳細

btrfs xattr

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の設計

B木の紹介

btrfs(B-tree File System)ファイルシステムでは、すべてのメタデータがB木によって管理されています。

ファイルシステムは木の森によって構成され、superblockがファイルシステムを構成するすべてのB木を指します:

  • FS Tree:ファイル関連のメタデータ(inode、ディレクトリなど)を管理
  • Chunk tree:ディスクデバイスを管理し、各デバイスはChunk Treeにitemとして存在
  • Extent Tree:ディスクスペースの割り当てを管理し、btrfsがディスクスペースを割り当てるたびに、その情報がExtent treeに挿入されます。Extent Treeを照会することで空きディスクスペースの情報を取得
  • Checksum Tree:データブロックのチェックサムを保存

B木のデータ構造

FS Treeを例に:

ノードは内部ノードとリーフノードに分かれます

内部ノードは検索専用でデータを保存せず、単に[key,block-pointer]ペアを保持します。

リーフノードは[item,data]キーバリューペアを保持します。リーフノードはheaderitem配列、data配列の2つの部分に分かれます。itemはヘッダから末尾へ成長し、dataは末尾からヘッダへ成長します。item内のoffsetsizeフィールドを使用して対応するdataを特定できます。item内のkeyは一意のitemを識別します。

ファイルシステムはオブジェクト(ファイル、ディレクトリなど)で構成され、各オブジェクトには独自の64ビットobject_idがあります。各オブジェクトには複数の異なるタイプのitemを持つことができ、itemkeyは3つの部分で構成されます:object_idtype(itemのタイプを識別)、offset(オブジェクト内のitemのオフセットを識別)。

ファイルオブジェクト:

item 機能 Key type Key offset
Inode item inode BTRFS_INODE_ITEM_KEY 0
extent data item ファイルデータを保存 BTRFS_EXTENT_DATA_KEY データブロックのファイル内オフセット

ディレクトリオブジェクト:

item 機能 Key type Key offset
Inode item inode BTRFS_INODE_ITEM_KEY 0
dir item ファイル名からファイルのobject\_idを検索 BTRFS_DIR_ITEM_KEY 64ビットファイル名ハッシュ
index item ファイルの走査 BTRFS_DIR_INDEX_KEY Inodeシーケンス番号
Xattr item 拡張属性 BTRFS_XATTR_ITEM_KEY 64ビットファイル名ハッシュ

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

btrfs_setxattrbtrfs_getxattrbtrfs_removexattrbtrfs_listxattrはそれぞれ拡張属性の設定、読み取り、削除、一覧表示に対応します。

btrfs_setxattrを例に:

btrfs_insert_xattr_item:

leaf = path->nodes[0];
btrfs_cpu_key_to_disk(&disk_key, &location);
// 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);     // name_lenを書き込む
btrfs_set_dir_transid(leaf, dir_item, trans->transid);
btrfs_set_dir_data_len(leaf, dir_item, data_len);    // 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); // xattrの名前を書き込む
write_extent_buffer(leaf, data, data_ptr, data_len); // xattrのデータを書き込む
btrfs_mark_buffer_dirty(path->nodes[0]);

btrfs_match_dir_item_name:

// ディレクトリitem内のすべてのエントリを走査し、特定の名前を持つものを見つける
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)    // 一致するxattrを見つける
                return dir_item;
        cur += this_len;
        dir_item = (struct btrfs_dir_item *)((char *)dir_item +
                                             this_len);
}

タグ: Btrfs linux ファイルシステム 拡張属性 xattr

7月7日 19:42 投稿