bcachefs: bch2_alloc_write() should be writing for all devices

Alloc info isn't stored on a particular device, it makes no sense to
only be writing it out for rw members - this was causing fsck to not fix
alloc info errors, oops.

Also, make sure we write out alloc info in other repair paths.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2021-01-08 21:20:58 -05:00 committed by Kent Overstreet
parent dcf64dfbbc
commit 4291a3317f
4 changed files with 12 additions and 15 deletions

View File

@ -366,7 +366,7 @@ int bch2_alloc_write(struct bch_fs *c, unsigned flags)
unsigned i;
int ret = 0;
for_each_rw_member(ca, c, i) {
for_each_member_device(ca, c, i) {
bch2_dev_alloc_write(c, ca, flags);
if (ret) {
percpu_ref_put(&ca->io_ref);

View File

@ -510,7 +510,7 @@ enum {
/* misc: */
BCH_FS_FIXED_GENS,
BCH_FS_ALLOC_WRITTEN,
BCH_FS_NEED_ALLOC_WRITE,
BCH_FS_REBUILD_REPLICAS,
BCH_FS_HOLD_BTREE_WRITES,
};

View File

@ -132,6 +132,7 @@ static int bch2_gc_mark_key(struct bch_fs *c, struct bkey_s_c k,
ptr->gen)) {
g2->_mark.gen = g->_mark.gen = ptr->gen;
g2->gen_valid = g->gen_valid = true;
set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags);
}
if (mustfix_fsck_err_on(gen_cmp(ptr->gen, g->mark.gen) > 0, c,
@ -145,6 +146,7 @@ static int bch2_gc_mark_key(struct bch_fs *c, struct bkey_s_c k,
g2->_mark.dirty_sectors = 0;
g2->_mark.cached_sectors = 0;
set_bit(BCH_FS_FIXED_GENS, &c->flags);
set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags);
}
}
}
@ -571,7 +573,7 @@ static int bch2_gc_done(struct bch_fs *c,
fsck_err(c, _msg ": got %llu, should be %llu" \
, ##__VA_ARGS__, dst->_f, src->_f); \
dst->_f = src->_f; \
ret = 1; \
set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags); \
}
#define copy_stripe_field(_f, _msg, ...) \
if (dst->_f != src->_f) { \
@ -582,7 +584,7 @@ static int bch2_gc_done(struct bch_fs *c,
dst->_f, src->_f); \
dst->_f = src->_f; \
dst->dirty = true; \
ret = 1; \
set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags); \
}
#define copy_bucket_field(_f) \
if (dst->b[b].mark._f != src->b[b].mark._f) { \
@ -593,7 +595,7 @@ static int bch2_gc_done(struct bch_fs *c,
bch2_data_types[dst->b[b].mark.data_type],\
dst->b[b].mark._f, src->b[b].mark._f); \
dst->b[b]._mark._f = src->b[b].mark._f; \
ret = 1; \
set_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags); \
}
#define copy_dev_field(_f, _msg, ...) \
copy_field(_f, "dev %u has wrong " _msg, i, ##__VA_ARGS__)

View File

@ -938,7 +938,7 @@ int bch2_fs_recovery(struct bch_fs *c)
struct bch_sb_field_clean *clean = NULL;
struct jset *last_journal_entry = NULL;
u64 blacklist_seq, journal_seq;
bool write_sb = false, need_write_alloc = false;
bool write_sb = false;
int ret;
if (c->sb.clean)
@ -1084,10 +1084,8 @@ use_clean:
bch_info(c, "starting metadata mark and sweep");
err = "error in mark and sweep";
ret = bch2_gc(c, &c->journal_keys, true, true);
if (ret < 0)
goto err;
if (ret)
need_write_alloc = true;
goto err;
bch_verbose(c, "mark and sweep done");
}
@ -1097,10 +1095,8 @@ use_clean:
bch_info(c, "starting mark and sweep");
err = "error in mark and sweep";
ret = bch2_gc(c, &c->journal_keys, true, false);
if (ret < 0)
goto err;
if (ret)
need_write_alloc = true;
goto err;
bch_verbose(c, "mark and sweep done");
}
@ -1124,7 +1120,8 @@ use_clean:
goto err;
bch_verbose(c, "journal replay done");
if (need_write_alloc && !c->opts.nochanges) {
if (test_bit(BCH_FS_NEED_ALLOC_WRITE, &c->flags) &&
!c->opts.nochanges) {
/*
* note that even when filesystem was clean there might be work
* to do here, if we ran gc (because of fsck) which recalculated
@ -1139,8 +1136,6 @@ use_clean:
goto err;
}
bch_verbose(c, "alloc write done");
set_bit(BCH_FS_ALLOC_WRITTEN, &c->flags);
}
if (!c->sb.clean) {