Commit 67163cde authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Trust in memory bucket mark

This fixes a bug in the journal replay -> extent_replay_key ->
split_compressed path, when we do an update that changes alloc info but
the alloc info in the btree isn't up to date yet.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 7d5224fc
...@@ -205,20 +205,6 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, ...@@ -205,20 +205,6 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c,
get_alloc_field(a.v, &d, i)); get_alloc_field(a.v, &d, i));
} }
static inline struct bkey_alloc_unpacked
alloc_mem_to_key(struct bucket *g, struct bucket_mark m)
{
return (struct bkey_alloc_unpacked) {
.gen = m.gen,
.oldest_gen = g->oldest_gen,
.data_type = m.data_type,
.dirty_sectors = m.dirty_sectors,
.cached_sectors = m.cached_sectors,
.read_time = g->io_time[READ],
.write_time = g->io_time[WRITE],
};
}
int bch2_alloc_read(struct bch_fs *c, struct journal_keys *journal_keys) int bch2_alloc_read(struct bch_fs *c, struct journal_keys *journal_keys)
{ {
struct btree_trans trans; struct btree_trans trans;
......
...@@ -17,6 +17,20 @@ struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c); ...@@ -17,6 +17,20 @@ struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c);
void bch2_alloc_pack(struct bkey_i_alloc *, void bch2_alloc_pack(struct bkey_i_alloc *,
const struct bkey_alloc_unpacked); const struct bkey_alloc_unpacked);
static inline struct bkey_alloc_unpacked
alloc_mem_to_key(struct bucket *g, struct bucket_mark m)
{
return (struct bkey_alloc_unpacked) {
.gen = m.gen,
.oldest_gen = g->oldest_gen,
.data_type = m.data_type,
.dirty_sectors = m.dirty_sectors,
.cached_sectors = m.cached_sectors,
.read_time = g->io_time[READ],
.write_time = g->io_time[WRITE],
};
}
#define ALLOC_SCAN_BATCH(ca) max_t(size_t, 1, (ca)->mi.nbuckets >> 9) #define ALLOC_SCAN_BATCH(ca) max_t(size_t, 1, (ca)->mi.nbuckets >> 9)
const char *bch2_alloc_invalid(const struct bch_fs *, struct bkey_s_c); const char *bch2_alloc_invalid(const struct bch_fs *, struct bkey_s_c);
......
...@@ -1361,7 +1361,7 @@ static int trans_get_key(struct btree_trans *trans, ...@@ -1361,7 +1361,7 @@ static int trans_get_key(struct btree_trans *trans,
: !bkey_cmp(pos, i->iter->pos))) { : !bkey_cmp(pos, i->iter->pos))) {
*iter = i->iter; *iter = i->iter;
*k = bkey_i_to_s_c(i->k); *k = bkey_i_to_s_c(i->k);
return 0; return 1;
} }
*iter = __bch2_trans_get_iter(trans, btree_id, pos, *iter = __bch2_trans_get_iter(trans, btree_id, pos,
...@@ -1424,9 +1424,27 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans, ...@@ -1424,9 +1424,27 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
ret = trans_get_key(trans, BTREE_ID_ALLOC, ret = trans_get_key(trans, BTREE_ID_ALLOC,
POS(p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr)), POS(p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr)),
&iter, &k); &iter, &k);
if (ret) if (ret < 0)
return ret; return ret;
if (!ret) {
/*
* During journal replay, and if gc repairs alloc info at
* runtime, the alloc info in the btree might not be up to date
* yet - so, trust the in memory mark:
*/
struct bucket *g;
struct bucket_mark m;
percpu_down_read(&c->mark_lock);
g = bucket(ca, iter->pos.offset);
m = READ_ONCE(g->mark);
u = alloc_mem_to_key(g, m);
percpu_up_read(&c->mark_lock);
} else {
/*
* Unless we're already updating that key:
*/
if (k.k->type != KEY_TYPE_alloc) { if (k.k->type != KEY_TYPE_alloc) {
bch_err_ratelimited(c, "pointer to nonexistent bucket %u:%zu", bch_err_ratelimited(c, "pointer to nonexistent bucket %u:%zu",
p.ptr.dev, p.ptr.dev,
...@@ -1436,6 +1454,7 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans, ...@@ -1436,6 +1454,7 @@ static int bch2_trans_mark_pointer(struct btree_trans *trans,
} }
u = bch2_alloc_unpack(k); u = bch2_alloc_unpack(k);
}
if (gen_after(u.gen, p.ptr.gen)) { if (gen_after(u.gen, p.ptr.gen)) {
ret = 1; ret = 1;
...@@ -1484,7 +1503,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans, ...@@ -1484,7 +1503,7 @@ static int bch2_trans_mark_stripe_ptr(struct btree_trans *trans,
int ret = 0; int ret = 0;
ret = trans_get_key(trans, BTREE_ID_EC, POS(0, p.idx), &iter, &k); ret = trans_get_key(trans, BTREE_ID_EC, POS(0, p.idx), &iter, &k);
if (ret) if (ret < 0)
return ret; return ret;
if (k.k->type != KEY_TYPE_stripe) { if (k.k->type != KEY_TYPE_stripe) {
...@@ -1599,7 +1618,7 @@ static int __bch2_trans_mark_reflink_p(struct btree_trans *trans, ...@@ -1599,7 +1618,7 @@ static int __bch2_trans_mark_reflink_p(struct btree_trans *trans,
ret = trans_get_key(trans, BTREE_ID_REFLINK, ret = trans_get_key(trans, BTREE_ID_REFLINK,
POS(0, idx), &iter, &k); POS(0, idx), &iter, &k);
if (ret) if (ret < 0)
return ret; return ret;
if (k.k->type != KEY_TYPE_reflink_v) { if (k.k->type != KEY_TYPE_reflink_v) {
......
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