]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: bcachefs_metadata_version_cached_backpointers
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 7 Feb 2025 06:33:35 +0000 (01:33 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Mar 2025 01:02:14 +0000 (21:02 -0400)
Cached pointers now have backpointers.

This means that we'll be able to kill cached pointers in the
bucket_invalidate path, when invalidating/reusing buckets containing
cached data, instead of leaving them around to be cleaned up by gc_gens
garbago collection - which requires a full metadata scan.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/backpointers.c
fs/bcachefs/bcachefs_format.h
fs/bcachefs/buckets.c
fs/bcachefs/sb-downgrade.c

index bb799b86aa699a54ace9faafd711735ecc9470c7..c9dfc3657696b4d90f6030de7e463ce15c573b85 100644 (file)
@@ -611,9 +611,6 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
        struct extent_ptr_decoded p;
 
        bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
-               if (p.ptr.cached)
-                       continue;
-
                if (p.ptr.dev == BCH_SB_MEMBER_INVALID)
                        continue;
 
@@ -621,9 +618,11 @@ static int check_extent_to_backpointers(struct btree_trans *trans,
                struct bch_dev *ca = bch2_dev_rcu_noerror(c, p.ptr.dev);
                bool check = ca && test_bit(PTR_BUCKET_NR(ca, &p.ptr), ca->bucket_backpointer_mismatches);
                bool empty = ca && test_bit(PTR_BUCKET_NR(ca, &p.ptr), ca->bucket_backpointer_empty);
+
+               bool stale = p.ptr.cached && (!ca || dev_ptr_stale_rcu(ca, &p.ptr));
                rcu_read_unlock();
 
-               if (check || empty) {
+               if ((check || empty) && !stale) {
                        struct bkey_i_backpointer bp;
                        bch2_extent_ptr_to_bp(c, btree, level, k, p, entry, &bp);
 
@@ -857,9 +856,8 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
                        goto err;
        }
 
-       /* Cached pointers don't have backpointers: */
-
        if (sectors[ALLOC_dirty]  != a->dirty_sectors ||
+           sectors[ALLOC_cached] != a->cached_sectors ||
            sectors[ALLOC_stripe] != a->stripe_sectors) {
                if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_backpointer_bucket_gen) {
                        ret = bch2_backpointers_maybe_flush(trans, alloc_k, last_flushed);
@@ -868,6 +866,7 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
                }
 
                if (sectors[ALLOC_dirty]  > a->dirty_sectors ||
+                   sectors[ALLOC_cached] > a->cached_sectors ||
                    sectors[ALLOC_stripe] > a->stripe_sectors) {
                        ret = check_bucket_backpointers_to_extents(trans, ca, alloc_k.k->p) ?:
                                -BCH_ERR_transaction_restart_nested;
@@ -875,7 +874,8 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
                }
 
                if (!sectors[ALLOC_dirty] &&
-                   !sectors[ALLOC_stripe])
+                   !sectors[ALLOC_stripe] &&
+                   !sectors[ALLOC_cached])
                        __set_bit(alloc_k.k->p.offset, ca->bucket_backpointer_empty);
                else
                        __set_bit(alloc_k.k->p.offset, ca->bucket_backpointer_mismatches);
index f70f0108401f7f398a2d0edc6abeb39b673c4abe..ef5009b18dd5eeab81348f3c8a611adfd6acb9b0 100644 (file)
@@ -686,7 +686,8 @@ struct bch_sb_field_ext {
        x(inode_depth,                  BCH_VERSION(1, 17))             \
        x(persistent_inode_cursors,     BCH_VERSION(1, 18))             \
        x(autofix_errors,               BCH_VERSION(1, 19))             \
-       x(directory_size,               BCH_VERSION(1, 20))
+       x(directory_size,               BCH_VERSION(1, 20))             \
+       x(cached_backpointers,          BCH_VERSION(1, 21))
 
 enum bcachefs_metadata_version {
        bcachefs_metadata_version_min = 9,
index 88af61bc799d38c7b8a635d5c7e9571529933ee3..bb7742cf00145fe3f29aa02bdb67763e78a51da6 100644 (file)
@@ -590,11 +590,9 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
                if (ret)
                        goto err;
 
-               if (!p.ptr.cached) {
-                       ret = bch2_bucket_backpointer_mod(trans, k, &bp, insert);
-                       if (ret)
-                               goto err;
-               }
+               ret = bch2_bucket_backpointer_mod(trans, k, &bp, insert);
+               if (ret)
+                       goto err;
        }
 
        if (flags & BTREE_TRIGGER_gc) {
index 051214fdc73521dd2ab5b05609fdcc34caa34daa..ef985c851300da68610138083f3e1fd80dc8cbc8 100644 (file)
          BIT_ULL(BCH_RECOVERY_PASS_check_allocations),         \
          BCH_FSCK_ERR_accounting_mismatch,                     \
          BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0,       \
-         BCH_FSCK_ERR_accounting_key_junk_at_end)
+         BCH_FSCK_ERR_accounting_key_junk_at_end)              \
+       x(cached_backpointers,                                  \
+         BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
+         BCH_FSCK_ERR_ptr_to_missing_backpointer)
 
 #define DOWNGRADE_TABLE()                                      \
        x(bucket_stripe_sectors,                                \