aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/super.c3
-rw-r--r--fs/btrfs/transaction.c12
2 files changed, 11 insertions, 4 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 14d2be03f95a..8eb6191d86da 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -265,6 +265,9 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
return;
}
ACCESS_ONCE(trans->transaction->aborted) = errno;
+ /* Wake up anybody who may be waiting on this transaction */
+ wake_up(&root->fs_info->transaction_wait);
+ wake_up(&root->fs_info->transaction_blocked_wait);
__btrfs_std_error(root->fs_info, function, line, errno, NULL);
}
/*
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 8c8b80085e75..c11b7efcc561 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -302,7 +302,8 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
static inline int is_transaction_blocked(struct btrfs_transaction *trans)
{
return (trans->state >= TRANS_STATE_BLOCKED &&
- trans->state < TRANS_STATE_UNBLOCKED);
+ trans->state < TRANS_STATE_UNBLOCKED &&
+ !trans->aborted);
}
/* wait for commit against the current transaction to become unblocked
@@ -320,7 +321,8 @@ static void wait_current_trans(struct btrfs_root *root)
spin_unlock(&root->fs_info->trans_lock);
wait_event(root->fs_info->transaction_wait,
- cur_trans->state >= TRANS_STATE_UNBLOCKED);
+ cur_trans->state >= TRANS_STATE_UNBLOCKED ||
+ cur_trans->aborted);
put_transaction(cur_trans);
} else {
spin_unlock(&root->fs_info->trans_lock);
@@ -1392,7 +1394,8 @@ static void wait_current_trans_commit_start(struct btrfs_root *root,
struct btrfs_transaction *trans)
{
wait_event(root->fs_info->transaction_blocked_wait,
- trans->state >= TRANS_STATE_COMMIT_START);
+ trans->state >= TRANS_STATE_COMMIT_START ||
+ trans->aborted);
}
/*
@@ -1403,7 +1406,8 @@ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root,
struct btrfs_transaction *trans)
{
wait_event(root->fs_info->transaction_wait,
- trans->state >= TRANS_STATE_UNBLOCKED);
+ trans->state >= TRANS_STATE_UNBLOCKED ||
+ trans->aborted);
}
/*