diff options
| author | Yan, Zheng <zheng.yan@oracle.com> | 2010-05-16 10:49:58 -0400 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2010-05-25 10:34:52 -0400 |
| commit | d68fc57b7e3245cfacf2e3b47acfed1946a11786 (patch) | |
| tree | c2572fcd935017440c8370c8a12ceb49a7fc4f1f | |
| parent | 8929ecfa50f266163832eeacfbc3642ed5eb83b6 (diff) | |
Btrfs: Metadata reservation for orphan inodes
reserve metadata space for handling orphan inodes
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
| -rw-r--r-- | fs/btrfs/btrfs_inode.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 16 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 32 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 28 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 299 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 10 | ||||
| -rw-r--r-- | fs/btrfs/root-tree.c | 23 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 16 |
9 files changed, 365 insertions, 66 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 40510d9351f5..6ad63f17eca0 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
| @@ -151,6 +151,7 @@ struct btrfs_inode { | |||
| 151 | * of these. | 151 | * of these. |
| 152 | */ | 152 | */ |
| 153 | unsigned ordered_data_close:1; | 153 | unsigned ordered_data_close:1; |
| 154 | unsigned orphan_meta_reserved:1; | ||
| 154 | unsigned dummy_inode:1; | 155 | unsigned dummy_inode:1; |
| 155 | 156 | ||
| 156 | /* | 157 | /* |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 504d5daf2f1c..fc324f9fcb42 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -1069,7 +1069,6 @@ struct btrfs_root { | |||
| 1069 | int ref_cows; | 1069 | int ref_cows; |
| 1070 | int track_dirty; | 1070 | int track_dirty; |
| 1071 | int in_radix; | 1071 | int in_radix; |
| 1072 | int clean_orphans; | ||
| 1073 | 1072 | ||
| 1074 | u64 defrag_trans_start; | 1073 | u64 defrag_trans_start; |
| 1075 | struct btrfs_key defrag_progress; | 1074 | struct btrfs_key defrag_progress; |
| @@ -1083,8 +1082,11 @@ struct btrfs_root { | |||
| 1083 | 1082 | ||
| 1084 | struct list_head root_list; | 1083 | struct list_head root_list; |
| 1085 | 1084 | ||
| 1086 | spinlock_t list_lock; | 1085 | spinlock_t orphan_lock; |
| 1087 | struct list_head orphan_list; | 1086 | struct list_head orphan_list; |
| 1087 | struct btrfs_block_rsv *orphan_block_rsv; | ||
| 1088 | int orphan_item_inserted; | ||
| 1089 | int orphan_cleanup_state; | ||
| 1088 | 1090 | ||
| 1089 | spinlock_t inode_lock; | 1091 | spinlock_t inode_lock; |
| 1090 | /* red-black tree that keeps track of in-memory inodes */ | 1092 | /* red-black tree that keeps track of in-memory inodes */ |
| @@ -2080,6 +2082,9 @@ int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans, | |||
| 2080 | int num_items, int *retries); | 2082 | int num_items, int *retries); |
| 2081 | void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, | 2083 | void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, |
| 2082 | struct btrfs_root *root); | 2084 | struct btrfs_root *root); |
| 2085 | int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans, | ||
| 2086 | struct inode *inode); | ||
| 2087 | void btrfs_orphan_release_metadata(struct inode *inode); | ||
| 2083 | int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, | 2088 | int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, |
| 2084 | struct btrfs_pending_snapshot *pending); | 2089 | struct btrfs_pending_snapshot *pending); |
| 2085 | int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes); | 2090 | int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes); |
| @@ -2404,6 +2409,13 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
| 2404 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); | 2409 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); |
| 2405 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); | 2410 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); |
| 2406 | void btrfs_orphan_cleanup(struct btrfs_root *root); | 2411 | void btrfs_orphan_cleanup(struct btrfs_root *root); |
| 2412 | void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans, | ||
| 2413 | struct btrfs_pending_snapshot *pending, | ||
| 2414 | u64 *bytes_to_reserve); | ||
| 2415 | void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans, | ||
| 2416 | struct btrfs_pending_snapshot *pending); | ||
| 2417 | void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans, | ||
| 2418 | struct btrfs_root *root); | ||
| 2407 | int btrfs_cont_expand(struct inode *inode, loff_t size); | 2419 | int btrfs_cont_expand(struct inode *inode, loff_t size); |
| 2408 | int btrfs_invalidate_inodes(struct btrfs_root *root); | 2420 | int btrfs_invalidate_inodes(struct btrfs_root *root); |
| 2409 | void btrfs_add_delayed_iput(struct inode *inode); | 2421 | void btrfs_add_delayed_iput(struct inode *inode); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 309d8c08a640..82955b73a962 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -894,7 +894,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
| 894 | root->ref_cows = 0; | 894 | root->ref_cows = 0; |
| 895 | root->track_dirty = 0; | 895 | root->track_dirty = 0; |
| 896 | root->in_radix = 0; | 896 | root->in_radix = 0; |
| 897 | root->clean_orphans = 0; | 897 | root->orphan_item_inserted = 0; |
| 898 | root->orphan_cleanup_state = 0; | ||
| 898 | 899 | ||
| 899 | root->fs_info = fs_info; | 900 | root->fs_info = fs_info; |
| 900 | root->objectid = objectid; | 901 | root->objectid = objectid; |
| @@ -904,12 +905,13 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
| 904 | root->in_sysfs = 0; | 905 | root->in_sysfs = 0; |
| 905 | root->inode_tree = RB_ROOT; | 906 | root->inode_tree = RB_ROOT; |
| 906 | root->block_rsv = NULL; | 907 | root->block_rsv = NULL; |
| 908 | root->orphan_block_rsv = NULL; | ||
| 907 | 909 | ||
| 908 | INIT_LIST_HEAD(&root->dirty_list); | 910 | INIT_LIST_HEAD(&root->dirty_list); |
| 909 | INIT_LIST_HEAD(&root->orphan_list); | 911 | INIT_LIST_HEAD(&root->orphan_list); |
| 910 | INIT_LIST_HEAD(&root->root_list); | 912 | INIT_LIST_HEAD(&root->root_list); |
| 911 | spin_lock_init(&root->node_lock); | 913 | spin_lock_init(&root->node_lock); |
| 912 | spin_lock_init(&root->list_lock); | 914 | spin_lock_init(&root->orphan_lock); |
| 913 | spin_lock_init(&root->inode_lock); | 915 | spin_lock_init(&root->inode_lock); |
| 914 | spin_lock_init(&root->accounting_lock); | 916 | spin_lock_init(&root->accounting_lock); |
| 915 | mutex_init(&root->objectid_mutex); | 917 | mutex_init(&root->objectid_mutex); |
| @@ -1193,19 +1195,23 @@ again: | |||
| 1193 | if (root) | 1195 | if (root) |
| 1194 | return root; | 1196 | return root; |
| 1195 | 1197 | ||
| 1196 | ret = btrfs_find_orphan_item(fs_info->tree_root, location->objectid); | ||
| 1197 | if (ret == 0) | ||
| 1198 | ret = -ENOENT; | ||
| 1199 | if (ret < 0) | ||
| 1200 | return ERR_PTR(ret); | ||
| 1201 | |||
| 1202 | root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location); | 1198 | root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location); |
| 1203 | if (IS_ERR(root)) | 1199 | if (IS_ERR(root)) |
| 1204 | return root; | 1200 | return root; |
| 1205 | 1201 | ||
| 1206 | WARN_ON(btrfs_root_refs(&root->root_item) == 0); | ||
| 1207 | set_anon_super(&root->anon_super, NULL); | 1202 | set_anon_super(&root->anon_super, NULL); |
| 1208 | 1203 | ||
| 1204 | if (btrfs_root_refs(&root->root_item) == 0) { | ||
| 1205 | ret = -ENOENT; | ||
| 1206 | goto fail; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | ret = btrfs_find_orphan_item(fs_info->tree_root, location->objectid); | ||
| 1210 | if (ret < 0) | ||
| 1211 | goto fail; | ||
| 1212 | if (ret == 0) | ||
| 1213 | root->orphan_item_inserted = 1; | ||
| 1214 | |||
| 1209 | ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); | 1215 | ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); |
| 1210 | if (ret) | 1216 | if (ret) |
| 1211 | goto fail; | 1217 | goto fail; |
| @@ -1214,10 +1220,9 @@ again: | |||
| 1214 | ret = radix_tree_insert(&fs_info->fs_roots_radix, | 1220 | ret = radix_tree_insert(&fs_info->fs_roots_radix, |
| 1215 | (unsigned long)root->root_key.objectid, | 1221 | (unsigned long)root->root_key.objectid, |
| 1216 | root); | 1222 | root); |
| 1217 | if (ret == 0) { | 1223 | if (ret == 0) |
| 1218 | root->in_radix = 1; | 1224 | root->in_radix = 1; |
| 1219 | root->clean_orphans = 1; | 1225 | |
| 1220 | } | ||
| 1221 | spin_unlock(&fs_info->fs_roots_radix_lock); | 1226 | spin_unlock(&fs_info->fs_roots_radix_lock); |
| 1222 | radix_tree_preload_end(); | 1227 | radix_tree_preload_end(); |
| 1223 | if (ret) { | 1228 | if (ret) { |
| @@ -1981,6 +1986,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1981 | BUG_ON(ret); | 1986 | BUG_ON(ret); |
| 1982 | 1987 | ||
| 1983 | if (!(sb->s_flags & MS_RDONLY)) { | 1988 | if (!(sb->s_flags & MS_RDONLY)) { |
| 1989 | ret = btrfs_cleanup_fs_roots(fs_info); | ||
| 1990 | BUG_ON(ret); | ||
| 1991 | |||
| 1984 | ret = btrfs_recover_relocation(tree_root); | 1992 | ret = btrfs_recover_relocation(tree_root); |
| 1985 | if (ret < 0) { | 1993 | if (ret < 0) { |
| 1986 | printk(KERN_WARNING | 1994 | printk(KERN_WARNING |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index cb814a71800d..a713f69f0c7a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3626,6 +3626,34 @@ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, | |||
| 3626 | trans->bytes_reserved = 0; | 3626 | trans->bytes_reserved = 0; |
| 3627 | } | 3627 | } |
| 3628 | 3628 | ||
| 3629 | int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans, | ||
| 3630 | struct inode *inode) | ||
| 3631 | { | ||
| 3632 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 3633 | struct btrfs_block_rsv *src_rsv = get_block_rsv(trans, root); | ||
| 3634 | struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv; | ||
| 3635 | |||
| 3636 | /* | ||
| 3637 | * one for deleting orphan item, one for updating inode and | ||
| 3638 | * two for calling btrfs_truncate_inode_items. | ||
| 3639 | * | ||
| 3640 | * btrfs_truncate_inode_items is a delete operation, it frees | ||
| 3641 | * more space than it uses in most cases. So two units of | ||
| 3642 | * metadata space should be enough for calling it many times. | ||
| 3643 | * If all of the metadata space is used, we can commit | ||
| 3644 | * transaction and use space it freed. | ||
| 3645 | */ | ||
| 3646 | u64 num_bytes = calc_trans_metadata_size(root, 4); | ||
| 3647 | return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes); | ||
| 3648 | } | ||
| 3649 | |||
| 3650 | void btrfs_orphan_release_metadata(struct inode *inode) | ||
| 3651 | { | ||
| 3652 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 3653 | u64 num_bytes = calc_trans_metadata_size(root, 4); | ||
| 3654 | btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes); | ||
| 3655 | } | ||
| 3656 | |||
| 3629 | int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, | 3657 | int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, |
| 3630 | struct btrfs_pending_snapshot *pending) | 3658 | struct btrfs_pending_snapshot *pending) |
| 3631 | { | 3659 | { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f9c40b839452..bef69bedf3cf 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -1982,32 +1982,196 @@ void btrfs_run_delayed_iputs(struct btrfs_root *root) | |||
| 1982 | } | 1982 | } |
| 1983 | 1983 | ||
| 1984 | /* | 1984 | /* |
| 1985 | * calculate extra metadata reservation when snapshotting a subvolume | ||
| 1986 | * contains orphan files. | ||
| 1987 | */ | ||
| 1988 | void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans, | ||
| 1989 | struct btrfs_pending_snapshot *pending, | ||
| 1990 | u64 *bytes_to_reserve) | ||
| 1991 | { | ||
| 1992 | struct btrfs_root *root; | ||
| 1993 | struct btrfs_block_rsv *block_rsv; | ||
| 1994 | u64 num_bytes; | ||
| 1995 | int index; | ||
| 1996 | |||
| 1997 | root = pending->root; | ||
| 1998 | if (!root->orphan_block_rsv || list_empty(&root->orphan_list)) | ||
| 1999 | return; | ||
| 2000 | |||
| 2001 | block_rsv = root->orphan_block_rsv; | ||
| 2002 | |||
| 2003 | /* orphan block reservation for the snapshot */ | ||
| 2004 | num_bytes = block_rsv->size; | ||
| 2005 | |||
| 2006 | /* | ||
| 2007 | * after the snapshot is created, COWing tree blocks may use more | ||
| 2008 | * space than it frees. So we should make sure there is enough | ||
| 2009 | * reserved space. | ||
| 2010 | */ | ||
| 2011 | index = trans->transid & 0x1; | ||
| 2012 | if (block_rsv->reserved + block_rsv->freed[index] < block_rsv->size) { | ||
| 2013 | num_bytes += block_rsv->size - | ||
| 2014 | (block_rsv->reserved + block_rsv->freed[index]); | ||
| 2015 | } | ||
| 2016 | |||
| 2017 | *bytes_to_reserve += num_bytes; | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans, | ||
| 2021 | struct btrfs_pending_snapshot *pending) | ||
| 2022 | { | ||
| 2023 | struct btrfs_root *root = pending->root; | ||
| 2024 | struct btrfs_root *snap = pending->snap; | ||
| 2025 | struct btrfs_block_rsv *block_rsv; | ||
| 2026 | u64 num_bytes; | ||
| 2027 | int index; | ||
| 2028 | int ret; | ||
| 2029 | |||
| 2030 | if (!root->orphan_block_rsv || list_empty(&root->orphan_list)) | ||
| 2031 | return; | ||
| 2032 | |||
| 2033 | /* refill source subvolume's orphan block reservation */ | ||
| 2034 | block_rsv = root->orphan_block_rsv; | ||
| 2035 | index = trans->transid & 0x1; | ||
| 2036 | if (block_rsv->reserved + block_rsv->freed[index] < block_rsv->size) { | ||
| 2037 | num_bytes = block_rsv->size - | ||
| 2038 | (block_rsv->reserved + block_rsv->freed[index]); | ||
| 2039 | ret = btrfs_block_rsv_migrate(&pending->block_rsv, | ||
| 2040 | root->orphan_block_rsv, | ||
| 2041 | num_bytes); | ||
| 2042 | BUG_ON(ret); | ||
| 2043 | } | ||
| 2044 | |||
| 2045 | /* setup orphan block reservation for the snapshot */ | ||
| 2046 | block_rsv = btrfs_alloc_block_rsv(snap); | ||
| 2047 | BUG_ON(!block_rsv); | ||
| 2048 | |||
| 2049 | btrfs_add_durable_block_rsv(root->fs_info, block_rsv); | ||
| 2050 | snap->orphan_block_rsv = block_rsv; | ||
| 2051 | |||
| 2052 | num_bytes = root->orphan_block_rsv->size; | ||
| 2053 | ret = btrfs_block_rsv_migrate(&pending->block_rsv, | ||
| 2054 | block_rsv, num_bytes); | ||
| 2055 | BUG_ON(ret); | ||
| 2056 | |||
| 2057 | #if 0 | ||
| 2058 | /* insert orphan item for the snapshot */ | ||
| 2059 | WARN_ON(!root->orphan_item_inserted); | ||
| 2060 | ret = btrfs_insert_orphan_item(trans, root->fs_info->tree_root, | ||
| 2061 | snap->root_key.objectid); | ||
| 2062 | BUG_ON(ret); | ||
| 2063 | snap->orphan_item_inserted = 1; | ||
| 2064 | #endif | ||
| 2065 | } | ||
| 2066 | |||
| 2067 | enum btrfs_orphan_cleanup_state { | ||
| 2068 | ORPHAN_CLEANUP_STARTED = 1, | ||
| 2069 | ORPHAN_CLEANUP_DONE = 2, | ||
| 2070 | }; | ||
| 2071 | |||
| 2072 | /* | ||
| 2073 | * This is called in transaction commmit time. If there are no orphan | ||
| 2074 | * files in the subvolume, it removes orphan item and frees block_rsv | ||
| 2075 | * structure. | ||
| 2076 | */ | ||
| 2077 | void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans, | ||
| 2078 | struct btrfs_root *root) | ||
| 2079 | { | ||
| 2080 | int ret; | ||
| 2081 | |||
| 2082 | if (!list_empty(&root->orphan_list) || | ||
| 2083 | root->orphan_cleanup_state != ORPHAN_CLEANUP_DONE) | ||
| 2084 | return; | ||
| 2085 | |||
| 2086 | if (root->orphan_item_inserted && | ||
| 2087 | btrfs_root_refs(&root->root_item) > 0) { | ||
| 2088 | ret = btrfs_del_orphan_item(trans, root->fs_info->tree_root, | ||
| 2089 | root->root_key.objectid); | ||
| 2090 | BUG_ON(ret); | ||
| 2091 | root->orphan_item_inserted = 0; | ||
| 2092 | } | ||
| 2093 | |||
| 2094 | if (root->orphan_block_rsv) { | ||
| 2095 | WARN_ON(root->orphan_block_rsv->size > 0); | ||
| 2096 | btrfs_free_block_rsv(root, root->orphan_block_rsv); | ||
| 2097 | root->orphan_block_rsv = NULL; | ||
| 2098 | } | ||
| 2099 | } | ||
| 2100 | |||
| 2101 | /* | ||
| 1985 | * This creates an orphan entry for the given inode in case something goes | 2102 | * This creates an orphan entry for the given inode in case something goes |
| 1986 | * wrong in the middle of an unlink/truncate. | 2103 | * wrong in the middle of an unlink/truncate. |
| 2104 | * | ||
| 2105 | * NOTE: caller of this function should reserve 5 units of metadata for | ||
| 2106 | * this function. | ||
| 1987 | */ | 2107 | */ |
| 1988 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | 2108 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) |
| 1989 | { | 2109 | { |
| 1990 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2110 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1991 | int ret = 0; | 2111 | struct btrfs_block_rsv *block_rsv = NULL; |
| 2112 | int reserve = 0; | ||
| 2113 | int insert = 0; | ||
| 2114 | int ret; | ||
| 1992 | 2115 | ||
| 1993 | spin_lock(&root->list_lock); | 2116 | if (!root->orphan_block_rsv) { |
| 2117 | block_rsv = btrfs_alloc_block_rsv(root); | ||
| 2118 | BUG_ON(!block_rsv); | ||
| 2119 | } | ||
| 1994 | 2120 | ||
| 1995 | /* already on the orphan list, we're good */ | 2121 | spin_lock(&root->orphan_lock); |
| 1996 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { | 2122 | if (!root->orphan_block_rsv) { |
| 1997 | spin_unlock(&root->list_lock); | 2123 | root->orphan_block_rsv = block_rsv; |
| 1998 | return 0; | 2124 | } else if (block_rsv) { |
| 2125 | btrfs_free_block_rsv(root, block_rsv); | ||
| 2126 | block_rsv = NULL; | ||
| 1999 | } | 2127 | } |
| 2000 | 2128 | ||
| 2001 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); | 2129 | if (list_empty(&BTRFS_I(inode)->i_orphan)) { |
| 2130 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); | ||
| 2131 | #if 0 | ||
| 2132 | /* | ||
| 2133 | * For proper ENOSPC handling, we should do orphan | ||
| 2134 | * cleanup when mounting. But this introduces backward | ||
| 2135 | * compatibility issue. | ||
| 2136 | */ | ||
| 2137 | if (!xchg(&root->orphan_item_inserted, 1)) | ||
| 2138 | insert = 2; | ||
| 2139 | else | ||
| 2140 | insert = 1; | ||
| 2141 | #endif | ||
| 2142 | insert = 1; | ||
| 2143 | } else { | ||
| 2144 | WARN_ON(!BTRFS_I(inode)->orphan_meta_reserved); | ||
| 2145 | } | ||
| 2002 | 2146 | ||
| 2003 | spin_unlock(&root->list_lock); | 2147 | if (!BTRFS_I(inode)->orphan_meta_reserved) { |
| 2148 | BTRFS_I(inode)->orphan_meta_reserved = 1; | ||
| 2149 | reserve = 1; | ||
| 2150 | } | ||
| 2151 | spin_unlock(&root->orphan_lock); | ||
| 2004 | 2152 | ||
| 2005 | /* | 2153 | if (block_rsv) |
| 2006 | * insert an orphan item to track this unlinked/truncated file | 2154 | btrfs_add_durable_block_rsv(root->fs_info, block_rsv); |
| 2007 | */ | ||
| 2008 | ret = btrfs_insert_orphan_item(trans, root, inode->i_ino); | ||
| 2009 | 2155 | ||
| 2010 | return ret; | 2156 | /* grab metadata reservation from transaction handle */ |
| 2157 | if (reserve) { | ||
| 2158 | ret = btrfs_orphan_reserve_metadata(trans, inode); | ||
| 2159 | BUG_ON(ret); | ||
| 2160 | } | ||
| 2161 | |||
| 2162 | /* insert an orphan item to track this unlinked/truncated file */ | ||
| 2163 | if (insert >= 1) { | ||
| 2164 | ret = btrfs_insert_orphan_item(trans, root, inode->i_ino); | ||
| 2165 | BUG_ON(ret); | ||
| 2166 | } | ||
| 2167 | |||
| 2168 | /* insert an orphan item to track subvolume contains orphan files */ | ||
| 2169 | if (insert >= 2) { | ||
| 2170 | ret = btrfs_insert_orphan_item(trans, root->fs_info->tree_root, | ||
| 2171 | root->root_key.objectid); | ||
| 2172 | BUG_ON(ret); | ||
| 2173 | } | ||
| 2174 | return 0; | ||
| 2011 | } | 2175 | } |
| 2012 | 2176 | ||
| 2013 | /* | 2177 | /* |
| @@ -2017,26 +2181,31 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | |||
| 2017 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode) | 2181 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode) |
| 2018 | { | 2182 | { |
| 2019 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2183 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 2184 | int delete_item = 0; | ||
| 2185 | int release_rsv = 0; | ||
| 2020 | int ret = 0; | 2186 | int ret = 0; |
| 2021 | 2187 | ||
| 2022 | spin_lock(&root->list_lock); | 2188 | spin_lock(&root->orphan_lock); |
| 2023 | 2189 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { | |
| 2024 | if (list_empty(&BTRFS_I(inode)->i_orphan)) { | 2190 | list_del_init(&BTRFS_I(inode)->i_orphan); |
| 2025 | spin_unlock(&root->list_lock); | 2191 | delete_item = 1; |
| 2026 | return 0; | ||
| 2027 | } | 2192 | } |
| 2028 | 2193 | ||
| 2029 | list_del_init(&BTRFS_I(inode)->i_orphan); | 2194 | if (BTRFS_I(inode)->orphan_meta_reserved) { |
| 2030 | if (!trans) { | 2195 | BTRFS_I(inode)->orphan_meta_reserved = 0; |
| 2031 | spin_unlock(&root->list_lock); | 2196 | release_rsv = 1; |
| 2032 | return 0; | ||
| 2033 | } | 2197 | } |
| 2198 | spin_unlock(&root->orphan_lock); | ||
| 2034 | 2199 | ||
| 2035 | spin_unlock(&root->list_lock); | 2200 | if (trans && delete_item) { |
| 2201 | ret = btrfs_del_orphan_item(trans, root, inode->i_ino); | ||
| 2202 | BUG_ON(ret); | ||
| 2203 | } | ||
| 2036 | 2204 | ||
| 2037 | ret = btrfs_del_orphan_item(trans, root, inode->i_ino); | 2205 | if (release_rsv) |
| 2206 | btrfs_orphan_release_metadata(inode); | ||
| 2038 | 2207 | ||
| 2039 | return ret; | 2208 | return 0; |
| 2040 | } | 2209 | } |
| 2041 | 2210 | ||
| 2042 | /* | 2211 | /* |
| @@ -2053,7 +2222,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
| 2053 | struct inode *inode; | 2222 | struct inode *inode; |
| 2054 | int ret = 0, nr_unlink = 0, nr_truncate = 0; | 2223 | int ret = 0, nr_unlink = 0, nr_truncate = 0; |
| 2055 | 2224 | ||
| 2056 | if (!xchg(&root->clean_orphans, 0)) | 2225 | if (cmpxchg(&root->orphan_cleanup_state, 0, ORPHAN_CLEANUP_STARTED)) |
| 2057 | return; | 2226 | return; |
| 2058 | 2227 | ||
| 2059 | path = btrfs_alloc_path(); | 2228 | path = btrfs_alloc_path(); |
| @@ -2106,16 +2275,15 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
| 2106 | found_key.type = BTRFS_INODE_ITEM_KEY; | 2275 | found_key.type = BTRFS_INODE_ITEM_KEY; |
| 2107 | found_key.offset = 0; | 2276 | found_key.offset = 0; |
| 2108 | inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL); | 2277 | inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL); |
| 2109 | if (IS_ERR(inode)) | 2278 | BUG_ON(IS_ERR(inode)); |
| 2110 | break; | ||
| 2111 | 2279 | ||
| 2112 | /* | 2280 | /* |
| 2113 | * add this inode to the orphan list so btrfs_orphan_del does | 2281 | * add this inode to the orphan list so btrfs_orphan_del does |
| 2114 | * the proper thing when we hit it | 2282 | * the proper thing when we hit it |
| 2115 | */ | 2283 | */ |
| 2116 | spin_lock(&root->list_lock); | 2284 | spin_lock(&root->orphan_lock); |
| 2117 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); | 2285 | list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list); |
| 2118 | spin_unlock(&root->list_lock); | 2286 | spin_unlock(&root->orphan_lock); |
| 2119 | 2287 | ||
| 2120 | /* | 2288 | /* |
| 2121 | * if this is a bad inode, means we actually succeeded in | 2289 | * if this is a bad inode, means we actually succeeded in |
| @@ -2142,13 +2310,23 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
| 2142 | /* this will do delete_inode and everything for us */ | 2310 | /* this will do delete_inode and everything for us */ |
| 2143 | iput(inode); | 2311 | iput(inode); |
| 2144 | } | 2312 | } |
| 2313 | btrfs_free_path(path); | ||
| 2314 | |||
| 2315 | root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE; | ||
| 2316 | |||
| 2317 | if (root->orphan_block_rsv) | ||
| 2318 | btrfs_block_rsv_release(root, root->orphan_block_rsv, | ||
| 2319 | (u64)-1); | ||
| 2320 | |||
| 2321 | if (root->orphan_block_rsv || root->orphan_item_inserted) { | ||
| 2322 | trans = btrfs_join_transaction(root, 1); | ||
| 2323 | btrfs_end_transaction(trans, root); | ||
| 2324 | } | ||
| 2145 | 2325 | ||
| 2146 | if (nr_unlink) | 2326 | if (nr_unlink) |
| 2147 | printk(KERN_INFO "btrfs: unlinked %d orphans\n", nr_unlink); | 2327 | printk(KERN_INFO "btrfs: unlinked %d orphans\n", nr_unlink); |
| 2148 | if (nr_truncate) | 2328 | if (nr_truncate) |
| 2149 | printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate); | 2329 | printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate); |
| 2150 | |||
| 2151 | btrfs_free_path(path); | ||
| 2152 | } | 2330 | } |
| 2153 | 2331 | ||
| 2154 | /* | 2332 | /* |
| @@ -3181,6 +3359,7 @@ out: | |||
| 3181 | if (pending_del_nr) { | 3359 | if (pending_del_nr) { |
| 3182 | ret = btrfs_del_items(trans, root, path, pending_del_slot, | 3360 | ret = btrfs_del_items(trans, root, path, pending_del_slot, |
| 3183 | pending_del_nr); | 3361 | pending_del_nr); |
| 3362 | BUG_ON(ret); | ||
| 3184 | } | 3363 | } |
| 3185 | btrfs_free_path(path); | 3364 | btrfs_free_path(path); |
| 3186 | return err; | 3365 | return err; |
| @@ -3386,7 +3565,10 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) | |||
| 3386 | } | 3565 | } |
| 3387 | } | 3566 | } |
| 3388 | 3567 | ||
| 3389 | trans = btrfs_start_transaction(root, 1); | 3568 | trans = btrfs_start_transaction(root, 5); |
| 3569 | if (IS_ERR(trans)) | ||
| 3570 | return PTR_ERR(trans); | ||
| 3571 | |||
| 3390 | btrfs_set_trans_block_group(trans, inode); | 3572 | btrfs_set_trans_block_group(trans, inode); |
| 3391 | 3573 | ||
| 3392 | ret = btrfs_orphan_add(trans, inode); | 3574 | ret = btrfs_orphan_add(trans, inode); |
| @@ -3406,8 +3588,11 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) | |||
| 3406 | i_size_write(inode, attr->ia_size); | 3588 | i_size_write(inode, attr->ia_size); |
| 3407 | btrfs_ordered_update_i_size(inode, inode->i_size, NULL); | 3589 | btrfs_ordered_update_i_size(inode, inode->i_size, NULL); |
| 3408 | 3590 | ||
| 3409 | trans = btrfs_start_transaction(root, 1); | 3591 | trans = btrfs_start_transaction(root, 0); |
| 3592 | BUG_ON(IS_ERR(trans)); | ||
| 3410 | btrfs_set_trans_block_group(trans, inode); | 3593 | btrfs_set_trans_block_group(trans, inode); |
| 3594 | trans->block_rsv = root->orphan_block_rsv; | ||
| 3595 | BUG_ON(!trans->block_rsv); | ||
| 3411 | 3596 | ||
| 3412 | ret = btrfs_update_inode(trans, root, inode); | 3597 | ret = btrfs_update_inode(trans, root, inode); |
| 3413 | BUG_ON(ret); | 3598 | BUG_ON(ret); |
| @@ -3487,10 +3672,21 @@ void btrfs_delete_inode(struct inode *inode) | |||
| 3487 | btrfs_i_size_write(inode, 0); | 3672 | btrfs_i_size_write(inode, 0); |
| 3488 | 3673 | ||
| 3489 | while (1) { | 3674 | while (1) { |
| 3490 | trans = btrfs_start_transaction(root, 1); | 3675 | trans = btrfs_start_transaction(root, 0); |
| 3676 | BUG_ON(IS_ERR(trans)); | ||
| 3491 | btrfs_set_trans_block_group(trans, inode); | 3677 | btrfs_set_trans_block_group(trans, inode); |
| 3492 | ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0); | 3678 | trans->block_rsv = root->orphan_block_rsv; |
| 3679 | |||
| 3680 | ret = btrfs_block_rsv_check(trans, root, | ||
| 3681 | root->orphan_block_rsv, 0, 5); | ||
| 3682 | if (ret) { | ||
| 3683 | BUG_ON(ret != -EAGAIN); | ||
| 3684 | ret = btrfs_commit_transaction(trans, root); | ||
| 3685 | BUG_ON(ret); | ||
| 3686 | continue; | ||
| 3687 | } | ||
| 3493 | 3688 | ||
| 3689 | ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0); | ||
| 3494 | if (ret != -EAGAIN) | 3690 | if (ret != -EAGAIN) |
| 3495 | break; | 3691 | break; |
| 3496 | 3692 | ||
| @@ -3498,6 +3694,7 @@ void btrfs_delete_inode(struct inode *inode) | |||
| 3498 | btrfs_end_transaction(trans, root); | 3694 | btrfs_end_transaction(trans, root); |
| 3499 | trans = NULL; | 3695 | trans = NULL; |
| 3500 | btrfs_btree_balance_dirty(root, nr); | 3696 | btrfs_btree_balance_dirty(root, nr); |
| 3697 | |||
| 3501 | } | 3698 | } |
| 3502 | 3699 | ||
| 3503 | if (ret == 0) { | 3700 | if (ret == 0) { |
| @@ -5247,8 +5444,10 @@ static void btrfs_truncate(struct inode *inode) | |||
| 5247 | btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); | 5444 | btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); |
| 5248 | btrfs_ordered_update_i_size(inode, inode->i_size, NULL); | 5445 | btrfs_ordered_update_i_size(inode, inode->i_size, NULL); |
| 5249 | 5446 | ||
| 5250 | trans = btrfs_start_transaction(root, 1); | 5447 | trans = btrfs_start_transaction(root, 0); |
| 5448 | BUG_ON(IS_ERR(trans)); | ||
| 5251 | btrfs_set_trans_block_group(trans, inode); | 5449 | btrfs_set_trans_block_group(trans, inode); |
| 5450 | trans->block_rsv = root->orphan_block_rsv; | ||
| 5252 | 5451 | ||
| 5253 | /* | 5452 | /* |
| 5254 | * setattr is responsible for setting the ordered_data_close flag, | 5453 | * setattr is responsible for setting the ordered_data_close flag, |
| @@ -5271,6 +5470,23 @@ static void btrfs_truncate(struct inode *inode) | |||
| 5271 | btrfs_add_ordered_operation(trans, root, inode); | 5470 | btrfs_add_ordered_operation(trans, root, inode); |
| 5272 | 5471 | ||
| 5273 | while (1) { | 5472 | while (1) { |
| 5473 | if (!trans) { | ||
| 5474 | trans = btrfs_start_transaction(root, 0); | ||
| 5475 | BUG_ON(IS_ERR(trans)); | ||
| 5476 | btrfs_set_trans_block_group(trans, inode); | ||
| 5477 | trans->block_rsv = root->orphan_block_rsv; | ||
| 5478 | } | ||
| 5479 | |||
| 5480 | ret = btrfs_block_rsv_check(trans, root, | ||
| 5481 | root->orphan_block_rsv, 0, 5); | ||
| 5482 | if (ret) { | ||
| 5483 | BUG_ON(ret != -EAGAIN); | ||
| 5484 | ret = btrfs_commit_transaction(trans, root); | ||
| 5485 | BUG_ON(ret); | ||
| 5486 | trans = NULL; | ||
| 5487 | continue; | ||
| 5488 | } | ||
| 5489 | |||
| 5274 | ret = btrfs_truncate_inode_items(trans, root, inode, | 5490 | ret = btrfs_truncate_inode_items(trans, root, inode, |
| 5275 | inode->i_size, | 5491 | inode->i_size, |
| 5276 | BTRFS_EXTENT_DATA_KEY); | 5492 | BTRFS_EXTENT_DATA_KEY); |
| @@ -5282,10 +5498,8 @@ static void btrfs_truncate(struct inode *inode) | |||
| 5282 | 5498 | ||
| 5283 | nr = trans->blocks_used; | 5499 | nr = trans->blocks_used; |
| 5284 | btrfs_end_transaction(trans, root); | 5500 | btrfs_end_transaction(trans, root); |
| 5501 | trans = NULL; | ||
| 5285 | btrfs_btree_balance_dirty(root, nr); | 5502 | btrfs_btree_balance_dirty(root, nr); |
| 5286 | |||
| 5287 | trans = btrfs_start_transaction(root, 1); | ||
| 5288 | btrfs_set_trans_block_group(trans, inode); | ||
| 5289 | } | 5503 | } |
| 5290 | 5504 | ||
| 5291 | if (ret == 0 && inode->i_nlink > 0) { | 5505 | if (ret == 0 && inode->i_nlink > 0) { |
| @@ -5371,6 +5585,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
| 5371 | ei->reserved_extents = 0; | 5585 | ei->reserved_extents = 0; |
| 5372 | 5586 | ||
| 5373 | ei->ordered_data_close = 0; | 5587 | ei->ordered_data_close = 0; |
| 5588 | ei->orphan_meta_reserved = 0; | ||
| 5374 | ei->dummy_inode = 0; | 5589 | ei->dummy_inode = 0; |
| 5375 | ei->force_compress = 0; | 5590 | ei->force_compress = 0; |
| 5376 | 5591 | ||
| @@ -5417,13 +5632,13 @@ void btrfs_destroy_inode(struct inode *inode) | |||
| 5417 | spin_unlock(&root->fs_info->ordered_extent_lock); | 5632 | spin_unlock(&root->fs_info->ordered_extent_lock); |
| 5418 | } | 5633 | } |
| 5419 | 5634 | ||
| 5420 | spin_lock(&root->list_lock); | 5635 | spin_lock(&root->orphan_lock); |
| 5421 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { | 5636 | if (!list_empty(&BTRFS_I(inode)->i_orphan)) { |
| 5422 | printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n", | 5637 | printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n", |
| 5423 | inode->i_ino); | 5638 | inode->i_ino); |
| 5424 | list_del_init(&BTRFS_I(inode)->i_orphan); | 5639 | list_del_init(&BTRFS_I(inode)->i_orphan); |
| 5425 | } | 5640 | } |
| 5426 | spin_unlock(&root->list_lock); | 5641 | spin_unlock(&root->orphan_lock); |
| 5427 | 5642 | ||
| 5428 | while (1) { | 5643 | while (1) { |
| 5429 | ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); | 5644 | ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a0686658a3f6..4cdb98cf26de 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -1297,10 +1297,12 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
| 1297 | dest->root_item.drop_level = 0; | 1297 | dest->root_item.drop_level = 0; |
| 1298 | btrfs_set_root_refs(&dest->root_item, 0); | 1298 | btrfs_set_root_refs(&dest->root_item, 0); |
| 1299 | 1299 | ||
| 1300 | ret = btrfs_insert_orphan_item(trans, | 1300 | if (!xchg(&dest->orphan_item_inserted, 1)) { |
| 1301 | root->fs_info->tree_root, | 1301 | ret = btrfs_insert_orphan_item(trans, |
| 1302 | dest->root_key.objectid); | 1302 | root->fs_info->tree_root, |
| 1303 | BUG_ON(ret); | 1303 | dest->root_key.objectid); |
| 1304 | BUG_ON(ret); | ||
| 1305 | } | ||
| 1304 | 1306 | ||
| 1305 | ret = btrfs_commit_transaction(trans, root); | 1307 | ret = btrfs_commit_transaction(trans, root); |
| 1306 | BUG_ON(ret); | 1308 | BUG_ON(ret); |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 67fa2d29d663..b91ccd972644 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
| @@ -259,6 +259,8 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) | |||
| 259 | struct extent_buffer *leaf; | 259 | struct extent_buffer *leaf; |
| 260 | struct btrfs_path *path; | 260 | struct btrfs_path *path; |
| 261 | struct btrfs_key key; | 261 | struct btrfs_key key; |
| 262 | struct btrfs_key root_key; | ||
| 263 | struct btrfs_root *root; | ||
| 262 | int err = 0; | 264 | int err = 0; |
| 263 | int ret; | 265 | int ret; |
| 264 | 266 | ||
| @@ -270,6 +272,9 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) | |||
| 270 | key.type = BTRFS_ORPHAN_ITEM_KEY; | 272 | key.type = BTRFS_ORPHAN_ITEM_KEY; |
| 271 | key.offset = 0; | 273 | key.offset = 0; |
| 272 | 274 | ||
| 275 | root_key.type = BTRFS_ROOT_ITEM_KEY; | ||
| 276 | root_key.offset = (u64)-1; | ||
| 277 | |||
| 273 | while (1) { | 278 | while (1) { |
| 274 | ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); | 279 | ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0); |
| 275 | if (ret < 0) { | 280 | if (ret < 0) { |
| @@ -294,13 +299,25 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) | |||
| 294 | key.type != BTRFS_ORPHAN_ITEM_KEY) | 299 | key.type != BTRFS_ORPHAN_ITEM_KEY) |
| 295 | break; | 300 | break; |
| 296 | 301 | ||
| 297 | ret = btrfs_find_dead_roots(tree_root, key.offset); | 302 | root_key.objectid = key.offset; |
| 298 | if (ret) { | 303 | key.offset++; |
| 304 | |||
| 305 | root = btrfs_read_fs_root_no_name(tree_root->fs_info, | ||
| 306 | &root_key); | ||
| 307 | if (!IS_ERR(root)) | ||
| 308 | continue; | ||
| 309 | |||
| 310 | ret = PTR_ERR(root); | ||
| 311 | if (ret != -ENOENT) { | ||
| 299 | err = ret; | 312 | err = ret; |
| 300 | break; | 313 | break; |
| 301 | } | 314 | } |
| 302 | 315 | ||
| 303 | key.offset++; | 316 | ret = btrfs_find_dead_roots(tree_root, root_key.objectid); |
| 317 | if (ret) { | ||
| 318 | err = ret; | ||
| 319 | break; | ||
| 320 | } | ||
| 304 | } | 321 | } |
| 305 | 322 | ||
| 306 | btrfs_free_path(path); | 323 | btrfs_free_path(path); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 38d91c7e8db2..574285c8cbd4 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -694,11 +694,11 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 694 | if (btrfs_super_log_root(&root->fs_info->super_copy) != 0) | 694 | if (btrfs_super_log_root(&root->fs_info->super_copy) != 0) |
| 695 | return -EINVAL; | 695 | return -EINVAL; |
| 696 | 696 | ||
| 697 | /* recover relocation */ | 697 | ret = btrfs_cleanup_fs_roots(root->fs_info); |
| 698 | ret = btrfs_recover_relocation(root); | ||
| 699 | WARN_ON(ret); | 698 | WARN_ON(ret); |
| 700 | 699 | ||
| 701 | ret = btrfs_cleanup_fs_roots(root->fs_info); | 700 | /* recover relocation */ |
| 701 | ret = btrfs_recover_relocation(root); | ||
| 702 | WARN_ON(ret); | 702 | WARN_ON(ret); |
| 703 | 703 | ||
| 704 | sb->s_flags &= ~MS_RDONLY; | 704 | sb->s_flags &= ~MS_RDONLY; |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 6217bb6d516a..cfe7f588ef05 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -676,6 +676,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 676 | 676 | ||
| 677 | btrfs_free_log(trans, root); | 677 | btrfs_free_log(trans, root); |
| 678 | btrfs_update_reloc_root(trans, root); | 678 | btrfs_update_reloc_root(trans, root); |
| 679 | btrfs_orphan_commit_root(trans, root); | ||
| 679 | 680 | ||
| 680 | if (root->commit_root != root->node) { | 681 | if (root->commit_root != root->node) { |
| 681 | switch_commit_root(root); | 682 | switch_commit_root(root); |
| @@ -835,6 +836,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 835 | struct extent_buffer *tmp; | 836 | struct extent_buffer *tmp; |
| 836 | struct extent_buffer *old; | 837 | struct extent_buffer *old; |
| 837 | int ret; | 838 | int ret; |
| 839 | int retries = 0; | ||
| 840 | u64 to_reserve = 0; | ||
| 838 | u64 index = 0; | 841 | u64 index = 0; |
| 839 | u64 objectid; | 842 | u64 objectid; |
| 840 | 843 | ||
| @@ -850,6 +853,17 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 850 | goto fail; | 853 | goto fail; |
| 851 | } | 854 | } |
| 852 | 855 | ||
| 856 | btrfs_orphan_pre_snapshot(trans, pending, &to_reserve); | ||
| 857 | |||
| 858 | if (to_reserve > 0) { | ||
| 859 | ret = btrfs_block_rsv_add(trans, root, &pending->block_rsv, | ||
| 860 | to_reserve, &retries); | ||
| 861 | if (ret) { | ||
| 862 | pending->error = ret; | ||
| 863 | goto fail; | ||
| 864 | } | ||
| 865 | } | ||
| 866 | |||
| 853 | key.objectid = objectid; | 867 | key.objectid = objectid; |
| 854 | key.offset = (u64)-1; | 868 | key.offset = (u64)-1; |
| 855 | key.type = BTRFS_ROOT_ITEM_KEY; | 869 | key.type = BTRFS_ROOT_ITEM_KEY; |
| @@ -909,6 +923,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 909 | key.offset = (u64)-1; | 923 | key.offset = (u64)-1; |
| 910 | pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); | 924 | pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); |
| 911 | BUG_ON(IS_ERR(pending->snap)); | 925 | BUG_ON(IS_ERR(pending->snap)); |
| 926 | |||
| 927 | btrfs_orphan_post_snapshot(trans, pending); | ||
| 912 | fail: | 928 | fail: |
| 913 | kfree(new_root_item); | 929 | kfree(new_root_item); |
| 914 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); | 930 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); |
