Btrfs: introduce extent buffer cache for each i-node
RFC PATCH 1/1 Btrfs: introduce extent buffer cache for each i-node
This patch introduce extent buffer cache for every i-node. By this way, we needn't search the item from the root of b+ tree, and can save the search time. Besides that we can also reduce the lock contention of the root.
Implementation:
- add two pointers of extent buffer into btrfs_inode struct, one for nodes/leaves of fs/file tree, the other for nodes/leaves of the log tree.
- add a BTRFS_HEADER_FLAG_COWED flag, which is used to mark the cowed nodes/leaves
- When we want to search fs/file trees or the relative log trees, we must try to search the cached extent buffer at first, if we can not find the item, we will do the common search. At some condition, we will jump to the common search directly:
I. a new transaction starts.
II. the cached extent buffer was cowed.
III. the cached extent buffer's level is below the level we must lock. and so on.
And beside that, if we can not find the item, and the slot points to the first the item or the last item in the leaf, we must jump out the cached extent buffer search, and do the common search.
- After the common search (use btrfs_search_slot), we will cache the leaf or the level-1 node into the btrfs i-node object.
I have do small file write performance (inline file) by sysbench for the patch, and found it can make btrfs 5%~10% faster.
Surely, I will do function test(such as xfstests) and run more performance test next to validate this patch. And there is some redundant code in this patch. I will cleanup it in the next version.
--- fs/btrfs/btrfs_inode.h | 3 + fs/btrfs/ctree.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++-- fs/btrfs/ctree.h | 41 +++++- fs/btrfs/dir-item.c | 28 +++-- fs/btrfs/extent_io.c | 2 +- fs/btrfs/file-item.c | 14 +- fs/btrfs/file.c | 5 +- fs/btrfs/inode-item.c | 11 +- fs/btrfs/inode.c | 44 ++++--- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/super.c | 3 +- fs/btrfs/tree-log.c | 19 ++- fs/btrfs/xattr.c | 2 +- 14 files changed, 463 insertions(+), 71 deletions(-)
fs/btrfs/btrfs_inode.h +3 -0
@@ -164,6 +164,9 @@ struct btrfs_inode {struct btrfs_delayed_node *delayed_node; +struct extent_buffer *fs_eb; +struct extent_buffer *log_eb; +struct inode vfs_inode; };
fs/btrfs/ctree.c +348 -10
394 lines not on this page · raw message
fs/btrfs/ctree.h +34 -7
88 lines not on this page · raw message
fs/btrfs/dir-item.c +18 -10
@@ -32,6 +32,7 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root *root, + struct inode *inode, struct btrfs_path *path, struct btrfs_key *cpu_key, u32 data_size,
@@ -43,7 +44,8 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handlestruct btrfs_item *item;struct extent_buffer *leaf; - ret =btrfs_insert_empty_item (trans, root, path, cpu_key, data_size); + ret =btrfs_insert_empty_item_for_inode (trans, root, inode, path, + cpu_key, data_size);if (ret == -EEXIST ) {struct btrfs_dir_item *di; di =btrfs_match_dir_item_name (root, path, name, name_len);
@@ -68,7 +70,8 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle*/ int btrfs_insert_xattr_item (struct btrfs_trans_handle *trans,struct btrfs_root *root, -struct btrfs_path *path,u64 objectid, +struct inode *inode, +struct btrfs_path *path,const char *name,u16 name_len,const void *data,u16 data_len) {
@@ -82,13 +85,13 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,BUG_ON (name_len + data_len >BTRFS_MAX_XATTR_SIZE (root)); - key.objectid = objectid; + key.objectid =btrfs_ino (inode);btrfs_set_key_type (&key,BTRFS_XATTR_ITEM_KEY ); key.offset =btrfs_name_hash (name, name_len); data_size =sizeof (*dir_item) + name_len + data_len; - dir_item =insert_with_overflow (trans, root, path, &key, data_size, - name, name_len); + dir_item =insert_with_overflow (trans, root, inode, path, &key, + data_size, name, name_len);if (IS_ERR (dir_item))return PTR_ERR (dir_item);memset (&location,0 ,sizeof (location));
@@ -144,7 +147,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_rootbtrfs_cpu_key_to_disk (&disk_key, location); data_size =sizeof (*dir_item) + name_len; - dir_item =insert_with_overflow (trans, root, path, &key, data_size, + dir_item =insert_with_overflow (trans, root, dir, path, &key, data_size, name, name_len);if (IS_ERR (dir_item)) { ret =PTR_ERR (dir_item);
@@ -184,13 +187,14 @@ out_free: }/* -* lookup a directory item based on name. 'dir' is the objectid +* lookup a directory item based on name. 'dirid' is the objectid * we're searching in, and 'mod' tells us if you plan on deleting the * item (use mod < 0) or changing the options (use mod > 0) */ struct btrfs_dir_item *btrfs_lookup_dir_item (struct btrfs_trans_handle *trans,struct btrfs_root *root, -struct btrfs_path *path,u64 dir, +struct inode *dir, +struct btrfs_path *path,u64 dirid,const char *name,int name_len,int mod) {
@@ -199,12 +203,16 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,int ins_len = mod <0 ?-1 :0 ;int cow = mod !=0 ; - key.objectid = dir; + key.objectid = dirid;btrfs_set_key_type (&key,BTRFS_DIR_ITEM_KEY ); key.offset =btrfs_name_hash (name, name_len); - ret =btrfs_search_slot (trans, root, &key, path, ins_len, cow); +if (dir) + ret =btrfs_search_slot_for_inode (trans, root, dir, &key, path, + ins_len, cow); +else + ret =btrfs_search_slot (trans, root, &key, path, ins_len, cow);if (ret <0 )return ERR_PTR (ret);if (ret >0 )
fs/btrfs/extent_io.c +1 -1
@@ -3396,7 +3396,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,* because there might be preallocation past i_size */ ret =btrfs_lookup_file_extent (NULL ,BTRFS_I (inode)->root, - path,btrfs_ino (inode),-1 ,0 ); + path, inode,-1 ,0 );if (ret <0 ) {btrfs_free_path (path);return ret;
fs/btrfs/file-item.c +8 -6
@@ -36,7 +36,7 @@int btrfs_insert_file_extent (struct btrfs_trans_handle *trans,struct btrfs_root *root, -u64 objectid,u64 pos, +struct inode *inode,u64 pos,u64 disk_offset,u64 disk_num_bytes,u64 num_bytes,u64 offset,u64 ram_bytes,u8 compression,u8 encryption,u16 other_encoding)
@@ -46,6 +46,7 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,struct btrfs_key file_key;struct btrfs_path *path;struct extent_buffer *leaf; +u64 objectid =btrfs_ino (inode); path =btrfs_alloc_path ();if (!path)
@@ -55,8 +56,8 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,btrfs_set_key_type (&file_key,BTRFS_EXTENT_DATA_KEY ); path->leave_spinning =1 ; - ret =btrfs_insert_empty_item (trans, root, path, &file_key, -sizeof (*item)); + ret =btrfs_insert_empty_item_for_inode (trans, root, inode, path, + &file_key,sizeof (*item));if (ret <0 ) goto out;BUG_ON (ret);
@@ -133,7 +134,7 @@ fail:int btrfs_lookup_file_extent (struct btrfs_trans_handle *trans,struct btrfs_root *root, -struct btrfs_path *path,u64 objectid, +struct btrfs_path *path,struct inode *inode,u64 offset,int mod) {int ret;
@@ -141,10 +142,11 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,int ins_len = mod <0 ?-1 :0 ;int cow = mod !=0 ; - file_key.objectid = objectid; + file_key.objectid =btrfs_ino (inode); file_key.offset = offset;btrfs_set_key_type (&file_key,BTRFS_EXTENT_DATA_KEY ); - ret =btrfs_search_slot (trans, root, &file_key, path, ins_len, cow); + ret =btrfs_search_slot_for_inode (trans, root, inode, &file_key, path, + ins_len, cow);return ret; }
fs/btrfs/file.c +3 -2
@@ -577,7 +577,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,while (1 ) { recow =0 ; - ret =btrfs_lookup_file_extent (trans, root, path, ino, + ret =btrfs_lookup_file_extent (trans, root, path, inode, search_start,-1 );if (ret <0 )break ;
@@ -865,7 +865,8 @@ again: key.type =BTRFS_EXTENT_DATA_KEY ; key.offset = split; - ret =btrfs_search_slot (trans, root, &key, path,-1 ,1 ); + ret =btrfs_search_slot_for_inode (trans, root, inode, &key, path, +-1 ,1 );if (ret <0 ) goto out;if (ret >0 && path->slots[0 ] >0 )
fs/btrfs/inode-item.c +6 -5
@@ -77,9 +77,9 @@ btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans, }int btrfs_del_inode_ref (struct btrfs_trans_handle *trans, -struct btrfs_root *root, -const char *name,int name_len, -u64 inode_objectid,u64 ref_objectid,u64 *index) +struct btrfs_root *root, +const char *name,int name_len, +struct inode *inode,u64 ref_objectid,u64 *index) {struct btrfs_path *path;struct btrfs_key key;
@@ -92,7 +92,7 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,int ret;int del_len = name_len +sizeof (*ref); - key.objectid = inode_objectid; + key.objectid =btrfs_ino (inode); key.offset = ref_objectid;btrfs_set_key_type (&key,BTRFS_INODE_REF_KEY );
@@ -102,7 +102,8 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans, path->leave_spinning =1 ; - ret =btrfs_search_slot (trans, root, &key, path,-1 ,1 ); + ret =btrfs_search_slot_for_inode (trans, root, inode, &key, + path,-1 ,1 );if (ret >0 ) { ret = -ENOENT ; goto out;
fs/btrfs/inode.c +26 -18
146 lines not on this page · raw message
fs/btrfs/ioctl.c +1 -1
@@ -2657,7 +2657,7 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) } dir_id =btrfs_super_root_dir (root->fs_info->super_copy); - di =btrfs_lookup_dir_item (trans, root->fs_info->tree_root, path, + di =btrfs_lookup_dir_item (trans, root->fs_info->tree_root,NULL , path, dir_id,"default" ,7 ,1 );if (IS_ERR_OR_NULL (di)) {btrfs_free_path (path);
fs/btrfs/relocation.c +1 -1
@@ -1477,7 +1477,7 @@ static int get_new_location(struct inode *reloc_inode, u64 *new_bytenr,return -ENOMEM ; bytenr -=BTRFS_I (reloc_inode)->index_cnt; - ret =btrfs_lookup_file_extent (NULL , root, path,btrfs_ino (reloc_inode), + ret =btrfs_lookup_file_extent (NULL , root, path, reloc_inode, bytenr,0 );if (ret <0 ) goto out;
fs/btrfs/super.c +2 -1
@@ -573,7 +573,8 @@ static struct dentry *get_default_root(struct super_block *sb,* to mount. */ dir_id =btrfs_super_root_dir (root->fs_info->super_copy); - di =btrfs_lookup_dir_item (NULL , root, path, dir_id,"default" ,7 ,0 ); + di =btrfs_lookup_dir_item (NULL , root,NULL , path, dir_id,"default" , +7 ,0 );if (IS_ERR (di)) {btrfs_free_path (path);return ERR_CAST (di);
fs/btrfs/tree-log.c +11 -8
@@ -519,7 +519,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,* file. This must be done before the btrfs_drop_extents run * so we don't try to drop this extent. */ - ret =btrfs_lookup_file_extent (trans, root, path,btrfs_ino (inode), + ret =btrfs_lookup_file_extent (trans, root, path, inode, start,0 ); if (ret == 0 &&
@@ -719,7 +719,8 @@ static noinline int inode_in_dir(struct btrfs_root *root, goto out;btrfs_release_path (path); - di =btrfs_lookup_dir_item (NULL , root, path, dirid, name, name_len,0 ); + di =btrfs_lookup_dir_item (NULL , root,NULL , path, dirid, name, + name_len,0 );if (di && !IS_ERR (di)) {btrfs_dir_item_key_to_cpu (path->nodes[0 ], di, &location);if (location.objectid != objectid)
@@ -922,7 +923,7 @@ again:btrfs_release_path (path);/* look for a conflicing name */ - di =btrfs_lookup_dir_item (trans, root, path,btrfs_ino (dir), + di =btrfs_lookup_dir_item (trans, root, dir, path,btrfs_ino (dir), name, namelen,0 );if (di && !IS_ERR (di)) { ret =drop_one_dir_item (trans, root, path, dir, di);
@@ -1229,8 +1230,9 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,btrfs_release_path (path);if (key->type ==BTRFS_DIR_ITEM_KEY ) { - dst_di =btrfs_lookup_dir_item (trans, root, path, key->objectid, - name, name_len,1 ); + dst_di =btrfs_lookup_dir_item (trans, root,NULL , path, + key->objectid, name, + name_len,1 ); }else if (key->type ==BTRFS_DIR_INDEX_KEY ) { dst_di = btrfs_lookup_dir_index_item(trans, root, path, key->objectid,
@@ -1450,7 +1452,8 @@ again: name_len); log_di =NULL ;if (log && dir_key->type ==BTRFS_DIR_ITEM_KEY ) { - log_di =btrfs_lookup_dir_item (trans, log, log_path, + log_di =btrfs_lookup_dir_item (trans, log, dir, + log_path, dir_key->objectid, name, name_len,0 ); }else if (log && dir_key->type ==BTRFS_DIR_INDEX_KEY ) {
@@ -2262,7 +2265,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, goto out_unlock; } - di =btrfs_lookup_dir_item (trans, log, path, dir_ino, + di =btrfs_lookup_dir_item (trans, log, dir, path, dir_ino, name, name_len,-1 );if (IS_ERR (di)) { err =PTR_ERR (di);
@@ -2351,7 +2354,7 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans, log = root->log_root;mutex_lock (&BTRFS_I (inode)->log_mutex); - ret =btrfs_del_inode_ref (trans, log, name, name_len,btrfs_ino (inode), + ret =btrfs_del_inode_ref (trans, log, name, name_len, inode, dirid, &index);mutex_unlock (&BTRFS_I (inode)->log_mutex);if (ret == -ENOSPC ) {
fs/btrfs/xattr.c +1 -1
@@ -125,7 +125,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans, } again: - ret =btrfs_insert_xattr_item (trans, root, path,btrfs_ino (inode), + ret =btrfs_insert_xattr_item (trans, root, inode, path, name, name_len, value, size);/* * If we're setting an xattr to a new value but the new value is say
Signature · 1 line
1.7.6.5