diff options
| author | Chris Mason <chris.mason@oracle.com> | 2007-04-05 10:38:44 -0400 | 
|---|---|---|
| committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-05 10:38:44 -0400 | 
| commit | 5f26f772e5c4e833ffcb0599f54deda466d2a3e5 (patch) | |
| tree | 2ef0183b42e2bd51feff52c2e6f97570514907b9 | |
| parent | bae45de03c4d54a9893dedf8a015beb2608b896a (diff) | |
Btrfs: more inode indexed directory work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
| -rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/dir-item.c | 18 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 90 | 
4 files changed, 70 insertions, 45 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 87c56222a62..61d7b4738af 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -921,6 +921,10 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root  int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root  			  *root, struct btrfs_path *path, u64 dir,  			  const char *name, int name_len, int mod); +int btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, +				struct btrfs_root *root, +				struct btrfs_path *path, u64 dir, +				u64 objectid, int mod);  int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path,  			      const char *name, int name_len);  /* inode-map.c */ diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 2a87e23ac9c..62d0c0916a7 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -80,6 +80,24 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root  	return ret;  } +int btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, +				struct btrfs_root *root, +				struct btrfs_path *path, u64 dir, +				u64 objectid, int mod) +{ +	int ret; +	struct btrfs_key key; +	int ins_len = mod < 0 ? -1 : 0; +	int cow = mod != 0; + +	key.objectid = dir; +	key.flags = 0; +	btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); +	key.offset = objectid; +	ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); +	return ret; +} +  int btrfs_match_dir_item_name(struct btrfs_root *root,  			      struct btrfs_path *path,  			      const char *name, int name_len) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 688aa861a92..7c21f63f1b9 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -224,6 +224,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root  	path = btrfs_alloc_path();  	BUG_ON(!path);  	btrfs_init_path(path); +  	ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);  	if (ret) {  		printk("failed to find %Lu\n", key.objectid); @@ -363,8 +364,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root  	if (root->fs_info->last_insert.objectid > search_start)  		search_start = root->fs_info->last_insert.objectid; -	path = btrfs_alloc_path(); -  check_failed:  	btrfs_init_path(path);  	ins->objectid = search_start; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 4b042460e87..d776b29a167 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -132,13 +132,20 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,  	ret = btrfs_del_item(trans, root, path);  	BUG_ON(ret); + +	btrfs_release_path(root, path); +	ret = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, +					  objectid, -1); +	BUG_ON(ret); +	ret = btrfs_del_item(trans, root, path); +	BUG_ON(ret);  	dentry->d_inode->i_ctime = dir->i_ctime;  err:  	btrfs_release_path(root, path);  	btrfs_free_path(path);  	if (ret == 0) {  		inode_dec_link_count(dentry->d_inode); -		dir->i_size -= name_len; +		dir->i_size -= name_len * 2;  		mark_inode_dirty(dir);  	}  	return ret; @@ -168,8 +175,10 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)  	struct btrfs_path *path;  	struct btrfs_key key;  	struct btrfs_trans_handle *trans; -	struct btrfs_disk_key *found_key; +	struct btrfs_key found_key; +	int found_type;  	struct btrfs_leaf *leaf; +	char *goodnames = "..";  	path = btrfs_alloc_path();  	BUG_ON(!path); @@ -178,46 +187,42 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)  	trans = btrfs_start_transaction(root, 1);  	key.objectid = inode->i_ino;  	key.offset = (u64)-1; -	key.flags = 0; -	btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); -	ret = btrfs_search_slot(trans, root, &key, path, -1, 1); -	if (ret < 0) { -		err = ret; -		goto out; -	} +	key.flags = (u32)-1; +	while(1) { +		ret = btrfs_search_slot(trans, root, &key, path, -1, 1); +		if (ret < 0) { +			err = ret; +			goto out; +		} +		BUG_ON(ret == 0); +		if (path->slots[0] == 0) { +			err = -ENOENT; +			goto out; +		} +		path->slots[0]--; +		leaf = btrfs_buffer_leaf(path->nodes[0]); +		btrfs_disk_key_to_cpu(&found_key, +				      &leaf->items[path->slots[0]].key); +		found_type = btrfs_key_type(&found_key); +		if (found_key.objectid != inode->i_ino) { +			err = -ENOENT; +			goto out; +		} +		if ((found_type != BTRFS_DIR_ITEM_KEY && +		     found_type != BTRFS_DIR_INDEX_KEY) || +	            (!btrfs_match_dir_item_name(root, path, goodnames, 2) && +	            !btrfs_match_dir_item_name(root, path, goodnames, 1))) { +			err = -ENOTEMPTY; +			goto out; +		} +		ret = btrfs_del_item(trans, root, path); +		BUG_ON(ret); -	BUG_ON(ret == 0); -	BUG_ON(path->slots[0] == 0); -	path->slots[0]--; -	leaf = btrfs_buffer_leaf(path->nodes[0]); -	found_key = &leaf->items[path->slots[0]].key; -	if (btrfs_disk_key_objectid(found_key) != inode->i_ino) { -		err = -ENOENT; -		goto out; -	} -	if (btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY || -	    btrfs_disk_key_offset(found_key) != 2) { -		err = -ENOTEMPTY; -		goto out; -	} -	ret = btrfs_del_item(trans, root, path); -	BUG_ON(ret); -	btrfs_release_path(root, path); -	key.offset = 1; -	ret = btrfs_search_slot(trans, root, &key, path, -1, 1); -	if (ret < 0) { -		err = ret; -		goto out; -	} -	if (ret > 0) { -		err = -ENOTEMPTY; -		goto out; -	} -	ret = btrfs_del_item(trans, root, path); -	if (ret) { -		err = ret; -		goto out; +		if (found_type == BTRFS_DIR_ITEM_KEY && found_key.offset == 1) +			break; +		btrfs_release_path(root, path);  	} +	ret = 0;  	btrfs_release_path(root, path);  	/* now the directory is empty */ @@ -676,7 +681,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,  				    dentry->d_parent->d_inode->i_ino,  				    inode->i_ino, 0);  	if (ret == 0) { -		dentry->d_parent->d_inode->i_size += dentry->d_name.len; +		dentry->d_parent->d_inode->i_size += dentry->d_name.len * 2;  		ret = btrfs_update_inode(trans, btrfs_sb(inode->i_sb),  					 dentry->d_parent->d_inode);  	} @@ -754,7 +759,7 @@ static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans,  				    dir->i_ino, 1);  	if (ret)  		goto error; -	inode->i_size = 3; +	inode->i_size = 6;  	ret = btrfs_update_inode(trans, root, inode);  error:  	return ret; @@ -915,7 +920,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,  	if (create)  		trans = btrfs_start_transaction(root, 1); -  	ret = btrfs_lookup_file_extent(trans, root, path,  				       inode->i_ino,  				       iblock << inode->i_blkbits, 0);  | 
