aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
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 {