diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c276ac9a0ec3..2c6791493637 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, |
| @@ -4016,8 +4034,7 @@ again: | |||
| 4016 | if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID) | 4034 | if (found_key.objectid != BTRFS_TREE_LOG_OBJECTID) |
| 4017 | break; | 4035 | break; |
| 4018 | 4036 | ||
| 4019 | log = btrfs_read_fs_root_no_radix(log_root_tree, | 4037 | log = btrfs_read_fs_root(log_root_tree, &found_key); |
| 4020 | &found_key); | ||
| 4021 | if (IS_ERR(log)) { | 4038 | if (IS_ERR(log)) { |
| 4022 | ret = PTR_ERR(log); | 4039 | ret = PTR_ERR(log); |
| 4023 | btrfs_error(fs_info, ret, | 4040 | btrfs_error(fs_info, ret, |
