@@ -451,53 +451,63 @@ void bch2_btree_node_lock_write_nofail(struct btree_trans *trans,
451
451
452
452
/* relock */
453
453
454
- static inline bool btree_path_get_locks (struct btree_trans * trans ,
455
- struct btree_path * path ,
456
- bool upgrade ,
457
- struct get_locks_fail * f )
454
+ static int btree_path_get_locks (struct btree_trans * trans ,
455
+ struct btree_path * path ,
456
+ bool upgrade ,
457
+ struct get_locks_fail * f ,
458
+ int restart_err )
458
459
{
459
460
unsigned l = path -> level ;
460
- int fail_idx = -1 ;
461
461
462
462
do {
463
463
if (!btree_path_node (path , l ))
464
464
break ;
465
465
466
466
if (!(upgrade
467
467
? bch2_btree_node_upgrade (trans , path , l )
468
- : bch2_btree_node_relock (trans , path , l ))) {
469
- fail_idx = l ;
470
-
471
- if (f ) {
472
- f -> l = l ;
473
- f -> b = path -> l [l ].b ;
474
- }
475
- }
468
+ : bch2_btree_node_relock (trans , path , l )))
469
+ goto err ;
476
470
477
471
l ++ ;
478
472
} while (l < path -> locks_want );
479
473
474
+ if (path -> uptodate == BTREE_ITER_NEED_RELOCK )
475
+ path -> uptodate = BTREE_ITER_UPTODATE ;
476
+
477
+ return path -> uptodate < BTREE_ITER_NEED_RELOCK ? 0 : -1 ;
478
+ err :
479
+ if (f ) {
480
+ f -> l = l ;
481
+ f -> b = path -> l [l ].b ;
482
+ }
483
+
484
+ /*
485
+ * Do transaction restart before unlocking, so we don't pop
486
+ * should_be_locked asserts
487
+ */
488
+ if (restart_err ) {
489
+ btree_trans_restart (trans , restart_err );
490
+ } else if (path -> should_be_locked && !trans -> restarted ) {
491
+ if (upgrade )
492
+ path -> locks_want = l ;
493
+ return -1 ;
494
+ }
495
+
496
+ __bch2_btree_path_unlock (trans , path );
497
+ btree_path_set_dirty (path , BTREE_ITER_NEED_TRAVERSE );
498
+
480
499
/*
481
500
* When we fail to get a lock, we have to ensure that any child nodes
482
501
* can't be relocked so bch2_btree_path_traverse has to walk back up to
483
502
* the node that we failed to relock:
484
503
*/
485
- if (fail_idx >= 0 ) {
486
- __bch2_btree_path_unlock (trans , path );
487
- btree_path_set_dirty (path , BTREE_ITER_NEED_TRAVERSE );
488
-
489
- do {
490
- path -> l [fail_idx ].b = upgrade
491
- ? ERR_PTR (- BCH_ERR_no_btree_node_upgrade )
492
- : ERR_PTR (- BCH_ERR_no_btree_node_relock );
493
- -- fail_idx ;
494
- } while (fail_idx >= 0 );
495
- }
496
-
497
- if (path -> uptodate == BTREE_ITER_NEED_RELOCK )
498
- path -> uptodate = BTREE_ITER_UPTODATE ;
504
+ do {
505
+ path -> l [l ].b = upgrade
506
+ ? ERR_PTR (- BCH_ERR_no_btree_node_upgrade )
507
+ : ERR_PTR (- BCH_ERR_no_btree_node_relock );
508
+ } while (l -- );
499
509
500
- return path -> uptodate < BTREE_ITER_NEED_RELOCK ;
510
+ return - restart_err ?: -1 ;
501
511
}
502
512
503
513
bool __bch2_btree_node_relock (struct btree_trans * trans ,
@@ -596,9 +606,7 @@ int bch2_btree_path_relock_intent(struct btree_trans *trans,
596
606
__flatten
597
607
bool bch2_btree_path_relock_norestart (struct btree_trans * trans , struct btree_path * path )
598
608
{
599
- struct get_locks_fail f ;
600
-
601
- bool ret = btree_path_get_locks (trans , path , false, & f );
609
+ bool ret = !btree_path_get_locks (trans , path , false, NULL , 0 );
602
610
bch2_trans_verify_locks (trans );
603
611
return ret ;
604
612
}
@@ -614,28 +622,32 @@ int __bch2_btree_path_relock(struct btree_trans *trans,
614
622
return 0 ;
615
623
}
616
624
617
- bool bch2_btree_path_upgrade_noupgrade_sibs (struct btree_trans * trans ,
618
- struct btree_path * path ,
619
- unsigned new_locks_want ,
620
- struct get_locks_fail * f )
625
+ bool __bch2_btree_path_upgrade_norestart (struct btree_trans * trans ,
626
+ struct btree_path * path ,
627
+ unsigned new_locks_want )
621
628
{
622
- path -> locks_want = max_t ( unsigned , path -> locks_want , new_locks_want ) ;
629
+ path -> locks_want = new_locks_want ;
623
630
624
- bool ret = btree_path_get_locks (trans , path , true, f );
625
- bch2_trans_verify_locks (trans );
631
+ struct get_locks_fail f = {};
632
+ bool ret = !btree_path_get_locks (trans , path , true, & f , 0 );
633
+
634
+ bch2_btree_path_verify_locks (path );
626
635
return ret ;
627
636
}
628
637
629
638
int __bch2_btree_path_upgrade (struct btree_trans * trans ,
630
639
struct btree_path * path ,
631
640
unsigned new_locks_want )
632
641
{
633
- struct get_locks_fail f = {};
634
642
unsigned old_locks = path -> nodes_locked ;
635
643
unsigned old_locks_want = path -> locks_want ;
636
- int ret = 0 ;
637
644
638
- if (bch2_btree_path_upgrade_noupgrade_sibs (trans , path , new_locks_want , & f ))
645
+ path -> locks_want = max_t (unsigned , path -> locks_want , new_locks_want );
646
+
647
+ struct get_locks_fail f = {};
648
+ int ret = btree_path_get_locks (trans , path , true, & f ,
649
+ BCH_ERR_transaction_restart_upgrade );
650
+ if (!ret )
639
651
goto out ;
640
652
641
653
/*
@@ -667,7 +679,7 @@ int __bch2_btree_path_upgrade(struct btree_trans *trans,
667
679
linked -> btree_id == path -> btree_id &&
668
680
linked -> locks_want < new_locks_want ) {
669
681
linked -> locks_want = new_locks_want ;
670
- btree_path_get_locks (trans , linked , true, NULL );
682
+ btree_path_get_locks (trans , linked , true, NULL , 0 );
671
683
}
672
684
}
673
685
@@ -691,7 +703,6 @@ int __bch2_btree_path_upgrade(struct btree_trans *trans,
691
703
trace_trans_restart_upgrade (trans -> c , buf .buf );
692
704
printbuf_exit (& buf );
693
705
}
694
- ret = btree_trans_restart (trans , BCH_ERR_transaction_restart_upgrade );
695
706
out :
696
707
bch2_trans_verify_locks (trans );
697
708
return ret ;
@@ -752,7 +763,7 @@ static inline void __bch2_trans_unlock(struct btree_trans *trans)
752
763
__bch2_btree_path_unlock (trans , path );
753
764
}
754
765
755
- static noinline __cold int bch2_trans_relock_fail (struct btree_trans * trans , struct btree_path * path ,
766
+ static noinline __cold void bch2_trans_relock_fail (struct btree_trans * trans , struct btree_path * path ,
756
767
struct get_locks_fail * f , bool trace )
757
768
{
758
769
if (!trace )
@@ -786,7 +797,6 @@ static noinline __cold int bch2_trans_relock_fail(struct btree_trans *trans, str
786
797
out :
787
798
__bch2_trans_unlock (trans );
788
799
bch2_trans_verify_locks (trans );
789
- return btree_trans_restart (trans , BCH_ERR_transaction_restart_relock );
790
800
}
791
801
792
802
static inline int __bch2_trans_relock (struct btree_trans * trans , bool trace )
@@ -803,10 +813,14 @@ static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace)
803
813
804
814
trans_for_each_path (trans , path , i ) {
805
815
struct get_locks_fail f ;
816
+ int ret ;
806
817
807
818
if (path -> should_be_locked &&
808
- !btree_path_get_locks (trans , path , false, & f ))
809
- return bch2_trans_relock_fail (trans , path , & f , trace );
819
+ (ret = btree_path_get_locks (trans , path , false, & f ,
820
+ BCH_ERR_transaction_restart_relock ))) {
821
+ bch2_trans_relock_fail (trans , path , & f , trace );
822
+ return ret ;
823
+ }
810
824
}
811
825
812
826
trans_set_locked (trans , true);
0 commit comments