diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 70 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 9 |
2 files changed, 42 insertions, 37 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a5aca3997d42..62a332d34fdb 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2387,13 +2387,29 @@ fail: | |||
2387 | 2387 | ||
2388 | } | 2388 | } |
2389 | 2389 | ||
2390 | static struct btrfs_block_group_cache * | ||
2391 | next_block_group(struct btrfs_root *root, | ||
2392 | struct btrfs_block_group_cache *cache) | ||
2393 | { | ||
2394 | struct rb_node *node; | ||
2395 | spin_lock(&root->fs_info->block_group_cache_lock); | ||
2396 | node = rb_next(&cache->cache_node); | ||
2397 | btrfs_put_block_group(cache); | ||
2398 | if (node) { | ||
2399 | cache = rb_entry(node, struct btrfs_block_group_cache, | ||
2400 | cache_node); | ||
2401 | atomic_inc(&cache->count); | ||
2402 | } else | ||
2403 | cache = NULL; | ||
2404 | spin_unlock(&root->fs_info->block_group_cache_lock); | ||
2405 | return cache; | ||
2406 | } | ||
2407 | |||
2390 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | 2408 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, |
2391 | struct btrfs_root *root) | 2409 | struct btrfs_root *root) |
2392 | { | 2410 | { |
2393 | struct btrfs_block_group_cache *cache, *entry; | 2411 | struct btrfs_block_group_cache *cache; |
2394 | struct rb_node *n; | ||
2395 | int err = 0; | 2412 | int err = 0; |
2396 | int werr = 0; | ||
2397 | struct btrfs_path *path; | 2413 | struct btrfs_path *path; |
2398 | u64 last = 0; | 2414 | u64 last = 0; |
2399 | 2415 | ||
@@ -2402,39 +2418,35 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
2402 | return -ENOMEM; | 2418 | return -ENOMEM; |
2403 | 2419 | ||
2404 | while (1) { | 2420 | while (1) { |
2405 | cache = NULL; | 2421 | if (last == 0) { |
2406 | spin_lock(&root->fs_info->block_group_cache_lock); | 2422 | err = btrfs_run_delayed_refs(trans, root, |
2407 | for (n = rb_first(&root->fs_info->block_group_cache_tree); | 2423 | (unsigned long)-1); |
2408 | n; n = rb_next(n)) { | 2424 | BUG_ON(err); |
2409 | entry = rb_entry(n, struct btrfs_block_group_cache, | ||
2410 | cache_node); | ||
2411 | if (entry->dirty) { | ||
2412 | cache = entry; | ||
2413 | break; | ||
2414 | } | ||
2415 | } | 2425 | } |
2416 | spin_unlock(&root->fs_info->block_group_cache_lock); | ||
2417 | 2426 | ||
2418 | if (!cache) | 2427 | cache = btrfs_lookup_first_block_group(root->fs_info, last); |
2419 | break; | 2428 | while (cache) { |
2429 | if (cache->dirty) | ||
2430 | break; | ||
2431 | cache = next_block_group(root, cache); | ||
2432 | } | ||
2433 | if (!cache) { | ||
2434 | if (last == 0) | ||
2435 | break; | ||
2436 | last = 0; | ||
2437 | continue; | ||
2438 | } | ||
2420 | 2439 | ||
2421 | cache->dirty = 0; | 2440 | cache->dirty = 0; |
2422 | last += cache->key.offset; | 2441 | last = cache->key.objectid + cache->key.offset; |
2423 | 2442 | ||
2424 | err = write_one_cache_group(trans, root, | 2443 | err = write_one_cache_group(trans, root, path, cache); |
2425 | path, cache); | 2444 | BUG_ON(err); |
2426 | /* | 2445 | btrfs_put_block_group(cache); |
2427 | * if we fail to write the cache group, we want | ||
2428 | * to keep it marked dirty in hopes that a later | ||
2429 | * write will work | ||
2430 | */ | ||
2431 | if (err) { | ||
2432 | werr = err; | ||
2433 | continue; | ||
2434 | } | ||
2435 | } | 2446 | } |
2447 | |||
2436 | btrfs_free_path(path); | 2448 | btrfs_free_path(path); |
2437 | return werr; | 2449 | return 0; |
2438 | } | 2450 | } |
2439 | 2451 | ||
2440 | int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr) | 2452 | int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr) |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2dbf1c1f56ee..81f7124c3051 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -444,9 +444,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
444 | 444 | ||
445 | btrfs_write_dirty_block_groups(trans, root); | 445 | btrfs_write_dirty_block_groups(trans, root); |
446 | 446 | ||
447 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
448 | BUG_ON(ret); | ||
449 | |||
450 | while (1) { | 447 | while (1) { |
451 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); | 448 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); |
452 | if (old_root_bytenr == root->node->start) | 449 | if (old_root_bytenr == root->node->start) |
@@ -457,9 +454,8 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
457 | &root->root_key, | 454 | &root->root_key, |
458 | &root->root_item); | 455 | &root->root_item); |
459 | BUG_ON(ret); | 456 | BUG_ON(ret); |
460 | btrfs_write_dirty_block_groups(trans, root); | ||
461 | 457 | ||
462 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 458 | ret = btrfs_write_dirty_block_groups(trans, root); |
463 | BUG_ON(ret); | 459 | BUG_ON(ret); |
464 | } | 460 | } |
465 | free_extent_buffer(root->commit_root); | 461 | free_extent_buffer(root->commit_root); |
@@ -495,9 +491,6 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
495 | root = list_entry(next, struct btrfs_root, dirty_list); | 491 | root = list_entry(next, struct btrfs_root, dirty_list); |
496 | 492 | ||
497 | update_cowonly_root(trans, root); | 493 | update_cowonly_root(trans, root); |
498 | |||
499 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
500 | BUG_ON(ret); | ||
501 | } | 494 | } |
502 | return 0; | 495 | return 0; |
503 | } | 496 | } |