Skip to content

Commit 2dd202d

Browse files
author
Kent Overstreet
committed
bcachefs: Recovery no longer holds state_lock
state_lock guards against devices coming or leaving, changing state, or the filesystem changing between ro <-> rw. But it's not necessary for running recovery passes, and holding it blocks asynchronous events that would cause us to go RO or kick out devices. Signed-off-by: Kent Overstreet <[email protected]>
1 parent c6c6a39 commit 2dd202d

File tree

8 files changed

+31
-36
lines changed

8 files changed

+31
-36
lines changed

fs/bcachefs/alloc_background.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,8 @@ int bch2_bucket_gens_init(struct bch_fs *c)
589589

590590
int bch2_alloc_read(struct bch_fs *c)
591591
{
592+
down_read(&c->state_lock);
593+
592594
struct btree_trans *trans = bch2_trans_get(c);
593595
struct bch_dev *ca = NULL;
594596
int ret;
@@ -652,6 +654,7 @@ int bch2_alloc_read(struct bch_fs *c)
652654
bch2_dev_put(ca);
653655
bch2_trans_put(trans);
654656

657+
up_read(&c->state_lock);
655658
bch_err_fn(c, ret);
656659
return ret;
657660
}

fs/bcachefs/backpointers.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
10231023
* Can't allow devices to come/go/resize while we have bucket bitmaps
10241024
* allocated
10251025
*/
1026-
lockdep_assert_held(&c->state_lock);
1026+
down_read(&c->state_lock);
10271027

10281028
for_each_member_device(c, ca) {
10291029
BUG_ON(ca->bucket_backpointer_mismatches);
@@ -1108,6 +1108,7 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
11081108
ca->bucket_backpointer_mismatches = NULL;
11091109
}
11101110

1111+
up_read(&c->state_lock);
11111112
bch_err_fn(c, ret);
11121113
return ret;
11131114
}

fs/bcachefs/btree_gc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,8 +1021,7 @@ int bch2_check_allocations(struct bch_fs *c)
10211021
{
10221022
int ret;
10231023

1024-
lockdep_assert_held(&c->state_lock);
1025-
1024+
down_read(&c->state_lock);
10261025
down_write(&c->gc_lock);
10271026

10281027
bch2_btree_interior_updates_flush(c);
@@ -1060,6 +1059,7 @@ int bch2_check_allocations(struct bch_fs *c)
10601059
percpu_up_write(&c->mark_lock);
10611060

10621061
up_write(&c->gc_lock);
1062+
up_read(&c->state_lock);
10631063

10641064
/*
10651065
* At startup, allocations can happen directly instead of via the

fs/bcachefs/errcode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#define BCH_ERRCODES() \
66
x(ERANGE, ERANGE_option_too_small) \
77
x(ERANGE, ERANGE_option_too_big) \
8+
x(EINVAL, injected) \
9+
x(BCH_ERR_injected, injected_fs_start) \
810
x(EINVAL, mount_option) \
911
x(BCH_ERR_mount_option, option_name) \
1012
x(BCH_ERR_mount_option, option_value) \

fs/bcachefs/opts.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,14 +482,12 @@ void bch2_opts_to_text(struct printbuf *out,
482482

483483
int bch2_opt_check_may_set(struct bch_fs *c, struct bch_dev *ca, int id, u64 v)
484484
{
485-
lockdep_assert_held(&c->state_lock);
486-
487485
int ret = 0;
488486

489487
switch (id) {
490488
case Opt_state:
491489
if (ca)
492-
return __bch2_dev_set_state(c, ca, v, BCH_FORCE_IF_DEGRADED);
490+
return bch2_dev_set_state(c, ca, v, BCH_FORCE_IF_DEGRADED);
493491
break;
494492

495493
case Opt_compression:

fs/bcachefs/recovery_passes.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,28 +234,22 @@ static int bch2_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass)
234234

235235
int bch2_run_online_recovery_passes(struct bch_fs *c)
236236
{
237-
int ret = 0;
238-
239-
down_read(&c->state_lock);
240-
241237
for (unsigned i = 0; i < ARRAY_SIZE(recovery_pass_fns); i++) {
242238
struct recovery_pass_fn *p = recovery_pass_fns + i;
243239

244240
if (!(p->when & PASS_ONLINE))
245241
continue;
246242

247-
ret = bch2_run_recovery_pass(c, i);
243+
int ret = bch2_run_recovery_pass(c, i);
248244
if (bch2_err_matches(ret, BCH_ERR_restart_recovery)) {
249245
i = c->curr_recovery_pass;
250246
continue;
251247
}
252248
if (ret)
253-
break;
249+
return ret;
254250
}
255251

256-
up_read(&c->state_lock);
257-
258-
return ret;
252+
return 0;
259253
}
260254

261255
int bch2_run_recovery_passes(struct bch_fs *c)

fs/bcachefs/super.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,11 @@ int bch2_fs_read_write(struct bch_fs *c)
533533

534534
int bch2_fs_read_write_early(struct bch_fs *c)
535535
{
536-
lockdep_assert_held(&c->state_lock);
536+
down_write(&c->state_lock);
537+
int ret = __bch2_fs_read_write(c, true);
538+
up_write(&c->state_lock);
537539

538-
return __bch2_fs_read_write(c, true);
540+
return ret;
539541
}
540542

541543
/* Filesystem startup/shutdown: */
@@ -1019,38 +1021,39 @@ static void print_mount_opts(struct bch_fs *c)
10191021
int bch2_fs_start(struct bch_fs *c)
10201022
{
10211023
time64_t now = ktime_get_real_seconds();
1022-
int ret;
1024+
int ret = 0;
10231025

10241026
print_mount_opts(c);
10251027

10261028
down_write(&c->state_lock);
1029+
mutex_lock(&c->sb_lock);
10271030

10281031
BUG_ON(test_bit(BCH_FS_started, &c->flags));
10291032

1030-
mutex_lock(&c->sb_lock);
1033+
if (!bch2_sb_field_get_minsize(&c->disk_sb, ext,
1034+
sizeof(struct bch_sb_field_ext) / sizeof(u64))) {
1035+
mutex_unlock(&c->sb_lock);
1036+
up_write(&c->state_lock);
1037+
ret = -BCH_ERR_ENOSPC_sb;
1038+
goto err;
1039+
}
10311040

10321041
ret = bch2_sb_members_v2_init(c);
10331042
if (ret) {
10341043
mutex_unlock(&c->sb_lock);
1044+
up_write(&c->state_lock);
10351045
goto err;
10361046
}
10371047

10381048
for_each_online_member(c, ca)
10391049
bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount = cpu_to_le64(now);
10401050

1041-
struct bch_sb_field_ext *ext =
1042-
bch2_sb_field_get_minsize(&c->disk_sb, ext, sizeof(*ext) / sizeof(u64));
10431051
mutex_unlock(&c->sb_lock);
10441052

1045-
if (!ext) {
1046-
bch_err(c, "insufficient space in superblock for sb_field_ext");
1047-
ret = -BCH_ERR_ENOSPC_sb;
1048-
goto err;
1049-
}
1050-
10511053
for_each_rw_member(c, ca)
10521054
bch2_dev_allocator_add(c, ca);
10531055
bch2_recalc_capacity(c);
1056+
up_write(&c->state_lock);
10541057

10551058
c->recovery_task = current;
10561059
ret = BCH_SB_INITIALIZED(c->disk_sb.sb)
@@ -1066,31 +1069,28 @@ int bch2_fs_start(struct bch_fs *c)
10661069
goto err;
10671070

10681071
if (bch2_fs_init_fault("fs_start")) {
1069-
bch_err(c, "fs_start fault injected");
1070-
ret = -EINVAL;
1072+
ret = -BCH_ERR_injected_fs_start;
10711073
goto err;
10721074
}
10731075

10741076
set_bit(BCH_FS_started, &c->flags);
10751077
wake_up(&c->ro_ref_wait);
10761078

1079+
down_write(&c->state_lock);
10771080
if (c->opts.read_only) {
10781081
bch2_fs_read_only(c);
10791082
} else {
10801083
ret = !test_bit(BCH_FS_rw, &c->flags)
10811084
? bch2_fs_read_write(c)
10821085
: bch2_fs_read_write_late(c);
1083-
if (ret)
1084-
goto err;
10851086
}
1087+
up_write(&c->state_lock);
10861088

1087-
ret = 0;
10881089
err:
10891090
if (ret)
10901091
bch_err_msg(c, ret, "starting filesystem");
10911092
else
10921093
bch_verbose(c, "done starting filesystem");
1093-
up_write(&c->state_lock);
10941094
return ret;
10951095
}
10961096

fs/bcachefs/sysfs.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,8 +631,6 @@ static ssize_t sysfs_opt_store(struct bch_fs *c,
631631
if (unlikely(!bch2_write_ref_tryget(c, BCH_WRITE_REF_sysfs)))
632632
return -EROFS;
633633

634-
down_write(&c->state_lock);
635-
636634
char *tmp = kstrdup(buf, GFP_KERNEL);
637635
if (!tmp) {
638636
ret = -ENOMEM;
@@ -675,7 +673,6 @@ static ssize_t sysfs_opt_store(struct bch_fs *c,
675673

676674
ret = size;
677675
err:
678-
up_write(&c->state_lock);
679676
bch2_write_ref_put(c, BCH_WRITE_REF_sysfs);
680677
return ret;
681678
}

0 commit comments

Comments
 (0)