aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-02-13 11:09:14 -0500
committerJosef Bacik <jbacik@fusionio.com>2013-02-20 12:59:57 -0500
commit569e0f358c0c37f6733702d4a5d2c412860f7169 (patch)
tree8ab0ece9bd2716da66a43406628f6f5176604817 /fs/btrfs/transaction.c
parentdde5740fdd6175fc95aecf4ccc7856fbbad9b44e (diff)
Btrfs: place ordered operations on a per transaction list
Miao made the ordered operations stuff run async, which introduced a deadlock where we could get somebody (sync) racing in and committing the transaction while a commit was already happening. The new committer would try and flush ordered operations which would hang waiting for the commit to finish because it is done asynchronously and no longer inherits the callers trans handle. To fix this we need to make the ordered operations list a per transaction list. We can get new inodes added to the ordered operation list by truncating them and then having another process writing to them, so this makes it so that anybody trying to add an ordered operation _must_ start a transaction in order to add itself to the list, which will keep new inodes from getting added to the ordered operations list after we start committing. This should fix the deadlock and also keeps us from doing a lot more work than we need to during commit. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index d574d830a1c4..0c87d18d1881 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -157,6 +157,7 @@ loop:
157 spin_lock_init(&cur_trans->delayed_refs.lock); 157 spin_lock_init(&cur_trans->delayed_refs.lock);
158 158
159 INIT_LIST_HEAD(&cur_trans->pending_snapshots); 159 INIT_LIST_HEAD(&cur_trans->pending_snapshots);
160 INIT_LIST_HEAD(&cur_trans->ordered_operations);
160 list_add_tail(&cur_trans->list, &fs_info->trans_list); 161 list_add_tail(&cur_trans->list, &fs_info->trans_list);
161 extent_io_tree_init(&cur_trans->dirty_pages, 162 extent_io_tree_init(&cur_trans->dirty_pages,
162 fs_info->btree_inode->i_mapping); 163 fs_info->btree_inode->i_mapping);
@@ -1456,7 +1457,7 @@ static int btrfs_flush_all_pending_stuffs(struct btrfs_trans_handle *trans,
1456 * it here and no for sure that nothing new will be added 1457 * it here and no for sure that nothing new will be added
1457 * to the list 1458 * to the list
1458 */ 1459 */
1459 ret = btrfs_run_ordered_operations(root, 1); 1460 ret = btrfs_run_ordered_operations(trans, root, 1);
1460 1461
1461 return ret; 1462 return ret;
1462} 1463}
@@ -1479,7 +1480,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1479 int should_grow = 0; 1480 int should_grow = 0;
1480 unsigned long now = get_seconds(); 1481 unsigned long now = get_seconds();
1481 1482
1482 ret = btrfs_run_ordered_operations(root, 0); 1483 ret = btrfs_run_ordered_operations(trans, root, 0);
1483 if (ret) { 1484 if (ret) {
1484 btrfs_abort_transaction(trans, root, ret); 1485 btrfs_abort_transaction(trans, root, ret);
1485 btrfs_end_transaction(trans, root); 1486 btrfs_end_transaction(trans, root);