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 01438e9ba2e2..6cef48572e9e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2659,11 +2659,26 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
2659 | struct extent_buffer *leaf; | 2659 | struct extent_buffer *leaf; |
2660 | int ret; | 2660 | int ret; |
2661 | 2661 | ||
2662 | /* | ||
2663 | * If root is tree root, it means this inode is used to | ||
2664 | * store free space information. And these inodes are updated | ||
2665 | * when committing the transaction, so they needn't delaye to | ||
2666 | * be updated, or deadlock will occured. | ||
2667 | */ | ||
2668 | if (!is_free_space_inode(root, inode)) { | ||
2669 | ret = btrfs_delayed_update_inode(trans, root, inode); | ||
2670 | if (!ret) | ||
2671 | btrfs_set_inode_last_trans(trans, inode); | ||
2672 | return ret; | ||
2673 | } | ||
2674 | |||
2662 | path = btrfs_alloc_path(); | 2675 | path = btrfs_alloc_path(); |
2663 | BUG_ON(!path); | 2676 | if (!path) |
2677 | return -ENOMEM; | ||
2678 | |||
2664 | path->leave_spinning = 1; | 2679 | path->leave_spinning = 1; |
2665 | ret = btrfs_lookup_inode(trans, root, path, | 2680 | ret = btrfs_lookup_inode(trans, root, path, &BTRFS_I(inode)->location, |
2666 | &BTRFS_I(inode)->location, 1); | 2681 | 1); |
2667 | if (ret) { | 2682 | if (ret) { |
2668 | if (ret > 0) | 2683 | if (ret > 0) |
2669 | ret = -ENOENT; | 2684 | ret = -ENOENT; |
@@ -2673,7 +2688,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
2673 | btrfs_unlock_up_safe(path, 1); | 2688 | btrfs_unlock_up_safe(path, 1); |
2674 | leaf = path->nodes[0]; | 2689 | leaf = path->nodes[0]; |
2675 | inode_item = btrfs_item_ptr(leaf, path->slots[0], | 2690 | inode_item = btrfs_item_ptr(leaf, path->slots[0], |
2676 | struct btrfs_inode_item); | 2691 | struct btrfs_inode_item); |
2677 | 2692 | ||
2678 | fill_inode_item(trans, leaf, inode_item, inode); | 2693 | fill_inode_item(trans, leaf, inode_item, inode); |
2679 | btrfs_mark_buffer_dirty(leaf); | 2694 | btrfs_mark_buffer_dirty(leaf); |
@@ -2684,7 +2699,6 @@ failed: | |||
2684 | return ret; | 2699 | return ret; |
2685 | } | 2700 | } |
2686 | 2701 | ||
2687 | |||
2688 | /* | 2702 | /* |
2689 | * unlink helper that gets used here in inode.c and in the tree logging | 2703 | * unlink helper that gets used here in inode.c and in the tree logging |
2690 | * recovery code. It remove a link in a directory with a given name, and | 2704 | * 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, | |||
2737 | goto err; | 2751 | goto err; |
2738 | } | 2752 | } |
2739 | 2753 | ||
2740 | di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino, | 2754 | ret = btrfs_delete_delayed_dir_index(trans, root, dir, index); |
2741 | index, name, name_len, -1); | 2755 | if (ret) |
2742 | if (IS_ERR(di)) { | ||
2743 | ret = PTR_ERR(di); | ||
2744 | goto err; | ||
2745 | } | ||
2746 | if (!di) { | ||
2747 | ret = -ENOENT; | ||
2748 | goto err; | 2756 | goto err; |
2749 | } | ||
2750 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
2751 | btrfs_release_path(root, path); | ||
2752 | 2757 | ||
2753 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, | 2758 | ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len, |
2754 | inode, dir_ino); | 2759 | inode, dir_ino); |
@@ -2939,6 +2944,14 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir, | |||
2939 | index = btrfs_inode_ref_index(path->nodes[0], ref); | 2944 | index = btrfs_inode_ref_index(path->nodes[0], ref); |
2940 | btrfs_release_path(root, path); | 2945 | btrfs_release_path(root, path); |
2941 | 2946 | ||
2947 | /* | ||
2948 | * This is a commit root search, if we can lookup inode item and other | ||
2949 | * relative items in the commit root, it means the transaction of | ||
2950 | * dir/file creation has been committed, and the dir index item that we | ||
2951 | * delay to insert has also been inserted into the commit root. So | ||
2952 | * we needn't worry about the delayed insertion of the dir index item | ||
2953 | * here. | ||
2954 | */ | ||
2942 | di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino, index, | 2955 | di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino, index, |
2943 | dentry->d_name.name, dentry->d_name.len, 0); | 2956 | dentry->d_name.name, dentry->d_name.len, 0); |
2944 | if (IS_ERR(di)) { | 2957 | if (IS_ERR(di)) { |
@@ -3045,24 +3058,16 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, | |||
3045 | btrfs_release_path(root, path); | 3058 | btrfs_release_path(root, path); |
3046 | index = key.offset; | 3059 | index = key.offset; |
3047 | } | 3060 | } |
3061 | btrfs_release_path(root, path); | ||
3048 | 3062 | ||
3049 | di = btrfs_lookup_dir_index_item(trans, root, path, dir_ino, | 3063 | ret = btrfs_delete_delayed_dir_index(trans, root, dir, index); |
3050 | index, name, name_len, -1); | ||
3051 | BUG_ON(!di || IS_ERR(di)); | ||
3052 | |||
3053 | leaf = path->nodes[0]; | ||
3054 | btrfs_dir_item_key_to_cpu(leaf, di, &key); | ||
3055 | WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid); | ||
3056 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
3057 | BUG_ON(ret); | 3064 | BUG_ON(ret); |
3058 | btrfs_release_path(root, path); | ||
3059 | 3065 | ||
3060 | btrfs_i_size_write(dir, dir->i_size - name_len * 2); | 3066 | btrfs_i_size_write(dir, dir->i_size - name_len * 2); |
3061 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | 3067 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; |
3062 | ret = btrfs_update_inode(trans, root, dir); | 3068 | ret = btrfs_update_inode(trans, root, dir); |
3063 | BUG_ON(ret); | 3069 | BUG_ON(ret); |
3064 | 3070 | ||
3065 | btrfs_free_path(path); | ||
3066 | return 0; | 3071 | return 0; |
3067 | } | 3072 | } |
3068 | 3073 | ||
@@ -3323,6 +3328,15 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
3323 | if (root->ref_cows || root == root->fs_info->tree_root) | 3328 | if (root->ref_cows || root == root->fs_info->tree_root) |
3324 | btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); | 3329 | btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); |
3325 | 3330 | ||
3331 | /* | ||
3332 | * This function is also used to drop the items in the log tree before | ||
3333 | * we relog the inode, so if root != BTRFS_I(inode)->root, it means | ||
3334 | * it is used to drop the loged items. So we shouldn't kill the delayed | ||
3335 | * items. | ||
3336 | */ | ||
3337 | if (min_type == 0 && root == BTRFS_I(inode)->root) | ||
3338 | btrfs_kill_delayed_inode_items(inode); | ||
3339 | |||
3326 | path = btrfs_alloc_path(); | 3340 | path = btrfs_alloc_path(); |
3327 | BUG_ON(!path); | 3341 | BUG_ON(!path); |
3328 | path->reada = -1; | 3342 | path->reada = -1; |
@@ -4232,7 +4246,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
4232 | return d_splice_alias(inode, dentry); | 4246 | return d_splice_alias(inode, dentry); |
4233 | } | 4247 | } |
4234 | 4248 | ||
4235 | static unsigned char btrfs_filetype_table[] = { | 4249 | unsigned char btrfs_filetype_table[] = { |
4236 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK | 4250 | DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK |
4237 | }; | 4251 | }; |
4238 | 4252 | ||
@@ -4246,6 +4260,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4246 | struct btrfs_key key; | 4260 | struct btrfs_key key; |
4247 | struct btrfs_key found_key; | 4261 | struct btrfs_key found_key; |
4248 | struct btrfs_path *path; | 4262 | struct btrfs_path *path; |
4263 | struct list_head ins_list; | ||
4264 | struct list_head del_list; | ||
4249 | int ret; | 4265 | int ret; |
4250 | struct extent_buffer *leaf; | 4266 | struct extent_buffer *leaf; |
4251 | int slot; | 4267 | int slot; |
@@ -4258,6 +4274,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4258 | char tmp_name[32]; | 4274 | char tmp_name[32]; |
4259 | char *name_ptr; | 4275 | char *name_ptr; |
4260 | int name_len; | 4276 | int name_len; |
4277 | int is_curr = 0; /* filp->f_pos points to the current index? */ | ||
4261 | 4278 | ||
4262 | /* FIXME, use a real flag for deciding about the key type */ | 4279 | /* FIXME, use a real flag for deciding about the key type */ |
4263 | if (root->fs_info->tree_root == root) | 4280 | if (root->fs_info->tree_root == root) |
@@ -4280,8 +4297,16 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4280 | filp->f_pos = 2; | 4297 | filp->f_pos = 2; |
4281 | } | 4298 | } |
4282 | path = btrfs_alloc_path(); | 4299 | path = btrfs_alloc_path(); |
4300 | if (!path) | ||
4301 | return -ENOMEM; | ||
4283 | path->reada = 2; | 4302 | path->reada = 2; |
4284 | 4303 | ||
4304 | if (key_type == BTRFS_DIR_INDEX_KEY) { | ||
4305 | INIT_LIST_HEAD(&ins_list); | ||
4306 | INIT_LIST_HEAD(&del_list); | ||
4307 | btrfs_get_delayed_items(inode, &ins_list, &del_list); | ||
4308 | } | ||
4309 | |||
4285 | btrfs_set_key_type(&key, key_type); | 4310 | btrfs_set_key_type(&key, key_type); |
4286 | key.offset = filp->f_pos; | 4311 | key.offset = filp->f_pos; |
4287 | key.objectid = btrfs_ino(inode); | 4312 | key.objectid = btrfs_ino(inode); |
@@ -4311,8 +4336,13 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4311 | break; | 4336 | break; |
4312 | if (found_key.offset < filp->f_pos) | 4337 | if (found_key.offset < filp->f_pos) |
4313 | goto next; | 4338 | goto next; |
4339 | if (key_type == BTRFS_DIR_INDEX_KEY && | ||
4340 | btrfs_should_delete_dir_index(&del_list, | ||
4341 | found_key.offset)) | ||
4342 | goto next; | ||
4314 | 4343 | ||
4315 | filp->f_pos = found_key.offset; | 4344 | filp->f_pos = found_key.offset; |
4345 | is_curr = 1; | ||
4316 | 4346 | ||
4317 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 4347 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
4318 | di_cur = 0; | 4348 | di_cur = 0; |
@@ -4367,6 +4397,15 @@ next: | |||
4367 | path->slots[0]++; | 4397 | path->slots[0]++; |
4368 | } | 4398 | } |
4369 | 4399 | ||
4400 | if (key_type == BTRFS_DIR_INDEX_KEY) { | ||
4401 | if (is_curr) | ||
4402 | filp->f_pos++; | ||
4403 | ret = btrfs_readdir_delayed_dir_index(filp, dirent, filldir, | ||
4404 | &ins_list); | ||
4405 | if (ret) | ||
4406 | goto nopos; | ||
4407 | } | ||
4408 | |||
4370 | /* Reached end of directory/root. Bump pos past the last item. */ | 4409 | /* Reached end of directory/root. Bump pos past the last item. */ |
4371 | if (key_type == BTRFS_DIR_INDEX_KEY) | 4410 | if (key_type == BTRFS_DIR_INDEX_KEY) |
4372 | /* | 4411 | /* |
@@ -4379,6 +4418,8 @@ next: | |||
4379 | nopos: | 4418 | nopos: |
4380 | ret = 0; | 4419 | ret = 0; |
4381 | err: | 4420 | err: |
4421 | if (key_type == BTRFS_DIR_INDEX_KEY) | ||
4422 | btrfs_put_delayed_items(&ins_list, &del_list); | ||
4382 | btrfs_free_path(path); | 4423 | btrfs_free_path(path); |
4383 | return ret; | 4424 | return ret; |
4384 | } | 4425 | } |
@@ -4459,6 +4500,8 @@ void btrfs_dirty_inode(struct inode *inode) | |||
4459 | } | 4500 | } |
4460 | } | 4501 | } |
4461 | btrfs_end_transaction(trans, root); | 4502 | btrfs_end_transaction(trans, root); |
4503 | if (BTRFS_I(inode)->delayed_node) | ||
4504 | btrfs_balance_delayed_items(root); | ||
4462 | } | 4505 | } |
4463 | 4506 | ||
4464 | /* | 4507 | /* |
@@ -4527,9 +4570,12 @@ int btrfs_set_inode_index(struct inode *dir, u64 *index) | |||
4527 | int ret = 0; | 4570 | int ret = 0; |
4528 | 4571 | ||
4529 | if (BTRFS_I(dir)->index_cnt == (u64)-1) { | 4572 | if (BTRFS_I(dir)->index_cnt == (u64)-1) { |
4530 | ret = btrfs_set_inode_index_count(dir); | 4573 | ret = btrfs_inode_delayed_dir_index_count(dir); |
4531 | if (ret) | 4574 | if (ret) { |
4532 | return ret; | 4575 | ret = btrfs_set_inode_index_count(dir); |
4576 | if (ret) | ||
4577 | return ret; | ||
4578 | } | ||
4533 | } | 4579 | } |
4534 | 4580 | ||
4535 | *index = BTRFS_I(dir)->index_cnt; | 4581 | *index = BTRFS_I(dir)->index_cnt; |
@@ -4701,7 +4747,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
4701 | 4747 | ||
4702 | if (ret == 0) { | 4748 | if (ret == 0) { |
4703 | ret = btrfs_insert_dir_item(trans, root, name, name_len, | 4749 | ret = btrfs_insert_dir_item(trans, root, name, name_len, |
4704 | parent_ino, &key, | 4750 | parent_inode, &key, |
4705 | btrfs_inode_type(inode), index); | 4751 | btrfs_inode_type(inode), index); |
4706 | BUG_ON(ret); | 4752 | BUG_ON(ret); |
4707 | 4753 | ||
@@ -6816,6 +6862,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
6816 | ei->dummy_inode = 0; | 6862 | ei->dummy_inode = 0; |
6817 | ei->force_compress = BTRFS_COMPRESS_NONE; | 6863 | ei->force_compress = BTRFS_COMPRESS_NONE; |
6818 | 6864 | ||
6865 | ei->delayed_node = NULL; | ||
6866 | |||
6819 | inode = &ei->vfs_inode; | 6867 | inode = &ei->vfs_inode; |
6820 | extent_map_tree_init(&ei->extent_tree, GFP_NOFS); | 6868 | extent_map_tree_init(&ei->extent_tree, GFP_NOFS); |
6821 | extent_io_tree_init(&ei->io_tree, &inode->i_data, GFP_NOFS); | 6869 | extent_io_tree_init(&ei->io_tree, &inode->i_data, GFP_NOFS); |
@@ -6906,6 +6954,7 @@ void btrfs_destroy_inode(struct inode *inode) | |||
6906 | inode_tree_del(inode); | 6954 | inode_tree_del(inode); |
6907 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); | 6955 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); |
6908 | free: | 6956 | free: |
6957 | btrfs_remove_delayed_node(inode); | ||
6909 | call_rcu(&inode->i_rcu, btrfs_i_callback); | 6958 | call_rcu(&inode->i_rcu, btrfs_i_callback); |
6910 | } | 6959 | } |
6911 | 6960 | ||