Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
        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);
                up_read(&ca->bucket_lock);
        }
 err:
-       up_read(&c->state_lock);
+       up_read(&c->gc_lock);
        return ret;
 }
 
 
        bch2_copygc_stop(ca);
 
        if (resize) {
+               down_write(&c->gc_lock);
                down_write(&ca->bucket_lock);
                percpu_down_write(&c->mark_lock);
        }
 
        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++) {