diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-02-20 05:08:52 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fb.com> | 2014-03-10 15:16:40 -0400 |
commit | 48cab2e0714913a63155f800a55609a4ff6a36b9 (patch) | |
tree | 1767dcb212dc53386e30e4bafa13b1bc8f475785 /fs/btrfs/tree-log.c | |
parent | 5c902ba6223f6a6575054226931fafc51314a25f (diff) |
Btrfs: fix the skipped transaction commit during the file sync
We may abort the wait earlier if ->last_trans_log_full_commit was set to
the current transaction id, at this case, we need commit the current
transaction instead of the log sub-transaction. But the current code
didn't tell the caller to do it (return 0, not -EAGAIN). Fix it.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 5a4e10b9ac3e..8a03b39648be 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2364,6 +2364,7 @@ static int wait_log_commit(struct btrfs_trans_handle *trans, | |||
2364 | { | 2364 | { |
2365 | DEFINE_WAIT(wait); | 2365 | DEFINE_WAIT(wait); |
2366 | int index = transid % 2; | 2366 | int index = transid % 2; |
2367 | int ret = 0; | ||
2367 | 2368 | ||
2368 | /* | 2369 | /* |
2369 | * we only allow two pending log transactions at a time, | 2370 | * we only allow two pending log transactions at a time, |
@@ -2371,21 +2372,26 @@ static int wait_log_commit(struct btrfs_trans_handle *trans, | |||
2371 | * current transaction, we're done | 2372 | * current transaction, we're done |
2372 | */ | 2373 | */ |
2373 | do { | 2374 | do { |
2375 | if (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) == | ||
2376 | trans->transid) { | ||
2377 | ret = -EAGAIN; | ||
2378 | break; | ||
2379 | } | ||
2380 | |||
2374 | prepare_to_wait(&root->log_commit_wait[index], | 2381 | prepare_to_wait(&root->log_commit_wait[index], |
2375 | &wait, TASK_UNINTERRUPTIBLE); | 2382 | &wait, TASK_UNINTERRUPTIBLE); |
2376 | mutex_unlock(&root->log_mutex); | 2383 | mutex_unlock(&root->log_mutex); |
2377 | 2384 | ||
2378 | if (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) != | 2385 | if (root->log_transid < transid + 2 && |
2379 | trans->transid && root->log_transid < transid + 2 && | ||
2380 | atomic_read(&root->log_commit[index])) | 2386 | atomic_read(&root->log_commit[index])) |
2381 | schedule(); | 2387 | schedule(); |
2382 | 2388 | ||
2383 | finish_wait(&root->log_commit_wait[index], &wait); | 2389 | finish_wait(&root->log_commit_wait[index], &wait); |
2384 | mutex_lock(&root->log_mutex); | 2390 | mutex_lock(&root->log_mutex); |
2385 | } while (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) != | 2391 | } while (root->log_transid < transid + 2 && |
2386 | trans->transid && root->log_transid < transid + 2 && | ||
2387 | atomic_read(&root->log_commit[index])); | 2392 | atomic_read(&root->log_commit[index])); |
2388 | return 0; | 2393 | |
2394 | return ret; | ||
2389 | } | 2395 | } |
2390 | 2396 | ||
2391 | static void wait_for_writer(struct btrfs_trans_handle *trans, | 2397 | static void wait_for_writer(struct btrfs_trans_handle *trans, |
@@ -2433,15 +2439,16 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2433 | log_transid = root->log_transid; | 2439 | log_transid = root->log_transid; |
2434 | index1 = root->log_transid % 2; | 2440 | index1 = root->log_transid % 2; |
2435 | if (atomic_read(&root->log_commit[index1])) { | 2441 | if (atomic_read(&root->log_commit[index1])) { |
2436 | wait_log_commit(trans, root, root->log_transid); | 2442 | ret = wait_log_commit(trans, root, root->log_transid); |
2437 | mutex_unlock(&root->log_mutex); | 2443 | mutex_unlock(&root->log_mutex); |
2438 | return 0; | 2444 | return ret; |
2439 | } | 2445 | } |
2440 | atomic_set(&root->log_commit[index1], 1); | 2446 | atomic_set(&root->log_commit[index1], 1); |
2441 | 2447 | ||
2442 | /* wait for previous tree log sync to complete */ | 2448 | /* wait for previous tree log sync to complete */ |
2443 | if (atomic_read(&root->log_commit[(index1 + 1) % 2])) | 2449 | if (atomic_read(&root->log_commit[(index1 + 1) % 2])) |
2444 | wait_log_commit(trans, root, root->log_transid - 1); | 2450 | wait_log_commit(trans, root, root->log_transid - 1); |
2451 | |||
2445 | while (1) { | 2452 | while (1) { |
2446 | int batch = atomic_read(&root->log_batch); | 2453 | int batch = atomic_read(&root->log_batch); |
2447 | /* when we're on an ssd, just kick the log commit out */ | 2454 | /* when we're on an ssd, just kick the log commit out */ |
@@ -2529,11 +2536,10 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2529 | if (atomic_read(&log_root_tree->log_commit[index2])) { | 2536 | if (atomic_read(&log_root_tree->log_commit[index2])) { |
2530 | blk_finish_plug(&plug); | 2537 | blk_finish_plug(&plug); |
2531 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); | 2538 | btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); |
2532 | wait_log_commit(trans, log_root_tree, | 2539 | ret = wait_log_commit(trans, log_root_tree, |
2533 | log_root_tree->log_transid); | 2540 | log_root_tree->log_transid); |
2534 | btrfs_free_logged_extents(log, log_transid); | 2541 | btrfs_free_logged_extents(log, log_transid); |
2535 | mutex_unlock(&log_root_tree->log_mutex); | 2542 | mutex_unlock(&log_root_tree->log_mutex); |
2536 | ret = 0; | ||
2537 | goto out; | 2543 | goto out; |
2538 | } | 2544 | } |
2539 | atomic_set(&log_root_tree->log_commit[index2], 1); | 2545 | atomic_set(&log_root_tree->log_commit[index2], 1); |