1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

bcachefs: bch2_bucket_ref_update()

If we hit an inconsistency when updating allocation information, we
don't want to fail the update if it's for a deletion - only if it's for
a new key.

Rename check_bucket_ref() -> bucket_ref_update() so we can centralize
the logic to do this.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-04-19 19:03:58 -04:00
parent 9cc455d1bc
commit 70e3e039cf
3 changed files with 42 additions and 33 deletions

View file

@ -485,19 +485,22 @@ int bch2_update_cached_sectors_list(struct btree_trans *trans, unsigned dev, s64
return bch2_update_replicas_list(trans, &r.e, sectors); return bch2_update_replicas_list(trans, &r.e, sectors);
} }
int bch2_check_bucket_ref(struct btree_trans *trans, int bch2_bucket_ref_update(struct btree_trans *trans,
struct bkey_s_c k, struct bkey_s_c k,
const struct bch_extent_ptr *ptr, const struct bch_extent_ptr *ptr,
s64 sectors, enum bch_data_type ptr_data_type, s64 sectors, enum bch_data_type ptr_data_type,
u8 b_gen, u8 bucket_data_type, u8 b_gen, u8 bucket_data_type,
u32 bucket_sectors) u32 *bucket_sectors)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct bch_dev *ca = bch2_dev_bkey_exists(c, ptr->dev); struct bch_dev *ca = bch2_dev_bkey_exists(c, ptr->dev);
size_t bucket_nr = PTR_BUCKET_NR(ca, ptr); size_t bucket_nr = PTR_BUCKET_NR(ca, ptr);
struct printbuf buf = PRINTBUF; struct printbuf buf = PRINTBUF;
bool inserting = sectors > 0;
int ret = 0; int ret = 0;
BUG_ON(!sectors);
if (gen_after(ptr->gen, b_gen)) { if (gen_after(ptr->gen, b_gen)) {
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
BCH_FSCK_ERR_ptr_gen_newer_than_bucket_gen, BCH_FSCK_ERR_ptr_gen_newer_than_bucket_gen,
@ -507,8 +510,9 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
bch2_data_type_str(bucket_data_type ?: ptr_data_type), bch2_data_type_str(bucket_data_type ?: ptr_data_type),
ptr->gen, ptr->gen,
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)); (bch2_bkey_val_to_text(&buf, c, k), buf.buf));
ret = -EIO; if (inserting)
goto err; goto err;
goto out;
} }
if (gen_cmp(b_gen, ptr->gen) > BUCKET_GC_GEN_MAX) { if (gen_cmp(b_gen, ptr->gen) > BUCKET_GC_GEN_MAX) {
@ -521,11 +525,17 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
ptr->gen, ptr->gen,
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), buf.buf)); bch2_bkey_val_to_text(&buf, c, k), buf.buf));
ret = -EIO; if (inserting)
goto err; goto err;
goto out;
} }
if (b_gen != ptr->gen && !ptr->cached) { if (b_gen != ptr->gen && ptr->cached) {
ret = 1;
goto out;
}
if (b_gen != ptr->gen) {
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
BCH_FSCK_ERR_stale_dirty_ptr, BCH_FSCK_ERR_stale_dirty_ptr,
"bucket %u:%zu gen %u (mem gen %u) data type %s: stale dirty ptr (gen %u)\n" "bucket %u:%zu gen %u (mem gen %u) data type %s: stale dirty ptr (gen %u)\n"
@ -536,12 +546,8 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
ptr->gen, ptr->gen,
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), buf.buf)); bch2_bkey_val_to_text(&buf, c, k), buf.buf));
ret = -EIO; if (inserting)
goto err; goto err;
}
if (b_gen != ptr->gen) {
ret = 1;
goto out; goto out;
} }
@ -555,28 +561,33 @@ int bch2_check_bucket_ref(struct btree_trans *trans,
bch2_data_type_str(ptr_data_type), bch2_data_type_str(ptr_data_type),
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), buf.buf)); bch2_bkey_val_to_text(&buf, c, k), buf.buf));
ret = -EIO; if (inserting)
goto err; goto err;
goto out;
} }
if ((u64) bucket_sectors + sectors > U32_MAX) { if ((u64) *bucket_sectors + sectors > U32_MAX) {
bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, bch2_fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
BCH_FSCK_ERR_bucket_sector_count_overflow, BCH_FSCK_ERR_bucket_sector_count_overflow,
"bucket %u:%zu gen %u data type %s sector count overflow: %u + %lli > U32_MAX\n" "bucket %u:%zu gen %u data type %s sector count overflow: %u + %lli > U32_MAX\n"
"while marking %s", "while marking %s",
ptr->dev, bucket_nr, b_gen, ptr->dev, bucket_nr, b_gen,
bch2_data_type_str(bucket_data_type ?: ptr_data_type), bch2_data_type_str(bucket_data_type ?: ptr_data_type),
bucket_sectors, sectors, *bucket_sectors, sectors,
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), buf.buf)); bch2_bkey_val_to_text(&buf, c, k), buf.buf));
ret = -EIO; if (inserting)
goto err; goto err;
sectors = -*bucket_sectors;
} }
*bucket_sectors += sectors;
out: out:
printbuf_exit(&buf); printbuf_exit(&buf);
return ret; return ret;
err: err:
bch2_dump_trans_updates(trans); bch2_dump_trans_updates(trans);
ret = -EIO;
goto out; goto out;
} }
@ -723,14 +734,12 @@ static int __mark_pointer(struct btree_trans *trans,
u32 *dst_sectors = !ptr->cached u32 *dst_sectors = !ptr->cached
? dirty_sectors ? dirty_sectors
: cached_sectors; : cached_sectors;
int ret = bch2_check_bucket_ref(trans, k, ptr, sectors, ptr_data_type, int ret = bch2_bucket_ref_update(trans, k, ptr, sectors, ptr_data_type,
bucket_gen, *bucket_data_type, *dst_sectors); bucket_gen, *bucket_data_type, dst_sectors);
if (ret) if (ret)
return ret; return ret;
*dst_sectors += sectors;
if (!*dirty_sectors && !*cached_sectors) if (!*dirty_sectors && !*cached_sectors)
*bucket_data_type = 0; *bucket_data_type = 0;
else if (*bucket_data_type != BCH_DATA_stripe) else if (*bucket_data_type != BCH_DATA_stripe)

View file

@ -337,9 +337,9 @@ int bch2_replicas_deltas_realloc(struct btree_trans *, unsigned);
void bch2_fs_usage_initialize(struct bch_fs *); void bch2_fs_usage_initialize(struct bch_fs *);
int bch2_check_bucket_ref(struct btree_trans *, struct bkey_s_c, int bch2_bucket_ref_update(struct btree_trans *, struct bkey_s_c,
const struct bch_extent_ptr *, const struct bch_extent_ptr *,
s64, enum bch_data_type, u8, u8, u32); s64, enum bch_data_type, u8, u8, u32 *);
int bch2_trigger_extent(struct btree_trans *, enum btree_id, unsigned, int bch2_trigger_extent(struct btree_trans *, enum btree_id, unsigned,
struct bkey_s_c, struct bkey_s, struct bkey_s_c, struct bkey_s,

View file

@ -243,13 +243,13 @@ static int __mark_stripe_bucket(struct btree_trans *trans,
} }
} }
ret = bch2_check_bucket_ref(trans, s.s_c, ptr, sectors, data_type, if (sectors) {
bucket_gen, *bucket_data_type, ret = bch2_bucket_ref_update(trans, s.s_c, ptr, sectors, data_type,
*bucket_dirty_sectors); bucket_gen, *bucket_data_type,
if (ret) bucket_dirty_sectors);
goto err; if (ret)
goto err;
*bucket_dirty_sectors += sectors; }
if (!deleting) { if (!deleting) {
*bucket_stripe = s.k->p.offset; *bucket_stripe = s.k->p.offset;