bcachefs: Fix a deadlock in the RO path

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2020-06-17 17:30:38 -04:00 committed by Kent Overstreet
parent 47a5649a0a
commit b9c3d13978
2 changed files with 11 additions and 3 deletions

View file

@ -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;
}

View file

@ -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++) {