diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 111 |
1 files changed, 80 insertions, 31 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7cd8ab0ef04d..3470f67c6258 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2647,11 +2647,26 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
2647 | struct extent_buffer *leaf; | 2647 | struct extent_buffer *leaf; |
2648 | int ret; | 2648 | int ret; |
2649 | 2649 | ||
2650 | /* | ||
2651 | * If root is tree root, it means this inode is used to | ||
2652 | * store free space information. And these inodes are updated | ||
2653 | * when committing the transaction, so they needn't delaye to | ||
2654 | * be updated, or deadlock will occured. | ||
2655 | */ | ||
2656 | if (likely(root != root->fs_info->tree_root)) { | ||
2657 | ret = btrfs_delayed_update_inode(trans, root, inode); | ||
2658 | if (!ret) | ||
2659 | btrfs_set_inode_last_trans(trans, inode); | ||
2660 | return ret; | ||
2661 | } | ||
2662 | |||
2650 | path = btrfs_alloc_path(); | 2663 | path = btrfs_alloc_path(); |
2651 | BUG_ON(!path); | 2664 | if (!path) |
2665 | return -ENOMEM; | ||
2666 | |||
2652 | path->leave_spinning = 1; | 2667 | path->leave_spinning = 1; |
2653 | ret = btrfs_lookup_inode(trans, root, path, | 2668 | ret = btrfs_lookup_inode(trans, root, path, &BTRFS_I(inode)->location, |
2654 | &BTRFS_I(inode)->location, 1); | 2669 | 1); |
2655 | if (ret) { | 2670 | if (ret) { |
2656 | if (ret > 0) | 2671 | if (ret > 0) |
2657 | ret = -ENOENT; | 2672 | ret = -ENOENT; |
@@ -2661,7 +2676,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
2661 | btrfs_unlock_up_safe(path, 1); | 2676 | btrfs_unlock_up_safe(path, 1); |
2662 | leaf = path->nodes[0]; | 2677 | leaf = path->nodes[0]; |
2663 | inode_item = btrfs_item_ptr(leaf, path->slots[0], | 2678 | inode_item = btrfs_item_ptr(leaf, path->slots[0], |
2664 | struct btrfs_inode_item); | 2679 | struct btrfs_inode_item); |
2665 | 2680 | ||
2666 | fill_inode_item(trans, leaf, inode_item, inode); | 2681 | fill_inode_item(trans, leaf, inode_item, inode); |
2667 | btrfs_mark_buffer_dirty(leaf); | 2682 | btrfs_mark_buffer_dirty(leaf); |
@@ -2672,7 +2687,6 @@ failed: | |||
2672 | return ret; | 2687 | return ret; |
2673 | } | 2688 | } |
2674 | 2689 | ||
2675 | |||
2676 | /* | 2690 | /* |
2677 | * unlink helper that gets used here in inode.c and in the tree logging | 2691 | * unlink helper that gets used here in inode.c and in the tree logging |
2678 | * recovery code. It remove a link in a directory with a given name, and | 2692 | * recovery code. It remove a link in a directory with a given name, and |
@@ -2724,18 +2738,9 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, | |||
2724 | goto err; | 2738 | goto err; |
2725 | } | 2739 | } |
2726 | 2740 | ||
2727 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | 2741 | ret = btrfs_delete_delayed_dir_index(trans, root, dir, index); |
2728 | index, name, name_len, -1); | 2742 | if (ret) |
2729 | if (IS_ERR(di)) { | ||
2730 | ret = PTR_ERR(di); | ||
2731 | goto err; | ||
2732 | } | ||
2733 | if (!di) { | ||
2734 | ret = -ENOENT; | ||
2735 | goto err; | 2743 | goto err; |
2736 | } | ||
2737 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
2738 | btrfs_release_path(root, path); | ||
2739 | 2744 | ||
2740 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, | 2745 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, |
2741 | inode, dir->i_ino); | 2746 | inode, dir->i_ino); |
@@ -2924,6 +2929,14 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir, | |||
2924 | index = btrfs_inode_ref_index(path->nodes[0], ref); | 2929 | index = btrfs_inode_ref_index(path->nodes[0], ref); |
2925 | btrfs_release_path(root, path); | 2930 | btrfs_release_path(root, path); |
2926 | 2931 | ||
2932 | /* | ||
2933 | * This is a commit root search, if we can lookup inode item and other | ||
2934 | * relative items in the commit root, it means the transaction of | ||
2935 | * dir/file creation has been committed, and the dir index item that we | ||
2936 | * delay to insert has also been inserted into the commit root. So | ||
2937 | * we needn't worry about the delayed insertion of the dir index item | ||
2938 | * here. | ||
2939 | */ | ||
2927 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, index, | 2940 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, index, |
2928 | dentry->d_name.name, dentry->d_name.len, 0); | 2941 | dentry->d_name.name, dentry->d_name.len, 0); |
2929 | if (IS_ERR(di)) { | 2942 | if (IS_ERR(di)) { |
@@ -3029,24 +3042,16 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, | |||
3029 | btrfs_release_path(root, path); | 3042 | btrfs_release_path(root, path); |
3030 | index = key.offset; | 3043 | index = key.offset; |
3031 | } | 3044 | } |
3045 | btrfs_release_path(root, path); | ||
3032 | 3046 | ||
3033 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | 3047 | ret = btrfs_delete_delayed_dir_index(trans, root, dir, index); |
3034 | index, name, name_len, -1); | ||
3035 | BUG_ON(!di || IS_ERR(di)); | ||
3036 | |||
3037 | leaf = path->nodes[0]; | ||
3038 | btrfs_dir_item_key_to_cpu(leaf, di, &key); | ||
3039 | WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid); | ||
3040 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
3041 | BUG_ON(ret); | 3048 | BUG_ON(ret); |
3042 | btrfs_release_path(root, path); | ||
3043 | 3049 | ||
3044 | btrfs_i_size_write(dir, dir->i_size - name_len * 2); | 3050 | btrfs_i_size_write(dir, dir->i_size - name_len * 2); |
3045 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | 3051 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; |
3046 | ret = btrfs_update_inode(trans, root, dir); | 3052 | ret = btrfs_update_inode(trans, root, dir); |
3047 | BUG_ON(ret); | 3053 | BUG_ON(ret); |
3048 | 3054 | ||
3049 | btrfs_free_path(path); | ||
3050 | return 0; | 3055 | return 0; |
3051 | } | 3056 | } |
3052 | 3057 | ||
@@ -3306,6 +3311,15 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
3306 | if (root->ref_cows || root == root->fs_info->tree_root) | 3311 | if (root->ref_cows || root == root->fs_info->tree_root) |
3307 | btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); | 3312 | btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); |
3308 | 3313 | ||
3314 | /* | ||
3315 | * This function is also used to drop the items in the log tree before | ||
3316 | * we relog the inode, so if root != BTRFS_I(inode)->root, it means | ||
3317 | * it is used to drop the loged items. So we shouldn't kill the delayed | ||
3318 | * items. | ||
3319 | */ | ||
3320 | if (min_type == 0 && root == BTRFS_I(inode)->root) | ||
3321 | btrfs_kill_delayed_inode_items(inode); | ||
3322 | |||
3309 | path = btrfs_alloc_path(); | 3323 | path = btrfs_alloc_path(); |
3310 | BUG_ON(!path); | 3324 | BUG_ON(!path); |
3311 | path->reada = -1; | 3325 | path->reada = -1; |
@@ -4208,7 +4222,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
4208 | return d_splice_alias(inode, dentry); | 4222 | return d_splice_alias(inode, dentry); |
4209 | } | 4223 | } |
4210 | 4224 | ||
4211 | static unsigned char btrfs_filetype_table[] = { | 4225 | unsigned char btrfs_filetype_table[] = { |
4212 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK | 4226 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK |
4213 | }; | 4227 | }; |
4214 | 4228 | ||
@@ -4222,6 +4236,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4222 | struct btrfs_key key; | 4236 | struct btrfs_key key; |
4223 | struct btrfs_key found_key; | 4237 | struct btrfs_key found_key; |
4224 | struct btrfs_path *path; | 4238 | struct btrfs_path *path; |
4239 | struct list_head ins_list; | ||
4240 | struct list_head del_list; | ||
4225 | int ret; | 4241 | int ret; |
4226 | struct extent_buffer *leaf; | 4242 | struct extent_buffer *leaf; |
4227 | int slot; | 4243 | int slot; |
@@ -4234,6 +4250,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4234 | char tmp_name[32]; | 4250 | char tmp_name[32]; |
4235 | char *name_ptr; | 4251 | char *name_ptr; |
4236 | int name_len; | 4252 | int name_len; |
4253 | int is_curr = 0; /* filp->f_pos points to the current index? */ | ||
4237 | 4254 | ||
4238 | /* FIXME, use a real flag for deciding about the key type */ | 4255 | /* FIXME, use a real flag for deciding about the key type */ |
4239 | if (root->fs_info->tree_root == root) | 4256 | if (root->fs_info->tree_root == root) |
@@ -4258,8 +4275,16 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4258 | filp->f_pos = 2; | 4275 | filp->f_pos = 2; |
4259 | } | 4276 | } |
4260 | path = btrfs_alloc_path(); | 4277 | path = btrfs_alloc_path(); |
4278 | if (!path) | ||
4279 | return -ENOMEM; | ||
4261 | path->reada = 2; | 4280 | path->reada = 2; |
4262 | 4281 | ||
4282 | if (key_type == BTRFS_DIR_INDEX_KEY) { | ||
4283 | INIT_LIST_HEAD(&ins_list); | ||
4284 | INIT_LIST_HEAD(&del_list); | ||
4285 | btrfs_get_delayed_items(inode, &ins_list, &del_list); | ||
4286 | } | ||
4287 | |||
4263 | btrfs_set_key_type(&key, key_type); | 4288 | btrfs_set_key_type(&key, key_type); |
4264 | key.offset = filp->f_pos; | 4289 | key.offset = filp->f_pos; |
4265 | key.objectid = inode->i_ino; | 4290 | key.objectid = inode->i_ino; |
@@ -4289,8 +4314,13 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4289 | break; | 4314 | break; |
4290 | if (found_key.offset < filp->f_pos) | 4315 | if (found_key.offset < filp->f_pos) |
4291 | goto next; | 4316 | goto next; |
4317 | if (key_type == BTRFS_DIR_INDEX_KEY && | ||
4318 | btrfs_should_delete_dir_index(&del_list, | ||
4319 | found_key.offset)) | ||
4320 | goto next; | ||
4292 | 4321 | ||
4293 | filp->f_pos = found_key.offset; | 4322 | filp->f_pos = found_key.offset; |
4323 | is_curr = 1; | ||
4294 | 4324 | ||
4295 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 4325 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
4296 | di_cur = 0; | 4326 | di_cur = 0; |
@@ -4345,6 +4375,15 @@ next: | |||
4345 | path->slots[0]++; | 4375 | path->slots[0]++; |
4346 | } | 4376 | } |
4347 | 4377 | ||
4378 | if (key_type == BTRFS_DIR_INDEX_KEY) { | ||
4379 | if (is_curr) | ||
4380 | filp->f_pos++; | ||
4381 | ret = btrfs_readdir_delayed_dir_index(filp, dirent, filldir, | ||
4382 | &ins_list); | ||
4383 | if (ret) | ||
4384 | goto nopos; | ||
4385 | } | ||
4386 | |||
4348 | /* Reached end of directory/root. Bump pos past the last item. */ | 4387 | /* Reached end of directory/root. Bump pos past the last item. */ |
4349 | if (key_type == BTRFS_DIR_INDEX_KEY) | 4388 | if (key_type == BTRFS_DIR_INDEX_KEY) |
4350 | /* | 4389 | /* |
@@ -4357,6 +4396,8 @@ next: | |||
4357 | nopos: | 4396 | nopos: |
4358 | ret = 0; | 4397 | ret = 0; |
4359 | err: | 4398 | err: |
4399 | if (key_type == BTRFS_DIR_INDEX_KEY) | ||
4400 | btrfs_put_delayed_items(&ins_list, &del_list); | ||
4360 | btrfs_free_path(path); | 4401 | btrfs_free_path(path); |
4361 | return ret; | 4402 | return ret; |
4362 | } | 4403 | } |
@@ -4434,6 +4475,8 @@ void btrfs_dirty_inode(struct inode *inode) | |||
4434 | } | 4475 | } |
4435 | } | 4476 | } |
4436 | btrfs_end_transaction(trans, root); | 4477 | btrfs_end_transaction(trans, root); |
4478 | if (BTRFS_I(inode)->delayed_node) | ||
4479 | btrfs_balance_delayed_items(root); | ||
4437 | } | 4480 | } |
4438 | 4481 | ||
4439 | /* | 4482 | /* |
@@ -4502,9 +4545,12 @@ int btrfs_set_inode_index(struct inode *dir, u64 *index) | |||
4502 | int ret = 0; | 4545 | int ret = 0; |
4503 | 4546 | ||
4504 | if (BTRFS_I(dir)->index_cnt == (u64)-1) { | 4547 | if (BTRFS_I(dir)->index_cnt == (u64)-1) { |
4505 | ret = btrfs_set_inode_index_count(dir); | 4548 | ret = btrfs_inode_delayed_dir_index_count(dir); |
4506 | if (ret) | 4549 | if (ret) { |
4507 | return ret; | 4550 | ret = btrfs_set_inode_index_count(dir); |
4551 | if (ret) | ||
4552 | return ret; | ||
4553 | } | ||
4508 | } | 4554 | } |
4509 | 4555 | ||
4510 | *index = BTRFS_I(dir)->index_cnt; | 4556 | *index = BTRFS_I(dir)->index_cnt; |
@@ -4671,7 +4717,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
4671 | 4717 | ||
4672 | if (ret == 0) { | 4718 | if (ret == 0) { |
4673 | ret = btrfs_insert_dir_item(trans, root, name, name_len, | 4719 | ret = btrfs_insert_dir_item(trans, root, name, name_len, |
4674 | parent_inode->i_ino, &key, | 4720 | parent_inode, &key, |
4675 | btrfs_inode_type(inode), index); | 4721 | btrfs_inode_type(inode), index); |
4676 | BUG_ON(ret); | 4722 | BUG_ON(ret); |
4677 | 4723 | ||
@@ -6784,6 +6830,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
6784 | ei->dummy_inode = 0; | 6830 | ei->dummy_inode = 0; |
6785 | ei->force_compress = BTRFS_COMPRESS_NONE; | 6831 | ei->force_compress = BTRFS_COMPRESS_NONE; |
6786 | 6832 | ||
6833 | ei->delayed_node = NULL; | ||
6834 | |||
6787 | inode = &ei->vfs_inode; | 6835 | inode = &ei->vfs_inode; |
6788 | extent_map_tree_init(&ei->extent_tree, GFP_NOFS); | 6836 | extent_map_tree_init(&ei->extent_tree, GFP_NOFS); |
6789 | extent_io_tree_init(&ei->io_tree, &inode->i_data, GFP_NOFS); | 6837 | extent_io_tree_init(&ei->io_tree, &inode->i_data, GFP_NOFS); |
@@ -6874,6 +6922,7 @@ void btrfs_destroy_inode(struct inode *inode) | |||
6874 | inode_tree_del(inode); | 6922 | inode_tree_del(inode); |
6875 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); | 6923 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); |
6876 | free: | 6924 | free: |
6925 | btrfs_remove_delayed_node(inode); | ||
6877 | call_rcu(&inode->i_rcu, btrfs_i_callback); | 6926 | call_rcu(&inode->i_rcu, btrfs_i_callback); |
6878 | } | 6927 | } |
6879 | 6928 | ||