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 0e3b7b5..b19719b 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 95caeab..caffc68 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 dc14bfe..e4bb74d 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 8767c33..9879845 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;