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 /fs | |
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>
Diffstat (limited to 'fs')
-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); |