Commit 9104fc19 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Fix accounting read + device removal

accounting read was checking if accounting replicas entries were marked
in the superblock prior to applying accounting from the journal,
which meant that a recently removed device could spuriously trigger a
"not marked in superblocked" error (when journal entries zero out the
offending counter).
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1e0272ef
...@@ -324,7 +324,8 @@ int bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a, ...@@ -324,7 +324,8 @@ int bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a,
{ {
struct bch_replicas_padded r; struct bch_replicas_padded r;
if (accounting_to_replicas(&r.e, a.k->p) && if (mode != BCH_ACCOUNTING_read &&
accounting_to_replicas(&r.e, a.k->p) &&
!bch2_replicas_marked_locked(c, &r.e)) !bch2_replicas_marked_locked(c, &r.e))
return -BCH_ERR_btree_insert_need_mark_replicas; return -BCH_ERR_btree_insert_need_mark_replicas;
...@@ -592,7 +593,6 @@ int bch2_gc_accounting_done(struct bch_fs *c) ...@@ -592,7 +593,6 @@ int bch2_gc_accounting_done(struct bch_fs *c)
static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k) static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct printbuf buf = PRINTBUF;
if (k.k->type != KEY_TYPE_accounting) if (k.k->type != KEY_TYPE_accounting)
return 0; return 0;
...@@ -601,22 +601,6 @@ static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k) ...@@ -601,22 +601,6 @@ static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k)
int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k), int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k),
BCH_ACCOUNTING_read); BCH_ACCOUNTING_read);
percpu_up_read(&c->mark_lock); percpu_up_read(&c->mark_lock);
if (bch2_accounting_key_is_zero(bkey_s_c_to_accounting(k)) &&
ret == -BCH_ERR_btree_insert_need_mark_replicas)
ret = 0;
struct disk_accounting_pos acc;
bpos_to_disk_accounting_pos(&acc, k.k->p);
if (fsck_err_on(ret == -BCH_ERR_btree_insert_need_mark_replicas,
trans, accounting_replicas_not_marked,
"accounting not marked in superblock replicas\n %s",
(bch2_accounting_key_to_text(&buf, &acc),
buf.buf)))
ret = bch2_accounting_update_sb_one(c, k.k->p);
fsck_err:
printbuf_exit(&buf);
return ret; return ret;
} }
...@@ -628,6 +612,7 @@ int bch2_accounting_read(struct bch_fs *c) ...@@ -628,6 +612,7 @@ int bch2_accounting_read(struct bch_fs *c)
{ {
struct bch_accounting_mem *acc = &c->accounting; struct bch_accounting_mem *acc = &c->accounting;
struct btree_trans *trans = bch2_trans_get(c); struct btree_trans *trans = bch2_trans_get(c);
struct printbuf buf = PRINTBUF;
int ret = for_each_btree_key(trans, iter, int ret = for_each_btree_key(trans, iter,
BTREE_ID_accounting, POS_MIN, BTREE_ID_accounting, POS_MIN,
...@@ -678,6 +663,30 @@ int bch2_accounting_read(struct bch_fs *c) ...@@ -678,6 +663,30 @@ int bch2_accounting_read(struct bch_fs *c)
keys->gap = keys->nr = dst - keys->data; keys->gap = keys->nr = dst - keys->data;
percpu_down_read(&c->mark_lock); percpu_down_read(&c->mark_lock);
for (unsigned i = 0; i < acc->k.nr; i++) {
u64 v[BCH_ACCOUNTING_MAX_COUNTERS];
bch2_accounting_mem_read_counters(acc, i, v, ARRAY_SIZE(v), false);
if (bch2_is_zero(v, sizeof(v[0]) * acc->k.data[i].nr_counters))
continue;
struct bch_replicas_padded r;
if (!accounting_to_replicas(&r.e, acc->k.data[i].pos))
continue;
struct disk_accounting_pos k;
bpos_to_disk_accounting_pos(&k, acc->k.data[i].pos);
if (fsck_err_on(!bch2_replicas_marked_locked(c, &r.e),
trans, accounting_replicas_not_marked,
"accounting not marked in superblock replicas\n %s",
(printbuf_reset(&buf),
bch2_accounting_key_to_text(&buf, &k),
buf.buf)))
ret = bch2_accounting_update_sb_one(c, acc->k.data[i].pos);
}
preempt_disable(); preempt_disable();
struct bch_fs_usage_base *usage = this_cpu_ptr(c->usage); struct bch_fs_usage_base *usage = this_cpu_ptr(c->usage);
...@@ -713,8 +722,10 @@ int bch2_accounting_read(struct bch_fs *c) ...@@ -713,8 +722,10 @@ int bch2_accounting_read(struct bch_fs *c)
} }
} }
preempt_enable(); preempt_enable();
fsck_err:
percpu_up_read(&c->mark_lock); percpu_up_read(&c->mark_lock);
err: err:
printbuf_exit(&buf);
bch2_trans_put(trans); bch2_trans_put(trans);
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
......
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