Merge branch 'delayed_inode' into inode_numbers

Conflicts:
	fs/btrfs/inode.c
	fs/btrfs/ioctl.c
	fs/btrfs/transaction.c

Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
Chris Mason
2011-05-22 07:07:01 -04:00
16 changed files with 2075 additions and 92 deletions

View File

@@ -2659,11 +2659,26 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
struct extent_buffer *leaf;
int ret;
/*
* If root is tree root, it means this inode is used to
* store free space information. And these inodes are updated
* when committing the transaction, so they needn't delaye to
* be updated, or deadlock will occured.
*/
if (!is_free_space_inode(root, inode)) {
ret = btrfs_delayed_update_inode(trans, root, inode);
if (!ret)
btrfs_set_inode_last_trans(trans, inode);
return ret;
}
path = btrfs_alloc_path();
BUG_ON(!path);
if (!path)
return -ENOMEM;
path->leave_spinning = 1;
ret = btrfs_lookup_inode(trans, root, path,
&BTRFS_I(inode)->location, 1);
ret = btrfs_lookup_inode(trans, root, path, &BTRFS_I(inode)->location,
1);
if (ret) {
if (ret > 0)
ret = -ENOENT;
@@ -2673,7 +2688,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
btrfs_unlock_up_safe(path, 1);
leaf = path->nodes[0];
inode_item = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_inode_item);
struct btrfs_inode_item);
fill_inode_item(trans, leaf, inode_item, inode);
btrfs_mark_buffer_dirty(leaf);
@@ -2684,7 +2699,6 @@ failed:
return ret;
}
/*
* unlink helper that gets used here in inode.c and in the tree logging
* recovery code. It remove a link in a directory with a given name, and
@@ -2737,18 +2751,9 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
goto err;
}
di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino,
index, name, name_len, -1);
if (IS_ERR(di)) {
ret = PTR_ERR(di);
ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
if (ret)
goto err;
}
if (!di) {
ret = -ENOENT;
goto err;
}
ret = btrfs_delete_one_dir_name(trans, root, path, di);
btrfs_release_path(root, path);
ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
inode, dir_ino);
@@ -2939,6 +2944,14 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir,
index = btrfs_inode_ref_index(path->nodes[0], ref);
btrfs_release_path(root, path);
/*
* This is a commit root search, if we can lookup inode item and other
* relative items in the commit root, it means the transaction of
* dir/file creation has been committed, and the dir index item that we
* delay to insert has also been inserted into the commit root. So
* we needn't worry about the delayed insertion of the dir index item
* here.
*/
di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino, index,
dentry->d_name.name, dentry->d_name.len, 0);
if (IS_ERR(di)) {
@@ -3045,24 +3058,16 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
btrfs_release_path(root, path);
index = key.offset;
}
di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino,
index, name, name_len, -1);
BUG_ON(!di || IS_ERR(di));
leaf = path->nodes[0];
btrfs_dir_item_key_to_cpu(leaf, di, &key);
WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid);
ret = btrfs_delete_one_dir_name(trans, root, path, di);
BUG_ON(ret);
btrfs_release_path(root, path);
ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
BUG_ON(ret);
btrfs_i_size_write(dir, dir->i_size - name_len * 2);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
ret = btrfs_update_inode(trans, root, dir);
BUG_ON(ret);
btrfs_free_path(path);
return 0;
}
@@ -3323,6 +3328,15 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
if (root->ref_cows || root == root->fs_info->tree_root)
btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
/*
* This function is also used to drop the items in the log tree before
* we relog the inode, so if root != BTRFS_I(inode)->root, it means
* it is used to drop the loged items. So we shouldn't kill the delayed
* items.
*/
if (min_type == 0 && root == BTRFS_I(inode)->root)
btrfs_kill_delayed_inode_items(inode);
path = btrfs_alloc_path();
BUG_ON(!path);
path->reada = -1;
@@ -4232,7 +4246,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
return d_splice_alias(inode, dentry);
}
static unsigned char btrfs_filetype_table[] = {
unsigned char btrfs_filetype_table[] = {
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
};
@@ -4246,6 +4260,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
struct btrfs_key key;
struct btrfs_key found_key;
struct btrfs_path *path;
struct list_head ins_list;
struct list_head del_list;
int ret;
struct extent_buffer *leaf;
int slot;
@@ -4258,6 +4274,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
char tmp_name[32];
char *name_ptr;
int name_len;
int is_curr = 0; /* filp->f_pos points to the current index? */
/* FIXME, use a real flag for deciding about the key type */
if (root->fs_info->tree_root == root)
@@ -4280,8 +4297,16 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
filp->f_pos = 2;
}
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
path->reada = 2;
if (key_type == BTRFS_DIR_INDEX_KEY) {
INIT_LIST_HEAD(&ins_list);
INIT_LIST_HEAD(&del_list);
btrfs_get_delayed_items(inode, &ins_list, &del_list);
}
btrfs_set_key_type(&key, key_type);
key.offset = filp->f_pos;
key.objectid = btrfs_ino(inode);
@@ -4311,8 +4336,13 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
break;
if (found_key.offset < filp->f_pos)
goto next;
if (key_type == BTRFS_DIR_INDEX_KEY &&
btrfs_should_delete_dir_index(&del_list,
found_key.offset))
goto next;
filp->f_pos = found_key.offset;
is_curr = 1;
di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
di_cur = 0;
@@ -4367,6 +4397,15 @@ next:
path->slots[0]++;
}
if (key_type == BTRFS_DIR_INDEX_KEY) {
if (is_curr)
filp->f_pos++;
ret = btrfs_readdir_delayed_dir_index(filp, dirent, filldir,
&ins_list);
if (ret)
goto nopos;
}
/* Reached end of directory/root. Bump pos past the last item. */
if (key_type == BTRFS_DIR_INDEX_KEY)
/*
@@ -4379,6 +4418,8 @@ next:
nopos:
ret = 0;
err:
if (key_type == BTRFS_DIR_INDEX_KEY)
btrfs_put_delayed_items(&ins_list, &del_list);
btrfs_free_path(path);
return ret;
}
@@ -4459,6 +4500,8 @@ void btrfs_dirty_inode(struct inode *inode)
}
}
btrfs_end_transaction(trans, root);
if (BTRFS_I(inode)->delayed_node)
btrfs_balance_delayed_items(root);
}
/*
@@ -4527,9 +4570,12 @@ int btrfs_set_inode_index(struct inode *dir, u64 *index)
int ret = 0;
if (BTRFS_I(dir)->index_cnt == (u64)-1) {
ret = btrfs_set_inode_index_count(dir);
if (ret)
return ret;
ret = btrfs_inode_delayed_dir_index_count(dir);
if (ret) {
ret = btrfs_set_inode_index_count(dir);
if (ret)
return ret;
}
}
*index = BTRFS_I(dir)->index_cnt;
@@ -4701,7 +4747,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
if (ret == 0) {
ret = btrfs_insert_dir_item(trans, root, name, name_len,
parent_ino, &key,
parent_inode, &key,
btrfs_inode_type(inode), index);
BUG_ON(ret);
@@ -6816,6 +6862,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
ei->dummy_inode = 0;
ei->force_compress = BTRFS_COMPRESS_NONE;
ei->delayed_node = NULL;
inode = &ei->vfs_inode;
extent_map_tree_init(&ei->extent_tree, GFP_NOFS);
extent_io_tree_init(&ei->io_tree, &inode->i_data, GFP_NOFS);
@@ -6906,6 +6954,7 @@ void btrfs_destroy_inode(struct inode *inode)
inode_tree_del(inode);
btrfs_drop_extent_cache(inode, 0, (u64)-1, 0);
free:
btrfs_remove_delayed_node(inode);
call_rcu(&inode->i_rcu, btrfs_i_callback);
}