diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 0e1c31e682fb..2fe31c3508c1 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -153,13 +153,24 @@ static int __commit_transaction(struct ctree_root *root) | |||
153 | return ret; | 153 | return ret; |
154 | } | 154 | } |
155 | 155 | ||
156 | int commit_transaction(struct ctree_root *root) | 156 | int commit_transaction(struct ctree_root *root, struct ctree_super_block *s) |
157 | { | 157 | { |
158 | int ret; | 158 | int ret = 0; |
159 | |||
159 | ret = __commit_transaction(root); | 160 | ret = __commit_transaction(root); |
160 | if (!ret && root != root->extent_root) | 161 | if (!ret && root != root->extent_root) |
161 | ret = __commit_transaction(root->extent_root); | 162 | ret = __commit_transaction(root->extent_root); |
162 | BUG_ON(ret); | 163 | BUG_ON(ret); |
164 | if (root->commit_root != root->node) { | ||
165 | struct tree_buffer *snap = root->commit_root; | ||
166 | root->commit_root = root->node; | ||
167 | root->node->count++; | ||
168 | ret = btrfs_drop_snapshot(root, snap); | ||
169 | BUG_ON(ret); | ||
170 | tree_block_release(root, snap); | ||
171 | } | ||
172 | write_ctree_super(root, s); | ||
173 | btrfs_finish_extent_commit(root); | ||
163 | return ret; | 174 | return ret; |
164 | } | 175 | } |
165 | 176 | ||
@@ -168,10 +179,13 @@ static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, | |||
168 | { | 179 | { |
169 | INIT_LIST_HEAD(&root->trans); | 180 | INIT_LIST_HEAD(&root->trans); |
170 | INIT_LIST_HEAD(&root->cache); | 181 | INIT_LIST_HEAD(&root->cache); |
182 | root->cache_size = 0; | ||
171 | root->fp = fp; | 183 | root->fp = fp; |
172 | root->node = NULL; | 184 | root->node = NULL; |
173 | root->node = read_tree_block(root, info->tree_root); | ||
174 | root->extent_root = extent_root; | 185 | root->extent_root = extent_root; |
186 | root->commit_root = NULL; | ||
187 | root->node = read_tree_block(root, info->tree_root); | ||
188 | memset(&root->current_insert, 0, sizeof(root->current_insert)); | ||
175 | return 0; | 189 | return 0; |
176 | } | 190 | } |
177 | 191 | ||
@@ -188,6 +202,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) | |||
188 | return NULL; | 202 | return NULL; |
189 | } | 203 | } |
190 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); | 204 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); |
205 | INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL); | ||
206 | INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL); | ||
191 | INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); | 207 | INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); |
192 | ret = pread(fp, super, sizeof(struct ctree_super_block), | 208 | ret = pread(fp, super, sizeof(struct ctree_super_block), |
193 | CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); | 209 | CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); |
@@ -204,6 +220,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) | |||
204 | BUG_ON(ret < 0); | 220 | BUG_ON(ret < 0); |
205 | __setup_root(root, extent_root, &super->root_info, fp); | 221 | __setup_root(root, extent_root, &super->root_info, fp); |
206 | __setup_root(extent_root, extent_root, &super->extent_info, fp); | 222 | __setup_root(extent_root, extent_root, &super->extent_info, fp); |
223 | root->commit_root = root->node; | ||
224 | root->node->count++; | ||
207 | return root; | 225 | return root; |
208 | } | 226 | } |
209 | 227 | ||
@@ -236,9 +254,11 @@ static int drop_cache(struct ctree_root *root) | |||
236 | } | 254 | } |
237 | return 0; | 255 | return 0; |
238 | } | 256 | } |
239 | int close_ctree(struct ctree_root *root) | 257 | int close_ctree(struct ctree_root *root, struct ctree_super_block *s) |
240 | { | 258 | { |
241 | commit_transaction(root); | 259 | commit_transaction(root, s); |
260 | __commit_transaction(root->extent_root); | ||
261 | write_ctree_super(root, s); | ||
242 | drop_cache(root->extent_root); | 262 | drop_cache(root->extent_root); |
243 | drop_cache(root); | 263 | drop_cache(root); |
244 | BUG_ON(!list_empty(&root->trans)); | 264 | BUG_ON(!list_empty(&root->trans)); |
@@ -249,6 +269,7 @@ int close_ctree(struct ctree_root *root) | |||
249 | tree_block_release(root, root->node); | 269 | tree_block_release(root, root->node); |
250 | if (root->extent_root->node) | 270 | if (root->extent_root->node) |
251 | tree_block_release(root->extent_root, root->extent_root->node); | 271 | tree_block_release(root->extent_root, root->extent_root->node); |
272 | tree_block_release(root, root->commit_root); | ||
252 | free(root); | 273 | free(root); |
253 | printf("on close %d blocks are allocated\n", allocated_blocks); | 274 | printf("on close %d blocks are allocated\n", allocated_blocks); |
254 | return 0; | 275 | return 0; |