mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
bcachefs: Fix ec_stripes_read()
Change it to not mark keys that will be overwritten by keys in the journal - this fixes a bug where we pop an assertion in bucket_set_stripe() because of a stale pointer - because the stripe that has the stale pointer has been deleted. This code could be factored out and used elsewhere, at some point. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
f516c87272
commit
e222d206f2
@ -1267,10 +1267,10 @@ int bch2_stripes_write(struct bch_fs *c, unsigned flags, bool *wrote)
|
||||
|
||||
int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys)
|
||||
{
|
||||
struct journal_key *i;
|
||||
struct btree_trans trans;
|
||||
struct btree_iter *iter;
|
||||
struct bkey_s_c k;
|
||||
struct btree_iter *btree_iter;
|
||||
struct journal_iter journal_iter;
|
||||
struct bkey_s_c btree_k, journal_k, k;
|
||||
int ret;
|
||||
|
||||
ret = bch2_fs_ec_start(c);
|
||||
@ -1279,10 +1279,41 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys)
|
||||
|
||||
bch2_trans_init(&trans, c, 0, 0);
|
||||
|
||||
for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN, 0, k, ret)
|
||||
btree_iter = bch2_trans_get_iter(&trans, BTREE_ID_EC, POS_MIN, 0);
|
||||
journal_iter = bch2_journal_iter_init(journal_keys, BTREE_ID_EC);
|
||||
|
||||
btree_k = bch2_btree_iter_peek(btree_iter);
|
||||
journal_k = bch2_journal_iter_peek(&journal_iter);
|
||||
|
||||
while (1) {
|
||||
if (btree_k.k && journal_k.k) {
|
||||
int cmp = bkey_cmp(btree_k.k->p, journal_k.k->p);
|
||||
|
||||
if (cmp < 0) {
|
||||
k = btree_k;
|
||||
btree_k = bch2_btree_iter_next(btree_iter);
|
||||
} else if (cmp == 0) {
|
||||
btree_k = bch2_btree_iter_next(btree_iter);
|
||||
k = journal_k;
|
||||
journal_k = bch2_journal_iter_next(&journal_iter);
|
||||
} else {
|
||||
k = journal_k;
|
||||
journal_k = bch2_journal_iter_next(&journal_iter);
|
||||
}
|
||||
} else if (btree_k.k) {
|
||||
k = btree_k;
|
||||
btree_k = bch2_btree_iter_next(btree_iter);
|
||||
} else if (journal_k.k) {
|
||||
k = journal_k;
|
||||
journal_k = bch2_journal_iter_next(&journal_iter);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
bch2_mark_key(c, k, 0, NULL, 0,
|
||||
BCH_BUCKET_MARK_ALLOC_READ|
|
||||
BCH_BUCKET_MARK_NOATOMIC);
|
||||
}
|
||||
|
||||
ret = bch2_trans_exit(&trans) ?: ret;
|
||||
if (ret) {
|
||||
@ -1290,13 +1321,6 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for_each_journal_key(*journal_keys, i)
|
||||
if (i->btree_id == BTREE_ID_EC)
|
||||
bch2_mark_key(c, bkey_i_to_s_c(i->k),
|
||||
0, NULL, 0,
|
||||
BCH_BUCKET_MARK_ALLOC_READ|
|
||||
BCH_BUCKET_MARK_NOATOMIC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,42 @@
|
||||
|
||||
#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
|
||||
|
||||
/* iterate over keys read from the journal: */
|
||||
|
||||
struct journal_iter bch2_journal_iter_init(struct journal_keys *keys,
|
||||
enum btree_id id)
|
||||
{
|
||||
return (struct journal_iter) {
|
||||
.keys = keys,
|
||||
.k = keys->d,
|
||||
.btree_id = id,
|
||||
};
|
||||
}
|
||||
|
||||
struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter)
|
||||
{
|
||||
while (1) {
|
||||
if (iter->k == iter->keys->d + iter->keys->nr)
|
||||
return bkey_s_c_null;
|
||||
|
||||
if (iter->k->btree_id == iter->btree_id)
|
||||
return bkey_i_to_s_c(iter->k->k);
|
||||
|
||||
iter->k++;
|
||||
}
|
||||
|
||||
return bkey_s_c_null;
|
||||
}
|
||||
|
||||
struct bkey_s_c bch2_journal_iter_next(struct journal_iter *iter)
|
||||
{
|
||||
if (iter->k == iter->keys->d + iter->keys->nr)
|
||||
return bkey_s_c_null;
|
||||
|
||||
iter->k++;
|
||||
return bch2_journal_iter_peek(iter);
|
||||
}
|
||||
|
||||
/* sort and dedup all keys in the journal: */
|
||||
|
||||
static void journal_entries_free(struct list_head *list)
|
||||
|
@ -18,6 +18,17 @@ struct journal_keys {
|
||||
#define for_each_journal_key(keys, i) \
|
||||
for (i = (keys).d; i < (keys).d + (keys).nr; (i)++)
|
||||
|
||||
struct journal_iter {
|
||||
struct journal_keys *keys;
|
||||
struct journal_key *k;
|
||||
enum btree_id btree_id;
|
||||
};
|
||||
|
||||
struct journal_iter bch2_journal_iter_init(struct journal_keys *,
|
||||
enum btree_id);
|
||||
struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *);
|
||||
struct bkey_s_c bch2_journal_iter_next(struct journal_iter *);
|
||||
|
||||
int bch2_fs_recovery(struct bch_fs *);
|
||||
int bch2_fs_initialize(struct bch_fs *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user