Btrfs: if we've already started a trans handle, use that one
We currently track trans handles in current->journal_info, but we don't actually use it. This patch fixes it. This will cover the case where we have multiple people starting transactions down the call chain. This keeps us from having to allocate a new handle and all of that, we just increase the use count of the current handle, save the old block_rsv, and return. I tested this with xfstests and it worked out fine. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
This commit is contained in:
parent
7a7eaa40a3
commit
2a1eb4614d
2 changed files with 19 additions and 0 deletions
|
@ -184,6 +184,15 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
|
|||
|
||||
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
|
||||
return ERR_PTR(-EROFS);
|
||||
|
||||
if (current->journal_info) {
|
||||
WARN_ON(type != TRANS_JOIN && type != TRANS_JOIN_NOLOCK);
|
||||
h = current->journal_info;
|
||||
h->use_count++;
|
||||
h->orig_rsv = h->block_rsv;
|
||||
h->block_rsv = NULL;
|
||||
goto got_it;
|
||||
}
|
||||
again:
|
||||
h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
|
||||
if (!h)
|
||||
|
@ -213,7 +222,9 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
|
|||
h->block_group = 0;
|
||||
h->bytes_reserved = 0;
|
||||
h->delayed_ref_updates = 0;
|
||||
h->use_count = 1;
|
||||
h->block_rsv = NULL;
|
||||
h->orig_rsv = NULL;
|
||||
|
||||
smp_mb();
|
||||
if (cur_trans->blocked && may_wait_transaction(root, type)) {
|
||||
|
@ -241,6 +252,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
|
|||
}
|
||||
}
|
||||
|
||||
got_it:
|
||||
if (type != TRANS_JOIN_NOLOCK)
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
record_root_in_trans(h, root);
|
||||
|
@ -428,6 +440,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
|||
struct btrfs_fs_info *info = root->fs_info;
|
||||
int count = 0;
|
||||
|
||||
if (--trans->use_count) {
|
||||
trans->block_rsv = trans->orig_rsv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (count < 4) {
|
||||
unsigned long cur = trans->delayed_ref_updates;
|
||||
trans->delayed_ref_updates = 0;
|
||||
|
|
|
@ -47,11 +47,13 @@ struct btrfs_trans_handle {
|
|||
u64 transid;
|
||||
u64 block_group;
|
||||
u64 bytes_reserved;
|
||||
unsigned long use_count;
|
||||
unsigned long blocks_reserved;
|
||||
unsigned long blocks_used;
|
||||
unsigned long delayed_ref_updates;
|
||||
struct btrfs_transaction *transaction;
|
||||
struct btrfs_block_rsv *block_rsv;
|
||||
struct btrfs_block_rsv *orig_rsv;
|
||||
};
|
||||
|
||||
struct btrfs_pending_snapshot {
|
||||
|
|
Loading…
Reference in a new issue