diff options
-rw-r--r-- | fs/btrfs/ctree.c | 16 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 145 |
2 files changed, 88 insertions, 73 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 0d5c686f2b98..1dd8a71f567d 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1211,7 +1211,11 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
1211 | BUG_ON(tm->slot != 0); | 1211 | BUG_ON(tm->slot != 0); |
1212 | eb_rewin = alloc_dummy_extent_buffer(eb->start, | 1212 | eb_rewin = alloc_dummy_extent_buffer(eb->start, |
1213 | fs_info->tree_root->nodesize); | 1213 | fs_info->tree_root->nodesize); |
1214 | BUG_ON(!eb_rewin); | 1214 | if (!eb_rewin) { |
1215 | btrfs_tree_read_unlock(eb); | ||
1216 | free_extent_buffer(eb); | ||
1217 | return NULL; | ||
1218 | } | ||
1215 | btrfs_set_header_bytenr(eb_rewin, eb->start); | 1219 | btrfs_set_header_bytenr(eb_rewin, eb->start); |
1216 | btrfs_set_header_backref_rev(eb_rewin, | 1220 | btrfs_set_header_backref_rev(eb_rewin, |
1217 | btrfs_header_backref_rev(eb)); | 1221 | btrfs_header_backref_rev(eb)); |
@@ -1219,7 +1223,11 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
1219 | btrfs_set_header_level(eb_rewin, btrfs_header_level(eb)); | 1223 | btrfs_set_header_level(eb_rewin, btrfs_header_level(eb)); |
1220 | } else { | 1224 | } else { |
1221 | eb_rewin = btrfs_clone_extent_buffer(eb); | 1225 | eb_rewin = btrfs_clone_extent_buffer(eb); |
1222 | BUG_ON(!eb_rewin); | 1226 | if (!eb_rewin) { |
1227 | btrfs_tree_read_unlock(eb); | ||
1228 | free_extent_buffer(eb); | ||
1229 | return NULL; | ||
1230 | } | ||
1223 | } | 1231 | } |
1224 | 1232 | ||
1225 | btrfs_tree_read_unlock(eb); | 1233 | btrfs_tree_read_unlock(eb); |
@@ -2772,6 +2780,10 @@ again: | |||
2772 | BTRFS_READ_LOCK); | 2780 | BTRFS_READ_LOCK); |
2773 | } | 2781 | } |
2774 | b = tree_mod_log_rewind(root->fs_info, b, time_seq); | 2782 | b = tree_mod_log_rewind(root->fs_info, b, time_seq); |
2783 | if (!b) { | ||
2784 | ret = -ENOMEM; | ||
2785 | goto done; | ||
2786 | } | ||
2775 | p->locks[level] = BTRFS_READ_LOCK; | 2787 | p->locks[level] = BTRFS_READ_LOCK; |
2776 | p->nodes[level] = b; | 2788 | p->nodes[level] = b; |
2777 | } else { | 2789 | } else { |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c137f98fbd24..ef25c7d048e2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -4222,6 +4222,76 @@ static void __free_extent_buffer(struct extent_buffer *eb) | |||
4222 | kmem_cache_free(extent_buffer_cache, eb); | 4222 | kmem_cache_free(extent_buffer_cache, eb); |
4223 | } | 4223 | } |
4224 | 4224 | ||
4225 | static int extent_buffer_under_io(struct extent_buffer *eb) | ||
4226 | { | ||
4227 | return (atomic_read(&eb->io_pages) || | ||
4228 | test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) || | ||
4229 | test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)); | ||
4230 | } | ||
4231 | |||
4232 | /* | ||
4233 | * Helper for releasing extent buffer page. | ||
4234 | */ | ||
4235 | static void btrfs_release_extent_buffer_page(struct extent_buffer *eb, | ||
4236 | unsigned long start_idx) | ||
4237 | { | ||
4238 | unsigned long index; | ||
4239 | unsigned long num_pages; | ||
4240 | struct page *page; | ||
4241 | int mapped = !test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags); | ||
4242 | |||
4243 | BUG_ON(extent_buffer_under_io(eb)); | ||
4244 | |||
4245 | num_pages = num_extent_pages(eb->start, eb->len); | ||
4246 | index = start_idx + num_pages; | ||
4247 | if (start_idx >= index) | ||
4248 | return; | ||
4249 | |||
4250 | do { | ||
4251 | index--; | ||
4252 | page = extent_buffer_page(eb, index); | ||
4253 | if (page && mapped) { | ||
4254 | spin_lock(&page->mapping->private_lock); | ||
4255 | /* | ||
4256 | * We do this since we'll remove the pages after we've | ||
4257 | * removed the eb from the radix tree, so we could race | ||
4258 | * and have this page now attached to the new eb. So | ||
4259 | * only clear page_private if it's still connected to | ||
4260 | * this eb. | ||
4261 | */ | ||
4262 | if (PagePrivate(page) && | ||
4263 | page->private == (unsigned long)eb) { | ||
4264 | BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)); | ||
4265 | BUG_ON(PageDirty(page)); | ||
4266 | BUG_ON(PageWriteback(page)); | ||
4267 | /* | ||
4268 | * We need to make sure we haven't be attached | ||
4269 | * to a new eb. | ||
4270 | */ | ||
4271 | ClearPagePrivate(page); | ||
4272 | set_page_private(page, 0); | ||
4273 | /* One for the page private */ | ||
4274 | page_cache_release(page); | ||
4275 | } | ||
4276 | spin_unlock(&page->mapping->private_lock); | ||
4277 | |||
4278 | } | ||
4279 | if (page) { | ||
4280 | /* One for when we alloced the page */ | ||
4281 | page_cache_release(page); | ||
4282 | } | ||
4283 | } while (index != start_idx); | ||
4284 | } | ||
4285 | |||
4286 | /* | ||
4287 | * Helper for releasing the extent buffer. | ||
4288 | */ | ||
4289 | static inline void btrfs_release_extent_buffer(struct extent_buffer *eb) | ||
4290 | { | ||
4291 | btrfs_release_extent_buffer_page(eb, 0); | ||
4292 | __free_extent_buffer(eb); | ||
4293 | } | ||
4294 | |||
4225 | static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, | 4295 | static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, |
4226 | u64 start, | 4296 | u64 start, |
4227 | unsigned long len, | 4297 | unsigned long len, |
@@ -4276,7 +4346,10 @@ struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src) | |||
4276 | 4346 | ||
4277 | for (i = 0; i < num_pages; i++) { | 4347 | for (i = 0; i < num_pages; i++) { |
4278 | p = alloc_page(GFP_ATOMIC); | 4348 | p = alloc_page(GFP_ATOMIC); |
4279 | BUG_ON(!p); | 4349 | if (!p) { |
4350 | btrfs_release_extent_buffer(new); | ||
4351 | return NULL; | ||
4352 | } | ||
4280 | attach_extent_buffer_page(new, p); | 4353 | attach_extent_buffer_page(new, p); |
4281 | WARN_ON(PageDirty(p)); | 4354 | WARN_ON(PageDirty(p)); |
4282 | SetPageUptodate(p); | 4355 | SetPageUptodate(p); |
@@ -4317,76 +4390,6 @@ err: | |||
4317 | return NULL; | 4390 | return NULL; |
4318 | } | 4391 | } |
4319 | 4392 | ||
4320 | static int extent_buffer_under_io(struct extent_buffer *eb) | ||
4321 | { | ||
4322 | return (atomic_read(&eb->io_pages) || | ||
4323 | test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) || | ||
4324 | test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)); | ||
4325 | } | ||
4326 | |||
4327 | /* | ||
4328 | * Helper for releasing extent buffer page. | ||
4329 | */ | ||
4330 | static void btrfs_release_extent_buffer_page(struct extent_buffer *eb, | ||
4331 | unsigned long start_idx) | ||
4332 | { | ||
4333 | unsigned long index; | ||
4334 | unsigned long num_pages; | ||
4335 | struct page *page; | ||
4336 | int mapped = !test_bit(EXTENT_BUFFER_DUMMY, &eb->bflags); | ||
4337 | |||
4338 | BUG_ON(extent_buffer_under_io(eb)); | ||
4339 | |||
4340 | num_pages = num_extent_pages(eb->start, eb->len); | ||
4341 | index = start_idx + num_pages; | ||
4342 | if (start_idx >= index) | ||
4343 | return; | ||
4344 | |||
4345 | do { | ||
4346 | index--; | ||
4347 | page = extent_buffer_page(eb, index); | ||
4348 | if (page && mapped) { | ||
4349 | spin_lock(&page->mapping->private_lock); | ||
4350 | /* | ||
4351 | * We do this since we'll remove the pages after we've | ||
4352 | * removed the eb from the radix tree, so we could race | ||
4353 | * and have this page now attached to the new eb. So | ||
4354 | * only clear page_private if it's still connected to | ||
4355 | * this eb. | ||
4356 | */ | ||
4357 | if (PagePrivate(page) && | ||
4358 | page->private == (unsigned long)eb) { | ||
4359 | BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)); | ||
4360 | BUG_ON(PageDirty(page)); | ||
4361 | BUG_ON(PageWriteback(page)); | ||
4362 | /* | ||
4363 | * We need to make sure we haven't be attached | ||
4364 | * to a new eb. | ||
4365 | */ | ||
4366 | ClearPagePrivate(page); | ||
4367 | set_page_private(page, 0); | ||
4368 | /* One for the page private */ | ||
4369 | page_cache_release(page); | ||
4370 | } | ||
4371 | spin_unlock(&page->mapping->private_lock); | ||
4372 | |||
4373 | } | ||
4374 | if (page) { | ||
4375 | /* One for when we alloced the page */ | ||
4376 | page_cache_release(page); | ||
4377 | } | ||
4378 | } while (index != start_idx); | ||
4379 | } | ||
4380 | |||
4381 | /* | ||
4382 | * Helper for releasing the extent buffer. | ||
4383 | */ | ||
4384 | static inline void btrfs_release_extent_buffer(struct extent_buffer *eb) | ||
4385 | { | ||
4386 | btrfs_release_extent_buffer_page(eb, 0); | ||
4387 | __free_extent_buffer(eb); | ||
4388 | } | ||
4389 | |||
4390 | static void check_buffer_tree_ref(struct extent_buffer *eb) | 4393 | static void check_buffer_tree_ref(struct extent_buffer *eb) |
4391 | { | 4394 | { |
4392 | int refs; | 4395 | int refs; |