Skip to content

Commit d1433de

Browse files
Miao XieJosef Bacik
authored andcommitted
Btrfs: just wait or commit our own log sub-transaction
We might commit the log sub-transaction which didn't contain the metadata we logged. It was because we didn't record the log transid and just select the current log sub-transaction to commit, but the right one might be committed by the other task already. Actually, we needn't do anything and it is safe that we go back directly in this case. This patch improves the log sync by the above idea. We record the transid of the log sub-transaction in which we log the metadata, and the transid of the log sub-transaction we have committed. If the committed transid is >= the transid we record when logging the metadata, we just go back. Signed-off-by: Miao Xie <[email protected]> Signed-off-by: Josef Bacik <[email protected]>
1 parent 8b050d3 commit d1433de

File tree

4 files changed

+47
-23
lines changed

4 files changed

+47
-23
lines changed

fs/btrfs/ctree.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,9 @@ struct btrfs_root {
17231723
atomic_t log_commit[2];
17241724
atomic_t log_batch;
17251725
int log_transid;
1726+
/* No matter the commit succeeds or not*/
1727+
int log_transid_committed;
1728+
/* Just be updated when the commit succeeds. */
17261729
int last_log_commit;
17271730
pid_t log_start_pid;
17281731
bool log_multiple_pids;

fs/btrfs/disk-io.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,7 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
12091209
atomic_set(&root->orphan_inodes, 0);
12101210
atomic_set(&root->refs, 1);
12111211
root->log_transid = 0;
1212+
root->log_transid_committed = -1;
12121213
root->last_log_commit = 0;
12131214
if (fs_info)
12141215
extent_io_tree_init(&root->dirty_log_pages,
@@ -1422,6 +1423,7 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
14221423
WARN_ON(root->log_root);
14231424
root->log_root = log_root;
14241425
root->log_transid = 0;
1426+
root->log_transid_committed = -1;
14251427
root->last_log_commit = 0;
14261428
return 0;
14271429
}

fs/btrfs/tree-log.c

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
156156
if (ctx) {
157157
index = root->log_transid % 2;
158158
list_add_tail(&ctx->list, &root->log_ctxs[index]);
159+
ctx->log_transid = root->log_transid;
159160
}
160161
mutex_unlock(&root->log_mutex);
161162
return 0;
@@ -181,6 +182,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
181182
if (ctx) {
182183
index = root->log_transid % 2;
183184
list_add_tail(&ctx->list, &root->log_ctxs[index]);
185+
ctx->log_transid = root->log_transid;
184186
}
185187
out:
186188
mutex_unlock(&root->log_mutex);
@@ -2387,13 +2389,13 @@ static void wait_log_commit(struct btrfs_trans_handle *trans,
23872389
&wait, TASK_UNINTERRUPTIBLE);
23882390
mutex_unlock(&root->log_mutex);
23892391

2390-
if (root->log_transid < transid + 2 &&
2392+
if (root->log_transid_committed < transid &&
23912393
atomic_read(&root->log_commit[index]))
23922394
schedule();
23932395

23942396
finish_wait(&root->log_commit_wait[index], &wait);
23952397
mutex_lock(&root->log_mutex);
2396-
} while (root->log_transid < transid + 2 &&
2398+
} while (root->log_transid_committed < transid &&
23972399
atomic_read(&root->log_commit[index]));
23982400
}
23992401

@@ -2470,18 +2472,24 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
24702472
struct blk_plug plug;
24712473

24722474
mutex_lock(&root->log_mutex);
2473-
log_transid = root->log_transid;
2474-
index1 = root->log_transid % 2;
2475+
log_transid = ctx->log_transid;
2476+
if (root->log_transid_committed >= log_transid) {
2477+
mutex_unlock(&root->log_mutex);
2478+
return ctx->log_ret;
2479+
}
2480+
2481+
index1 = log_transid % 2;
24752482
if (atomic_read(&root->log_commit[index1])) {
2476-
wait_log_commit(trans, root, root->log_transid);
2483+
wait_log_commit(trans, root, log_transid);
24772484
mutex_unlock(&root->log_mutex);
24782485
return ctx->log_ret;
24792486
}
2487+
ASSERT(log_transid == root->log_transid);
24802488
atomic_set(&root->log_commit[index1], 1);
24812489

24822490
/* wait for previous tree log sync to complete */
24832491
if (atomic_read(&root->log_commit[(index1 + 1) % 2]))
2484-
wait_log_commit(trans, root, root->log_transid - 1);
2492+
wait_log_commit(trans, root, log_transid - 1);
24852493

24862494
while (1) {
24872495
int batch = atomic_read(&root->log_batch);
@@ -2535,9 +2543,16 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
25352543
*/
25362544
mutex_unlock(&root->log_mutex);
25372545

2546+
btrfs_init_log_ctx(&root_log_ctx);
2547+
25382548
mutex_lock(&log_root_tree->log_mutex);
25392549
atomic_inc(&log_root_tree->log_batch);
25402550
atomic_inc(&log_root_tree->log_writers);
2551+
2552+
index2 = log_root_tree->log_transid % 2;
2553+
list_add_tail(&root_log_ctx.list, &log_root_tree->log_ctxs[index2]);
2554+
root_log_ctx.log_transid = log_root_tree->log_transid;
2555+
25412556
mutex_unlock(&log_root_tree->log_mutex);
25422557

25432558
ret = update_log_root(trans, log);
@@ -2550,6 +2565,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
25502565
}
25512566

25522567
if (ret) {
2568+
if (!list_empty(&root_log_ctx.list))
2569+
list_del_init(&root_log_ctx.list);
2570+
25532571
blk_finish_plug(&plug);
25542572
if (ret != -ENOSPC) {
25552573
btrfs_abort_transaction(trans, root, ret);
@@ -2565,26 +2583,29 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
25652583
goto out;
25662584
}
25672585

2568-
index2 = log_root_tree->log_transid % 2;
2569-
2570-
btrfs_init_log_ctx(&root_log_ctx);
2571-
list_add_tail(&root_log_ctx.list, &log_root_tree->log_ctxs[index2]);
2586+
if (log_root_tree->log_transid_committed >= root_log_ctx.log_transid) {
2587+
mutex_unlock(&log_root_tree->log_mutex);
2588+
ret = root_log_ctx.log_ret;
2589+
goto out;
2590+
}
25722591

2592+
index2 = root_log_ctx.log_transid % 2;
25732593
if (atomic_read(&log_root_tree->log_commit[index2])) {
25742594
blk_finish_plug(&plug);
25752595
btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
25762596
wait_log_commit(trans, log_root_tree,
2577-
log_root_tree->log_transid);
2597+
root_log_ctx.log_transid);
25782598
btrfs_free_logged_extents(log, log_transid);
25792599
mutex_unlock(&log_root_tree->log_mutex);
25802600
ret = root_log_ctx.log_ret;
25812601
goto out;
25822602
}
2603+
ASSERT(root_log_ctx.log_transid == log_root_tree->log_transid);
25832604
atomic_set(&log_root_tree->log_commit[index2], 1);
25842605

25852606
if (atomic_read(&log_root_tree->log_commit[(index2 + 1) % 2])) {
25862607
wait_log_commit(trans, log_root_tree,
2587-
log_root_tree->log_transid - 1);
2608+
root_log_ctx.log_transid - 1);
25882609
}
25892610

25902611
wait_for_writer(trans, log_root_tree);
@@ -2652,26 +2673,22 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
26522673
*/
26532674
btrfs_remove_all_log_ctxs(log_root_tree, index2, ret);
26542675

2655-
/*
2656-
* It is dangerous if log_commit is changed before we set
2657-
* ->log_ret of log ctx. Because the readers may not get
2658-
* the return value.
2659-
*/
2660-
smp_wmb();
2661-
2676+
mutex_lock(&log_root_tree->log_mutex);
2677+
log_root_tree->log_transid_committed++;
26622678
atomic_set(&log_root_tree->log_commit[index2], 0);
2663-
smp_mb();
2679+
mutex_unlock(&log_root_tree->log_mutex);
2680+
26642681
if (waitqueue_active(&log_root_tree->log_commit_wait[index2]))
26652682
wake_up(&log_root_tree->log_commit_wait[index2]);
26662683
out:
26672684
/* See above. */
26682685
btrfs_remove_all_log_ctxs(root, index1, ret);
26692686

2670-
/* See above. */
2671-
smp_wmb();
2687+
mutex_lock(&root->log_mutex);
2688+
root->log_transid_committed++;
26722689
atomic_set(&root->log_commit[index1], 0);
2690+
mutex_unlock(&root->log_mutex);
26732691

2674-
smp_mb();
26752692
if (waitqueue_active(&root->log_commit_wait[index1]))
26762693
wake_up(&root->log_commit_wait[index1]);
26772694
return ret;

fs/btrfs/tree-log.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424

2525
struct btrfs_log_ctx {
2626
int log_ret;
27+
int log_transid;
2728
struct list_head list;
2829
};
2930

3031
static inline void btrfs_init_log_ctx(struct btrfs_log_ctx *ctx)
3132
{
3233
ctx->log_ret = 0;
34+
ctx->log_transid = 0;
3335
INIT_LIST_HEAD(&ctx->list);
3436
}
3537

0 commit comments

Comments
 (0)