diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c276ac9a0ec3..ff60d8978ae2 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/blkdev.h> | ||
21 | #include <linux/list_sort.h> | 22 | #include <linux/list_sort.h> |
22 | #include "ctree.h" | 23 | #include "ctree.h" |
23 | #include "transaction.h" | 24 | #include "transaction.h" |
@@ -279,11 +280,23 @@ static int process_one_buffer(struct btrfs_root *log, | |||
279 | { | 280 | { |
280 | int ret = 0; | 281 | int ret = 0; |
281 | 282 | ||
283 | /* | ||
284 | * If this fs is mixed then we need to be able to process the leaves to | ||
285 | * pin down any logged extents, so we have to read the block. | ||
286 | */ | ||
287 | if (btrfs_fs_incompat(log->fs_info, MIXED_GROUPS)) { | ||
288 | ret = btrfs_read_buffer(eb, gen); | ||
289 | if (ret) | ||
290 | return ret; | ||
291 | } | ||
292 | |||
282 | if (wc->pin) | 293 | if (wc->pin) |
283 | ret = btrfs_pin_extent_for_log_replay(log->fs_info->extent_root, | 294 | ret = btrfs_pin_extent_for_log_replay(log->fs_info->extent_root, |
284 | eb->start, eb->len); | 295 | eb->start, eb->len); |
285 | 296 | ||
286 | if (!ret && btrfs_buffer_uptodate(eb, gen, 0)) { | 297 | if (!ret && btrfs_buffer_uptodate(eb, gen, 0)) { |
298 | if (wc->pin && btrfs_header_level(eb) == 0) | ||
299 | ret = btrfs_exclude_logged_extents(log, eb); | ||
287 | if (wc->write) | 300 | if (wc->write) |
288 | btrfs_write_tree_block(eb); | 301 | btrfs_write_tree_block(eb); |
289 | if (wc->wait) | 302 | if (wc->wait) |
@@ -2016,13 +2029,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
2016 | eb, i, &key); | 2029 | eb, i, &key); |
2017 | if (ret) | 2030 | if (ret) |
2018 | break; | 2031 | break; |
2019 | } else if (key.type == BTRFS_INODE_REF_KEY) { | 2032 | } else if (key.type == BTRFS_INODE_REF_KEY || |
2020 | ret = add_inode_ref(wc->trans, root, log, path, | 2033 | key.type == BTRFS_INODE_EXTREF_KEY) { |
2021 | eb, i, &key); | ||
2022 | if (ret && ret != -ENOENT) | ||
2023 | break; | ||
2024 | ret = 0; | ||
2025 | } else if (key.type == BTRFS_INODE_EXTREF_KEY) { | ||
2026 | ret = add_inode_ref(wc->trans, root, log, path, | 2034 | ret = add_inode_ref(wc->trans, root, log, path, |
2027 | eb, i, &key); | 2035 | eb, i, &key); |
2028 | if (ret && ret != -ENOENT) | 2036 | if (ret && ret != -ENOENT) |
@@ -2358,6 +2366,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2358 | struct btrfs_root *log = root->log_root; | 2366 | struct btrfs_root *log = root->log_root; |
2359 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; | 2367 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; |
2360 | unsigned long log_transid = 0; | 2368 | unsigned long log_transid = 0; |
2369 | struct blk_plug plug; | ||
2361 | 2370 | ||
2362 | mutex_lock(&root->log_mutex); | 2371 | mutex_lock(&root->log_mutex); |
2363 | log_transid = root->log_transid; | 2372 | log_transid = root->log_transid; |
@@ -2401,8 +2410,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2401 | /* we start IO on all the marked extents here, but we don't actually | 2410 | /* we start IO on all the marked extents here, but we don't actually |
2402 | * wait for them until later. | 2411 | * wait for them until later. |
2403 | */ | 2412 | */ |
2413 | blk_start_plug(&plug); | ||
2404 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark); | 2414 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark); |
2405 | if (ret) { | 2415 | if (ret) { |
2416 | blk_finish_plug(&plug); | ||
2406 | btrfs_abort_transaction(trans, root, ret); | 2417 | btrfs_abort_transaction(trans, root, ret); |
2407 | btrfs_free_logged_extents(log, log_transid); | 2418 | btrfs_free_logged_extents(log, log_transid); |
2408 | mutex_unlock(&root->log_mutex); | 2419 | mutex_unlock(&root->log_mutex); |
@@ -2437,6 +2448,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2437 | } | 2448 | } |
2438 | 2449 | ||
2439 | if (ret) { | 2450 | if (ret) { |
2451 | blk_finish_plug(&plug); | ||
2440 | if (ret != -ENOSPC) { | 2452 | if (ret != -ENOSPC) { |
2441 | btrfs_abort_transaction(trans, root, ret); | 2453 | btrfs_abort_transaction(trans, root, ret); |
2442 | mutex_unlock(&log_root_tree->log_mutex); | 2454 | mutex_unlock(&log_root_tree->log_mutex); |
@@ -2452,6 +2464,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2452 | 2464 | ||
2453 | index2 = log_root_tree->log_transid % 2; | 2465 | index2 = log_root_tree->log_transid % 2; |
2454 | if (atomic_read(&log_root_tree->log_commit[index2])) { | 2466 | if (atomic_read(&log_root_tree->log_commit[index2])) { |
2467 | blk_finish_plug(&plug); | ||
2455 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2468 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2456 | wait_log_commit(trans, log_root_tree, | 2469 | wait_log_commit(trans, log_root_tree, |
2457 | log_root_tree->log_transid); | 2470 | log_root_tree->log_transid); |
@@ -2474,6 +2487,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2474 | * check the full commit flag again | 2487 | * check the full commit flag again |
2475 | */ | 2488 | */ |
2476 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2489 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { |
2490 | blk_finish_plug(&plug); | ||
2477 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2491 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2478 | btrfs_free_logged_extents(log, log_transid); | 2492 | btrfs_free_logged_extents(log, log_transid); |
2479 | mutex_unlock(&log_root_tree->log_mutex); | 2493 | mutex_unlock(&log_root_tree->log_mutex); |
@@ -2481,9 +2495,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2481 | goto out_wake_log_root; | 2495 | goto out_wake_log_root; |
2482 | } | 2496 | } |
2483 | 2497 | ||
2484 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, | 2498 | ret = btrfs_write_marked_extents(log_root_tree, |
2485 | &log_root_tree->dirty_log_pages, | 2499 | &log_root_tree->dirty_log_pages, |
2486 | EXTENT_DIRTY | EXTENT_NEW); | 2500 | EXTENT_DIRTY | EXTENT_NEW); |
2501 | blk_finish_plug(&plug); | ||
2487 | if (ret) { | 2502 | if (ret) { |
2488 | btrfs_abort_transaction(trans, root, ret); | 2503 | btrfs_abort_transaction(trans, root, ret); |
2489 | btrfs_free_logged_extents(log, log_transid); | 2504 | btrfs_free_logged_extents(log, log_transid); |
@@ -2491,6 +2506,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2491 | goto out_wake_log_root; | 2506 | goto out_wake_log_root; |
2492 | } | 2507 | } |
2493 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2508 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2509 | btrfs_wait_marked_extents(log_root_tree, | ||
2510 | &log_root_tree->dirty_log_pages, | ||
2511 | EXTENT_NEW | EXTENT_DIRTY); | ||
2494 | btrfs_wait_logged_extents(log, log_transid); | 2512 | btrfs_wait_logged_extents(log, log_transid); |
2495 | 2513 | ||
2496 | btrfs_set_super_log_root(root->fs_info->super_for_commit, | 2514 | btrfs_set_super_log_root(root->fs_info->super_for_commit, |
@@ -3728,8 +3746,9 @@ next_slot: | |||
3728 | } | 3746 | } |
3729 | 3747 | ||
3730 | log_extents: | 3748 | log_extents: |
3749 | btrfs_release_path(path); | ||
3750 | btrfs_release_path(dst_path); | ||
3731 | if (fast_search) { | 3751 | if (fast_search) { |
3732 | btrfs_release_path(dst_path); | ||
3733 | ret = btrfs_log_changed_extents(trans, root, inode, dst_path); | 3752 | ret = btrfs_log_changed_extents(trans, root, inode, dst_path); |
3734 | if (ret) { | 3753 | if (ret) { |
3735 | err = ret; | 3754 | err = ret; |
@@ -3746,8 +3765,6 @@ log_extents: | |||
3746 | } | 3765 | } |
3747 | 3766 | ||
3748 | if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) { | 3767 | if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) { |
3749 | btrfs_release_path(path); | ||
3750 | btrfs_release_path(dst_path); | ||
3751 | ret = log_directory_changes(trans, root, inode, path, dst_path); | 3768 | ret = log_directory_changes(trans, root, inode, path, dst_path); |
3752 | if (ret) { | 3769 | if (ret) { |
3753 | err = ret; | 3770 | err = ret; |
@@ -4016,8 +4033,7 @@ again: | |||
4016 | if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID) | 4033 | if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID) |
4017 | break; | 4034 | break; |
4018 | 4035 | ||
4019 | log = btrfs_read_fs_root_no_radix(log_root_tree, | 4036 | log = btrfs_read_fs_root(log_root_tree, &found_key); |
4020 | &found_key); | ||
4021 | if (IS_ERR(log)) { | 4037 | if (IS_ERR(log)) { |
4022 | ret = PTR_ERR(log); | 4038 | ret = PTR_ERR(log); |
4023 | btrfs_error(fs_info, ret, | 4039 | btrfs_error(fs_info, ret, |