diff options
Diffstat (limited to 'fs/btrfs/inode.c')
| -rw-r--r-- | fs/btrfs/inode.c | 134 |
1 files changed, 127 insertions, 7 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6036b36789cc..db9cbd91eb4c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -3089,6 +3089,11 @@ void btrfs_delete_inode(struct inode *inode) | |||
| 3089 | } | 3089 | } |
| 3090 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 3090 | btrfs_wait_ordered_range(inode, 0, (u64)-1); |
| 3091 | 3091 | ||
| 3092 | if (inode->i_nlink > 0) { | ||
| 3093 | BUG_ON(btrfs_root_refs(&root->root_item) != 0); | ||
| 3094 | goto no_delete; | ||
| 3095 | } | ||
| 3096 | |||
| 3092 | btrfs_i_size_write(inode, 0); | 3097 | btrfs_i_size_write(inode, 0); |
| 3093 | trans = btrfs_join_transaction(root, 1); | 3098 | trans = btrfs_join_transaction(root, 1); |
| 3094 | 3099 | ||
| @@ -3225,11 +3230,13 @@ static void inode_tree_add(struct inode *inode) | |||
| 3225 | struct btrfs_inode *entry; | 3230 | struct btrfs_inode *entry; |
| 3226 | struct rb_node **p; | 3231 | struct rb_node **p; |
| 3227 | struct rb_node *parent; | 3232 | struct rb_node *parent; |
| 3228 | |||
| 3229 | again: | 3233 | again: |
| 3230 | p = &root->inode_tree.rb_node; | 3234 | p = &root->inode_tree.rb_node; |
| 3231 | parent = NULL; | 3235 | parent = NULL; |
| 3232 | 3236 | ||
| 3237 | if (hlist_unhashed(&inode->i_hash)) | ||
| 3238 | return; | ||
| 3239 | |||
| 3233 | spin_lock(&root->inode_lock); | 3240 | spin_lock(&root->inode_lock); |
| 3234 | while (*p) { | 3241 | while (*p) { |
| 3235 | parent = *p; | 3242 | parent = *p; |
| @@ -3256,13 +3263,87 @@ again: | |||
| 3256 | static void inode_tree_del(struct inode *inode) | 3263 | static void inode_tree_del(struct inode *inode) |
| 3257 | { | 3264 | { |
| 3258 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3265 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 3266 | int empty = 0; | ||
| 3259 | 3267 | ||
| 3260 | spin_lock(&root->inode_lock); | 3268 | spin_lock(&root->inode_lock); |
| 3261 | if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) { | 3269 | if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) { |
| 3262 | rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree); | 3270 | rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree); |
| 3263 | RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); | 3271 | RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); |
| 3272 | empty = RB_EMPTY_ROOT(&root->inode_tree); | ||
| 3264 | } | 3273 | } |
| 3265 | spin_unlock(&root->inode_lock); | 3274 | spin_unlock(&root->inode_lock); |
| 3275 | |||
| 3276 | if (empty && btrfs_root_refs(&root->root_item) == 0) { | ||
| 3277 | synchronize_srcu(&root->fs_info->subvol_srcu); | ||
| 3278 | spin_lock(&root->inode_lock); | ||
| 3279 | empty = RB_EMPTY_ROOT(&root->inode_tree); | ||
| 3280 | spin_unlock(&root->inode_lock); | ||
| 3281 | if (empty) | ||
| 3282 | btrfs_add_dead_root(root); | ||
| 3283 | } | ||
| 3284 | } | ||
| 3285 | |||
| 3286 | int btrfs_invalidate_inodes(struct btrfs_root *root) | ||
| 3287 | { | ||
| 3288 | struct rb_node *node; | ||
| 3289 | struct rb_node *prev; | ||
| 3290 | struct btrfs_inode *entry; | ||
| 3291 | struct inode *inode; | ||
| 3292 | u64 objectid = 0; | ||
| 3293 | |||
| 3294 | WARN_ON(btrfs_root_refs(&root->root_item) != 0); | ||
| 3295 | |||
| 3296 | spin_lock(&root->inode_lock); | ||
| 3297 | again: | ||
| 3298 | node = root->inode_tree.rb_node; | ||
| 3299 | prev = NULL; | ||
| 3300 | while (node) { | ||
| 3301 | prev = node; | ||
| 3302 | entry = rb_entry(node, struct btrfs_inode, rb_node); | ||
| 3303 | |||
| 3304 | if (objectid < entry->vfs_inode.i_ino) | ||
| 3305 | node = node->rb_left; | ||
| 3306 | else if (objectid > entry->vfs_inode.i_ino) | ||
| 3307 | node = node->rb_right; | ||
| 3308 | else | ||
| 3309 | break; | ||
| 3310 | } | ||
| 3311 | if (!node) { | ||
| 3312 | while (prev) { | ||
| 3313 | entry = rb_entry(prev, struct btrfs_inode, rb_node); | ||
| 3314 | if (objectid <= entry->vfs_inode.i_ino) { | ||
| 3315 | node = prev; | ||
| 3316 | break; | ||
| 3317 | } | ||
| 3318 | prev = rb_next(prev); | ||
| 3319 | } | ||
| 3320 | } | ||
| 3321 | while (node) { | ||
| 3322 | entry = rb_entry(node, struct btrfs_inode, rb_node); | ||
| 3323 | objectid = entry->vfs_inode.i_ino + 1; | ||
| 3324 | inode = igrab(&entry->vfs_inode); | ||
| 3325 | if (inode) { | ||
| 3326 | spin_unlock(&root->inode_lock); | ||
| 3327 | if (atomic_read(&inode->i_count) > 1) | ||
| 3328 | d_prune_aliases(inode); | ||
| 3329 | /* | ||
| 3330 | * btrfs_drop_inode will remove it from | ||
| 3331 | * the inode cache when its usage count | ||
| 3332 | * hits zero. | ||
| 3333 | */ | ||
| 3334 | iput(inode); | ||
| 3335 | cond_resched(); | ||
| 3336 | spin_lock(&root->inode_lock); | ||
| 3337 | goto again; | ||
| 3338 | } | ||
| 3339 | |||
| 3340 | if (cond_resched_lock(&root->inode_lock)) | ||
| 3341 | goto again; | ||
| 3342 | |||
| 3343 | node = rb_next(node); | ||
| 3344 | } | ||
| 3345 | spin_unlock(&root->inode_lock); | ||
| 3346 | return 0; | ||
| 3266 | } | 3347 | } |
| 3267 | 3348 | ||
| 3268 | static noinline void init_btrfs_i(struct inode *inode) | 3349 | static noinline void init_btrfs_i(struct inode *inode) |
| @@ -3379,8 +3460,11 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
| 3379 | struct btrfs_root *root = BTRFS_I(dir)->root; | 3460 | struct btrfs_root *root = BTRFS_I(dir)->root; |
| 3380 | struct btrfs_root *sub_root = root; | 3461 | struct btrfs_root *sub_root = root; |
| 3381 | struct btrfs_key location; | 3462 | struct btrfs_key location; |
| 3463 | int index; | ||
| 3382 | int ret; | 3464 | int ret; |
| 3383 | 3465 | ||
| 3466 | dentry->d_op = &btrfs_dentry_operations; | ||
| 3467 | |||
| 3384 | if (dentry->d_name.len > BTRFS_NAME_LEN) | 3468 | if (dentry->d_name.len > BTRFS_NAME_LEN) |
| 3385 | return ERR_PTR(-ENAMETOOLONG); | 3469 | return ERR_PTR(-ENAMETOOLONG); |
| 3386 | 3470 | ||
| @@ -3399,6 +3483,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
| 3399 | 3483 | ||
| 3400 | BUG_ON(location.type != BTRFS_ROOT_ITEM_KEY); | 3484 | BUG_ON(location.type != BTRFS_ROOT_ITEM_KEY); |
| 3401 | 3485 | ||
| 3486 | index = srcu_read_lock(&root->fs_info->subvol_srcu); | ||
| 3402 | ret = fixup_tree_root_location(root, dir, dentry, | 3487 | ret = fixup_tree_root_location(root, dir, dentry, |
| 3403 | &location, &sub_root); | 3488 | &location, &sub_root); |
| 3404 | if (ret < 0) { | 3489 | if (ret < 0) { |
| @@ -3409,9 +3494,24 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
| 3409 | } else { | 3494 | } else { |
| 3410 | inode = btrfs_iget(dir->i_sb, &location, sub_root); | 3495 | inode = btrfs_iget(dir->i_sb, &location, sub_root); |
| 3411 | } | 3496 | } |
| 3497 | srcu_read_unlock(&root->fs_info->subvol_srcu, index); | ||
| 3498 | |||
| 3412 | return inode; | 3499 | return inode; |
| 3413 | } | 3500 | } |
| 3414 | 3501 | ||
| 3502 | static int btrfs_dentry_delete(struct dentry *dentry) | ||
| 3503 | { | ||
| 3504 | struct btrfs_root *root; | ||
| 3505 | |||
| 3506 | if (!dentry->d_inode) | ||
| 3507 | return 0; | ||
| 3508 | |||
| 3509 | root = BTRFS_I(dentry->d_inode)->root; | ||
| 3510 | if (btrfs_root_refs(&root->root_item) == 0) | ||
| 3511 | return 1; | ||
| 3512 | return 0; | ||
| 3513 | } | ||
| 3514 | |||
| 3415 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | 3515 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, |
| 3416 | struct nameidata *nd) | 3516 | struct nameidata *nd) |
| 3417 | { | 3517 | { |
| @@ -4773,11 +4873,11 @@ out: | |||
| 4773 | * create a new subvolume directory/inode (helper for the ioctl). | 4873 | * create a new subvolume directory/inode (helper for the ioctl). |
| 4774 | */ | 4874 | */ |
| 4775 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | 4875 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, |
| 4776 | struct btrfs_root *new_root, struct dentry *dentry, | 4876 | struct btrfs_root *new_root, |
| 4777 | u64 new_dirid, u64 alloc_hint) | 4877 | u64 new_dirid, u64 alloc_hint) |
| 4778 | { | 4878 | { |
| 4779 | struct inode *inode; | 4879 | struct inode *inode; |
| 4780 | int error; | 4880 | int err; |
| 4781 | u64 index = 0; | 4881 | u64 index = 0; |
| 4782 | 4882 | ||
| 4783 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, | 4883 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, |
| @@ -4790,11 +4890,10 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | |||
| 4790 | inode->i_nlink = 1; | 4890 | inode->i_nlink = 1; |
| 4791 | btrfs_i_size_write(inode, 0); | 4891 | btrfs_i_size_write(inode, 0); |
| 4792 | 4892 | ||
| 4793 | error = btrfs_update_inode(trans, new_root, inode); | 4893 | err = btrfs_update_inode(trans, new_root, inode); |
| 4794 | if (error) | 4894 | BUG_ON(err); |
| 4795 | return error; | ||
| 4796 | 4895 | ||
| 4797 | d_instantiate(dentry, inode); | 4896 | iput(inode); |
| 4798 | return 0; | 4897 | return 0; |
| 4799 | } | 4898 | } |
| 4800 | 4899 | ||
| @@ -4872,6 +4971,16 @@ void btrfs_destroy_inode(struct inode *inode) | |||
| 4872 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | 4971 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); |
| 4873 | } | 4972 | } |
| 4874 | 4973 | ||
| 4974 | void btrfs_drop_inode(struct inode *inode) | ||
| 4975 | { | ||
| 4976 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 4977 | |||
| 4978 | if (inode->i_nlink > 0 && btrfs_root_refs(&root->root_item) == 0) | ||
| 4979 | generic_delete_inode(inode); | ||
| 4980 | else | ||
| 4981 | generic_drop_inode(inode); | ||
| 4982 | } | ||
| 4983 | |||
| 4875 | static void init_once(void *foo) | 4984 | static void init_once(void *foo) |
| 4876 | { | 4985 | { |
| 4877 | struct btrfs_inode *ei = (struct btrfs_inode *) foo; | 4986 | struct btrfs_inode *ei = (struct btrfs_inode *) foo; |
| @@ -4973,6 +5082,10 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 4973 | old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | 5082 | old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) |
| 4974 | filemap_flush(old_inode->i_mapping); | 5083 | filemap_flush(old_inode->i_mapping); |
| 4975 | 5084 | ||
| 5085 | /* close the racy window with snapshot create/destroy ioctl */ | ||
| 5086 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | ||
| 5087 | down_read(&root->fs_info->subvol_sem); | ||
| 5088 | |||
| 4976 | trans = btrfs_start_transaction(root, 1); | 5089 | trans = btrfs_start_transaction(root, 1); |
| 4977 | 5090 | ||
| 4978 | if (dest != root) | 5091 | if (dest != root) |
| @@ -5062,6 +5175,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 5062 | 5175 | ||
| 5063 | btrfs_end_transaction_throttle(trans, root); | 5176 | btrfs_end_transaction_throttle(trans, root); |
| 5064 | 5177 | ||
| 5178 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | ||
| 5179 | up_read(&root->fs_info->subvol_sem); | ||
| 5065 | return ret; | 5180 | return ret; |
| 5066 | } | 5181 | } |
| 5067 | 5182 | ||
| @@ -5420,6 +5535,7 @@ static struct inode_operations btrfs_dir_ro_inode_operations = { | |||
| 5420 | .lookup = btrfs_lookup, | 5535 | .lookup = btrfs_lookup, |
| 5421 | .permission = btrfs_permission, | 5536 | .permission = btrfs_permission, |
| 5422 | }; | 5537 | }; |
| 5538 | |||
| 5423 | static struct file_operations btrfs_dir_file_operations = { | 5539 | static struct file_operations btrfs_dir_file_operations = { |
| 5424 | .llseek = generic_file_llseek, | 5540 | .llseek = generic_file_llseek, |
| 5425 | .read = generic_read_dir, | 5541 | .read = generic_read_dir, |
| @@ -5506,3 +5622,7 @@ static struct inode_operations btrfs_symlink_inode_operations = { | |||
| 5506 | .listxattr = btrfs_listxattr, | 5622 | .listxattr = btrfs_listxattr, |
| 5507 | .removexattr = btrfs_removexattr, | 5623 | .removexattr = btrfs_removexattr, |
| 5508 | }; | 5624 | }; |
| 5625 | |||
| 5626 | struct dentry_operations btrfs_dentry_operations = { | ||
| 5627 | .d_delete = btrfs_dentry_delete, | ||
| 5628 | }; | ||
