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