diff options
-rw-r--r-- | fs/btrfs/transaction.c | 45 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 4 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 8 |
3 files changed, 53 insertions, 4 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 0b8f36d4400a..bca82a4ca8e6 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -344,10 +344,10 @@ int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans, | |||
344 | /* | 344 | /* |
345 | * 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 |
346 | * 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 |
347 | * those extents are on disk for transaction or log commit | 347 | * those extents are sent to disk but does not wait on them |
348 | */ | 348 | */ |
349 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | 349 | int btrfs_write_marked_extents(struct btrfs_root *root, |
350 | struct extent_io_tree *dirty_pages) | 350 | struct extent_io_tree *dirty_pages) |
351 | { | 351 | { |
352 | int ret; | 352 | int ret; |
353 | int err = 0; | 353 | int err = 0; |
@@ -394,6 +394,29 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | |||
394 | page_cache_release(page); | 394 | page_cache_release(page); |
395 | } | 395 | } |
396 | } | 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 | |||
397 | while (1) { | 420 | while (1) { |
398 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, | 421 | ret = find_first_extent_bit(dirty_pages, 0, &start, &end, |
399 | EXTENT_DIRTY); | 422 | EXTENT_DIRTY); |
@@ -424,6 +447,22 @@ int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | |||
424 | return werr; | 447 | return werr; |
425 | } | 448 | } |
426 | 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 | |||
427 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 466 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
428 | struct btrfs_root *root) | 467 | struct btrfs_root *root) |
429 | { | 468 | { |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index f68cbbe61e56..d4e3e7a6938c 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -108,5 +108,9 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | |||
108 | struct btrfs_root *root); | 108 | struct btrfs_root *root); |
109 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | 109 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, |
110 | struct extent_io_tree *dirty_pages); | 110 | struct extent_io_tree *dirty_pages); |
111 | int btrfs_write_marked_extents(struct btrfs_root *root, | ||
112 | struct extent_io_tree *dirty_pages); | ||
113 | int btrfs_wait_marked_extents(struct btrfs_root *root, | ||
114 | struct extent_io_tree *dirty_pages); | ||
111 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info); | 115 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info); |
112 | #endif | 116 | #endif |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 0a1bde268963..4aff766d171a 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2013,7 +2013,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2013 | goto out; | 2013 | goto out; |
2014 | } | 2014 | } |
2015 | 2015 | ||
2016 | ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); | 2016 | /* we start IO on all the marked extents here, but we don't actually |
2017 | * wait for them until later. | ||
2018 | */ | ||
2019 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages); | ||
2017 | BUG_ON(ret); | 2020 | BUG_ON(ret); |
2018 | 2021 | ||
2019 | btrfs_set_root_node(&log->root_item, log->node); | 2022 | btrfs_set_root_node(&log->root_item, log->node); |
@@ -2048,6 +2051,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2048 | 2051 | ||
2049 | index2 = log_root_tree->log_transid % 2; | 2052 | index2 = log_root_tree->log_transid % 2; |
2050 | if (atomic_read(&log_root_tree->log_commit[index2])) { | 2053 | if (atomic_read(&log_root_tree->log_commit[index2])) { |
2054 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | ||
2051 | wait_log_commit(trans, log_root_tree, | 2055 | wait_log_commit(trans, log_root_tree, |
2052 | log_root_tree->log_transid); | 2056 | log_root_tree->log_transid); |
2053 | mutex_unlock(&log_root_tree->log_mutex); | 2057 | mutex_unlock(&log_root_tree->log_mutex); |
@@ -2067,6 +2071,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2067 | * check the full commit flag again | 2071 | * check the full commit flag again |
2068 | */ | 2072 | */ |
2069 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2073 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { |
2074 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | ||
2070 | mutex_unlock(&log_root_tree->log_mutex); | 2075 | mutex_unlock(&log_root_tree->log_mutex); |
2071 | ret = -EAGAIN; | 2076 | ret = -EAGAIN; |
2072 | goto out_wake_log_root; | 2077 | goto out_wake_log_root; |
@@ -2075,6 +2080,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2075 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, | 2080 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, |
2076 | &log_root_tree->dirty_log_pages); | 2081 | &log_root_tree->dirty_log_pages); |
2077 | BUG_ON(ret); | 2082 | BUG_ON(ret); |
2083 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | ||
2078 | 2084 | ||
2079 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, | 2085 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, |
2080 | log_root_tree->node->start); | 2086 | log_root_tree->node->start); |