diff options
author | Yan, Zheng <zheng.yan@oracle.com> | 2009-09-21 16:00:26 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-09-21 16:00:26 -0400 |
commit | 76dda93c6ae2c1dc3e6cde34569d6aca26b0c918 (patch) | |
tree | f5ca46ec89d4ae2c762952d5f35e2c6f95ac046a /fs/btrfs/disk-io.c | |
parent | 4df27c4d5cc1dda54ed7d0a8389347f2df359cf9 (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/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 81 |
1 files changed, 62 insertions, 19 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a4f531047c4a..a0d41e713f3c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1378,8 +1378,10 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) | |||
1378 | 1378 | ||
1379 | err = bdi_register(bdi, NULL, "btrfs-%d", | 1379 | err = bdi_register(bdi, NULL, "btrfs-%d", |
1380 | atomic_inc_return(&btrfs_bdi_num)); | 1380 | atomic_inc_return(&btrfs_bdi_num)); |
1381 | if (err) | 1381 | if (err) { |
1382 | bdi_destroy(bdi); | ||
1382 | return err; | 1383 | return err; |
1384 | } | ||
1383 | 1385 | ||
1384 | bdi->ra_pages = default_backing_dev_info.ra_pages; | 1386 | bdi->ra_pages = default_backing_dev_info.ra_pages; |
1385 | bdi->unplug_io_fn = btrfs_unplug_io_fn; | 1387 | bdi->unplug_io_fn = btrfs_unplug_io_fn; |
@@ -1469,9 +1471,12 @@ static int cleaner_kthread(void *arg) | |||
1469 | break; | 1471 | break; |
1470 | 1472 | ||
1471 | vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); | 1473 | vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE); |
1472 | mutex_lock(&root->fs_info->cleaner_mutex); | 1474 | |
1473 | btrfs_clean_old_snapshots(root); | 1475 | if (!(root->fs_info->sb->s_flags & MS_RDONLY) && |
1474 | mutex_unlock(&root->fs_info->cleaner_mutex); | 1476 | mutex_trylock(&root->fs_info->cleaner_mutex)) { |
1477 | btrfs_clean_old_snapshots(root); | ||
1478 | mutex_unlock(&root->fs_info->cleaner_mutex); | ||
1479 | } | ||
1475 | 1480 | ||
1476 | if (freezing(current)) { | 1481 | if (freezing(current)) { |
1477 | refrigerator(); | 1482 | refrigerator(); |
@@ -1576,7 +1581,26 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1576 | err = -ENOMEM; | 1581 | err = -ENOMEM; |
1577 | goto fail; | 1582 | goto fail; |
1578 | } | 1583 | } |
1579 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); | 1584 | |
1585 | ret = init_srcu_struct(&fs_info->subvol_srcu); | ||
1586 | if (ret) { | ||
1587 | err = ret; | ||
1588 | goto fail; | ||
1589 | } | ||
1590 | |||
1591 | ret = setup_bdi(fs_info, &fs_info->bdi); | ||
1592 | if (ret) { | ||
1593 | err = ret; | ||
1594 | goto fail_srcu; | ||
1595 | } | ||
1596 | |||
1597 | fs_info->btree_inode = new_inode(sb); | ||
1598 | if (!fs_info->btree_inode) { | ||
1599 | err = -ENOMEM; | ||
1600 | goto fail_bdi; | ||
1601 | } | ||
1602 | |||
1603 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); | ||
1580 | INIT_LIST_HEAD(&fs_info->trans_list); | 1604 | INIT_LIST_HEAD(&fs_info->trans_list); |
1581 | INIT_LIST_HEAD(&fs_info->dead_roots); | 1605 | INIT_LIST_HEAD(&fs_info->dead_roots); |
1582 | INIT_LIST_HEAD(&fs_info->hashers); | 1606 | INIT_LIST_HEAD(&fs_info->hashers); |
@@ -1586,6 +1610,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1586 | spin_lock_init(&fs_info->delalloc_lock); | 1610 | spin_lock_init(&fs_info->delalloc_lock); |
1587 | spin_lock_init(&fs_info->new_trans_lock); | 1611 | spin_lock_init(&fs_info->new_trans_lock); |
1588 | spin_lock_init(&fs_info->ref_cache_lock); | 1612 | spin_lock_init(&fs_info->ref_cache_lock); |
1613 | spin_lock_init(&fs_info->fs_roots_radix_lock); | ||
1589 | 1614 | ||
1590 | init_completion(&fs_info->kobj_unregister); | 1615 | init_completion(&fs_info->kobj_unregister); |
1591 | fs_info->tree_root = tree_root; | 1616 | fs_info->tree_root = tree_root; |
@@ -1604,11 +1629,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1604 | fs_info->sb = sb; | 1629 | fs_info->sb = sb; |
1605 | fs_info->max_extent = (u64)-1; | 1630 | fs_info->max_extent = (u64)-1; |
1606 | fs_info->max_inline = 8192 * 1024; | 1631 | fs_info->max_inline = 8192 * 1024; |
1607 | if (setup_bdi(fs_info, &fs_info->bdi)) | ||
1608 | goto fail_bdi; | ||
1609 | fs_info->btree_inode = new_inode(sb); | ||
1610 | fs_info->btree_inode->i_ino = 1; | ||
1611 | fs_info->btree_inode->i_nlink = 1; | ||
1612 | fs_info->metadata_ratio = 8; | 1632 | fs_info->metadata_ratio = 8; |
1613 | 1633 | ||
1614 | fs_info->thread_pool_size = min_t(unsigned long, | 1634 | fs_info->thread_pool_size = min_t(unsigned long, |
@@ -1620,6 +1640,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1620 | sb->s_blocksize = 4096; | 1640 | sb->s_blocksize = 4096; |
1621 | sb->s_blocksize_bits = blksize_bits(4096); | 1641 | sb->s_blocksize_bits = blksize_bits(4096); |
1622 | 1642 | ||
1643 | fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID; | ||
1644 | fs_info->btree_inode->i_nlink = 1; | ||
1623 | /* | 1645 | /* |
1624 | * we set the i_size on the btree inode to the max possible int. | 1646 | * we set the i_size on the btree inode to the max possible int. |
1625 | * the real end of the address space is determined by all of | 1647 | * the real end of the address space is determined by all of |
@@ -1638,6 +1660,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1638 | 1660 | ||
1639 | BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops; | 1661 | BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops; |
1640 | 1662 | ||
1663 | BTRFS_I(fs_info->btree_inode)->root = tree_root; | ||
1664 | memset(&BTRFS_I(fs_info->btree_inode)->location, 0, | ||
1665 | sizeof(struct btrfs_key)); | ||
1666 | BTRFS_I(fs_info->btree_inode)->dummy_inode = 1; | ||
1667 | |||
1641 | spin_lock_init(&fs_info->block_group_cache_lock); | 1668 | spin_lock_init(&fs_info->block_group_cache_lock); |
1642 | fs_info->block_group_cache_tree.rb_node = NULL; | 1669 | fs_info->block_group_cache_tree.rb_node = NULL; |
1643 | 1670 | ||
@@ -1648,21 +1675,16 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1648 | fs_info->pinned_extents = &fs_info->freed_extents[0]; | 1675 | fs_info->pinned_extents = &fs_info->freed_extents[0]; |
1649 | fs_info->do_barriers = 1; | 1676 | fs_info->do_barriers = 1; |
1650 | 1677 | ||
1651 | BTRFS_I(fs_info->btree_inode)->root = tree_root; | ||
1652 | memset(&BTRFS_I(fs_info->btree_inode)->location, 0, | ||
1653 | sizeof(struct btrfs_key)); | ||
1654 | insert_inode_hash(fs_info->btree_inode); | ||
1655 | 1678 | ||
1656 | mutex_init(&fs_info->trans_mutex); | 1679 | mutex_init(&fs_info->trans_mutex); |
1657 | mutex_init(&fs_info->ordered_operations_mutex); | 1680 | mutex_init(&fs_info->ordered_operations_mutex); |
1658 | mutex_init(&fs_info->tree_log_mutex); | 1681 | mutex_init(&fs_info->tree_log_mutex); |
1659 | mutex_init(&fs_info->drop_mutex); | ||
1660 | mutex_init(&fs_info->chunk_mutex); | 1682 | mutex_init(&fs_info->chunk_mutex); |
1661 | mutex_init(&fs_info->transaction_kthread_mutex); | 1683 | mutex_init(&fs_info->transaction_kthread_mutex); |
1662 | mutex_init(&fs_info->cleaner_mutex); | 1684 | mutex_init(&fs_info->cleaner_mutex); |
1663 | mutex_init(&fs_info->volume_mutex); | 1685 | mutex_init(&fs_info->volume_mutex); |
1664 | mutex_init(&fs_info->tree_reloc_mutex); | ||
1665 | init_rwsem(&fs_info->extent_commit_sem); | 1686 | init_rwsem(&fs_info->extent_commit_sem); |
1687 | init_rwsem(&fs_info->subvol_sem); | ||
1666 | 1688 | ||
1667 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); | 1689 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); |
1668 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); | 1690 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); |
@@ -1941,6 +1963,9 @@ printk("thread pool is %d\n", fs_info->thread_pool_size); | |||
1941 | } | 1963 | } |
1942 | } | 1964 | } |
1943 | 1965 | ||
1966 | ret = btrfs_find_orphan_roots(tree_root); | ||
1967 | BUG_ON(ret); | ||
1968 | |||
1944 | if (!(sb->s_flags & MS_RDONLY)) { | 1969 | if (!(sb->s_flags & MS_RDONLY)) { |
1945 | ret = btrfs_recover_relocation(tree_root); | 1970 | ret = btrfs_recover_relocation(tree_root); |
1946 | BUG_ON(ret); | 1971 | BUG_ON(ret); |
@@ -2000,6 +2025,8 @@ fail_iput: | |||
2000 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 2025 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |
2001 | fail_bdi: | 2026 | fail_bdi: |
2002 | bdi_destroy(&fs_info->bdi); | 2027 | bdi_destroy(&fs_info->bdi); |
2028 | fail_srcu: | ||
2029 | cleanup_srcu_struct(&fs_info->subvol_srcu); | ||
2003 | fail: | 2030 | fail: |
2004 | kfree(extent_root); | 2031 | kfree(extent_root); |
2005 | kfree(tree_root); | 2032 | kfree(tree_root); |
@@ -2263,6 +2290,10 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | |||
2263 | radix_tree_delete(&fs_info->fs_roots_radix, | 2290 | radix_tree_delete(&fs_info->fs_roots_radix, |
2264 | (unsigned long)root->root_key.objectid); | 2291 | (unsigned long)root->root_key.objectid); |
2265 | spin_unlock(&fs_info->fs_roots_radix_lock); | 2292 | spin_unlock(&fs_info->fs_roots_radix_lock); |
2293 | |||
2294 | if (btrfs_root_refs(&root->root_item) == 0) | ||
2295 | synchronize_srcu(&fs_info->subvol_srcu); | ||
2296 | |||
2266 | free_fs_root(root); | 2297 | free_fs_root(root); |
2267 | return 0; | 2298 | return 0; |
2268 | } | 2299 | } |
@@ -2286,6 +2317,20 @@ static int del_fs_roots(struct btrfs_fs_info *fs_info) | |||
2286 | struct btrfs_root *gang[8]; | 2317 | struct btrfs_root *gang[8]; |
2287 | int i; | 2318 | int i; |
2288 | 2319 | ||
2320 | while (!list_empty(&fs_info->dead_roots)) { | ||
2321 | gang[0] = list_entry(fs_info->dead_roots.next, | ||
2322 | struct btrfs_root, root_list); | ||
2323 | list_del(&gang[0]->root_list); | ||
2324 | |||
2325 | if (gang[0]->in_radix) { | ||
2326 | btrfs_free_fs_root(fs_info, gang[0]); | ||
2327 | } else { | ||
2328 | free_extent_buffer(gang[0]->node); | ||
2329 | free_extent_buffer(gang[0]->commit_root); | ||
2330 | kfree(gang[0]); | ||
2331 | } | ||
2332 | } | ||
2333 | |||
2289 | while (1) { | 2334 | while (1) { |
2290 | ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, | 2335 | ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix, |
2291 | (void **)gang, 0, | 2336 | (void **)gang, 0, |
@@ -2315,9 +2360,6 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) | |||
2315 | root_objectid = gang[ret - 1]->root_key.objectid + 1; | 2360 | root_objectid = gang[ret - 1]->root_key.objectid + 1; |
2316 | for (i = 0; i < ret; i++) { | 2361 | for (i = 0; i < ret; i++) { |
2317 | root_objectid = gang[i]->root_key.objectid; | 2362 | root_objectid = gang[i]->root_key.objectid; |
2318 | ret = btrfs_find_dead_roots(fs_info->tree_root, | ||
2319 | root_objectid); | ||
2320 | BUG_ON(ret); | ||
2321 | btrfs_orphan_cleanup(gang[i]); | 2363 | btrfs_orphan_cleanup(gang[i]); |
2322 | } | 2364 | } |
2323 | root_objectid++; | 2365 | root_objectid++; |
@@ -2405,6 +2447,7 @@ int close_ctree(struct btrfs_root *root) | |||
2405 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 2447 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |
2406 | 2448 | ||
2407 | bdi_destroy(&fs_info->bdi); | 2449 | bdi_destroy(&fs_info->bdi); |
2450 | cleanup_srcu_struct(&fs_info->subvol_srcu); | ||
2408 | 2451 | ||
2409 | kfree(fs_info->extent_root); | 2452 | kfree(fs_info->extent_root); |
2410 | kfree(fs_info->tree_root); | 2453 | kfree(fs_info->tree_root); |