new dir format v2
PATCH 1/1 new dir format v2
Hello,
This is an updated version of the patch that I sent earlier. Instead of storing the index in the inode we store it in the inode reference, this way hardlinks and such will work properly because their own indexes will be stored correctly. I have a btrfs-progs patch as well, if this turns out to be ok I will send that along as well. Here are some performance numbers with 100,000 files. I would do a million but the ordered mode stuff makes a million files suck alot on my box, so 100k is the most reasonable amount I could do. Thank you,
Signed-off-by Josef Bacik <[email protected]>
btrfs_inode.h +15 -0
@@ -47,6 +47,21 @@ struct btrfs_inode {u64 last_trans;u64 delalloc_bytes;u32 flags; + +/* +* if this is a directory then index_cnt is the counter for the index +* number for new files that are created +*/ +u64 index_cnt; + +/* +* index holds the directory index for this inode on creation, so +* add_link can do what its supposed to. This isn't populated when the +* inode is read because there isn't really a reason to know this unless +* we are creating the directory index or deleting it, and deletion +* reads the index off of the inode reference at unlink time. +*/ +u64 index; };static inline struct btrfs_inode *BTRFS_I (struct inode *inode) {
ctree.h +5 -3
@@ -371,6 +371,7 @@ struct btrfs_dev_extent { } __attribute__ ((__packed__));struct btrfs_inode_ref { +__le64 index;__le16 name_len;/* name goes here */ } __attribute__ ((__packed__ ));
@@ -887,6 +888,7 @@ BTRFS_SETGET_STACK_FUNCS(block_group_fla/* struct btrfs_inode_ref */ BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16); +BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64);/* struct btrfs_inode_item */ BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64);
@@ -1502,7 +1504,7 @@ int btrfs_find_dead_roots(struct btrfs_r/* dir-item.c */ int btrfs_insert_dir_item (struct btrfs_trans_handle *trans,struct btrfs_root *root,const char *name,int name_len,u64 dir, -struct btrfs_key *location,u8 type); +struct btrfs_key *location,u8 type,u64 index); struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 dir,
@@ -1547,11 +1549,11 @@ int btrfs_insert_inode_ref(struct btrfs_int btrfs_insert_inode_ref (struct btrfs_trans_handle *trans,struct btrfs_root *root,const char *name,int name_len, -u64 inode_objectid,u64 ref_objectid); +u64 inode_objectid,u64 ref_objectid,u64 index);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 inode_objectid,u64 ref_objectid,u64 *index);int btrfs_insert_empty_inode (struct btrfs_trans_handle *trans,struct btrfs_root *root,struct btrfs_path *path,u64 objectid);
dir-item.c +2 -2
@@ -110,7 +110,7 @@ int btrfs_insert_xattr_item(struct btrfsint btrfs_insert_dir_item (struct btrfs_trans_handle *trans,struct btrfs_root *root,const char *name,int name_len,u64 dir, -struct btrfs_key *location,u8 type) +struct btrfs_key *location,u8 type,u64 index) {int ret =0 ;int ret2 =0 ;
@@ -156,7 +156,7 @@ second_insert:btrfs_release_path (root, path);btrfs_set_key_type (&key,BTRFS_DIR_INDEX_KEY ); - key.offset = location->objectid; + key.offset = index; dir_item =insert_with_overflow (trans, root, path, &key, data_size, name, name_len);if (IS_ERR (dir_item)) {
inode-item.c +8 -2
@@ -52,7 +52,7 @@ int btrfs_del_inode_ref(struct btrfs_traint 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 inode_objectid,u64 ref_objectid,u64 *index) {struct btrfs_path *path;struct btrfs_key key;
@@ -86,6 +86,10 @@ int btrfs_del_inode_ref(struct btrfs_tra } leaf = path->nodes[0 ]; item_size =btrfs_item_size_nr (leaf, path->slots[0 ]); + +if (index) + *index =btrfs_inode_ref_index (leaf, ref); +if (del_len == item_size) { ret =btrfs_del_item (trans, root, path); goto out;
@@ -106,7 +110,7 @@ int btrfs_insert_inode_ref(struct btrfs_int btrfs_insert_inode_ref (struct btrfs_trans_handle *trans,struct btrfs_root *root,const char *name,int name_len, -u64 inode_objectid,u64 ref_objectid) +u64 inode_objectid,u64 ref_objectid,u64 index) {struct btrfs_path *path;struct btrfs_key key;
@@ -138,6 +142,7 @@ int btrfs_insert_inode_ref(struct btrfs_ struct btrfs_inode_ref); ref = (struct btrfs_inode_ref *)((unsigned long )ref + old_size);btrfs_set_inode_ref_name_len (path->nodes[0 ], ref, name_len); +btrfs_set_inode_ref_index (path->nodes[0 ], ref, index); ptr = (unsigned long )(ref +1 ); ret =0 ; }else if (ret <0 ) {
@@ -146,6 +151,7 @@ int btrfs_insert_inode_ref(struct btrfs_ ref =btrfs_item_ptr (path->nodes[0 ], path->slots[0 ], struct btrfs_inode_ref);btrfs_set_inode_ref_name_len (path->nodes[0 ], ref, name_len); +btrfs_set_inode_ref_index (path->nodes[0 ], ref, index); ptr = (unsigned long )(ref +1 ); }write_extent_buffer (path->nodes[0 ], name, ptr, name_len);
inode.c +94 -22
237 lines not on this page · raw message
ioctl.c +2 -2
@@ -131,13 +131,13 @@ static noinline int create_subvol(struct dir = root->fs_info->sb->s_root->d_inode; ret =btrfs_insert_dir_item (trans, root->fs_info->tree_root, name, namelen, dir->i_ino, &key, -BTRFS_FT_DIR ); +BTRFS_FT_DIR ,0 );if (ret) goto fail; ret =btrfs_insert_inode_ref (trans, root->fs_info->tree_root, name, namelen, objectid, - root->fs_info->sb->s_root->d_inode->i_ino); + root->fs_info->sb->s_root->d_inode->i_ino,0 );if (ret) goto fail;
transaction.c +2 -2
@@ -591,14 +591,14 @@ static noinline int create_pending_snaps ret =btrfs_insert_dir_item (trans, root->fs_info->tree_root, pending->name, namelen, root->fs_info->sb->s_root->d_inode->i_ino, - &key,BTRFS_FT_DIR ); + &key,BTRFS_FT_DIR ,0 );if (ret) goto fail; ret =btrfs_insert_inode_ref (trans, root->fs_info->tree_root, pending->name,strlen (pending->name), objectid, - root->fs_info->sb->s_root->d_inode->i_ino); + root->fs_info->sb->s_root->d_inode->i_ino,0 );/* Invalidate existing dcache entry for new snapshot. */ btrfs_invalidate_dcache_root (root, pending->name, namelen);