bcachefs: bcachefs_metadata_version_backpointer_bucket_gen
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 17 Nov 2024 04:53:07 +0000 (23:53 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 29 Dec 2024 18:30:39 +0000 (13:30 -0500)
New on disk format version: backpointers new include the generation
number of the bucket they refer to, and the obsolete bucket_offset field
(no longer needed because we no longer store backpointers in alloc keys)
is gone.

This is an expensive forced upgrade - hopefully the last; we have to run
the extents_to_backpointers recovery pass to regenerate backpointers.

It's a forced incompatible upgrade because the alternative would've been
permamently making backpointers bigger, and as one of the biggest btrees
(along with the extents btree) that's not an ideal option.

It's worth it though, because this allows us to make the
check_extents_to_backpointers pass drastically cheaper: an upcoming
patch changes it to sum up backpointers in a bucket and check the sum
against the sector counts for that bucket, only looking for missing
backpointers if they don't match (and then only for specific buckets).

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

index 0e3b7b5d626e08a48d368f4b3cfceb7c887831fb..b19719b02df8f8f6cefe1b27806cdd027b4a4f37 100644 (file)
@@ -28,23 +28,6 @@ int bch2_backpointer_validate(struct bch_fs *c, struct bkey_s_c k,
        bkey_fsck_err_on(bp.k->p.inode == BCH_SB_MEMBER_INVALID,
                         c, backpointer_dev_bad,
                         "backpointer for BCH_SB_MEMBER_INVALID");
-
-       rcu_read_lock();
-       struct bch_dev *ca = bch2_dev_rcu_noerror(c, bp.k->p.inode);
-       if (!ca) {
-               /* these will be caught by fsck */
-               rcu_read_unlock();
-               return 0;
-       }
-
-       struct bpos bucket = bp_pos_to_bucket(ca, bp.k->p);
-       struct bpos bp_pos = bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset);
-       rcu_read_unlock();
-
-       bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
-                        !bpos_eq(bp.k->p, bp_pos),
-                        c, backpointer_bucket_offset_wrong,
-                        "backpointer bucket_offset wrong (%llu)", (u64) bp.v->bucket_offset);
 fsck_err:
        return ret;
 }
@@ -59,16 +42,17 @@ void bch2_backpointer_to_text(struct printbuf *out, struct bch_fs *c, struct bke
                u32 bucket_offset;
                struct bpos bucket = bp_pos_to_bucket_and_offset(ca, bp.k->p, &bucket_offset);
                rcu_read_unlock();
-               prt_printf(out, "bucket=%llu:%llu:%u", bucket.inode, bucket.offset, bucket_offset);
+               prt_printf(out, "bucket=%llu:%llu:%u ", bucket.inode, bucket.offset, bucket_offset);
        } else {
                rcu_read_unlock();
-               prt_printf(out, "sector=%llu:%llu", bp.k->p.inode, bp.k->p.offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT);
+               prt_printf(out, "sector=%llu:%llu ", bp.k->p.inode, bp.k->p.offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT);
        }
 
        bch2_btree_id_level_to_text(out, bp.v->btree_id, bp.v->level);
-       prt_printf(out, " suboffset=%u len=%u pos=",
+       prt_printf(out, " suboffset=%u len=%u gen=%u pos=",
                   (u32) bp.k->p.offset & ~(~0U << MAX_EXTENT_COMPRESS_RATIO_SHIFT),
-                  bp.v->bucket_len);
+                  bp.v->bucket_len,
+                  bp.v->bucket_gen);
        bch2_bpos_to_text(out, bp.v->pos);
 }
 
@@ -76,7 +60,6 @@ void bch2_backpointer_swab(struct bkey_s k)
 {
        struct bkey_s_backpointer bp = bkey_s_to_backpointer(k);
 
-       bp.v->bucket_offset     = swab40(bp.v->bucket_offset);
        bp.v->bucket_len        = swab32(bp.v->bucket_len);
        bch2_bpos_swab(&bp.v->pos);
 }
index 95caeabb8978f7c3233184ed610493edfafe54cd..caffc68407abb0fa8f3de676c574756b120335d3 100644 (file)
@@ -158,7 +158,7 @@ static inline void __bch2_extent_ptr_to_bp(struct bch_fs *c, struct bch_dev *ca,
                .btree_id       = btree_id,
                .level          = level,
                .data_type      = bch2_bkey_ptr_data_type(k, p, entry),
-               .bucket_offset  = bp_bucket_offset,
+               .bucket_gen     = p.ptr.gen,
                .bucket_len     = sectors,
                .pos            = k.k->p,
        };
index dc14bfe37e3bdf2b8f6d62be6957e716fd420578..e4bb74d6f439f4336d489ecac3a1978817e635b5 100644 (file)
@@ -463,7 +463,8 @@ struct bch_backpointer {
        __u8                    btree_id;
        __u8                    level;
        __u8                    data_type;
-       __u64                   bucket_offset:40;
+       __u8                    bucket_gen;
+       __u32                   pad;
        __u32                   bucket_len;
        struct bpos             pos;
 } __packed __aligned(8);
@@ -677,7 +678,8 @@ struct bch_sb_field_ext {
        x(disk_accounting_v3,           BCH_VERSION(1, 10))             \
        x(disk_accounting_inum,         BCH_VERSION(1, 11))             \
        x(rebalance_work_acct_fix,      BCH_VERSION(1, 12))             \
-       x(inode_has_child_snapshots,    BCH_VERSION(1, 13))
+       x(inode_has_child_snapshots,    BCH_VERSION(1, 13))             \
+       x(backpointer_bucket_gen,       BCH_VERSION(1, 14))
 
 enum bcachefs_metadata_version {
        bcachefs_metadata_version_min = 9,
index 8767c33c2b513f87db7b58bcd179bdf7c3685e0a..9879845413a694e640bf9cd82c6673a0dd087806 100644 (file)
          BCH_FSCK_ERR_accounting_mismatch)                     \
        x(inode_has_child_snapshots,                            \
          BIT_ULL(BCH_RECOVERY_PASS_check_inodes),              \
-         BCH_FSCK_ERR_inode_has_child_snapshots_wrong)
+         BCH_FSCK_ERR_inode_has_child_snapshots_wrong)         \
+       x(backpointer_bucket_gen,                               \
+         BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
+         BCH_FSCK_ERR_backpointer_to_missing_ptr,              \
+         BCH_FSCK_ERR_ptr_to_missing_backpointer)
 
 #define DOWNGRADE_TABLE()                                      \
        x(bucket_stripe_sectors,                                \
          BCH_FSCK_ERR_bkey_version_in_future)                  \
        x(rebalance_work_acct_fix,                              \
          BIT_ULL(BCH_RECOVERY_PASS_check_allocations),         \
-         BCH_FSCK_ERR_accounting_mismatch)
+         BCH_FSCK_ERR_accounting_mismatch,                     \
+         BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0,       \
+         BCH_FSCK_ERR_accounting_key_junk_at_end)              \
+       x(backpointer_bucket_gen,                               \
+         BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
+         BCH_FSCK_ERR_backpointer_bucket_offset_wrong,         \
+         BCH_FSCK_ERR_backpointer_to_missing_ptr,              \
+         BCH_FSCK_ERR_ptr_to_missing_backpointer)
 
 struct upgrade_downgrade_entry {
        u64             recovery_passes;