diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/transaction.c | 17 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 2 |
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 | } | ||
187 | again: | 196 | again: |
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 | ||
255 | got_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 | ||
57 | struct btrfs_pending_snapshot { | 59 | struct btrfs_pending_snapshot { |