diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 88f866f85e7a..bca82a4ca8e6 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -186,6 +186,9 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
186 | h->alloc_exclude_start = 0; | 186 | h->alloc_exclude_start = 0; |
187 | h->delayed_ref_updates = 0; | 187 | h->delayed_ref_updates = 0; |
188 | 188 | ||
189 | if (!current->journal_info) | ||
190 | current->journal_info = h; | ||
191 | |||
189 | root->fs_info->running_transaction->use_count++; | 192 | root->fs_info->running_transaction->use_count++; |
190 | record_root_in_trans(h, root); | 193 | record_root_in_trans(h, root); |
191 | mutex_unlock(&root->fs_info->trans_mutex); | 194 | mutex_unlock(&root->fs_info->trans_mutex); |
@@ -317,6 +320,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
317 | wake_up(&cur_trans->writer_wait); | 320 | wake_up(&cur_trans->writer_wait); |
318 | put_transaction(cur_trans); | 321 | put_transaction(cur_trans); |
319 | mutex_unlock(&info->trans_mutex); | 322 | mutex_unlock(&info->trans_mutex); |
323 | |||
324 | if (current->journal_info == trans) | ||
325 | current->journal_info = NULL; | ||
320 | memset(trans, 0, sizeof(*trans)); | 326 | memset(trans, 0, sizeof(*trans)); |
321 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 327 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
322 | 328 | ||
@@ -338,10 +344,10 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, | |||
338 | /* | 344 | /* |
339 | * when btree blocks are allocated, they have some corresponding bits set for | 345 | * when btree blocks are allocated, they have some corresponding bits set for |
340 | * them in one of two extent_io trees. This is used to make sure all of | 346 | * them in one of two extent_io trees. This is used to make sure all of |
341 | * those extents are on disk for transaction or log commit | 347 | * those extents are sent to disk but does not wait on them |
342 | */ | 348 | */ |
343 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | 349 | int btrfs_write_marked_extents(struct btrfs_root *root, |
344 | struct extent_io_tree *dirty_pages) | 350 | struct extent_io_tree *dirty_pages) |
345 | { | 351 | { |
346 | int ret; | 352 | int ret; |
347 | int err = 0; | 353 | int err = 0; |
@@ -388,6 +394,29 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | |||
388 | page_cache_release(page); | 394 | page_cache_release(page); |
389 | } | 395 | } |
390 | } | 396 | } |
397 | if (err) | ||
398 | werr = err; | ||
399 | return werr; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * when btree blocks are allocated, they have some corresponding bits set for | ||
404 | * them in one of two extent_io trees. This is used to make sure all of | ||
405 | * those extents are on disk for transaction or log commit. We wait | ||
406 | * on all the pages and clear them from the dirty pages state tree | ||
407 | */ | ||
408 | int btrfs_wait_marked_extents(struct btrfs_root *root, | ||
409 | struct extent_io_tree *dirty_pages) | ||
410 | { | ||
411 | int ret; | ||
412 | int err = 0; | ||
413 | int werr = 0; | ||
414 | struct page *page; | ||
415 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
416 | u64 start = 0; | ||
417 | u64 end; | ||
418 | unsigned long index; | ||
419 | |||
391 | while (1) { | 420 | while (1) { |
392 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, | 421 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, |
393 | EXTENT_DIRTY); | 422 | EXTENT_DIRTY); |
@@ -418,6 +447,22 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | |||
418 | return werr; | 447 | return werr; |
419 | } | 448 | } |
420 | 449 | ||
450 | /* | ||
451 | * when btree blocks are allocated, they have some corresponding bits set for | ||
452 | * them in one of two extent_io trees. This is used to make sure all of | ||
453 | * those extents are on disk for transaction or log commit | ||
454 | */ | ||
455 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | ||
456 | struct extent_io_tree *dirty_pages) | ||
457 | { | ||
458 | int ret; | ||
459 | int ret2; | ||
460 | |||
461 | ret = btrfs_write_marked_extents(root, dirty_pages); | ||
462 | ret2 = btrfs_wait_marked_extents(root, dirty_pages); | ||
463 | return ret || ret2; | ||
464 | } | ||
465 | |||
421 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 466 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
422 | struct btrfs_root *root) | 467 | struct btrfs_root *root) |
423 | { | 468 | { |
@@ -743,6 +788,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
743 | memcpy(&pending->root_key, &key, sizeof(key)); | 788 | memcpy(&pending->root_key, &key, sizeof(key)); |
744 | fail: | 789 | fail: |
745 | kfree(new_root_item); | 790 | kfree(new_root_item); |
791 | btrfs_unreserve_metadata_space(root, 6); | ||
746 | return ret; | 792 | return ret; |
747 | } | 793 | } |
748 | 794 | ||
@@ -1059,6 +1105,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1059 | 1105 | ||
1060 | mutex_unlock(&root->fs_info->trans_mutex); | 1106 | mutex_unlock(&root->fs_info->trans_mutex); |
1061 | 1107 | ||
1108 | if (current->journal_info == trans) | ||
1109 | current->journal_info = NULL; | ||
1110 | |||
1062 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 1111 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
1063 | return ret; | 1112 | return ret; |
1064 | } | 1113 | } |