printbuf_indent_sub(&buf, 2);
        prt_newline(&buf);
 
-       for_each_online_member(c, ca) {
+       bch2_printbuf_make_room(&buf, 4096);
+
+       rcu_read_lock();
+       buf.atomic++;
+
+       for_each_online_member_rcu(c, ca) {
                prt_printf(&buf, "Dev %u:\n", ca->dev_idx);
                printbuf_indent_add(&buf, 2);
                bch2_dev_alloc_debug_to_text(&buf, ca);
                prt_newline(&buf);
        }
 
+       --buf.atomic;
+       rcu_read_unlock();
+
        prt_printf(&buf, "Copygc debug:\n");
        printbuf_indent_add(&buf, 2);
        bch2_copygc_wait_to_text(&buf, c);
 
        struct workqueue_struct *write_ref_wq;
 
        /* ALLOCATION */
+       struct bch_devs_mask    online_devs;
        struct bch_devs_mask    rw_devs[BCH_DATA_NR];
        unsigned long           rw_devs_change_count;
 
 
        if (!dev)
                return -EINVAL;
 
-       for_each_online_member(c, ca)
+       rcu_read_lock();
+       for_each_online_member_rcu(c, ca)
                if (ca->dev == dev) {
-                       percpu_ref_put(&ca->io_ref[READ]);
+                       rcu_read_unlock();
                        return ca->dev_idx;
                }
+       rcu_read_unlock();
 
        return -BCH_ERR_ENOENT_dev_idx_not_found;
 }
 
        struct bch_fs *c = root->d_sb->s_fs_info;
        bool first = true;
 
-       for_each_online_member(c, ca) {
+       rcu_read_lock();
+       for_each_online_member_rcu(c, ca) {
                if (!first)
                        seq_putc(seq, ':');
                first = false;
                seq_puts(seq, ca->disk_sb.sb_name);
        }
+       rcu_read_unlock();
 
        return 0;
 }
 
        sb->s_bdi->ra_pages             = VM_READAHEAD_PAGES;
 
-       for_each_online_member(c, ca) {
+       rcu_read_lock();
+       for_each_online_member_rcu(c, ca) {
                struct block_device *bdev = ca->disk_sb.bdev;
 
                /* XXX: create an anonymous device for multi device filesystems */
                sb->s_bdev      = bdev;
                sb->s_dev       = bdev->bd_dev;
-               percpu_ref_put(&ca->io_ref[READ]);
                break;
        }
+       rcu_read_unlock();
 
        c->dev = sb->s_dev;
 
 
        for (struct bch_dev *_ca = NULL;                                \
             (_ca = __bch2_next_dev((_c), _ca, (_mask)));)
 
+#define for_each_online_member_rcu(_c, _ca)                            \
+       for_each_member_device_rcu(_c, _ca, &(_c)->online_devs)
+
 static inline void bch2_dev_get(struct bch_dev *ca)
 {
 #ifdef CONFIG_BCACHEFS_DEBUG
        return NULL;
 }
 
-/* XXX kill, move to struct bch_fs */
-static inline struct bch_devs_mask bch2_online_devs(struct bch_fs *c)
-{
-       struct bch_devs_mask devs;
-
-       memset(&devs, 0, sizeof(devs));
-       for_each_online_member(c, ca)
-               __set_bit(ca->dev_idx, devs.d);
-       return devs;
-}
-
 extern const struct bch_sb_field_ops bch_sb_field_ops_members_v1;
 extern const struct bch_sb_field_ops bch_sb_field_ops_members_v2;
 
 
                break;
        }
 
-       return bch2_have_enough_devs(c, bch2_online_devs(c), flags, true);
+       return bch2_have_enough_devs(c, c->online_devs, flags, true);
 }
 
 int bch2_fs_start(struct bch_fs *c)
                goto err;
        }
 
-       for_each_online_member(c, ca)
-               bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount = cpu_to_le64(now);
+       rcu_read_lock();
+       for_each_online_member_rcu(c, ca)
+               bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx)->last_mount =
+               cpu_to_le64(now);
+       rcu_read_unlock();
 
        /*
         * Dno't write superblock yet: recovery might have to downgrade
 
 static void bch2_dev_io_ref_stop(struct bch_dev *ca, int rw)
 {
+       if (rw == READ)
+               clear_bit(ca->dev_idx, ca->fs->online_devs.d);
+
        if (!percpu_ref_is_zero(&ca->io_ref[rw])) {
                reinit_completion(&ca->io_ref_completion[rw]);
                percpu_ref_kill(&ca->io_ref[rw]);
        if (ret)
                return ret;
 
+       set_bit(ca->dev_idx, c->online_devs.d);
+
        bch2_dev_sysfs_online(c, ca);
 
        struct printbuf name = PRINTBUF;
                        return true;
 
                /* do we have enough devices to read from?  */
-               new_online_devs = bch2_online_devs(c);
+               new_online_devs = c->online_devs;
                __clear_bit(ca->dev_idx, new_online_devs.d);
 
                return bch2_have_enough_devs(c, new_online_devs, flags, false);