aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ordered-data.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/ordered-data.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/ordered-data.c')
-rw-r--r--fs/btrfs/ordered-data.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 9489fa96e3ed..dc08d77b717e 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -612,10 +612,12 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
612 * extra check to make sure the ordered operation list really is empty 612 * extra check to make sure the ordered operation list really is empty
613 * before we return 613 * before we return
614 */ 614 */
615int btrfs_run_ordered_operations(struct btrfs_root *root, int wait) 615int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans,
616 struct btrfs_root *root, int wait)
616{ 617{
617 struct btrfs_inode *btrfs_inode; 618 struct btrfs_inode *btrfs_inode;
618 struct inode *inode; 619 struct inode *inode;
620 struct btrfs_transaction *cur_trans = trans->transaction;
619 struct list_head splice; 621 struct list_head splice;
620 struct list_head works; 622 struct list_head works;
621 struct btrfs_delalloc_work *work, *next; 623 struct btrfs_delalloc_work *work, *next;
@@ -626,7 +628,7 @@ int btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
626 628
627 mutex_lock(&root->fs_info->ordered_operations_mutex); 629 mutex_lock(&root->fs_info->ordered_operations_mutex);
628 spin_lock(&root->fs_info->ordered_extent_lock); 630 spin_lock(&root->fs_info->ordered_extent_lock);
629 list_splice_init(&root->fs_info->ordered_operations, &splice); 631 list_splice_init(&cur_trans->ordered_operations, &splice);
630 while (!list_empty(&splice)) { 632 while (!list_empty(&splice)) {
631 btrfs_inode = list_entry(splice.next, struct btrfs_inode, 633 btrfs_inode = list_entry(splice.next, struct btrfs_inode,
632 ordered_operations); 634 ordered_operations);
@@ -643,7 +645,7 @@ int btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
643 645
644 if (!wait) 646 if (!wait)
645 list_add_tail(&BTRFS_I(inode)->ordered_operations, 647 list_add_tail(&BTRFS_I(inode)->ordered_operations,
646 &root->fs_info->ordered_operations); 648 &cur_trans->ordered_operations);
647 spin_unlock(&root->fs_info->ordered_extent_lock); 649 spin_unlock(&root->fs_info->ordered_extent_lock);
648 650
649 work = btrfs_alloc_delalloc_work(inode, wait, 1); 651 work = btrfs_alloc_delalloc_work(inode, wait, 1);
@@ -653,7 +655,7 @@ int btrfs_run_ordered_operations(struct btrfs_root *root, int wait)
653 list_add_tail(&btrfs_inode->ordered_operations, 655 list_add_tail(&btrfs_inode->ordered_operations,
654 &splice); 656 &splice);
655 list_splice_tail(&splice, 657 list_splice_tail(&splice,
656 &root->fs_info->ordered_operations); 658 &cur_trans->ordered_operations);
657 spin_unlock(&root->fs_info->ordered_extent_lock); 659 spin_unlock(&root->fs_info->ordered_extent_lock);
658 ret = -ENOMEM; 660 ret = -ENOMEM;
659 goto out; 661 goto out;
@@ -1033,6 +1035,7 @@ out:
1033void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, 1035void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
1034 struct btrfs_root *root, struct inode *inode) 1036 struct btrfs_root *root, struct inode *inode)
1035{ 1037{
1038 struct btrfs_transaction *cur_trans = trans->transaction;
1036 u64 last_mod; 1039 u64 last_mod;
1037 1040
1038 last_mod = max(BTRFS_I(inode)->generation, BTRFS_I(inode)->last_trans); 1041 last_mod = max(BTRFS_I(inode)->generation, BTRFS_I(inode)->last_trans);
@@ -1047,7 +1050,7 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
1047 spin_lock(&root->fs_info->ordered_extent_lock); 1050 spin_lock(&root->fs_info->ordered_extent_lock);
1048 if (list_empty(&BTRFS_I(inode)->ordered_operations)) { 1051 if (list_empty(&BTRFS_I(inode)->ordered_operations)) {
1049 list_add_tail(&BTRFS_I(inode)->ordered_operations, 1052 list_add_tail(&BTRFS_I(inode)->ordered_operations,
1050 &root->fs_info->ordered_operations); 1053 &cur_trans->ordered_operations);
1051 } 1054 }
1052 spin_unlock(&root->fs_info->ordered_extent_lock); 1055 spin_unlock(&root->fs_info->ordered_extent_lock);
1053} 1056}