From 55833908f77f980ae446a841acaa788e7277ef9b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Dec 2025 12:04:01 -0500 Subject: [PATCH] Update bcachefs sources to af2c94ff96a4 bcachefs: Fix FORTIFY_SOURCE warning in replicas.c Signed-off-by: Kent Overstreet --- .bcachefs_revision | 2 +- libbcachefs/alloc/buckets.c | 247 ++++++++++++------------------ libbcachefs/alloc/replicas.c | 10 +- libbcachefs/alloc/types.h | 4 +- libbcachefs/sb/members.c | 3 + libbcachefs/snapshots/snapshot.c | 42 ++--- libbcachefs/snapshots/snapshot.h | 5 +- libbcachefs/snapshots/subvolume.c | 15 +- 8 files changed, 147 insertions(+), 181 deletions(-) diff --git a/.bcachefs_revision b/.bcachefs_revision index 4efcf333..03f5be4e 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -656fe6ab62bd41321e90e1567e6bf9c3ea058633 +af2c94ff96a44454a785878c6674fcf210c5a426 diff --git a/libbcachefs/alloc/buckets.c b/libbcachefs/alloc/buckets.c index 03cedf7f..cc9aa594 100644 --- a/libbcachefs/alloc/buckets.c +++ b/libbcachefs/alloc/buckets.c @@ -104,20 +104,33 @@ void bch2_dev_usage_to_text(struct printbuf *out, prt_printf(out, "capacity\t%llu\r\n", ca->mi.nbuckets); } +struct ptrs_repair { + u8 drop; + u8 drop_stripe; + u8 reset_gen; +}; + +static inline int drop_this_ptr(struct ptrs_repair *r, unsigned ptr_bit) +{ + r->drop |= ptr_bit; + return 0; +} + static int bch2_check_fix_ptr(struct btree_trans *trans, struct bkey_s_c k, struct extent_ptr_decoded p, const union bch_extent_entry *entry, - bool *do_update) + struct ptrs_repair *r, + unsigned ptr_bit) { + if (p.ptr.dev == BCH_SB_MEMBER_INVALID) + return 0; + struct bch_fs *c = trans->c; CLASS(printbuf, buf)(); CLASS(bch2_dev_tryget_noerror, ca)(c, p.ptr.dev); if (!ca) { - if (p.ptr.dev == BCH_SB_MEMBER_INVALID) - return 0; - if (test_bit(p.ptr.dev, c->devs_removed.d)) { if (ret_fsck_err(trans, ptr_to_removed_device, "pointer to removed device %u\n" @@ -125,7 +138,7 @@ static int bch2_check_fix_ptr(struct btree_trans *trans, p.ptr.dev, (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - *do_update = true; + return drop_this_ptr(r, ptr_bit); } else { if (ret_fsck_err(trans, ptr_to_invalid_device, "pointer to missing device %u\n" @@ -133,7 +146,7 @@ static int bch2_check_fix_ptr(struct btree_trans *trans, p.ptr.dev, (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - *do_update = true; + return drop_this_ptr(r, ptr_bit); } return 0; } @@ -146,7 +159,7 @@ static int bch2_check_fix_ptr(struct btree_trans *trans, p.ptr.dev, (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - *do_update = true; + return drop_this_ptr(r, ptr_bit); return 0; } @@ -161,14 +174,11 @@ static int bch2_check_fix_ptr(struct btree_trans *trans, p.ptr.gen, (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { - if (!p.ptr.cached) { - g->gen_valid = true; - g->gen = p.ptr.gen; - } else { - /* this pointer will be dropped */ - *do_update = true; - return 0; - } + if (p.ptr.cached) + return drop_this_ptr(r, ptr_bit); + + g->gen_valid = true; + g->gen = p.ptr.gen; } /* g->gen_valid == true */ @@ -182,39 +192,38 @@ static int bch2_check_fix_ptr(struct btree_trans *trans, p.ptr.gen, g->gen, (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { - if (!p.ptr.cached && - (g->data_type != BCH_DATA_btree || - data_type == BCH_DATA_btree)) { - g->data_type = data_type; - g->stripe_sectors = 0; - g->dirty_sectors = 0; - g->cached_sectors = 0; - } + if (p.ptr.cached) + return drop_this_ptr(r, ptr_bit); - *do_update = true; + /* XXX: if it's a data pointer, read it and see if it's good */ + r->reset_gen |= ptr_bit; } - if (ret_fsck_err_on(gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX, - trans, ptr_gen_newer_than_bucket_gen, - "bucket %u:%zu gen %u data type %s: ptr gen %u too stale\n" - "while marking %s", - p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), g->gen, - bch2_data_type_str(ptr_data_type(k.k, &p.ptr)), - p.ptr.gen, - (printbuf_reset(&buf), - bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - *do_update = true; - - if (ret_fsck_err_on(!p.ptr.cached && gen_cmp(p.ptr.gen, g->gen) < 0, - trans, stale_dirty_ptr, - "bucket %u:%zu data type %s stale dirty ptr: %u < %u\n" - "while marking %s", - p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), - bch2_data_type_str(ptr_data_type(k.k, &p.ptr)), - p.ptr.gen, g->gen, - (printbuf_reset(&buf), - bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - *do_update = true; + if (!p.ptr.cached) { + if (ret_fsck_err_on(gen_cmp(p.ptr.gen, g->gen) < 0, + trans, stale_dirty_ptr, + "bucket %u:%zu data type %s stale dirty ptr: %u < %u\n" + "while marking %s", + p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), + bch2_data_type_str(ptr_data_type(k.k, &p.ptr)), + p.ptr.gen, g->gen, + (printbuf_reset(&buf), + bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { + /* XXX: if it's a data pointer, read it and see if it's good */ + r->reset_gen |= ptr_bit; + } + } else { + if (ret_fsck_err_on(gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX, + trans, ptr_gen_newer_than_bucket_gen, + "bucket %u:%zu gen %u data type %s: ptr gen %u too stale\n" + "while marking %s", + p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr), g->gen, + bch2_data_type_str(ptr_data_type(k.k, &p.ptr)), + p.ptr.gen, + (printbuf_reset(&buf), + bch2_bkey_val_to_text(&buf, c, k), buf.buf))) + return drop_this_ptr(r, ptr_bit); + } if (data_type != BCH_DATA_btree && p.ptr.gen != g->gen) return 0; @@ -228,24 +237,23 @@ static int bch2_check_fix_ptr(struct btree_trans *trans, bch2_data_type_str(data_type), (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { - if (!p.ptr.cached && - data_type == BCH_DATA_btree) { - switch (g->data_type) { - case BCH_DATA_sb: - bch_err(c, "btree and superblock in the same bucket - cannot repair"); - return bch_err_throw(c, fsck_repair_unimplemented); - case BCH_DATA_journal: - try(bch2_dev_journal_bucket_delete(ca, PTR_BUCKET_NR(ca, &p.ptr))); - break; - } + if (p.ptr.cached || + data_type != BCH_DATA_btree) + return drop_this_ptr(r, ptr_bit); - g->data_type = data_type; - g->stripe_sectors = 0; - g->dirty_sectors = 0; - g->cached_sectors = 0; - } else { - *do_update = true; + switch (g->data_type) { + case BCH_DATA_sb: + bch_err(c, "btree and superblock in the same bucket - cannot repair"); + return bch_err_throw(c, fsck_repair_unimplemented); + case BCH_DATA_journal: + try(bch2_dev_journal_bucket_delete(ca, PTR_BUCKET_NR(ca, &p.ptr))); + break; } + + g->data_type = data_type; + g->stripe_sectors = 0; + g->dirty_sectors = 0; + g->cached_sectors = 0; } if (p.has_ec) { @@ -257,126 +265,67 @@ static int bch2_check_fix_ptr(struct btree_trans *trans, "while marking %s", (u64) p.ec.idx, (printbuf_reset(&buf), - bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - *do_update = true; - - if (ret_fsck_err_on(m && m->alive && !bch2_ptr_matches_stripe_m(m, p), + bch2_bkey_val_to_text(&buf, c, k), buf.buf)) || + ret_fsck_err_on(m && m->alive && !bch2_ptr_matches_stripe_m(m, p), trans, ptr_to_incorrect_stripe, "pointer does not match stripe %llu\n" "while marking %s", (u64) p.ec.idx, (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) - *do_update = true; + r->drop_stripe |= ptr_bit; } return 0; } -static bool should_drop_ptr(struct bch_fs *c, struct bkey_s_c k, - struct extent_ptr_decoded p, - const union bch_extent_entry *entry) -{ - struct bch_dev *ca = bch2_dev_rcu_noerror(c, p.ptr.dev); - if (!ca) - return true; - - struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr); - enum bch_data_type data_type = bch2_bkey_ptr_data_type(k, p, entry); - - if (p.ptr.cached) { - return !g->gen_valid || gen_cmp(p.ptr.gen, g->gen); - } else { - return gen_cmp(p.ptr.gen, g->gen) < 0 || - gen_cmp(g->gen, p.ptr.gen) > BUCKET_GC_GEN_MAX || - (g->data_type && g->data_type != data_type); - } -} - int bch2_check_fix_ptrs(struct btree_trans *trans, enum btree_id btree, unsigned level, struct bkey_s_c k, enum btree_iter_update_trigger_flags flags) { struct bch_fs *c = trans->c; - struct bkey_ptrs_c ptrs_c = bch2_bkey_ptrs_c(k); - const union bch_extent_entry *entry_c; - struct extent_ptr_decoded p = { 0 }; - bool do_update = false; - CLASS(printbuf, buf)(); /* We don't yet do btree key updates correctly for when we're RW */ BUG_ON(test_bit(BCH_FS_rw, &c->flags)); - bkey_for_each_ptr_decode(k.k, ptrs_c, p, entry_c) - try(bch2_check_fix_ptr(trans, k, p, entry_c, &do_update)); + struct ptrs_repair r = {}; - if (do_update) { + struct bkey_ptrs_c ptrs_c = bch2_bkey_ptrs_c(k); + const union bch_extent_entry *entry_c; + struct extent_ptr_decoded p; + unsigned ptr_bit = 1; + + bkey_for_each_ptr_decode(k.k, ptrs_c, p, entry_c) { + try(bch2_check_fix_ptr(trans, k, p, entry_c, &r, ptr_bit)); + ptr_bit <<= 1; + } + + if (r.drop || + r.drop_stripe || + r.reset_gen) { struct bkey_i *new = errptr_try(bch2_trans_kmalloc(trans, BKEY_EXTENT_U64s_MAX * sizeof(u64))); bkey_reassemble(new, k); - scoped_guard(rcu) - bch2_bkey_drop_ptrs(bkey_i_to_s(new), p, entry, - !bch2_dev_exists(c, p.ptr.dev)); - - if (level) { - /* - * We don't want to drop btree node pointers - if the - * btree node isn't there anymore, the read path will - * sort it out: - */ - struct bkey_ptrs ptrs = bch2_bkey_ptrs(bkey_i_to_s(new)); - scoped_guard(rcu) - bkey_for_each_ptr(ptrs, ptr) { - struct bch_dev *ca = bch2_dev_rcu_noerror(c, ptr->dev); + struct bkey_ptrs ptrs = bch2_bkey_ptrs(bkey_i_to_s(new)); + if (r.reset_gen) { + unsigned ptr_bit = 1; + guard(rcu)(); + bkey_for_each_ptr(ptrs, ptr) { + if (r.reset_gen & ptr_bit) { + struct bch_dev *ca = bch2_dev_rcu(c, ptr->dev); if (ca) ptr->gen = PTR_GC_BUCKET(ca, ptr)->gen; } - } else { - scoped_guard(rcu) - bch2_bkey_drop_ptrs(bkey_i_to_s(new), p, entry, - should_drop_ptr(c, bkey_i_to_s_c(new), p, entry)); - - struct bkey_ptrs ptrs; - union bch_extent_entry *entry; -again: - ptrs = bch2_bkey_ptrs(bkey_i_to_s(new)); - bkey_extent_entry_for_each(ptrs, entry) { - if (extent_entry_type(entry) == BCH_EXTENT_ENTRY_stripe_ptr) { - struct gc_stripe *m = genradix_ptr(&c->ec.gc_stripes, - entry->stripe_ptr.idx); - union bch_extent_entry *next_ptr; - - bkey_extent_entry_for_each_from(ptrs, next_ptr, entry) - if (extent_entry_type(next_ptr) == BCH_EXTENT_ENTRY_ptr) - goto found; - next_ptr = NULL; -found: - if (!next_ptr) { - bch_err(c, "aieee, found stripe ptr with no data ptr"); - continue; - } - - if (!m || !m->alive || - !__bch2_ptr_matches_stripe(&m->ptrs[entry->stripe_ptr.block], - &next_ptr->ptr, - m->sectors)) { - bch2_bkey_extent_entry_drop(c, new, entry); - goto again; - } - } + ptr_bit <<= 1; } } - if (0) { - printbuf_reset(&buf); - bch2_bkey_val_to_text(&buf, c, k); - bch_info(c, "updated %s", buf.buf); + if (r.drop_stripe) + bch2_bkey_drop_ec_mask(c, new, r.drop_stripe); - printbuf_reset(&buf); - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(new)); - bch_info(c, "new key %s", buf.buf); - } + if (r.drop) + bch2_bkey_drop_ptrs_mask(c, new, r.drop); struct bch_inode_opts opts; try(bch2_bkey_get_io_opts(trans, NULL, k, &opts)); diff --git a/libbcachefs/alloc/replicas.c b/libbcachefs/alloc/replicas.c index a1dea84f..57343b85 100644 --- a/libbcachefs/alloc/replicas.c +++ b/libbcachefs/alloc/replicas.c @@ -313,9 +313,10 @@ cpu_replicas_add_entry(struct bch_fs *c, cpu_replicas_entry(old, i), old->entry_size); - memcpy(&cpu_replicas_entry(&new, old->nr)->e, - new_entry, - replicas_entry_bytes(new_entry)); + unsafe_memcpy(&cpu_replicas_entry(&new, old->nr)->e, + new_entry, + replicas_entry_bytes(new_entry), + "embedded variable length struct"); bch2_cpu_replicas_sort(&new); return new; @@ -564,7 +565,8 @@ __bch2_sb_replicas_to_cpu_replicas(struct bch_sb_field_replicas *sb_r, for_each_replicas_entry(sb_r, src) { struct bch_replicas_entry_cpu *dst = cpu_replicas_entry(cpu_r, idx++); - memcpy(&dst->e, src, replicas_entry_bytes(src)); + unsafe_memcpy(&dst->e, src, replicas_entry_bytes(src), + "embedded variable length struct"); bch2_replicas_entry_sort(&dst->e); } diff --git a/libbcachefs/alloc/types.h b/libbcachefs/alloc/types.h index 92d8091f..a24296e4 100644 --- a/libbcachefs/alloc/types.h +++ b/libbcachefs/alloc/types.h @@ -61,11 +61,9 @@ struct open_bucket { struct ec_stripe_new *ec; }; -#define OPEN_BUCKET_LIST_MAX 15 - struct open_buckets { open_bucket_idx_t nr; - open_bucket_idx_t v[OPEN_BUCKET_LIST_MAX]; + open_bucket_idx_t v[BCH_BKEY_PTRS_MAX]; }; struct dev_stripe_state { diff --git a/libbcachefs/sb/members.c b/libbcachefs/sb/members.c index a99d3ce5..872dad8e 100644 --- a/libbcachefs/sb/members.c +++ b/libbcachefs/sb/members.c @@ -116,6 +116,9 @@ int bch2_sb_members_v2_init(struct bch_fs *c) DIV_ROUND_UP(sizeof(*mi2) + sizeof(struct bch_member) * c->sb.nr_devices, sizeof(u64))); + if (!mi2) + return bch_err_throw(c, ENOSPC_sb_members_v2); + mi1 = bch2_sb_field_get(c->disk_sb.sb, members_v1); memcpy(&mi2->_members[0], &mi1->_members[0], BCH_MEMBER_V1_BYTES * c->sb.nr_devices); diff --git a/libbcachefs/snapshots/snapshot.c b/libbcachefs/snapshots/snapshot.c index c6c6e74e..05f872dc 100644 --- a/libbcachefs/snapshots/snapshot.c +++ b/libbcachefs/snapshots/snapshot.c @@ -183,33 +183,37 @@ struct snapshot_t *bch2_snapshot_t_mut(struct bch_fs *c, u32 id) return __snapshot_t_mut(c, id); } -void bch2_snapshot_to_text(struct printbuf *out, struct bch_fs *c, - struct bkey_s_c k) +void bch2_snapshot_to_text(struct printbuf *out, struct bch_snapshot *s) { - struct bkey_s_c_snapshot s = bkey_s_c_to_snapshot(k); - - if (BCH_SNAPSHOT_SUBVOL(s.v)) + if (BCH_SNAPSHOT_SUBVOL(s)) prt_str(out, "subvol "); - if (BCH_SNAPSHOT_WILL_DELETE(s.v)) + if (BCH_SNAPSHOT_WILL_DELETE(s)) prt_str(out, "will_delete "); - if (BCH_SNAPSHOT_DELETED(s.v)) + if (BCH_SNAPSHOT_DELETED(s)) prt_str(out, "deleted "); - if (BCH_SNAPSHOT_NO_KEYS(s.v)) + if (BCH_SNAPSHOT_NO_KEYS(s)) prt_str(out, "no_keys "); prt_printf(out, "parent %10u children %10u %10u subvol %u tree %u", - le32_to_cpu(s.v->parent), - le32_to_cpu(s.v->children[0]), - le32_to_cpu(s.v->children[1]), - le32_to_cpu(s.v->subvol), - le32_to_cpu(s.v->tree)); + le32_to_cpu(s->parent), + le32_to_cpu(s->children[0]), + le32_to_cpu(s->children[1]), + le32_to_cpu(s->subvol), + le32_to_cpu(s->tree)); - if (bkey_val_bytes(k.k) > offsetof(struct bch_snapshot, depth)) - prt_printf(out, " depth %u skiplist %u %u %u", - le32_to_cpu(s.v->depth), - le32_to_cpu(s.v->skip[0]), - le32_to_cpu(s.v->skip[1]), - le32_to_cpu(s.v->skip[2])); + prt_printf(out, " depth %u skiplist %u %u %u", + le32_to_cpu(s->depth), + le32_to_cpu(s->skip[0]), + le32_to_cpu(s->skip[1]), + le32_to_cpu(s->skip[2])); +} + +void bch2_snapshot_key_to_text(struct printbuf *out, struct bch_fs *c, + struct bkey_s_c k) +{ + struct bch_snapshot snapshot; + bkey_val_copy_pad(&snapshot, bkey_s_c_to_snapshot(k)); + bch2_snapshot_to_text(out, &snapshot); } int bch2_snapshot_validate(struct bch_fs *c, struct bkey_s_c k, diff --git a/libbcachefs/snapshots/snapshot.h b/libbcachefs/snapshots/snapshot.h index 58c42b9f..5e70e927 100644 --- a/libbcachefs/snapshots/snapshot.h +++ b/libbcachefs/snapshots/snapshot.h @@ -16,7 +16,8 @@ struct bkey_i_snapshot_tree *__bch2_snapshot_tree_create(struct btree_trans *); int bch2_snapshot_tree_lookup(struct btree_trans *, u32, struct bch_snapshot_tree *); -void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); +void bch2_snapshot_to_text(struct printbuf *, struct bch_snapshot *); +void bch2_snapshot_key_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); int bch2_snapshot_validate(struct bch_fs *, struct bkey_s_c, struct bkey_validate_context); int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned, @@ -25,7 +26,7 @@ int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned, #define bch2_bkey_ops_snapshot ((struct bkey_ops) { \ .key_validate = bch2_snapshot_validate, \ - .val_to_text = bch2_snapshot_to_text, \ + .val_to_text = bch2_snapshot_key_to_text, \ .trigger = bch2_mark_snapshot, \ .min_val_size = 24, \ }) diff --git a/libbcachefs/snapshots/subvolume.c b/libbcachefs/snapshots/subvolume.c index 9ed17f47..8facff17 100644 --- a/libbcachefs/snapshots/subvolume.c +++ b/libbcachefs/snapshots/subvolume.c @@ -100,7 +100,8 @@ static int check_subvol(struct btree_trans *trans, subvol_children_iter.pos.inode, subvol_children_iter.pos.offset, (printbuf_reset(&buf), bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { - try(bch2_btree_bit_mod(trans, BTREE_ID_subvolume_children, subvol_children_iter.pos, true)); + try(bch2_btree_bit_mod(trans, BTREE_ID_subvolume_children, + subvol_children_iter.pos, true)); } } @@ -111,9 +112,17 @@ static int check_subvol(struct btree_trans *trans, if (!ret) { if (fsck_err_on(inode.bi_subvol != k.k->p.offset, trans, subvol_root_wrong_bi_subvol, - "subvol root %llu:%u has wrong bi_subvol field: got %u, should be %llu", + "subvol root %llu:%u has wrong bi_subvol field: got %u, should be %llu\n%s", inode.bi_inum, inode.bi_snapshot, - inode.bi_subvol, k.k->p.offset)) { + inode.bi_subvol, k.k->p.offset, + (printbuf_reset(&buf), + bch2_bkey_val_to_text(&buf, c, k), + prt_newline(&buf), + prt_printf(&buf, "snapshot %u: ", snapid), + bch2_snapshot_to_text(&buf, &snapshot), + prt_newline(&buf), + bch2_inode_unpacked_to_text(&buf, &inode), + buf.buf))) { inode.bi_subvol = k.k->p.offset; inode.bi_snapshot = le32_to_cpu(subvol.snapshot); try(__bch2_fsck_write_inode(trans, &inode));