aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-04-13 15:15:59 -0400
committerJosef Bacik <josef@redhat.com>2011-05-23 13:00:57 -0400
commit2a1eb4614d984d5cd4c928784e9afcf5c07f93be (patch)
tree892b123c194e490a2dc0bc5b45f641ac921e9d26 /fs
parent7a7eaa40a39bde4eefc91aadeb1ce3dc4e6a1252 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/transaction.c17
-rw-r--r--fs/btrfs/transaction.h2
2 files changed, 19 insertions, 0 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 70bfb26df967..46f40564c168 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -184,6 +184,15 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
184 184
185 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) 185 if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
186 return ERR_PTR(-EROFS); 186 return ERR_PTR(-EROFS);
187
188 if (current->journal_info) {
189 WARN_ON(type != TRANS_JOIN && type != TRANS_JOIN_NOLOCK);
190 h = current->journal_info;
191 h->use_count++;
192 h->orig_rsv = h->block_rsv;
193 h->block_rsv = NULL;
194 goto got_it;
195 }
187again: 196again:
188 h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); 197 h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
189 if (!h) 198 if (!h)
@@ -213,7 +222,9 @@ again:
213 h->block_group = 0; 222 h->block_group = 0;
214 h->bytes_reserved = 0; 223 h->bytes_reserved = 0;
215 h->delayed_ref_updates = 0; 224 h->delayed_ref_updates = 0;
225 h->use_count = 1;
216 h->block_rsv = NULL; 226 h->block_rsv = NULL;
227 h->orig_rsv = NULL;
217 228
218 smp_mb(); 229 smp_mb();
219 if (cur_trans->blocked && may_wait_transaction(root, type)) { 230 if (cur_trans->blocked && may_wait_transaction(root, type)) {
@@ -241,6 +252,7 @@ again:
241 } 252 }
242 } 253 }
243 254
255got_it:
244 if (type != TRANS_JOIN_NOLOCK) 256 if (type != TRANS_JOIN_NOLOCK)
245 mutex_lock(&root->fs_info->trans_mutex); 257 mutex_lock(&root->fs_info->trans_mutex);
246 record_root_in_trans(h, root); 258 record_root_in_trans(h, root);
@@ -428,6 +440,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
428 struct btrfs_fs_info *info = root->fs_info; 440 struct btrfs_fs_info *info = root->fs_info;
429 int count = 0; 441 int count = 0;
430 442
443 if (--trans->use_count) {
444 trans->block_rsv = trans->orig_rsv;
445 return 0;
446 }
447
431 while (count < 4) { 448 while (count < 4) {
432 unsigned long cur = trans->delayed_ref_updates; 449 unsigned long cur = trans->delayed_ref_updates;
433 trans->delayed_ref_updates = 0; 450 trans->delayed_ref_updates = 0;
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 1f573f09dba2..154314f80f8d 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -47,11 +47,13 @@ struct btrfs_trans_handle {
47 u64 transid; 47 u64 transid;
48 u64 block_group; 48 u64 block_group;
49 u64 bytes_reserved; 49 u64 bytes_reserved;
50 unsigned long use_count;
50 unsigned long blocks_reserved; 51 unsigned long blocks_reserved;
51 unsigned long blocks_used; 52 unsigned long blocks_used;
52 unsigned long delayed_ref_updates; 53 unsigned long delayed_ref_updates;
53 struct btrfs_transaction *transaction; 54 struct btrfs_transaction *transaction;
54 struct btrfs_block_rsv *block_rsv; 55 struct btrfs_block_rsv *block_rsv;
56 struct btrfs_block_rsv *orig_rsv;
55}; 57};
56 58
57struct btrfs_pending_snapshot { 59struct btrfs_pending_snapshot {