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 | |
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')
-rw-r--r-- | fs/btrfs/ctree.h | 12 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 81 | ||||
-rw-r--r-- | fs/btrfs/export.c | 133 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 21 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 134 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 320 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 3 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 41 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 69 | ||||
-rw-r--r-- | fs/btrfs/super.c | 1 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 10 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 13 |
12 files changed, 605 insertions, 233 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6ade48b227e9..bc57e236ac64 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -839,9 +839,7 @@ struct btrfs_fs_info { | |||
839 | struct mutex transaction_kthread_mutex; | 839 | struct mutex transaction_kthread_mutex; |
840 | struct mutex cleaner_mutex; | 840 | struct mutex cleaner_mutex; |
841 | struct mutex chunk_mutex; | 841 | struct mutex chunk_mutex; |
842 | struct mutex drop_mutex; | ||
843 | struct mutex volume_mutex; | 842 | struct mutex volume_mutex; |
844 | struct mutex tree_reloc_mutex; | ||
845 | /* | 843 | /* |
846 | * this protects the ordered operations list only while we are | 844 | * this protects the ordered operations list only while we are |
847 | * processing all of the entries on it. This way we make | 845 | * processing all of the entries on it. This way we make |
@@ -852,6 +850,10 @@ struct btrfs_fs_info { | |||
852 | struct mutex ordered_operations_mutex; | 850 | struct mutex ordered_operations_mutex; |
853 | struct rw_semaphore extent_commit_sem; | 851 | struct rw_semaphore extent_commit_sem; |
854 | 852 | ||
853 | struct rw_semaphore subvol_sem; | ||
854 | |||
855 | struct srcu_struct subvol_srcu; | ||
856 | |||
855 | struct list_head trans_list; | 857 | struct list_head trans_list; |
856 | struct list_head hashers; | 858 | struct list_head hashers; |
857 | struct list_head dead_roots; | 859 | struct list_head dead_roots; |
@@ -2142,6 +2144,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct | |||
2142 | int btrfs_search_root(struct btrfs_root *root, u64 search_start, | 2144 | int btrfs_search_root(struct btrfs_root *root, u64 search_start, |
2143 | u64 *found_objectid); | 2145 | u64 *found_objectid); |
2144 | int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); | 2146 | int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid); |
2147 | int btrfs_find_orphan_roots(struct btrfs_root *tree_root); | ||
2145 | int btrfs_set_root_node(struct btrfs_root_item *item, | 2148 | int btrfs_set_root_node(struct btrfs_root_item *item, |
2146 | struct extent_buffer *node); | 2149 | struct extent_buffer *node); |
2147 | /* dir-item.c */ | 2150 | /* dir-item.c */ |
@@ -2273,7 +2276,7 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end); | |||
2273 | int btrfs_writepages(struct address_space *mapping, | 2276 | int btrfs_writepages(struct address_space *mapping, |
2274 | struct writeback_control *wbc); | 2277 | struct writeback_control *wbc); |
2275 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, | 2278 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, |
2276 | struct btrfs_root *new_root, struct dentry *dentry, | 2279 | struct btrfs_root *new_root, |
2277 | u64 new_dirid, u64 alloc_hint); | 2280 | u64 new_dirid, u64 alloc_hint); |
2278 | int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | 2281 | int btrfs_merge_bio_hook(struct page *page, unsigned long offset, |
2279 | size_t size, struct bio *bio, unsigned long bio_flags); | 2282 | size_t size, struct bio *bio, unsigned long bio_flags); |
@@ -2289,6 +2292,7 @@ int btrfs_write_inode(struct inode *inode, int wait); | |||
2289 | void btrfs_dirty_inode(struct inode *inode); | 2292 | void btrfs_dirty_inode(struct inode *inode); |
2290 | struct inode *btrfs_alloc_inode(struct super_block *sb); | 2293 | struct inode *btrfs_alloc_inode(struct super_block *sb); |
2291 | void btrfs_destroy_inode(struct inode *inode); | 2294 | void btrfs_destroy_inode(struct inode *inode); |
2295 | void btrfs_drop_inode(struct inode *inode); | ||
2292 | int btrfs_init_cachep(void); | 2296 | int btrfs_init_cachep(void); |
2293 | void btrfs_destroy_cachep(void); | 2297 | void btrfs_destroy_cachep(void); |
2294 | long btrfs_ioctl_trans_end(struct file *file); | 2298 | long btrfs_ioctl_trans_end(struct file *file); |
@@ -2306,6 +2310,8 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); | |||
2306 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); | 2310 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); |
2307 | void btrfs_orphan_cleanup(struct btrfs_root *root); | 2311 | void btrfs_orphan_cleanup(struct btrfs_root *root); |
2308 | int btrfs_cont_expand(struct inode *inode, loff_t size); | 2312 | int btrfs_cont_expand(struct inode *inode, loff_t size); |
2313 | int btrfs_invalidate_inodes(struct btrfs_root *root); | ||
2314 | extern struct dentry_operations btrfs_dentry_operations; | ||
2309 | 2315 | ||
2310 | /* ioctl.c */ | 2316 | /* ioctl.c */ |
2311 | long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 2317 | long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
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); |
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index 9596b40caa4e..ba5c3fd5ab8c 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c | |||
@@ -28,7 +28,7 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | |||
28 | len = BTRFS_FID_SIZE_NON_CONNECTABLE; | 28 | len = BTRFS_FID_SIZE_NON_CONNECTABLE; |
29 | type = FILEID_BTRFS_WITHOUT_PARENT; | 29 | type = FILEID_BTRFS_WITHOUT_PARENT; |
30 | 30 | ||
31 | fid->objectid = BTRFS_I(inode)->location.objectid; | 31 | fid->objectid = inode->i_ino; |
32 | fid->root_objectid = BTRFS_I(inode)->root->objectid; | 32 | fid->root_objectid = BTRFS_I(inode)->root->objectid; |
33 | fid->gen = inode->i_generation; | 33 | fid->gen = inode->i_generation; |
34 | 34 | ||
@@ -60,34 +60,61 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | |||
60 | } | 60 | } |
61 | 61 | ||
62 | static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, | 62 | static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, |
63 | u64 root_objectid, u32 generation) | 63 | u64 root_objectid, u32 generation, |
64 | int check_generation) | ||
64 | { | 65 | { |
66 | struct btrfs_fs_info *fs_info = btrfs_sb(sb)->fs_info; | ||
65 | struct btrfs_root *root; | 67 | struct btrfs_root *root; |
68 | struct dentry *dentry; | ||
66 | struct inode *inode; | 69 | struct inode *inode; |
67 | struct btrfs_key key; | 70 | struct btrfs_key key; |
71 | int index; | ||
72 | int err = 0; | ||
73 | |||
74 | if (objectid < BTRFS_FIRST_FREE_OBJECTID) | ||
75 | return ERR_PTR(-ESTALE); | ||
68 | 76 | ||
69 | key.objectid = root_objectid; | 77 | key.objectid = root_objectid; |
70 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 78 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
71 | key.offset = (u64)-1; | 79 | key.offset = (u64)-1; |
72 | 80 | ||
73 | root = btrfs_read_fs_root_no_name(btrfs_sb(sb)->fs_info, &key); | 81 | index = srcu_read_lock(&fs_info->subvol_srcu); |
74 | if (IS_ERR(root)) | 82 | |
75 | return ERR_CAST(root); | 83 | root = btrfs_read_fs_root_no_name(fs_info, &key); |
84 | if (IS_ERR(root)) { | ||
85 | err = PTR_ERR(root); | ||
86 | goto fail; | ||
87 | } | ||
88 | |||
89 | if (btrfs_root_refs(&root->root_item) == 0) { | ||
90 | err = -ENOENT; | ||
91 | goto fail; | ||
92 | } | ||
76 | 93 | ||
77 | key.objectid = objectid; | 94 | key.objectid = objectid; |
78 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 95 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
79 | key.offset = 0; | 96 | key.offset = 0; |
80 | 97 | ||
81 | inode = btrfs_iget(sb, &key, root); | 98 | inode = btrfs_iget(sb, &key, root); |
82 | if (IS_ERR(inode)) | 99 | if (IS_ERR(inode)) { |
83 | return (void *)inode; | 100 | err = PTR_ERR(inode); |
101 | goto fail; | ||
102 | } | ||
103 | |||
104 | srcu_read_unlock(&fs_info->subvol_srcu, index); | ||
84 | 105 | ||
85 | if (generation != inode->i_generation) { | 106 | if (check_generation && generation != inode->i_generation) { |
86 | iput(inode); | 107 | iput(inode); |
87 | return ERR_PTR(-ESTALE); | 108 | return ERR_PTR(-ESTALE); |
88 | } | 109 | } |
89 | 110 | ||
90 | return d_obtain_alias(inode); | 111 | dentry = d_obtain_alias(inode); |
112 | if (!IS_ERR(dentry)) | ||
113 | dentry->d_op = &btrfs_dentry_operations; | ||
114 | return dentry; | ||
115 | fail: | ||
116 | srcu_read_unlock(&fs_info->subvol_srcu, index); | ||
117 | return ERR_PTR(err); | ||
91 | } | 118 | } |
92 | 119 | ||
93 | static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh, | 120 | static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh, |
@@ -111,7 +138,7 @@ static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh, | |||
111 | objectid = fid->parent_objectid; | 138 | objectid = fid->parent_objectid; |
112 | generation = fid->parent_gen; | 139 | generation = fid->parent_gen; |
113 | 140 | ||
114 | return btrfs_get_dentry(sb, objectid, root_objectid, generation); | 141 | return btrfs_get_dentry(sb, objectid, root_objectid, generation, 1); |
115 | } | 142 | } |
116 | 143 | ||
117 | static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh, | 144 | static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh, |
@@ -133,66 +160,76 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh, | |||
133 | root_objectid = fid->root_objectid; | 160 | root_objectid = fid->root_objectid; |
134 | generation = fid->gen; | 161 | generation = fid->gen; |
135 | 162 | ||
136 | return btrfs_get_dentry(sb, objectid, root_objectid, generation); | 163 | return btrfs_get_dentry(sb, objectid, root_objectid, generation, 1); |
137 | } | 164 | } |
138 | 165 | ||
139 | static struct dentry *btrfs_get_parent(struct dentry *child) | 166 | static struct dentry *btrfs_get_parent(struct dentry *child) |
140 | { | 167 | { |
141 | struct inode *dir = child->d_inode; | 168 | struct inode *dir = child->d_inode; |
169 | static struct dentry *dentry; | ||
142 | struct btrfs_root *root = BTRFS_I(dir)->root; | 170 | struct btrfs_root *root = BTRFS_I(dir)->root; |
143 | struct btrfs_key key; | ||
144 | struct btrfs_path *path; | 171 | struct btrfs_path *path; |
145 | struct extent_buffer *leaf; | 172 | struct extent_buffer *leaf; |
146 | int slot; | 173 | struct btrfs_root_ref *ref; |
147 | u64 objectid; | 174 | struct btrfs_key key; |
175 | struct btrfs_key found_key; | ||
148 | int ret; | 176 | int ret; |
149 | 177 | ||
150 | path = btrfs_alloc_path(); | 178 | path = btrfs_alloc_path(); |
151 | 179 | ||
152 | key.objectid = dir->i_ino; | 180 | if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) { |
153 | btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY); | 181 | key.objectid = root->root_key.objectid; |
154 | key.offset = (u64)-1; | 182 | key.type = BTRFS_ROOT_BACKREF_KEY; |
183 | key.offset = (u64)-1; | ||
184 | root = root->fs_info->tree_root; | ||
185 | } else { | ||
186 | key.objectid = dir->i_ino; | ||
187 | key.type = BTRFS_INODE_REF_KEY; | ||
188 | key.offset = (u64)-1; | ||
189 | } | ||
155 | 190 | ||
156 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 191 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
157 | if (ret < 0) { | 192 | if (ret < 0) |
158 | /* Error */ | 193 | goto fail; |
159 | btrfs_free_path(path); | 194 | |
160 | return ERR_PTR(ret); | 195 | BUG_ON(ret == 0); |
196 | if (path->slots[0] == 0) { | ||
197 | ret = -ENOENT; | ||
198 | goto fail; | ||
161 | } | 199 | } |
200 | |||
201 | path->slots[0]--; | ||
162 | leaf = path->nodes[0]; | 202 | leaf = path->nodes[0]; |
163 | slot = path->slots[0]; | 203 | |
164 | if (ret) { | 204 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
165 | /* btrfs_search_slot() returns the slot where we'd want to | 205 | if (found_key.objectid != key.objectid || found_key.type != key.type) { |
166 | insert a backref for parent inode #0xFFFFFFFFFFFFFFFF. | 206 | ret = -ENOENT; |
167 | The _real_ backref, telling us what the parent inode | 207 | goto fail; |
168 | _actually_ is, will be in the slot _before_ the one | ||
169 | that btrfs_search_slot() returns. */ | ||
170 | if (!slot) { | ||
171 | /* Unless there is _no_ key in the tree before... */ | ||
172 | btrfs_free_path(path); | ||
173 | return ERR_PTR(-EIO); | ||
174 | } | ||
175 | slot--; | ||
176 | } | 208 | } |
177 | 209 | ||
178 | btrfs_item_key_to_cpu(leaf, &key, slot); | 210 | if (found_key.type == BTRFS_ROOT_BACKREF_KEY) { |
211 | ref = btrfs_item_ptr(leaf, path->slots[0], | ||
212 | struct btrfs_root_ref); | ||
213 | key.objectid = btrfs_root_ref_dirid(leaf, ref); | ||
214 | } else { | ||
215 | key.objectid = found_key.offset; | ||
216 | } | ||
179 | btrfs_free_path(path); | 217 | btrfs_free_path(path); |
180 | 218 | ||
181 | if (key.objectid != dir->i_ino || key.type != BTRFS_INODE_REF_KEY) | 219 | if (found_key.type == BTRFS_ROOT_BACKREF_KEY) { |
182 | return ERR_PTR(-EINVAL); | 220 | return btrfs_get_dentry(root->fs_info->sb, key.objectid, |
183 | 221 | found_key.offset, 0, 0); | |
184 | objectid = key.offset; | 222 | } |
185 | |||
186 | /* If we are already at the root of a subvol, return the real root */ | ||
187 | if (objectid == dir->i_ino) | ||
188 | return dget(dir->i_sb->s_root); | ||
189 | 223 | ||
190 | /* Build a new key for the inode item */ | 224 | key.type = BTRFS_INODE_ITEM_KEY; |
191 | key.objectid = objectid; | ||
192 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | ||
193 | key.offset = 0; | 225 | key.offset = 0; |
194 | 226 | dentry = d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root)); | |
195 | return d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root)); | 227 | if (!IS_ERR(dentry)) |
228 | dentry->d_op = &btrfs_dentry_operations; | ||
229 | return dentry; | ||
230 | fail: | ||
231 | btrfs_free_path(path); | ||
232 | return ERR_PTR(ret); | ||
196 | } | 233 | } |
197 | 234 | ||
198 | const struct export_operations btrfs_export_ops = { | 235 | const struct export_operations btrfs_export_ops = { |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 8fc922982183..4bd04f3fa8bb 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -5463,9 +5463,24 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref) | |||
5463 | ret = btrfs_del_root(trans, tree_root, &root->root_key); | 5463 | ret = btrfs_del_root(trans, tree_root, &root->root_key); |
5464 | BUG_ON(ret); | 5464 | BUG_ON(ret); |
5465 | 5465 | ||
5466 | free_extent_buffer(root->node); | 5466 | if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { |
5467 | free_extent_buffer(root->commit_root); | 5467 | ret = btrfs_find_last_root(tree_root, root->root_key.objectid, |
5468 | kfree(root); | 5468 | NULL, NULL); |
5469 | BUG_ON(ret < 0); | ||
5470 | if (ret > 0) { | ||
5471 | ret = btrfs_del_orphan_item(trans, tree_root, | ||
5472 | root->root_key.objectid); | ||
5473 | BUG_ON(ret); | ||
5474 | } | ||
5475 | } | ||
5476 | |||
5477 | if (root->in_radix) { | ||
5478 | btrfs_free_fs_root(tree_root->fs_info, root); | ||
5479 | } else { | ||
5480 | free_extent_buffer(root->node); | ||
5481 | free_extent_buffer(root->commit_root); | ||
5482 | kfree(root); | ||
5483 | } | ||
5469 | out: | 5484 | out: |
5470 | btrfs_end_transaction(trans, tree_root); | 5485 | btrfs_end_transaction(trans, tree_root); |
5471 | kfree(wc); | 5486 | kfree(wc); |
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 | }; | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9b3a88755e51..a13fd556db74 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -230,8 +230,8 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
230 | struct btrfs_root_item root_item; | 230 | struct btrfs_root_item root_item; |
231 | struct btrfs_inode_item *inode_item; | 231 | struct btrfs_inode_item *inode_item; |
232 | struct extent_buffer *leaf; | 232 | struct extent_buffer *leaf; |
233 | struct btrfs_root *new_root = root; | 233 | struct btrfs_root *new_root; |
234 | struct inode *dir; | 234 | struct inode *dir = dentry->d_parent->d_inode; |
235 | int ret; | 235 | int ret; |
236 | int err; | 236 | int err; |
237 | u64 objectid; | 237 | u64 objectid; |
@@ -241,7 +241,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
241 | 241 | ||
242 | ret = btrfs_check_metadata_free_space(root); | 242 | ret = btrfs_check_metadata_free_space(root); |
243 | if (ret) | 243 | if (ret) |
244 | goto fail_commit; | 244 | return ret; |
245 | 245 | ||
246 | trans = btrfs_start_transaction(root, 1); | 246 | trans = btrfs_start_transaction(root, 1); |
247 | BUG_ON(!trans); | 247 | BUG_ON(!trans); |
@@ -304,11 +304,17 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
304 | if (ret) | 304 | if (ret) |
305 | goto fail; | 305 | goto fail; |
306 | 306 | ||
307 | key.offset = (u64)-1; | ||
308 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &key); | ||
309 | BUG_ON(IS_ERR(new_root)); | ||
310 | |||
311 | btrfs_record_root_in_trans(trans, new_root); | ||
312 | |||
313 | ret = btrfs_create_subvol_root(trans, new_root, new_dirid, | ||
314 | BTRFS_I(dir)->block_group); | ||
307 | /* | 315 | /* |
308 | * insert the directory item | 316 | * insert the directory item |
309 | */ | 317 | */ |
310 | key.offset = (u64)-1; | ||
311 | dir = dentry->d_parent->d_inode; | ||
312 | ret = btrfs_set_inode_index(dir, &index); | 318 | ret = btrfs_set_inode_index(dir, &index); |
313 | BUG_ON(ret); | 319 | BUG_ON(ret); |
314 | 320 | ||
@@ -325,30 +331,15 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
325 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, | 331 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, |
326 | objectid, root->root_key.objectid, | 332 | objectid, root->root_key.objectid, |
327 | dir->i_ino, index, name, namelen); | 333 | dir->i_ino, index, name, namelen); |
328 | BUG_ON(ret); | ||
329 | 334 | ||
330 | ret = btrfs_commit_transaction(trans, root); | 335 | BUG_ON(ret); |
331 | if (ret) | ||
332 | goto fail_commit; | ||
333 | |||
334 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &key); | ||
335 | BUG_ON(!new_root); | ||
336 | |||
337 | trans = btrfs_start_transaction(new_root, 1); | ||
338 | BUG_ON(!trans); | ||
339 | |||
340 | ret = btrfs_create_subvol_root(trans, new_root, dentry, new_dirid, | ||
341 | BTRFS_I(dir)->block_group); | ||
342 | if (ret) | ||
343 | goto fail; | ||
344 | 336 | ||
337 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); | ||
345 | fail: | 338 | fail: |
346 | nr = trans->blocks_used; | 339 | nr = trans->blocks_used; |
347 | err = btrfs_commit_transaction(trans, new_root); | 340 | err = btrfs_commit_transaction(trans, root); |
348 | if (err && !ret) | 341 | if (err && !ret) |
349 | ret = err; | 342 | ret = err; |
350 | fail_commit: | ||
351 | btrfs_btree_balance_dirty(root, nr); | ||
352 | return ret; | 343 | return ret; |
353 | } | 344 | } |
354 | 345 | ||
@@ -409,14 +400,15 @@ static inline int btrfs_may_create(struct inode *dir, struct dentry *child) | |||
409 | * sys_mkdirat and vfs_mkdir, but we only do a single component lookup | 400 | * sys_mkdirat and vfs_mkdir, but we only do a single component lookup |
410 | * inside this filesystem so it's quite a bit simpler. | 401 | * inside this filesystem so it's quite a bit simpler. |
411 | */ | 402 | */ |
412 | static noinline int btrfs_mksubvol(struct path *parent, char *name, | 403 | static noinline int btrfs_mksubvol(struct path *parent, |
413 | int mode, int namelen, | 404 | char *name, int namelen, |
414 | struct btrfs_root *snap_src) | 405 | struct btrfs_root *snap_src) |
415 | { | 406 | { |
407 | struct inode *dir = parent->dentry->d_inode; | ||
416 | struct dentry *dentry; | 408 | struct dentry *dentry; |
417 | int error; | 409 | int error; |
418 | 410 | ||
419 | mutex_lock_nested(&parent->dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 411 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
420 | 412 | ||
421 | dentry = lookup_one_len(name, parent->dentry, namelen); | 413 | dentry = lookup_one_len(name, parent->dentry, namelen); |
422 | error = PTR_ERR(dentry); | 414 | error = PTR_ERR(dentry); |
@@ -427,99 +419,39 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name, | |||
427 | if (dentry->d_inode) | 419 | if (dentry->d_inode) |
428 | goto out_dput; | 420 | goto out_dput; |
429 | 421 | ||
430 | if (!IS_POSIXACL(parent->dentry->d_inode)) | ||
431 | mode &= ~current_umask(); | ||
432 | |||
433 | error = mnt_want_write(parent->mnt); | 422 | error = mnt_want_write(parent->mnt); |
434 | if (error) | 423 | if (error) |
435 | goto out_dput; | 424 | goto out_dput; |
436 | 425 | ||
437 | error = btrfs_may_create(parent->dentry->d_inode, dentry); | 426 | error = btrfs_may_create(dir, dentry); |
438 | if (error) | 427 | if (error) |
439 | goto out_drop_write; | 428 | goto out_drop_write; |
440 | 429 | ||
441 | /* | 430 | down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem); |
442 | * Actually perform the low-level subvolume creation after all | 431 | |
443 | * this VFS fuzz. | 432 | if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0) |
444 | * | 433 | goto out_up_read; |
445 | * Eventually we want to pass in an inode under which we create this | 434 | |
446 | * subvolume, but for now all are under the filesystem root. | ||
447 | * | ||
448 | * Also we should pass on the mode eventually to allow creating new | ||
449 | * subvolume with specific mode bits. | ||
450 | */ | ||
451 | if (snap_src) { | 435 | if (snap_src) { |
452 | struct dentry *dir = dentry->d_parent; | 436 | error = create_snapshot(snap_src, dentry, |
453 | struct dentry *test = dir->d_parent; | 437 | name, namelen); |
454 | struct btrfs_path *path = btrfs_alloc_path(); | ||
455 | int ret; | ||
456 | u64 test_oid; | ||
457 | u64 parent_oid = BTRFS_I(dir->d_inode)->root->root_key.objectid; | ||
458 | |||
459 | test_oid = snap_src->root_key.objectid; | ||
460 | |||
461 | ret = btrfs_find_root_ref(snap_src->fs_info->tree_root, | ||
462 | path, parent_oid, test_oid); | ||
463 | if (ret == 0) | ||
464 | goto create; | ||
465 | btrfs_release_path(snap_src->fs_info->tree_root, path); | ||
466 | |||
467 | /* we need to make sure we aren't creating a directory loop | ||
468 | * by taking a snapshot of something that has our current | ||
469 | * subvol in its directory tree. So, this loops through | ||
470 | * the dentries and checks the forward refs for each subvolume | ||
471 | * to see if is references the subvolume where we are | ||
472 | * placing this new snapshot. | ||
473 | */ | ||
474 | while (1) { | ||
475 | if (!test || | ||
476 | dir == snap_src->fs_info->sb->s_root || | ||
477 | test == snap_src->fs_info->sb->s_root || | ||
478 | test->d_inode->i_sb != snap_src->fs_info->sb) { | ||
479 | break; | ||
480 | } | ||
481 | if (S_ISLNK(test->d_inode->i_mode)) { | ||
482 | printk(KERN_INFO "Btrfs symlink in snapshot " | ||
483 | "path, failed\n"); | ||
484 | error = -EMLINK; | ||
485 | btrfs_free_path(path); | ||
486 | goto out_drop_write; | ||
487 | } | ||
488 | test_oid = | ||
489 | BTRFS_I(test->d_inode)->root->root_key.objectid; | ||
490 | ret = btrfs_find_root_ref(snap_src->fs_info->tree_root, | ||
491 | path, test_oid, parent_oid); | ||
492 | if (ret == 0) { | ||
493 | printk(KERN_INFO "Btrfs snapshot creation " | ||
494 | "failed, looping\n"); | ||
495 | error = -EMLINK; | ||
496 | btrfs_free_path(path); | ||
497 | goto out_drop_write; | ||
498 | } | ||
499 | btrfs_release_path(snap_src->fs_info->tree_root, path); | ||
500 | test = test->d_parent; | ||
501 | } | ||
502 | create: | ||
503 | btrfs_free_path(path); | ||
504 | error = create_snapshot(snap_src, dentry, name, namelen); | ||
505 | } else { | 438 | } else { |
506 | error = create_subvol(BTRFS_I(parent->dentry->d_inode)->root, | 439 | error = create_subvol(BTRFS_I(dir)->root, dentry, |
507 | dentry, name, namelen); | 440 | name, namelen); |
508 | } | 441 | } |
509 | if (error) | 442 | if (!error) |
510 | goto out_drop_write; | 443 | fsnotify_mkdir(dir, dentry); |
511 | 444 | out_up_read: | |
512 | fsnotify_mkdir(parent->dentry->d_inode, dentry); | 445 | up_read(&BTRFS_I(dir)->root->fs_info->subvol_sem); |
513 | out_drop_write: | 446 | out_drop_write: |
514 | mnt_drop_write(parent->mnt); | 447 | mnt_drop_write(parent->mnt); |
515 | out_dput: | 448 | out_dput: |
516 | dput(dentry); | 449 | dput(dentry); |
517 | out_unlock: | 450 | out_unlock: |
518 | mutex_unlock(&parent->dentry->d_inode->i_mutex); | 451 | mutex_unlock(&dir->i_mutex); |
519 | return error; | 452 | return error; |
520 | } | 453 | } |
521 | 454 | ||
522 | |||
523 | static int btrfs_defrag_file(struct file *file) | 455 | static int btrfs_defrag_file(struct file *file) |
524 | { | 456 | { |
525 | struct inode *inode = fdentry(file)->d_inode; | 457 | struct inode *inode = fdentry(file)->d_inode; |
@@ -597,7 +529,8 @@ out_unlock: | |||
597 | return 0; | 529 | return 0; |
598 | } | 530 | } |
599 | 531 | ||
600 | static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | 532 | static noinline int btrfs_ioctl_resize(struct btrfs_root *root, |
533 | void __user *arg) | ||
601 | { | 534 | { |
602 | u64 new_size; | 535 | u64 new_size; |
603 | u64 old_size; | 536 | u64 old_size; |
@@ -706,10 +639,7 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
706 | { | 639 | { |
707 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 640 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; |
708 | struct btrfs_ioctl_vol_args *vol_args; | 641 | struct btrfs_ioctl_vol_args *vol_args; |
709 | struct btrfs_dir_item *di; | ||
710 | struct btrfs_path *path; | ||
711 | struct file *src_file; | 642 | struct file *src_file; |
712 | u64 root_dirid; | ||
713 | int namelen; | 643 | int namelen; |
714 | int ret = 0; | 644 | int ret = 0; |
715 | 645 | ||
@@ -727,32 +657,9 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
727 | goto out; | 657 | goto out; |
728 | } | 658 | } |
729 | 659 | ||
730 | path = btrfs_alloc_path(); | ||
731 | if (!path) { | ||
732 | ret = -ENOMEM; | ||
733 | goto out; | ||
734 | } | ||
735 | |||
736 | root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, | ||
737 | di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, | ||
738 | path, root_dirid, | ||
739 | vol_args->name, namelen, 0); | ||
740 | btrfs_free_path(path); | ||
741 | |||
742 | if (di && !IS_ERR(di)) { | ||
743 | ret = -EEXIST; | ||
744 | goto out; | ||
745 | } | ||
746 | |||
747 | if (IS_ERR(di)) { | ||
748 | ret = PTR_ERR(di); | ||
749 | goto out; | ||
750 | } | ||
751 | |||
752 | if (subvol) { | 660 | if (subvol) { |
753 | ret = btrfs_mksubvol(&file->f_path, vol_args->name, | 661 | ret = btrfs_mksubvol(&file->f_path, vol_args->name, namelen, |
754 | file->f_path.dentry->d_inode->i_mode, | 662 | NULL); |
755 | namelen, NULL); | ||
756 | } else { | 663 | } else { |
757 | struct inode *src_inode; | 664 | struct inode *src_inode; |
758 | src_file = fget(vol_args->fd); | 665 | src_file = fget(vol_args->fd); |
@@ -769,17 +676,156 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
769 | fput(src_file); | 676 | fput(src_file); |
770 | goto out; | 677 | goto out; |
771 | } | 678 | } |
772 | ret = btrfs_mksubvol(&file->f_path, vol_args->name, | 679 | ret = btrfs_mksubvol(&file->f_path, vol_args->name, namelen, |
773 | file->f_path.dentry->d_inode->i_mode, | 680 | BTRFS_I(src_inode)->root); |
774 | namelen, BTRFS_I(src_inode)->root); | ||
775 | fput(src_file); | 681 | fput(src_file); |
776 | } | 682 | } |
777 | |||
778 | out: | 683 | out: |
779 | kfree(vol_args); | 684 | kfree(vol_args); |
780 | return ret; | 685 | return ret; |
781 | } | 686 | } |
782 | 687 | ||
688 | /* | ||
689 | * helper to check if the subvolume references other subvolumes | ||
690 | */ | ||
691 | static noinline int may_destroy_subvol(struct btrfs_root *root) | ||
692 | { | ||
693 | struct btrfs_path *path; | ||
694 | struct btrfs_key key; | ||
695 | int ret; | ||
696 | |||
697 | path = btrfs_alloc_path(); | ||
698 | if (!path) | ||
699 | return -ENOMEM; | ||
700 | |||
701 | key.objectid = root->root_key.objectid; | ||
702 | key.type = BTRFS_ROOT_REF_KEY; | ||
703 | key.offset = (u64)-1; | ||
704 | |||
705 | ret = btrfs_search_slot(NULL, root->fs_info->tree_root, | ||
706 | &key, path, 0, 0); | ||
707 | if (ret < 0) | ||
708 | goto out; | ||
709 | BUG_ON(ret == 0); | ||
710 | |||
711 | ret = 0; | ||
712 | if (path->slots[0] > 0) { | ||
713 | path->slots[0]--; | ||
714 | btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); | ||
715 | if (key.objectid == root->root_key.objectid && | ||
716 | key.type == BTRFS_ROOT_REF_KEY) | ||
717 | ret = -ENOTEMPTY; | ||
718 | } | ||
719 | out: | ||
720 | btrfs_free_path(path); | ||
721 | return ret; | ||
722 | } | ||
723 | |||
724 | static noinline int btrfs_ioctl_snap_destroy(struct file *file, | ||
725 | void __user *arg) | ||
726 | { | ||
727 | struct dentry *parent = fdentry(file); | ||
728 | struct dentry *dentry; | ||
729 | struct inode *dir = parent->d_inode; | ||
730 | struct inode *inode; | ||
731 | struct btrfs_root *root = BTRFS_I(dir)->root; | ||
732 | struct btrfs_root *dest = NULL; | ||
733 | struct btrfs_ioctl_vol_args *vol_args; | ||
734 | struct btrfs_trans_handle *trans; | ||
735 | int namelen; | ||
736 | int ret; | ||
737 | int err = 0; | ||
738 | |||
739 | if (!capable(CAP_SYS_ADMIN)) | ||
740 | return -EPERM; | ||
741 | |||
742 | vol_args = memdup_user(arg, sizeof(*vol_args)); | ||
743 | if (IS_ERR(vol_args)) | ||
744 | return PTR_ERR(vol_args); | ||
745 | |||
746 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | ||
747 | namelen = strlen(vol_args->name); | ||
748 | if (strchr(vol_args->name, '/') || | ||
749 | strncmp(vol_args->name, "..", namelen) == 0) { | ||
750 | err = -EINVAL; | ||
751 | goto out; | ||
752 | } | ||
753 | |||
754 | err = mnt_want_write(file->f_path.mnt); | ||
755 | if (err) | ||
756 | goto out; | ||
757 | |||
758 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | ||
759 | dentry = lookup_one_len(vol_args->name, parent, namelen); | ||
760 | if (IS_ERR(dentry)) { | ||
761 | err = PTR_ERR(dentry); | ||
762 | goto out_unlock_dir; | ||
763 | } | ||
764 | |||
765 | if (!dentry->d_inode) { | ||
766 | err = -ENOENT; | ||
767 | goto out_dput; | ||
768 | } | ||
769 | |||
770 | inode = dentry->d_inode; | ||
771 | if (inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) { | ||
772 | err = -EINVAL; | ||
773 | goto out_dput; | ||
774 | } | ||
775 | |||
776 | dest = BTRFS_I(inode)->root; | ||
777 | |||
778 | mutex_lock(&inode->i_mutex); | ||
779 | err = d_invalidate(dentry); | ||
780 | if (err) | ||
781 | goto out_unlock; | ||
782 | |||
783 | down_write(&root->fs_info->subvol_sem); | ||
784 | |||
785 | err = may_destroy_subvol(dest); | ||
786 | if (err) | ||
787 | goto out_up_write; | ||
788 | |||
789 | trans = btrfs_start_transaction(root, 1); | ||
790 | ret = btrfs_unlink_subvol(trans, root, dir, | ||
791 | dest->root_key.objectid, | ||
792 | dentry->d_name.name, | ||
793 | dentry->d_name.len); | ||
794 | BUG_ON(ret); | ||
795 | |||
796 | btrfs_record_root_in_trans(trans, dest); | ||
797 | |||
798 | memset(&dest->root_item.drop_progress, 0, | ||
799 | sizeof(dest->root_item.drop_progress)); | ||
800 | dest->root_item.drop_level = 0; | ||
801 | btrfs_set_root_refs(&dest->root_item, 0); | ||
802 | |||
803 | ret = btrfs_insert_orphan_item(trans, | ||
804 | root->fs_info->tree_root, | ||
805 | dest->root_key.objectid); | ||
806 | BUG_ON(ret); | ||
807 | |||
808 | ret = btrfs_commit_transaction(trans, root); | ||
809 | BUG_ON(ret); | ||
810 | inode->i_flags |= S_DEAD; | ||
811 | out_up_write: | ||
812 | up_write(&root->fs_info->subvol_sem); | ||
813 | out_unlock: | ||
814 | mutex_unlock(&inode->i_mutex); | ||
815 | if (!err) { | ||
816 | btrfs_invalidate_inodes(dest); | ||
817 | d_delete(dentry); | ||
818 | } | ||
819 | out_dput: | ||
820 | dput(dentry); | ||
821 | out_unlock_dir: | ||
822 | mutex_unlock(&dir->i_mutex); | ||
823 | mnt_drop_write(file->f_path.mnt); | ||
824 | out: | ||
825 | kfree(vol_args); | ||
826 | return err; | ||
827 | } | ||
828 | |||
783 | static int btrfs_ioctl_defrag(struct file *file) | 829 | static int btrfs_ioctl_defrag(struct file *file) |
784 | { | 830 | { |
785 | struct inode *inode = fdentry(file)->d_inode; | 831 | struct inode *inode = fdentry(file)->d_inode; |
@@ -853,8 +899,8 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | |||
853 | return ret; | 899 | return ret; |
854 | } | 900 | } |
855 | 901 | ||
856 | static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | 902 | static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, |
857 | u64 off, u64 olen, u64 destoff) | 903 | u64 off, u64 olen, u64 destoff) |
858 | { | 904 | { |
859 | struct inode *inode = fdentry(file)->d_inode; | 905 | struct inode *inode = fdentry(file)->d_inode; |
860 | struct btrfs_root *root = BTRFS_I(inode)->root; | 906 | struct btrfs_root *root = BTRFS_I(inode)->root; |
@@ -1246,6 +1292,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
1246 | return btrfs_ioctl_snap_create(file, argp, 0); | 1292 | return btrfs_ioctl_snap_create(file, argp, 0); |
1247 | case BTRFS_IOC_SUBVOL_CREATE: | 1293 | case BTRFS_IOC_SUBVOL_CREATE: |
1248 | return btrfs_ioctl_snap_create(file, argp, 1); | 1294 | return btrfs_ioctl_snap_create(file, argp, 1); |
1295 | case BTRFS_IOC_SNAP_DESTROY: | ||
1296 | return btrfs_ioctl_snap_destroy(file, argp); | ||
1249 | case BTRFS_IOC_DEFRAG: | 1297 | case BTRFS_IOC_DEFRAG: |
1250 | return btrfs_ioctl_defrag(file); | 1298 | return btrfs_ioctl_defrag(file); |
1251 | case BTRFS_IOC_RESIZE: | 1299 | case BTRFS_IOC_RESIZE: |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index b320b103fa13..bc49914475eb 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -65,5 +65,6 @@ struct btrfs_ioctl_clone_range_args { | |||
65 | 65 | ||
66 | #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ | 66 | #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ |
67 | struct btrfs_ioctl_vol_args) | 67 | struct btrfs_ioctl_vol_args) |
68 | 68 | #define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \ | |
69 | struct btrfs_ioctl_vol_args) | ||
69 | #endif | 70 | #endif |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 3be16ccc7eea..48a504260635 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -3203,6 +3203,7 @@ static int check_extent_flags(u64 flags) | |||
3203 | return 0; | 3203 | return 0; |
3204 | } | 3204 | } |
3205 | 3205 | ||
3206 | |||
3206 | static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | 3207 | static noinline_for_stack int relocate_block_group(struct reloc_control *rc) |
3207 | { | 3208 | { |
3208 | struct rb_root blocks = RB_ROOT; | 3209 | struct rb_root blocks = RB_ROOT; |
@@ -3220,6 +3221,9 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3220 | if (!path) | 3221 | if (!path) |
3221 | return -ENOMEM; | 3222 | return -ENOMEM; |
3222 | 3223 | ||
3224 | rc->extents_found = 0; | ||
3225 | rc->extents_skipped = 0; | ||
3226 | |||
3223 | rc->search_start = rc->block_group->key.objectid; | 3227 | rc->search_start = rc->block_group->key.objectid; |
3224 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, | 3228 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, |
3225 | GFP_NOFS); | 3229 | GFP_NOFS); |
@@ -3475,14 +3479,15 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
3475 | btrfs_wait_ordered_extents(fs_info->tree_root, 0); | 3479 | btrfs_wait_ordered_extents(fs_info->tree_root, 0); |
3476 | 3480 | ||
3477 | while (1) { | 3481 | while (1) { |
3478 | mutex_lock(&fs_info->cleaner_mutex); | ||
3479 | btrfs_clean_old_snapshots(fs_info->tree_root); | ||
3480 | mutex_unlock(&fs_info->cleaner_mutex); | ||
3481 | |||
3482 | rc->extents_found = 0; | 3482 | rc->extents_found = 0; |
3483 | rc->extents_skipped = 0; | 3483 | rc->extents_skipped = 0; |
3484 | 3484 | ||
3485 | mutex_lock(&fs_info->cleaner_mutex); | ||
3486 | |||
3487 | btrfs_clean_old_snapshots(fs_info->tree_root); | ||
3485 | ret = relocate_block_group(rc); | 3488 | ret = relocate_block_group(rc); |
3489 | |||
3490 | mutex_unlock(&fs_info->cleaner_mutex); | ||
3486 | if (ret < 0) { | 3491 | if (ret < 0) { |
3487 | err = ret; | 3492 | err = ret; |
3488 | break; | 3493 | break; |
@@ -3530,6 +3535,26 @@ out: | |||
3530 | return err; | 3535 | return err; |
3531 | } | 3536 | } |
3532 | 3537 | ||
3538 | static noinline_for_stack int mark_garbage_root(struct btrfs_root *root) | ||
3539 | { | ||
3540 | struct btrfs_trans_handle *trans; | ||
3541 | int ret; | ||
3542 | |||
3543 | trans = btrfs_start_transaction(root->fs_info->tree_root, 1); | ||
3544 | |||
3545 | memset(&root->root_item.drop_progress, 0, | ||
3546 | sizeof(root->root_item.drop_progress)); | ||
3547 | root->root_item.drop_level = 0; | ||
3548 | btrfs_set_root_refs(&root->root_item, 0); | ||
3549 | ret = btrfs_update_root(trans, root->fs_info->tree_root, | ||
3550 | &root->root_key, &root->root_item); | ||
3551 | BUG_ON(ret); | ||
3552 | |||
3553 | ret = btrfs_end_transaction(trans, root->fs_info->tree_root); | ||
3554 | BUG_ON(ret); | ||
3555 | return 0; | ||
3556 | } | ||
3557 | |||
3533 | /* | 3558 | /* |
3534 | * recover relocation interrupted by system crash. | 3559 | * recover relocation interrupted by system crash. |
3535 | * | 3560 | * |
@@ -3589,8 +3614,12 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
3589 | fs_root = read_fs_root(root->fs_info, | 3614 | fs_root = read_fs_root(root->fs_info, |
3590 | reloc_root->root_key.offset); | 3615 | reloc_root->root_key.offset); |
3591 | if (IS_ERR(fs_root)) { | 3616 | if (IS_ERR(fs_root)) { |
3592 | err = PTR_ERR(fs_root); | 3617 | ret = PTR_ERR(fs_root); |
3593 | goto out; | 3618 | if (ret != -ENOENT) { |
3619 | err = ret; | ||
3620 | goto out; | ||
3621 | } | ||
3622 | mark_garbage_root(reloc_root); | ||
3594 | } | 3623 | } |
3595 | } | 3624 | } |
3596 | 3625 | ||
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 5ef72599a581..9351428f30e2 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -94,17 +94,23 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |||
94 | goto out; | 94 | goto out; |
95 | 95 | ||
96 | BUG_ON(ret == 0); | 96 | BUG_ON(ret == 0); |
97 | if (path->slots[0] == 0) { | ||
98 | ret = 1; | ||
99 | goto out; | ||
100 | } | ||
97 | l = path->nodes[0]; | 101 | l = path->nodes[0]; |
98 | BUG_ON(path->slots[0] == 0); | ||
99 | slot = path->slots[0] - 1; | 102 | slot = path->slots[0] - 1; |
100 | btrfs_item_key_to_cpu(l, &found_key, slot); | 103 | btrfs_item_key_to_cpu(l, &found_key, slot); |
101 | if (found_key.objectid != objectid) { | 104 | if (found_key.objectid != objectid || |
105 | found_key.type != BTRFS_ROOT_ITEM_KEY) { | ||
102 | ret = 1; | 106 | ret = 1; |
103 | goto out; | 107 | goto out; |
104 | } | 108 | } |
105 | read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), | 109 | if (item) |
106 | sizeof(*item)); | 110 | read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot), |
107 | memcpy(key, &found_key, sizeof(found_key)); | 111 | sizeof(*item)); |
112 | if (key) | ||
113 | memcpy(key, &found_key, sizeof(found_key)); | ||
108 | ret = 0; | 114 | ret = 0; |
109 | out: | 115 | out: |
110 | btrfs_free_path(path); | 116 | btrfs_free_path(path); |
@@ -249,6 +255,59 @@ err: | |||
249 | return ret; | 255 | return ret; |
250 | } | 256 | } |
251 | 257 | ||
258 | int btrfs_find_orphan_roots(struct btrfs_root *tree_root) | ||
259 | { | ||
260 | struct extent_buffer *leaf; | ||
261 | struct btrfs_path *path; | ||
262 | struct btrfs_key key; | ||
263 | int err = 0; | ||
264 | int ret; | ||
265 | |||
266 | path = btrfs_alloc_path(); | ||
267 | if (!path) | ||
268 | return -ENOMEM; | ||
269 | |||
270 | key.objectid = BTRFS_ORPHAN_OBJECTID; | ||
271 | key.type = BTRFS_ORPHAN_ITEM_KEY; | ||
272 | key.offset = 0; | ||
273 | |||
274 | while (1) { | ||
275 | ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); | ||
276 | if (ret < 0) { | ||
277 | err = ret; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | leaf = path->nodes[0]; | ||
282 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | ||
283 | ret = btrfs_next_leaf(tree_root, path); | ||
284 | if (ret < 0) | ||
285 | err = ret; | ||
286 | if (ret != 0) | ||
287 | break; | ||
288 | leaf = path->nodes[0]; | ||
289 | } | ||
290 | |||
291 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
292 | btrfs_release_path(tree_root, path); | ||
293 | |||
294 | if (key.objectid != BTRFS_ORPHAN_OBJECTID || | ||
295 | key.type != BTRFS_ORPHAN_ITEM_KEY) | ||
296 | break; | ||
297 | |||
298 | ret = btrfs_find_dead_roots(tree_root, key.offset); | ||
299 | if (ret) { | ||
300 | err = ret; | ||
301 | break; | ||
302 | } | ||
303 | |||
304 | key.offset++; | ||
305 | } | ||
306 | |||
307 | btrfs_free_path(path); | ||
308 | return err; | ||
309 | } | ||
310 | |||
252 | /* drop the root item for 'key' from 'root' */ | 311 | /* drop the root item for 'key' from 'root' */ |
253 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 312 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
254 | struct btrfs_key *key) | 313 | struct btrfs_key *key) |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 6d6d06cb6dfc..0242c8babae9 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -676,6 +676,7 @@ static int btrfs_unfreeze(struct super_block *sb) | |||
676 | } | 676 | } |
677 | 677 | ||
678 | static struct super_operations btrfs_super_ops = { | 678 | static struct super_operations btrfs_super_ops = { |
679 | .drop_inode = btrfs_drop_inode, | ||
679 | .delete_inode = btrfs_delete_inode, | 680 | .delete_inode = btrfs_delete_inode, |
680 | .put_super = btrfs_put_super, | 681 | .put_super = btrfs_put_super, |
681 | .sync_fs = btrfs_sync_fs, | 682 | .sync_fs = btrfs_sync_fs, |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 915077725fea..88f866f85e7a 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -104,7 +104,6 @@ static noinline int record_root_in_trans(struct btrfs_trans_handle *trans, | |||
104 | { | 104 | { |
105 | if (root->ref_cows && root->last_trans < trans->transid) { | 105 | if (root->ref_cows && root->last_trans < trans->transid) { |
106 | WARN_ON(root == root->fs_info->extent_root); | 106 | WARN_ON(root == root->fs_info->extent_root); |
107 | WARN_ON(root->root_item.refs == 0); | ||
108 | WARN_ON(root->commit_root != root->node); | 107 | WARN_ON(root->commit_root != root->node); |
109 | 108 | ||
110 | radix_tree_tag_set(&root->fs_info->fs_roots_radix, | 109 | radix_tree_tag_set(&root->fs_info->fs_roots_radix, |
@@ -1078,8 +1077,13 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root) | |||
1078 | 1077 | ||
1079 | while (!list_empty(&list)) { | 1078 | while (!list_empty(&list)) { |
1080 | root = list_entry(list.next, struct btrfs_root, root_list); | 1079 | root = list_entry(list.next, struct btrfs_root, root_list); |
1081 | list_del_init(&root->root_list); | 1080 | list_del(&root->root_list); |
1082 | btrfs_drop_snapshot(root, 0); | 1081 | |
1082 | if (btrfs_header_backref_rev(root->node) < | ||
1083 | BTRFS_MIXED_BACKREF_REV) | ||
1084 | btrfs_drop_snapshot(root, 0); | ||
1085 | else | ||
1086 | btrfs_drop_snapshot(root, 1); | ||
1083 | } | 1087 | } |
1084 | return 0; | 1088 | return 0; |
1085 | } | 1089 | } |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 6e674d76186d..4d7d9abef42f 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2841,7 +2841,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, | |||
2841 | if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb) | 2841 | if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb) |
2842 | break; | 2842 | break; |
2843 | 2843 | ||
2844 | if (parent == sb->s_root) | 2844 | if (IS_ROOT(parent)) |
2845 | break; | 2845 | break; |
2846 | 2846 | ||
2847 | parent = parent->d_parent; | 2847 | parent = parent->d_parent; |
@@ -2880,6 +2880,12 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
2880 | goto end_no_trans; | 2880 | goto end_no_trans; |
2881 | } | 2881 | } |
2882 | 2882 | ||
2883 | if (root != BTRFS_I(inode)->root || | ||
2884 | btrfs_root_refs(&root->root_item) == 0) { | ||
2885 | ret = 1; | ||
2886 | goto end_no_trans; | ||
2887 | } | ||
2888 | |||
2883 | ret = check_parent_dirs_for_sync(trans, inode, parent, | 2889 | ret = check_parent_dirs_for_sync(trans, inode, parent, |
2884 | sb, last_committed); | 2890 | sb, last_committed); |
2885 | if (ret) | 2891 | if (ret) |
@@ -2907,12 +2913,15 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
2907 | break; | 2913 | break; |
2908 | 2914 | ||
2909 | inode = parent->d_inode; | 2915 | inode = parent->d_inode; |
2916 | if (root != BTRFS_I(inode)->root) | ||
2917 | break; | ||
2918 | |||
2910 | if (BTRFS_I(inode)->generation > | 2919 | if (BTRFS_I(inode)->generation > |
2911 | root->fs_info->last_trans_committed) { | 2920 | root->fs_info->last_trans_committed) { |
2912 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 2921 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
2913 | BUG_ON(ret); | 2922 | BUG_ON(ret); |
2914 | } | 2923 | } |
2915 | if (parent == sb->s_root) | 2924 | if (IS_ROOT(parent)) |
2916 | break; | 2925 | break; |
2917 | 2926 | ||
2918 | parent = parent->d_parent; | 2927 | parent = parent->d_parent; |