aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-10-30 11:23:27 -0400
committerChris Mason <chris.mason@oracle.com>2008-10-30 11:23:27 -0400
commit87ef2bb46bfc4be0b40799e68115cbe28d80a1bd (patch)
tree8060158d9adee7ad2fc591c47ad1354b07237020 /fs/btrfs/transaction.c
parent09fde3c9ba360926ce021c184a1ee343f4d8fa19 (diff)
Btrfs: prevent looping forever in finish_current_insert and del_pending_extents
finish_current_insert and del_pending_extents process extent tree modifications that build up while we are changing the extent tree. It is a confusing bit of code that prevents recursion. Both functions run through a list of pending operations and both funcs add to the list of pending operations. If you have two procs in either one of them, they can end up looping forever making more work for each other. This patch makes them walk forward through the list of pending changes instead of always trying to process the entire list. At transaction commit time, we catch any changes that were left over. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 924af6f2aeac..968b84f17a19 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -430,7 +430,10 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
430 u64 old_root_bytenr; 430 u64 old_root_bytenr;
431 struct btrfs_root *tree_root = root->fs_info->tree_root; 431 struct btrfs_root *tree_root = root->fs_info->tree_root;
432 432
433 btrfs_extent_post_op(trans, root);
433 btrfs_write_dirty_block_groups(trans, root); 434 btrfs_write_dirty_block_groups(trans, root);
435 btrfs_extent_post_op(trans, root);
436
434 while(1) { 437 while(1) {
435 old_root_bytenr = btrfs_root_bytenr(&root->root_item); 438 old_root_bytenr = btrfs_root_bytenr(&root->root_item);
436 if (old_root_bytenr == root->node->start) 439 if (old_root_bytenr == root->node->start)
@@ -440,11 +443,15 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
440 btrfs_set_root_level(&root->root_item, 443 btrfs_set_root_level(&root->root_item,
441 btrfs_header_level(root->node)); 444 btrfs_header_level(root->node));
442 btrfs_set_root_generation(&root->root_item, trans->transid); 445 btrfs_set_root_generation(&root->root_item, trans->transid);
446
447 btrfs_extent_post_op(trans, root);
448
443 ret = btrfs_update_root(trans, tree_root, 449 ret = btrfs_update_root(trans, tree_root,
444 &root->root_key, 450 &root->root_key,
445 &root->root_item); 451 &root->root_item);
446 BUG_ON(ret); 452 BUG_ON(ret);
447 btrfs_write_dirty_block_groups(trans, root); 453 btrfs_write_dirty_block_groups(trans, root);
454 btrfs_extent_post_op(trans, root);
448 } 455 }
449 return 0; 456 return 0;
450} 457}
@@ -459,15 +466,20 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
459 struct list_head *next; 466 struct list_head *next;
460 struct extent_buffer *eb; 467 struct extent_buffer *eb;
461 468
469 btrfs_extent_post_op(trans, fs_info->tree_root);
470
462 eb = btrfs_lock_root_node(fs_info->tree_root); 471 eb = btrfs_lock_root_node(fs_info->tree_root);
463 btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb, 0); 472 btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb, 0);
464 btrfs_tree_unlock(eb); 473 btrfs_tree_unlock(eb);
465 free_extent_buffer(eb); 474 free_extent_buffer(eb);
466 475
476 btrfs_extent_post_op(trans, fs_info->tree_root);
477
467 while(!list_empty(&fs_info->dirty_cowonly_roots)) { 478 while(!list_empty(&fs_info->dirty_cowonly_roots)) {
468 next = fs_info->dirty_cowonly_roots.next; 479 next = fs_info->dirty_cowonly_roots.next;
469 list_del_init(next); 480 list_del_init(next);
470 root = list_entry(next, struct btrfs_root, dirty_list); 481 root = list_entry(next, struct btrfs_root, dirty_list);
482
471 update_cowonly_root(trans, root); 483 update_cowonly_root(trans, root);
472 } 484 }
473 return 0; 485 return 0;