bcachefs: Handle replica marking fsck errors locally

This simplifies the code quite a bit and eliminates an inconsistency - a
given bkey doesn't necessarily translate to a single replicas entry for
disk space accounting.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
Kent Overstreet 2021-11-28 15:13:54 -05:00 committed by Kent Overstreet
parent 58e1ea4bcb
commit 181fe42a75
4 changed files with 28 additions and 77 deletions

View file

@ -715,7 +715,6 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
unsigned flags =
BTREE_TRIGGER_GC|
(initial ? BTREE_TRIGGER_NOATOMIC : 0);
char buf[200];
int ret = 0;
deleted.p = k->k->p;
@ -733,18 +732,6 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
k->k->version.lo,
atomic64_read(&c->key_version)))
atomic64_set(&c->key_version, k->k->version.lo);
if (test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) ||
fsck_err_on(!bch2_bkey_replicas_marked(c, *k), c,
"superblock not marked as containing replicas\n"
" while marking %s",
(bch2_bkey_val_to_text(&PBUF(buf), c, *k), buf))) {
ret = bch2_mark_bkey_replicas(c, *k);
if (ret) {
bch_err(c, "error marking bkey replicas: %i", ret);
goto err;
}
}
}
ptrs = bch2_bkey_ptrs_c(*k);

View file

@ -420,16 +420,30 @@ static inline int __update_replicas(struct bch_fs *c,
return 0;
}
static inline int update_replicas(struct bch_fs *c,
static inline int update_replicas(struct bch_fs *c, struct bkey_s_c k,
struct bch_replicas_entry *r, s64 sectors,
unsigned journal_seq, bool gc)
{
struct bch_fs_usage __percpu *fs_usage;
int idx, ret = 0;
char buf[200];
percpu_down_read(&c->mark_lock);
idx = bch2_replicas_entry_idx(c, r);
if (idx < 0 &&
(test_bit(BCH_FS_REBUILD_REPLICAS, &c->flags) ||
fsck_err(c, "no replicas entry\n"
" while marking %s",
(bch2_bkey_val_to_text(&PBUF(buf), c, k), buf)))) {
percpu_up_read(&c->mark_lock);
ret = bch2_mark_replicas(c, r);
if (ret)
return ret;
percpu_down_read(&c->mark_lock);
idx = bch2_replicas_entry_idx(c, r);
}
if (idx < 0) {
ret = -1;
goto err;
@ -441,11 +455,13 @@ static inline int update_replicas(struct bch_fs *c,
fs_usage->replicas[idx] += sectors;
preempt_enable();
err:
fsck_err:
percpu_up_read(&c->mark_lock);
return ret;
}
static inline int update_cached_sectors(struct bch_fs *c,
struct bkey_s_c k,
unsigned dev, s64 sectors,
unsigned journal_seq, bool gc)
{
@ -453,7 +469,7 @@ static inline int update_cached_sectors(struct bch_fs *c,
bch2_replicas_entry_cached(&r.e, dev);
return update_replicas(c, &r.e, sectors, journal_seq, gc);
return update_replicas(c, k, &r.e, sectors, journal_seq, gc);
}
static struct replicas_delta_list *
@ -618,8 +634,9 @@ static int bch2_mark_alloc(struct btree_trans *trans,
if ((flags & BTREE_TRIGGER_BUCKET_INVALIDATE) &&
old_m.cached_sectors) {
ret = update_cached_sectors(c, ca->dev_idx, -old_m.cached_sectors,
journal_seq, gc);
ret = update_cached_sectors(c, new, ca->dev_idx,
-old_m.cached_sectors,
journal_seq, gc);
if (ret) {
bch2_fs_fatal_error(c, "bch2_mark_alloc(): no replicas entry while updating cached sectors");
return ret;
@ -920,6 +937,7 @@ static int bch2_mark_pointer(struct btree_trans *trans,
}
static int bch2_mark_stripe_ptr(struct btree_trans *trans,
struct bkey_s_c k,
struct bch_extent_stripe_ptr p,
enum bch_data_type data_type,
s64 sectors,
@ -959,7 +977,7 @@ static int bch2_mark_stripe_ptr(struct btree_trans *trans,
spin_unlock(&c->ec_stripes_heap_lock);
r.e.data_type = data_type;
update_replicas(c, &r.e, sectors, trans->journal_res.seq, gc);
update_replicas(c, k, &r.e, sectors, trans->journal_res.seq, gc);
return 0;
}
@ -1005,8 +1023,8 @@ static int bch2_mark_extent(struct btree_trans *trans,
if (p.ptr.cached) {
if (!stale) {
ret = update_cached_sectors(c, p.ptr.dev, disk_sectors,
journal_seq, gc);
ret = update_cached_sectors(c, k, p.ptr.dev,
disk_sectors, journal_seq, gc);
if (ret) {
bch2_fs_fatal_error(c, "bch2_mark_extent(): no replicas entry while updating cached sectors");
return ret;
@ -1016,7 +1034,7 @@ static int bch2_mark_extent(struct btree_trans *trans,
dirty_sectors += disk_sectors;
r.e.devs[r.e.nr_devs++] = p.ptr.dev;
} else {
ret = bch2_mark_stripe_ptr(trans, p.ec, data_type,
ret = bch2_mark_stripe_ptr(trans, k, p.ec, data_type,
disk_sectors, flags);
if (ret)
return ret;
@ -1031,7 +1049,7 @@ static int bch2_mark_extent(struct btree_trans *trans,
}
if (r.e.nr_devs) {
ret = update_replicas(c, &r.e, dirty_sectors, journal_seq, gc);
ret = update_replicas(c, k, &r.e, dirty_sectors, journal_seq, gc);
if (ret) {
char buf[200];
@ -1119,7 +1137,7 @@ static int bch2_mark_stripe(struct btree_trans *trans,
return ret;
}
ret = update_replicas(c, &m->r.e,
ret = update_replicas(c, new, &m->r.e,
((s64) m->sectors * m->nr_redundant),
journal_seq, gc);
if (ret) {

View file

@ -434,45 +434,6 @@ int bch2_mark_replicas(struct bch_fs *c, struct bch_replicas_entry *r)
return __bch2_mark_replicas(c, r, false);
}
static int __bch2_mark_bkey_replicas(struct bch_fs *c, struct bkey_s_c k,
bool check)
{
struct bch_replicas_padded search;
struct bch_devs_list cached = bch2_bkey_cached_devs(k);
unsigned i;
int ret;
memset(&search, 0, sizeof(search));
for (i = 0; i < cached.nr; i++) {
bch2_replicas_entry_cached(&search.e, cached.devs[i]);
ret = __bch2_mark_replicas(c, &search.e, check);
if (ret)
return ret;
}
bch2_bkey_to_replicas(&search.e, k);
ret = __bch2_mark_replicas(c, &search.e, check);
if (ret)
return ret;
if (search.e.data_type == BCH_DATA_parity) {
search.e.data_type = BCH_DATA_cached;
ret = __bch2_mark_replicas(c, &search.e, check);
if (ret)
return ret;
search.e.data_type = BCH_DATA_user;
ret = __bch2_mark_replicas(c, &search.e, check);
if (ret)
return ret;
}
return 0;
}
/* replicas delta list: */
int bch2_replicas_delta_list_mark(struct bch_fs *c,
@ -487,19 +448,6 @@ int bch2_replicas_delta_list_mark(struct bch_fs *c,
return ret;
}
/* bkey replicas: */
bool bch2_bkey_replicas_marked(struct bch_fs *c,
struct bkey_s_c k)
{
return __bch2_mark_bkey_replicas(c, k, true) == 0;
}
int bch2_mark_bkey_replicas(struct bch_fs *c, struct bkey_s_c k)
{
return __bch2_mark_bkey_replicas(c, k, false);
}
/*
* Old replicas_gc mechanism: only used for journal replicas entries now, should
* die at some point:

View file

@ -51,8 +51,6 @@ replicas_delta_next(struct replicas_delta *d)
int bch2_replicas_delta_list_mark(struct bch_fs *, struct replicas_delta_list *);
void bch2_bkey_to_replicas(struct bch_replicas_entry *, struct bkey_s_c);
bool bch2_bkey_replicas_marked(struct bch_fs *, struct bkey_s_c);
int bch2_mark_bkey_replicas(struct bch_fs *, struct bkey_s_c);
static inline void bch2_replicas_entry_cached(struct bch_replicas_entry *e,
unsigned dev)