]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: kill bch2_dev_bkey_exists() in bch2_check_fix_ptrs()
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 1 May 2024 23:10:17 +0000 (19:10 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 9 May 2024 20:23:36 +0000 (16:23 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/buckets.c
fs/bcachefs/sb-members.h

index ae6d6879e2e02dd25b47eaa19e7450a6fb45c10a..e28d28ac2a13d9ce9ec4e708ccf98378eb13cae2 100644 (file)
@@ -479,8 +479,20 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
 
        percpu_down_read(&c->mark_lock);
 
+       rcu_read_lock();
        bkey_for_each_ptr_decode(k.k, ptrs_c, p, entry_c) {
-               struct bch_dev *ca = bch2_dev_bkey_exists(c, p.ptr.dev);
+               struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
+               if (!ca) {
+                       if (fsck_err(c, ptr_to_invalid_device,
+                                    "pointer to missing device %u\n"
+                                    "while marking %s",
+                                    p.ptr.dev,
+                                    (printbuf_reset(&buf),
+                                     bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
+                               do_update = true;
+                       continue;
+               }
+
                struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
                enum bch_data_type data_type = bch2_bkey_ptr_data_type(k, p, entry_c);
 
@@ -590,6 +602,7 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
                                do_update = true;
                }
        }
+       rcu_read_unlock();
 
        if (do_update) {
                if (flags & BTREE_TRIGGER_is_root) {
@@ -603,6 +616,10 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
                if (ret)
                        goto err;
 
+               rcu_read_lock();
+               bch2_bkey_drop_ptrs(bkey_i_to_s(new), ptr, !bch2_dev_rcu(c, ptr->dev));
+               rcu_read_unlock();
+
                if (level) {
                        /*
                         * We don't want to drop btree node pointers - if the
@@ -610,19 +627,22 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
                         * sort it out:
                         */
                        struct bkey_ptrs ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
+                       rcu_read_lock();
                        bkey_for_each_ptr(ptrs, ptr) {
-                               struct bch_dev *ca = bch2_dev_bkey_exists(c, ptr->dev);
+                               struct bch_dev *ca = bch2_dev_rcu(c, ptr->dev);
                                struct bucket *g = PTR_GC_BUCKET(ca, ptr);
 
                                ptr->gen = g->gen;
                        }
+                       rcu_read_unlock();
                } else {
                        struct bkey_ptrs ptrs;
                        union bch_extent_entry *entry;
 restart_drop_ptrs:
                        ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
+                       rcu_read_lock();
                        bkey_for_each_ptr_decode(bkey_i_to_s(new).k, ptrs, p, entry) {
-                               struct bch_dev *ca = bch2_dev_bkey_exists(c, p.ptr.dev);
+                               struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
                                struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
                                enum bch_data_type data_type = bch2_bkey_ptr_data_type(bkey_i_to_s_c(new), p, entry);
 
@@ -637,6 +657,7 @@ restart_drop_ptrs:
                                        goto restart_drop_ptrs;
                                }
                        }
+                       rcu_read_unlock();
 again:
                        ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
                        bkey_extent_entry_for_each(ptrs, entry) {
index ae28b5d401e33f4f9aab732b6ef42f1351e3d9ba..dd93192ec065e8ecfb5d2ffb32e87f5d24599308 100644 (file)
@@ -189,17 +189,6 @@ static inline struct bch_dev *bch2_dev_have_ref(const struct bch_fs *c, unsigned
        return rcu_dereference_check(c->devs[dev], 1);
 }
 
-/*
- * If a key exists that references a device, the device won't be going away and
- * we can omit rcu_read_lock():
- */
-static inline struct bch_dev *bch2_dev_bkey_exists(const struct bch_fs *c, unsigned dev)
-{
-       EBUG_ON(!bch2_dev_exists(c, dev));
-
-       return rcu_dereference_check(c->devs[dev], 1);
-}
-
 static inline struct bch_dev *bch2_dev_locked(struct bch_fs *c, unsigned dev)
 {
        EBUG_ON(!bch2_dev_exists(c, dev));