Update bcachefs sources to af2c94ff96a4 bcachefs: Fix FORTIFY_SOURCE warning in replicas.c
Some checks failed
build / bcachefs-tools-msrv (push) Has been cancelled
.deb build orchestrator / publish (push) Has been cancelled
.deb build orchestrator / source-only (push) Has been cancelled
.deb build orchestrator / obs (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:forky], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:forky], map[build-arch:amd64 host-arch:ppc64el machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:forky], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:trixie], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:trixie], map[build-arch:amd64 host-arch:ppc64el machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:trixie], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:unstable], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:unstable], map[build-arch:amd64 host-arch:ppc64el machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:debian version:unstable], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:plucky], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:plucky], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:questing], map[build-arch:amd64 host-arch:amd64 machine-arch:amd64 runs-on:ubuntu-24.04]) (push) Has been cancelled
.deb build orchestrator / buildd (map[name:ubuntu version:questing], map[build-arch:arm64 host-arch:arm64 machine-arch:arm64 runs-on:ubuntu-24.04-arm]) (push) Has been cancelled
.deb build orchestrator / reprotest (push) Has been cancelled
Nix Flake actions / nix-matrix (push) Has been cancelled
Nix Flake actions / ${{ matrix.name }} (${{ matrix.system }}) (push) Has been cancelled

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2025-12-05 12:04:01 -05:00
parent d93ad5bbaa
commit 55833908f7
8 changed files with 147 additions and 181 deletions

View File

@ -1 +1 @@
656fe6ab62bd41321e90e1567e6bf9c3ea058633
af2c94ff96a44454a785878c6674fcf210c5a426

View File

@ -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));

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);

View File

@ -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,

View File

@ -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, \
})

View File

@ -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));