static inline bool bch2_dev_bucket_exists(struct bch_fs *c, struct bpos pos)
 {
        rcu_read_lock();
-       struct bch_dev *ca = bch2_dev_rcu(c, pos.inode);
+       struct bch_dev *ca = bch2_dev_rcu_noerror(c, pos.inode);
        bool ret = ca && bucket_valid(ca, pos.offset);
        rcu_read_unlock();
        return ret;
 
        struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
 
        rcu_read_lock();
-       struct bch_dev *ca = bch2_dev_rcu(c, bp.k->p.inode);
+       struct bch_dev *ca = bch2_dev_rcu_noerror(c, bp.k->p.inode);
        if (!ca) {
                /* these will be caught by fsck */
                rcu_read_unlock();
 void bch2_backpointer_k_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k)
 {
        rcu_read_lock();
-       struct bch_dev *ca = bch2_dev_rcu(c, k.k->p.inode);
+       struct bch_dev *ca = bch2_dev_rcu_noerror(c, k.k->p.inode);
        if (ca) {
                struct bpos bucket = bp_pos_to_bucket(ca, k.k->p);
                rcu_read_unlock();
                        continue;
 
                rcu_read_lock();
-               struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
+               struct bch_dev *ca = bch2_dev_rcu_noerror(c, p.ptr.dev);
                if (ca)
                        bch2_extent_ptr_to_bp(c, ca, btree, level, k, p, entry, &bucket_pos, &bp);
                rcu_read_unlock();
 
                        goto err;
 
                rcu_read_lock();
-               bch2_bkey_drop_ptrs(bkey_i_to_s(new), ptr, !bch2_dev_rcu(c, ptr->dev));
+               bch2_bkey_drop_ptrs(bkey_i_to_s(new), ptr, !bch2_dev_exists(c, ptr->dev));
                rcu_read_unlock();
 
                if (level) {
 
 {
        out->atomic++;
        rcu_read_lock();
-       struct bch_dev *ca = bch2_dev_rcu(c, ptr->dev);
+       struct bch_dev *ca = bch2_dev_rcu_noerror(c, ptr->dev);
        if (!ca) {
                prt_printf(out, "ptr: %u:%llu gen %u%s", ptr->dev,
                           (u64) ptr->offset, ptr->gen,
 {
        int ret = 0;
 
+       /* bad pointers are repaired by check_fix_ptrs(): */
        rcu_read_lock();
-       struct bch_dev *ca = bch2_dev_rcu(c, ptr->dev);
+       struct bch_dev *ca = bch2_dev_rcu_noerror(c, ptr->dev);
        if (!ca) {
                rcu_read_unlock();
                return 0;
 
                for (unsigned i = 0; i < e->nr_devs; i++) {
                        nr_online += test_bit(e->devs[i], devs.d);
 
-                       struct bch_dev *ca = bch2_dev_rcu(c, e->devs[i]);
+                       struct bch_dev *ca = bch2_dev_rcu_noerror(c, e->devs[i]);
                        nr_failed += !ca || ca->mi.state == BCH_MEMBER_STATE_failed;
                }
                rcu_read_unlock();
 
                                         lockdep_is_held(&c->state_lock));
 }
 
-static inline struct bch_dev *bch2_dev_rcu(struct bch_fs *c, unsigned dev)
+static inline struct bch_dev *bch2_dev_rcu_noerror(struct bch_fs *c, unsigned dev)
 {
        return c && dev < c->sb.nr_devices
                ? rcu_dereference(c->devs[dev])
                : NULL;
 }
 
+void bch2_dev_missing(struct bch_fs *, unsigned);
+
+static inline struct bch_dev *bch2_dev_rcu(struct bch_fs *c, unsigned dev)
+{
+       struct bch_dev *ca = bch2_dev_rcu_noerror(c, dev);
+       if (unlikely(!ca))
+               bch2_dev_missing(c, dev);
+       return ca;
+}
+
 static inline struct bch_dev *bch2_dev_tryget_noerror(struct bch_fs *c, unsigned dev)
 {
        rcu_read_lock();
-       struct bch_dev *ca = bch2_dev_rcu(c, dev);
+       struct bch_dev *ca = bch2_dev_rcu_noerror(c, dev);
        if (ca)
                bch2_dev_get(ca);
        rcu_read_unlock();
        return ca;
 }
 
-void bch2_dev_missing(struct bch_fs *, unsigned);
-
 static inline struct bch_dev *bch2_dev_tryget(struct bch_fs *c, unsigned dev)
 {
        struct bch_dev *ca = bch2_dev_tryget_noerror(c, dev);
-       if (!ca)
+       if (unlikely(!ca))
                bch2_dev_missing(c, dev);
        return ca;
 }