aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2009-09-21 16:00:26 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-21 16:00:26 -0400
commit76dda93c6ae2c1dc3e6cde34569d6aca26b0c918 (patch)
treef5ca46ec89d4ae2c762952d5f35e2c6f95ac046a /fs/btrfs/inode.c
parent4df27c4d5cc1dda54ed7d0a8389347f2df359cf9 (diff)
Btrfs: add snapshot/subvolume destroy ioctl
This patch adds snapshot/subvolume destroy ioctl. A subvolume that isn't being used and doesn't contains links to other subvolumes can be destroyed. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c134
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
3229again: 3233again:
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:
3256static void inode_tree_del(struct inode *inode) 3263static 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
3286int 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);
3297again:
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
3268static noinline void init_btrfs_i(struct inode *inode) 3349static 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
3502static 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
3415static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, 3515static 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 */
4775int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, 4875int 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
4974void 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
4875static void init_once(void *foo) 4984static 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
5423static struct file_operations btrfs_dir_file_operations = { 5539static 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
5626struct dentry_operations btrfs_dentry_operations = {
5627 .d_delete = btrfs_dentry_delete,
5628};