@@ -156,6 +156,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
156
156
if (ctx ) {
157
157
index = root -> log_transid % 2 ;
158
158
list_add_tail (& ctx -> list , & root -> log_ctxs [index ]);
159
+ ctx -> log_transid = root -> log_transid ;
159
160
}
160
161
mutex_unlock (& root -> log_mutex );
161
162
return 0 ;
@@ -181,6 +182,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
181
182
if (ctx ) {
182
183
index = root -> log_transid % 2 ;
183
184
list_add_tail (& ctx -> list , & root -> log_ctxs [index ]);
185
+ ctx -> log_transid = root -> log_transid ;
184
186
}
185
187
out :
186
188
mutex_unlock (& root -> log_mutex );
@@ -2387,13 +2389,13 @@ static void wait_log_commit(struct btrfs_trans_handle *trans,
2387
2389
& wait , TASK_UNINTERRUPTIBLE );
2388
2390
mutex_unlock (& root -> log_mutex );
2389
2391
2390
- if (root -> log_transid < transid + 2 &&
2392
+ if (root -> log_transid_committed < transid &&
2391
2393
atomic_read (& root -> log_commit [index ]))
2392
2394
schedule ();
2393
2395
2394
2396
finish_wait (& root -> log_commit_wait [index ], & wait );
2395
2397
mutex_lock (& root -> log_mutex );
2396
- } while (root -> log_transid < transid + 2 &&
2398
+ } while (root -> log_transid_committed < transid &&
2397
2399
atomic_read (& root -> log_commit [index ]));
2398
2400
}
2399
2401
@@ -2470,18 +2472,24 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2470
2472
struct blk_plug plug ;
2471
2473
2472
2474
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 ;
2475
2482
if (atomic_read (& root -> log_commit [index1 ])) {
2476
- wait_log_commit (trans , root , root -> log_transid );
2483
+ wait_log_commit (trans , root , log_transid );
2477
2484
mutex_unlock (& root -> log_mutex );
2478
2485
return ctx -> log_ret ;
2479
2486
}
2487
+ ASSERT (log_transid == root -> log_transid );
2480
2488
atomic_set (& root -> log_commit [index1 ], 1 );
2481
2489
2482
2490
/* wait for previous tree log sync to complete */
2483
2491
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 );
2485
2493
2486
2494
while (1 ) {
2487
2495
int batch = atomic_read (& root -> log_batch );
@@ -2535,9 +2543,16 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2535
2543
*/
2536
2544
mutex_unlock (& root -> log_mutex );
2537
2545
2546
+ btrfs_init_log_ctx (& root_log_ctx );
2547
+
2538
2548
mutex_lock (& log_root_tree -> log_mutex );
2539
2549
atomic_inc (& log_root_tree -> log_batch );
2540
2550
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
+
2541
2556
mutex_unlock (& log_root_tree -> log_mutex );
2542
2557
2543
2558
ret = update_log_root (trans , log );
@@ -2550,6 +2565,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2550
2565
}
2551
2566
2552
2567
if (ret ) {
2568
+ if (!list_empty (& root_log_ctx .list ))
2569
+ list_del_init (& root_log_ctx .list );
2570
+
2553
2571
blk_finish_plug (& plug );
2554
2572
if (ret != - ENOSPC ) {
2555
2573
btrfs_abort_transaction (trans , root , ret );
@@ -2565,26 +2583,29 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2565
2583
goto out ;
2566
2584
}
2567
2585
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
+ }
2572
2591
2592
+ index2 = root_log_ctx .log_transid % 2 ;
2573
2593
if (atomic_read (& log_root_tree -> log_commit [index2 ])) {
2574
2594
blk_finish_plug (& plug );
2575
2595
btrfs_wait_marked_extents (log , & log -> dirty_log_pages , mark );
2576
2596
wait_log_commit (trans , log_root_tree ,
2577
- log_root_tree -> log_transid );
2597
+ root_log_ctx . log_transid );
2578
2598
btrfs_free_logged_extents (log , log_transid );
2579
2599
mutex_unlock (& log_root_tree -> log_mutex );
2580
2600
ret = root_log_ctx .log_ret ;
2581
2601
goto out ;
2582
2602
}
2603
+ ASSERT (root_log_ctx .log_transid == log_root_tree -> log_transid );
2583
2604
atomic_set (& log_root_tree -> log_commit [index2 ], 1 );
2584
2605
2585
2606
if (atomic_read (& log_root_tree -> log_commit [(index2 + 1 ) % 2 ])) {
2586
2607
wait_log_commit (trans , log_root_tree ,
2587
- log_root_tree -> log_transid - 1 );
2608
+ root_log_ctx . log_transid - 1 );
2588
2609
}
2589
2610
2590
2611
wait_for_writer (trans , log_root_tree );
@@ -2652,26 +2673,22 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2652
2673
*/
2653
2674
btrfs_remove_all_log_ctxs (log_root_tree , index2 , ret );
2654
2675
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 ++ ;
2662
2678
atomic_set (& log_root_tree -> log_commit [index2 ], 0 );
2663
- smp_mb ();
2679
+ mutex_unlock (& log_root_tree -> log_mutex );
2680
+
2664
2681
if (waitqueue_active (& log_root_tree -> log_commit_wait [index2 ]))
2665
2682
wake_up (& log_root_tree -> log_commit_wait [index2 ]);
2666
2683
out :
2667
2684
/* See above. */
2668
2685
btrfs_remove_all_log_ctxs (root , index1 , ret );
2669
2686
2670
- /* See above. */
2671
- smp_wmb () ;
2687
+ mutex_lock ( & root -> log_mutex );
2688
+ root -> log_transid_committed ++ ;
2672
2689
atomic_set (& root -> log_commit [index1 ], 0 );
2690
+ mutex_unlock (& root -> log_mutex );
2673
2691
2674
- smp_mb ();
2675
2692
if (waitqueue_active (& root -> log_commit_wait [index1 ]))
2676
2693
wake_up (& root -> log_commit_wait [index1 ]);
2677
2694
return ret ;
0 commit comments