Commit 62a03559 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Rip out code for storing backpointers in alloc keys

We don't store backpointers in alloc keys anymore, since we gained the
btree write buffer.

This patch drops support for backpointers in alloc keys, and revs the on
disk format version so that we know a fsck is required.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 349b1d83
......@@ -451,6 +451,8 @@ void __bch2_alloc_to_v4(struct bkey_s_c k, struct bch_alloc_v4 *out)
if (src < dst)
memset(src, 0, dst - src);
SET_BCH_ALLOC_V4_NR_BACKPOINTERS(out, 0);
} else {
struct bkey_alloc_unpacked u = bch2_alloc_unpack(k);
......@@ -476,38 +478,26 @@ static noinline struct bkey_i_alloc_v4 *
__bch2_alloc_to_v4_mut(struct btree_trans *trans, struct bkey_s_c k)
{
struct bkey_i_alloc_v4 *ret;
ret = bch2_trans_kmalloc(trans, sizeof(struct bkey_i_alloc_v4));
if (IS_ERR(ret))
return ret;
if (k.k->type == KEY_TYPE_alloc_v4) {
struct bkey_s_c_alloc_v4 a = bkey_s_c_to_alloc_v4(k);
unsigned bytes = sizeof(struct bkey_i_alloc_v4) +
BCH_ALLOC_V4_NR_BACKPOINTERS(a.v) *
sizeof(struct bch_backpointer);
void *src, *dst;
/*
* Reserve space for one more backpointer here:
* Not sketchy at doing it this way, nope...
*/
ret = bch2_trans_kmalloc(trans, bytes + sizeof(struct bch_backpointer));
if (IS_ERR(ret))
return ret;
bkey_reassemble(&ret->k_i, k);
src = alloc_v4_backpointers(&ret->v);
SET_BCH_ALLOC_V4_BACKPOINTERS_START(&ret->v, BCH_ALLOC_V4_U64s);
dst = alloc_v4_backpointers(&ret->v);
memmove(dst, src, BCH_ALLOC_V4_NR_BACKPOINTERS(&ret->v) *
sizeof(struct bch_backpointer));
if (src < dst)
memset(src, 0, dst - src);
SET_BCH_ALLOC_V4_NR_BACKPOINTERS(&ret->v, 0);
set_alloc_v4_u64s(ret);
} else {
ret = bch2_trans_kmalloc(trans, sizeof(struct bkey_i_alloc_v4) +
sizeof(struct bch_backpointer));
if (IS_ERR(ret))
return ret;
bkey_alloc_v4_init(&ret->k_i);
ret->k.p = k.k->p;
bch2_alloc_to_v4(k, &ret->v);
......@@ -517,8 +507,12 @@ __bch2_alloc_to_v4_mut(struct btree_trans *trans, struct bkey_s_c k)
static inline struct bkey_i_alloc_v4 *bch2_alloc_to_v4_mut_inlined(struct btree_trans *trans, struct bkey_s_c k)
{
struct bkey_s_c_alloc_v4 a;
if (likely(k.k->type == KEY_TYPE_alloc_v4) &&
BCH_ALLOC_V4_BACKPOINTERS_START(bkey_s_c_to_alloc_v4(k).v) == BCH_ALLOC_V4_U64s) {
((a = bkey_s_c_to_alloc_v4(k), true) &&
BCH_ALLOC_V4_BACKPOINTERS_START(a.v) == BCH_ALLOC_V4_U64s &&
BCH_ALLOC_V4_NR_BACKPOINTERS(a.v) == 0)) {
/*
* Reserve space for one more backpointer here:
* Not sketchy at doing it this way, nope...
......
......@@ -345,17 +345,17 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc
if (!test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) {
struct bch_backpointer bp;
u64 bp_offset = 0;
struct bpos bp_pos = POS_MIN;
ret = bch2_get_next_backpointer(trans, POS(ca->dev_idx, b), -1,
&bp_offset, &bp,
&bp_pos, &bp,
BTREE_ITER_NOPRESERVE);
if (ret) {
ob = ERR_PTR(ret);
goto err;
}
if (bp_offset != U64_MAX) {
if (!bkey_eq(bp_pos, POS_MAX)) {
/*
* Bucket may have data in it - we don't call
* bc2h_trans_inconnsistent() because fsck hasn't
......
This diff is collapsed.
......@@ -53,16 +53,11 @@ static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c,
return ret;
}
bool bch2_bucket_backpointer_del(struct btree_trans *,
struct bkey_i_alloc_v4 *,
struct bch_backpointer);
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *,
struct bkey_i_alloc_v4 *,
int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *, struct bpos,
struct bch_backpointer, struct bkey_s_c, bool);
static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans,
struct bkey_i_alloc_v4 *a,
struct bpos bucket,
struct bch_backpointer bp,
struct bkey_s_c orig_k,
bool insert)
......@@ -71,13 +66,8 @@ static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans,
struct bkey_i_backpointer *bp_k;
int ret;
if (!insert &&
unlikely(BCH_ALLOC_V4_NR_BACKPOINTERS(&a->v)) &&
bch2_bucket_backpointer_del(trans, a, bp))
return 0;
if (unlikely(bch2_backpointers_no_use_write_buffer))
return bch2_bucket_backpointer_mod_nowritebuffer(trans, a, bp, orig_k, insert);
return bch2_bucket_backpointer_mod_nowritebuffer(trans, bucket, bp, orig_k, insert);
bp_k = bch2_trans_kmalloc_nomemzero(trans, sizeof(struct bkey_i_backpointer));
ret = PTR_ERR_OR_ZERO(bp_k);
......@@ -85,7 +75,7 @@ static inline int bch2_bucket_backpointer_mod(struct btree_trans *trans,
return ret;
bkey_backpointer_init(&bp_k->k_i);
bp_k->k.p = bucket_pos_to_bp(c, a->k.p, bp.bucket_offset);
bp_k->k.p = bucket_pos_to_bp(c, bucket, bp.bucket_offset);
bp_k->v = bp;
if (!insert) {
......@@ -126,12 +116,12 @@ static inline void bch2_extent_ptr_to_bp(struct bch_fs *c,
}
int bch2_get_next_backpointer(struct btree_trans *, struct bpos, int,
u64 *, struct bch_backpointer *, unsigned);
struct bpos *, struct bch_backpointer *, unsigned);
struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *, struct btree_iter *,
struct bpos, u64, struct bch_backpointer,
struct bpos, struct bch_backpointer,
unsigned);
struct btree *bch2_backpointer_get_node(struct btree_trans *, struct btree_iter *,
struct bpos, u64, struct bch_backpointer);
struct bpos, struct bch_backpointer);
int bch2_check_btree_backpointers(struct bch_fs *);
int bch2_check_extents_to_backpointers(struct bch_fs *);
......
......@@ -1558,7 +1558,8 @@ struct bch_sb_field_journal_seq_blacklist {
x(unwritten_extents, 24) \
x(bucket_gens, 25) \
x(lru_v2, 26) \
x(fragmentation_lru, 27)
x(fragmentation_lru, 27) \
x(no_bps_in_alloc_keys, 28)
enum bcachefs_metadata_version {
bcachefs_metadata_version_min = 9,
......
......@@ -60,6 +60,7 @@ enum btree_insert_flags {
int bch2_btree_delete_extent_at(struct btree_trans *, struct btree_iter *,
unsigned, unsigned);
int bch2_btree_delete_at(struct btree_trans *, struct btree_iter *, unsigned);
int bch2_btree_delete_at_buffered(struct btree_trans *, enum btree_id, struct bpos);
int bch2_btree_insert_nonextent(struct btree_trans *, enum btree_id,
struct bkey_i *, enum btree_update_flags);
......
......@@ -1802,6 +1802,20 @@ int bch2_btree_delete_at(struct btree_trans *trans,
return bch2_btree_delete_extent_at(trans, iter, 0, update_flags);
}
int bch2_btree_delete_at_buffered(struct btree_trans *trans,
enum btree_id btree, struct bpos pos)
{
struct bkey_i *k;
k = bch2_trans_kmalloc(trans, sizeof(*k));
if (IS_ERR(k))
return PTR_ERR(k);
bkey_init(&k->k);
k->k.p = pos;
return bch2_trans_update_buffered(trans, btree, k);
}
int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id,
struct bpos start, struct bpos end,
unsigned update_flags,
......
......@@ -1407,17 +1407,17 @@ static inline int bch2_trans_mark_pointer(struct btree_trans *trans,
bool insert = !(flags & BTREE_TRIGGER_OVERWRITE);
struct btree_iter iter;
struct bkey_i_alloc_v4 *a;
struct bpos bucket_pos;
struct bpos bucket;
struct bch_backpointer bp;
s64 sectors;
int ret;
bch2_extent_ptr_to_bp(trans->c, btree_id, level, k, p, &bucket_pos, &bp);
bch2_extent_ptr_to_bp(trans->c, btree_id, level, k, p, &bucket, &bp);
sectors = bp.bucket_len;
if (!insert)
sectors = -sectors;
a = bch2_trans_start_alloc_update(trans, &iter, bucket_pos);
a = bch2_trans_start_alloc_update(trans, &iter, bucket);
if (IS_ERR(a))
return PTR_ERR(a);
......@@ -1428,7 +1428,7 @@ static inline int bch2_trans_mark_pointer(struct btree_trans *trans,
goto err;
if (!p.ptr.cached) {
ret = bch2_bucket_backpointer_mod(trans, a, bp, k, insert);
ret = bch2_bucket_backpointer_mod(trans, bucket, bp, k, insert);
if (ret)
goto err;
}
......
......@@ -887,7 +887,7 @@ static int ec_stripe_key_update(struct btree_trans *trans,
static int ec_stripe_update_extent(struct btree_trans *trans,
struct bpos bucket, u8 gen,
struct ec_stripe_buf *s,
u64 *bp_offset)
struct bpos *bp_pos)
{
struct bch_fs *c = trans->c;
struct bch_backpointer bp;
......@@ -900,10 +900,10 @@ static int ec_stripe_update_extent(struct btree_trans *trans,
int ret, dev, block;
ret = bch2_get_next_backpointer(trans, bucket, gen,
bp_offset, &bp, BTREE_ITER_CACHED);
bp_pos, &bp, BTREE_ITER_CACHED);
if (ret)
return ret;
if (*bp_offset == U64_MAX)
if (bpos_eq(*bp_pos, SPOS_MAX))
return 0;
if (bp.level) {
......@@ -911,7 +911,7 @@ static int ec_stripe_update_extent(struct btree_trans *trans,
struct btree_iter node_iter;
struct btree *b;
b = bch2_backpointer_get_node(trans, &node_iter, bucket, *bp_offset, bp);
b = bch2_backpointer_get_node(trans, &node_iter, *bp_pos, bp);
bch2_trans_iter_exit(trans, &node_iter);
if (!b)
......@@ -925,8 +925,7 @@ static int ec_stripe_update_extent(struct btree_trans *trans,
return -EIO;
}
k = bch2_backpointer_get_key(trans, &iter, bucket, *bp_offset, bp,
BTREE_ITER_INTENT);
k = bch2_backpointer_get_key(trans, &iter, *bp_pos, bp, BTREE_ITER_INTENT);
ret = bkey_err(k);
if (ret)
return ret;
......@@ -985,7 +984,7 @@ static int ec_stripe_update_bucket(struct btree_trans *trans, struct ec_stripe_b
struct bch_fs *c = trans->c;
struct bch_extent_ptr bucket = s->key.v.ptrs[block];
struct bpos bucket_pos = PTR_BUCKET_POS(c, &bucket);
u64 bp_offset = 0;
struct bpos bp_pos = POS_MIN;
int ret = 0;
while (1) {
......@@ -993,13 +992,13 @@ static int ec_stripe_update_bucket(struct btree_trans *trans, struct ec_stripe_b
BTREE_INSERT_NOCHECK_RW|
BTREE_INSERT_NOFAIL,
ec_stripe_update_extent(trans, bucket_pos, bucket.gen,
s, &bp_offset));
s, &bp_pos));
if (ret)
break;
if (bp_offset == U64_MAX)
if (bkey_eq(bp_pos, POS_MAX))
break;
bp_offset++;
bp_pos = bpos_nosnap_successor(bp_pos);
}
return ret;
......
......@@ -626,7 +626,7 @@ void bch2_verify_bucket_evacuated(struct btree_trans *trans, struct bpos bucket,
struct bkey_s_c k;
struct printbuf buf = PRINTBUF;
struct bch_backpointer bp;
u64 bp_offset = 0;
struct bpos bp_pos = POS_MIN;
unsigned nr_bps = 0;
int ret;
......@@ -668,17 +668,16 @@ void bch2_verify_bucket_evacuated(struct btree_trans *trans, struct bpos bucket,
bch2_trans_begin(trans);
ret = bch2_get_next_backpointer(trans, bucket, gen,
&bp_offset, &bp,
&bp_pos, &bp,
BTREE_ITER_CACHED);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue;
if (ret)
break;
if (bp_offset == U64_MAX)
if (bkey_eq(bp_pos, POS_MAX))
break;
k = bch2_backpointer_get_key(trans, &iter,
bucket, bp_offset, bp, 0);
k = bch2_backpointer_get_key(trans, &iter, bp_pos, bp, 0);
ret = bkey_err(k);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue;
......@@ -692,7 +691,7 @@ void bch2_verify_bucket_evacuated(struct btree_trans *trans, struct bpos bucket,
if (++nr_bps > 10)
break;
bp_offset++;
bp_pos = bpos_nosnap_successor(bp_pos);
}
bch2_print_string_as_lines(KERN_ERR, buf.buf);
......@@ -716,7 +715,8 @@ int __bch2_evacuate_bucket(struct btree_trans *trans,
struct data_update_opts data_opts;
unsigned dirty_sectors, bucket_size;
u64 fragmentation;
u64 bp_offset = 0, cur_inum = U64_MAX;
u64 cur_inum = U64_MAX;
struct bpos bp_pos = POS_MIN;
int ret = 0;
bch2_bkey_buf_init(&sk);
......@@ -752,13 +752,13 @@ int __bch2_evacuate_bucket(struct btree_trans *trans,
bch2_trans_begin(trans);
ret = bch2_get_next_backpointer(trans, bucket, gen,
&bp_offset, &bp,
&bp_pos, &bp,
BTREE_ITER_CACHED);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue;
if (ret)
goto err;
if (bp_offset == U64_MAX)
if (bkey_eq(bp_pos, POS_MAX))
break;
if (!bp.level) {
......@@ -766,8 +766,7 @@ int __bch2_evacuate_bucket(struct btree_trans *trans,
struct bkey_s_c k;
unsigned i = 0;
k = bch2_backpointer_get_key(trans, &iter,
bucket, bp_offset, bp, 0);
k = bch2_backpointer_get_key(trans, &iter, bp_pos, bp, 0);
ret = bkey_err(k);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue;
......@@ -822,8 +821,7 @@ int __bch2_evacuate_bucket(struct btree_trans *trans,
} else {
struct btree *b;
b = bch2_backpointer_get_node(trans, &iter,
bucket, bp_offset, bp);
b = bch2_backpointer_get_node(trans, &iter, bp_pos, bp);
ret = PTR_ERR_OR_ZERO(b);
if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node)
continue;
......@@ -851,7 +849,7 @@ int __bch2_evacuate_bucket(struct btree_trans *trans,
}
}
next:
bp_offset++;
bp_pos = bpos_nosnap_successor(bp_pos);
}
trace_evacuate_bucket(c, &bucket, dirty_sectors, bucket_size, fragmentation, ret);
......
......@@ -1134,14 +1134,11 @@ int bch2_fs_recovery(struct bch_fs *c)
}
if (!c->opts.nochanges) {
if (c->sb.version < bcachefs_metadata_version_lru_v2) {
bch_info(c, "version prior to backpointers, upgrade and fsck required");
if (c->sb.version < bcachefs_metadata_version_no_bps_in_alloc_keys) {
bch_info(c, "version prior to no_bps_in_alloc_keys, upgrade and fsck required");
c->opts.version_upgrade = true;
c->opts.fsck = true;
c->opts.fix_errors = FSCK_OPT_YES;
} else if (c->sb.version < bcachefs_metadata_version_fragmentation_lru) {
bch_info(c, "version prior to backpointers, upgrade required");
c->opts.version_upgrade = true;
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment