summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/btree_gc.c9
-rw-r--r--fs/bcachefs/buckets.c5
2 files changed, 11 insertions, 3 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 3775b65a89a6..cdd4bc334530 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -932,7 +932,12 @@ int bch2_gc_gens(struct bch_fs *c)
unsigned i;
int ret;
- down_read(&c->state_lock);
+ /*
+ * Ideally we would be using state_lock and not gc_lock here, but that
+ * introduces a deadlock in the RO path - we currently take the state
+ * lock at the start of going RO, thus the gc thread may get stuck:
+ */
+ down_read(&c->gc_lock);
for_each_member_device(ca, c, i) {
down_read(&ca->bucket_lock);
@@ -959,7 +964,7 @@ int bch2_gc_gens(struct bch_fs *c)
up_read(&ca->bucket_lock);
}
err:
- up_read(&c->state_lock);
+ up_read(&c->gc_lock);
return ret;
}
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index 2c9ba18357fd..1ae9403847ca 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -2003,6 +2003,7 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
bch2_copygc_stop(ca);
if (resize) {
+ down_write(&c->gc_lock);
down_write(&ca->bucket_lock);
percpu_down_write(&c->mark_lock);
}
@@ -2025,8 +2026,10 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
swap(ca->buckets_nouse, buckets_nouse);
- if (resize)
+ if (resize) {
percpu_up_write(&c->mark_lock);
+ up_write(&c->gc_lock);
+ }
spin_lock(&c->freelist_lock);
for (i = 0; i < RESERVE_NR; i++) {