aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-06-10 16:47:23 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-07-01 08:52:27 -0400
commit501407aab8c947911b10cf5a0e0043019d5a4f17 (patch)
tree32bd0813ecea865ae52fbf969851cfe01292a593 /fs/btrfs/transaction.c
parentf971fe29b14eedd4abc389593b77fbdf94ac2d59 (diff)
Btrfs: stop waiting on current trans if we aborted
I hit a hang when run_delayed_refs returned an error in the beginning of btrfs_commit_transaction. If we decide we need to commit the transaction in btrfs_end_transaction we'll set BLOCKED and start to commit, but if we get an error this early on we'll just exit without committing. This is fine, except that anybody else who tried to start a transaction will sit in wait_current_trans() since we're set to BLOCKED and we never set it to something else and woke people up. To fix this we want to check for trans->aborted everywhere we wait for the transaction state to change, and make btrfs_abort_transaction() wake up any waiters there may be. All the callers will notice that the transaction has aborted and exit out properly. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c12
1 files changed, 8 insertions, 4 deletions
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,
302static inline int is_transaction_blocked(struct btrfs_transaction *trans) 302static inline int is_transaction_blocked(struct btrfs_transaction *trans)
303{ 303{
304 return (trans->state >= TRANS_STATE_BLOCKED && 304 return (trans->state >= TRANS_STATE_BLOCKED &&
305 trans->state < TRANS_STATE_UNBLOCKED); 305 trans->state < TRANS_STATE_UNBLOCKED &&
306 !trans->aborted);
306} 307}
307 308
308/* wait for commit against the current transaction to become unblocked 309/* wait for commit against the current transaction to become unblocked
@@ -320,7 +321,8 @@ static void wait_current_trans(struct btrfs_root *root)
320 spin_unlock(&root->fs_info->trans_lock); 321 spin_unlock(&root->fs_info->trans_lock);
321 322
322 wait_event(root->fs_info->transaction_wait, 323 wait_event(root->fs_info->transaction_wait,
323 cur_trans->state >= TRANS_STATE_UNBLOCKED); 324 cur_trans->state >= TRANS_STATE_UNBLOCKED ||
325 cur_trans->aborted);
324 put_transaction(cur_trans); 326 put_transaction(cur_trans);
325 } else { 327 } else {
326 spin_unlock(&root->fs_info->trans_lock); 328 spin_unlock(&root->fs_info->trans_lock);
@@ -1392,7 +1394,8 @@ static void wait_current_trans_commit_start(struct btrfs_root *root,
1392 struct btrfs_transaction *trans) 1394 struct btrfs_transaction *trans)
1393{ 1395{
1394 wait_event(root->fs_info->transaction_blocked_wait, 1396 wait_event(root->fs_info->transaction_blocked_wait,
1395 trans->state >= TRANS_STATE_COMMIT_START); 1397 trans->state >= TRANS_STATE_COMMIT_START ||
1398 trans->aborted);
1396} 1399}
1397 1400
1398/* 1401/*
@@ -1403,7 +1406,8 @@ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root,
1403 struct btrfs_transaction *trans) 1406 struct btrfs_transaction *trans)
1404{ 1407{
1405 wait_event(root->fs_info->transaction_wait, 1408 wait_event(root->fs_info->transaction_wait,
1406 trans->state >= TRANS_STATE_UNBLOCKED); 1409 trans->state >= TRANS_STATE_UNBLOCKED ||
1410 trans->aborted);
1407} 1411}
1408 1412
1409/* 1413/*