mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 13:53:33 +00:00
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:
parent
58e1ea4bcb
commit
181fe42a75
4 changed files with 28 additions and 77 deletions
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue