Hello, This patch changes the directory indexing stuff to use an artificial counter instead of the inode number. The index for a particular inode is stored directly in the inode so we can find the directory index item at unlink time and remove it. I added an index to the btrfs_inode for the index number, and index_cnt which is the counter for the directory. Tested it to make sure it didn''t blow up the box, if everybody is ok with the way I did this I will run some performance numbers, but I''m sure I did something stupid so I''ll wait till thats pointed out to do perf stuff :). Thank you, Signed-off-by: Josef Bacik <jbacik@redhat.com> diff -r 297d128bb63d btrfs_inode.h --- a/btrfs_inode.h Fri Jul 11 15:09:39 2008 -0400 +++ b/btrfs_inode.h Fri Jul 11 19:52:57 2008 -0400 @@ -47,6 +47,10 @@ struct btrfs_inode { u64 last_trans; u64 delalloc_bytes; u32 flags; + + /* directory indexing stuff */ + u64 index_cnt; /* the current index for this particular directory */ + u64 index; /* the index for this inode */ }; static inline struct btrfs_inode *BTRFS_I(struct inode *inode) { diff -r 297d128bb63d ctree.h --- a/ctree.h Fri Jul 11 15:09:39 2008 -0400 +++ b/ctree.h Fri Jul 11 19:52:57 2008 -0400 @@ -396,6 +396,7 @@ struct btrfs_inode_item { __le64 rdev; __le16 flags; __le16 compat_flags; + __le64 index; struct btrfs_timespec atime; struct btrfs_timespec ctime; struct btrfs_timespec mtime; @@ -901,6 +902,7 @@ BTRFS_SETGET_FUNCS(inode_flags, struct b BTRFS_SETGET_FUNCS(inode_flags, struct btrfs_inode_item, flags, 16); BTRFS_SETGET_FUNCS(inode_compat_flags, struct btrfs_inode_item, compat_flags, 16); +BTRFS_SETGET_FUNCS(inode_index, struct btrfs_inode_item, index, 64); static inline struct btrfs_timespec * btrfs_inode_atime(struct btrfs_inode_item *inode_item) @@ -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, diff -r 297d128bb63d dir-item.c --- a/dir-item.c Fri Jul 11 15:09:39 2008 -0400 +++ b/dir-item.c Fri Jul 11 19:52:57 2008 -0400 @@ -110,7 +110,7 @@ int btrfs_insert_xattr_item(struct btrfs 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) { 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)) { diff -r 297d128bb63d inode.c --- a/inode.c Fri Jul 11 15:09:39 2008 -0400 +++ b/inode.c Fri Jul 11 19:52:57 2008 -0400 @@ -831,6 +831,9 @@ void btrfs_read_locked_inode(struct inod inode->i_rdev = 0; rdev = btrfs_inode_rdev(leaf, inode_item); + BTRFS_I(inode)->index_cnt = (u64)-1; + BTRFS_I(inode)->index = btrfs_inode_index(leaf, inode_item); + alloc_group_block = btrfs_inode_block_group(leaf, inode_item); BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, alloc_group_block); @@ -903,6 +906,7 @@ static void fill_inode_item(struct exten btrfs_set_inode_generation(leaf, item, inode->i_generation); btrfs_set_inode_rdev(leaf, item, inode->i_rdev); btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); + btrfs_set_inode_index(leaf, item, BTRFS_I(inode)->index); btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group->key.objectid); } @@ -952,6 +956,7 @@ static int btrfs_unlink_trans(struct btr struct extent_buffer *leaf; struct btrfs_dir_item *di; struct btrfs_key key; + struct inode *inode = dentry->d_inode; path = btrfs_alloc_path(); if (!path) { @@ -977,7 +982,8 @@ static int btrfs_unlink_trans(struct btr btrfs_release_path(root, path); di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, - key.objectid, name, name_len, -1); + BTRFS_I(inode)->index, name, + name_len, -1); if (IS_ERR(di)) { ret = PTR_ERR(di); goto err; @@ -1603,6 +1609,7 @@ static int btrfs_init_locked_inode(struc inode->i_ino = args->ino; BTRFS_I(inode)->root = args->root; BTRFS_I(inode)->delalloc_bytes = 0; + BTRFS_I(inode)->index_cnt = (u64)-1; extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); extent_io_tree_init(&BTRFS_I(inode)->io_tree, inode->i_mapping, GFP_NOFS); @@ -1988,6 +1995,58 @@ static inline u8 btrfs_inode_type(struct return btrfs_type_by_mode[(inode->i_mode & S_IFMT) >> S_SHIFT]; } +static void btrfs_get_index_count(struct inode *inode) +{ + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_key key, found_key; + struct btrfs_path *path; + struct extent_buffer *leaf; + + int ret; + + key.objectid = inode->i_ino; + btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); + key.offset = (u64)-1; + + path = btrfs_alloc_path(); + if (!path) + return; + + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) + goto out; + + /* FIXME: we should be able to handle this */ + if (ret == 0) + goto out; + + /* + * MAGIC NUMBER EXPLANATION: + * since we search a directory based on f_pos we have to start at 2 + * since ''.'' and ''..'' have f_pos of 0 and 1 respectively, so everybody + * else has to start at 2 + */ + if (path->slots[0] == 0) { + BTRFS_I(inode)->index_cnt = 2; + goto out; + } + + path->slots[0]--; + + leaf = path->nodes[0]; + btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); + + if (found_key.objectid != inode->i_ino || + btrfs_key_type(&found_key) != BTRFS_DIR_INDEX_KEY) { + BTRFS_I(inode)->index_cnt = 2; + goto out; + } + + BTRFS_I(inode)->index_cnt = found_key.offset + 1; +out: + btrfs_free_path(path); +} + static int btrfs_add_link(struct btrfs_trans_handle *trans, struct dentry *dentry, struct inode *inode, int add_backref) @@ -1995,16 +2054,20 @@ static int btrfs_add_link(struct btrfs_t int ret; struct btrfs_key key; struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root; - struct inode *parent_inode; + struct inode *parent_inode = dentry->d_parent->d_inode; key.objectid = inode->i_ino; btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); key.offset = 0; + if (BTRFS_I(parent_inode)->index_cnt == (u64)-1) + btrfs_get_index_count(parent_inode); + ret = btrfs_insert_dir_item(trans, root, dentry->d_name.name, dentry->d_name.len, dentry->d_parent->d_inode->i_ino, - &key, btrfs_inode_type(inode)); + &key, btrfs_inode_type(inode), + BTRFS_I(parent_inode)->index_cnt); if (ret == 0) { if (add_backref) { ret = btrfs_insert_inode_ref(trans, root, @@ -2013,11 +2076,15 @@ static int btrfs_add_link(struct btrfs_t inode->i_ino, dentry->d_parent->d_inode->i_ino); } - parent_inode = dentry->d_parent->d_inode; + BTRFS_I(inode)->index = BTRFS_I(parent_inode)->index_cnt; + + BTRFS_I(parent_inode)->index_cnt++; parent_inode->i_size += dentry->d_name.len * 2; parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; ret = btrfs_update_inode(trans, root, dentry->d_parent->d_inode); + if (!ret) + ret = btrfs_update_inode(trans, root, inode); } return ret; } diff -r 297d128bb63d ioctl.c --- a/ioctl.c Fri Jul 11 15:09:39 2008 -0400 +++ b/ioctl.c Fri Jul 11 19:52:57 2008 -0400 @@ -131,7 +131,7 @@ 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; diff -r 297d128bb63d transaction.c --- a/transaction.c Fri Jul 11 15:09:39 2008 -0400 +++ b/transaction.c Fri Jul 11 19:52:57 2008 -0400 @@ -591,7 +591,7 @@ 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; -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html