Stripes now have backpointers.

This is needed for proper scrub - stripe checksums need to be verified,
separately from extents within the stripe, since a block may not be full
of live extents but it's still needed for reconstruct.

And this will be needed for (efficient) evacuate/repair paths.

Signed-off-by: Kent Overstreet <[email protected]>
---
 fs/bcachefs/backpointers.h    | 15 ++++++++++++++-
 fs/bcachefs/bcachefs_format.h |  3 ++-
 fs/bcachefs/ec.c              | 16 ++++++++++++++--
 fs/bcachefs/move.c            |  3 +++
 fs/bcachefs/sb-downgrade.c    |  3 +++
 5 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/fs/bcachefs/backpointers.h b/fs/bcachefs/backpointers.h
index 7786731d4ada..16575dbc5736 100644
--- a/fs/bcachefs/backpointers.h
+++ b/fs/bcachefs/backpointers.h
@@ -152,7 +152,20 @@ static inline void bch2_extent_ptr_to_bp(struct bch_fs *c,
                           struct bkey_i_backpointer *bp)
 {
        bkey_backpointer_init(&bp->k_i);
-       bp->k.p = POS(p.ptr.dev, ((u64) p.ptr.offset << 
MAX_EXTENT_COMPRESS_RATIO_SHIFT) + p.crc.offset);
+       bp->k.p.inode = p.ptr.dev;
+
+       if (k.k->type != KEY_TYPE_stripe)
+               bp->k.p.offset = ((u64) p.ptr.offset << 
MAX_EXTENT_COMPRESS_RATIO_SHIFT) + p.crc.offset;
+       else {
+               /*
+                * Put stripe backpointers where they won't collide with the
+                * extent backpointers within the stripe:
+                */
+               struct bkey_s_c_stripe s = bkey_s_c_to_stripe(k);
+               bp->k.p.offset = ((u64) (p.ptr.offset + 
le16_to_cpu(s.v->sectors)) <<
+                                 MAX_EXTENT_COMPRESS_RATIO_SHIFT) - 1;
+       }
+
        bp->v   = (struct bch_backpointer) {
                .btree_id       = btree_id,
                .level          = level,
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index ef5009b18dd5..bf3723a2bca4 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -687,7 +687,8 @@ struct bch_sb_field_ext {
        x(persistent_inode_cursors,     BCH_VERSION(1, 18))             \
        x(autofix_errors,               BCH_VERSION(1, 19))             \
        x(directory_size,               BCH_VERSION(1, 20))             \
-       x(cached_backpointers,          BCH_VERSION(1, 21))
+       x(cached_backpointers,          BCH_VERSION(1, 21))             \
+       x(stripe_backpointers,          BCH_VERSION(1, 22))
 
 enum bcachefs_metadata_version {
        bcachefs_metadata_version_min = 9,
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index 1aa56d28de33..36590c0ce09f 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -298,10 +298,22 @@ static int mark_stripe_bucket(struct btree_trans *trans,
        struct bpos bucket = PTR_BUCKET_POS(ca, ptr);
 
        if (flags & BTREE_TRIGGER_transactional) {
+               struct extent_ptr_decoded p = {
+                       .ptr = *ptr,
+                       .crc = bch2_extent_crc_unpack(s.k, NULL),
+               };
+               struct bkey_i_backpointer bp;
+               bch2_extent_ptr_to_bp(c, BTREE_ID_stripes, 0, s.s_c, p,
+                                     (const union bch_extent_entry *) ptr, 
&bp);
+
                struct bkey_i_alloc_v4 *a =
                        bch2_trans_start_alloc_update(trans, bucket, 0);
-               ret = PTR_ERR_OR_ZERO(a) ?:
-                       __mark_stripe_bucket(trans, ca, s, ptr_idx, deleting, 
bucket, &a->v, flags);
+               ret   = PTR_ERR_OR_ZERO(a) ?:
+                       __mark_stripe_bucket(trans, ca, s, ptr_idx, deleting, 
bucket, &a->v, flags) ?:
+                       bch2_bucket_backpointer_mod(trans, s.s_c, &bp,
+                                                   !(flags & 
BTREE_TRIGGER_overwrite));
+               if (ret)
+                       goto err;
        }
 
        if (flags & BTREE_TRIGGER_gc) {
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c
index e0e10deaea73..e944f2791546 100644
--- a/fs/bcachefs/move.c
+++ b/fs/bcachefs/move.c
@@ -774,6 +774,9 @@ static int __bch2_move_data_phys(struct moving_context 
*ctxt,
                if (!(data_types & BIT(bp.v->data_type)))
                        goto next;
 
+               if (!bp.v->level && bp.v->btree_id == BTREE_ID_stripes)
+                       goto next;
+
                k = bch2_backpointer_get_key(trans, bp, &iter, 0, 
&last_flushed);
                ret = bkey_err(k);
                if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
diff --git a/fs/bcachefs/sb-downgrade.c b/fs/bcachefs/sb-downgrade.c
index 34fd897680b3..c587334ffb55 100644
--- a/fs/bcachefs/sb-downgrade.c
+++ b/fs/bcachefs/sb-downgrade.c
@@ -95,6 +95,9 @@
          BIT_ULL(BCH_RECOVERY_PASS_check_inodes),              \
          BCH_FSCK_ERR_directory_size_mismatch)                 \
        x(cached_backpointers,                                  \
+         BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
+         BCH_FSCK_ERR_ptr_to_missing_backpointer)              \
+       x(stripe_backpointers,                                  \
          BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers),\
          BCH_FSCK_ERR_ptr_to_missing_backpointer)
 
-- 
2.45.2


Reply via email to