|
@@ -50,6 +50,14 @@ static noinline void switch_commit_root(struct btrfs_root *root)
|
|
|
root->commit_root = btrfs_root_node(root);
|
|
|
}
|
|
|
|
|
|
+static inline int can_join_transaction(struct btrfs_transaction *trans,
|
|
|
+ int type)
|
|
|
+{
|
|
|
+ return !(trans->in_commit &&
|
|
|
+ type != TRANS_JOIN &&
|
|
|
+ type != TRANS_JOIN_NOLOCK);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* either allocate a new transaction or hop into the existing one
|
|
|
*/
|
|
@@ -85,6 +93,10 @@ loop:
|
|
|
spin_unlock(&fs_info->trans_lock);
|
|
|
return cur_trans->aborted;
|
|
|
}
|
|
|
+ if (!can_join_transaction(cur_trans, type)) {
|
|
|
+ spin_unlock(&fs_info->trans_lock);
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
atomic_inc(&cur_trans->use_count);
|
|
|
atomic_inc(&cur_trans->num_writers);
|
|
|
cur_trans->num_joined++;
|
|
@@ -360,8 +372,11 @@ again:
|
|
|
|
|
|
do {
|
|
|
ret = join_transaction(root, type);
|
|
|
- if (ret == -EBUSY)
|
|
|
+ if (ret == -EBUSY) {
|
|
|
wait_current_trans(root);
|
|
|
+ if (unlikely(type == TRANS_ATTACH))
|
|
|
+ ret = -ENOENT;
|
|
|
+ }
|
|
|
} while (ret == -EBUSY);
|
|
|
|
|
|
if (ret < 0) {
|