Update bcachefs sources to dab31ca168 bcachefs: Add some logging for btree node rewrites due to errors

This commit is contained in:
Kent Overstreet 2023-02-10 15:49:12 -05:00
parent a104f0407b
commit 284c1f5148
4 changed files with 43 additions and 10 deletions

View File

@ -1 +1 @@
ea93c26e98081d8e1a5fc138e6334b3631983d77 dab31ca168df1c7a492a0a2a626ba6cd983b2a7a

View File

@ -1246,8 +1246,18 @@ start:
bio_put(&rb->bio); bio_put(&rb->bio);
printbuf_exit(&buf); printbuf_exit(&buf);
if (saw_error && !btree_node_read_error(b)) if (!btree_node_read_error(b) &&
(saw_error ||
btree_node_need_rewrite(b))) {
struct printbuf buf = PRINTBUF;
bch2_bpos_to_text(&buf, b->key.k.p);
bch_info(c, "%s: rewriting btree node at btree=%s level=%u %s due to error",
__func__, bch2_btree_ids[b->c.btree_id], b->c.level, buf.buf);
printbuf_exit(&buf);
bch2_btree_node_rewrite_async(c, b); bch2_btree_node_rewrite_async(c, b);
}
clear_btree_node_read_in_flight(b); clear_btree_node_read_in_flight(b);
wake_up_bit(&b->flags, BTREE_NODE_read_in_flight); wake_up_bit(&b->flags, BTREE_NODE_read_in_flight);

View File

@ -161,6 +161,7 @@ static void __btree_node_free(struct bch_fs *c, struct btree *b)
{ {
trace_and_count(c, btree_node_free, c, b); trace_and_count(c, btree_node_free, c, b);
BUG_ON(btree_node_write_blocked(b));
BUG_ON(btree_node_dirty(b)); BUG_ON(btree_node_dirty(b));
BUG_ON(btree_node_need_write(b)); BUG_ON(btree_node_need_write(b));
BUG_ON(b == btree_node_root(c, b)); BUG_ON(b == btree_node_root(c, b));
@ -806,6 +807,7 @@ static void btree_update_updated_node(struct btree_update *as, struct btree *b)
BUG_ON(as->mode != BTREE_INTERIOR_NO_UPDATE); BUG_ON(as->mode != BTREE_INTERIOR_NO_UPDATE);
BUG_ON(!btree_node_dirty(b)); BUG_ON(!btree_node_dirty(b));
BUG_ON(!b->c.level);
as->mode = BTREE_INTERIOR_UPDATING_NODE; as->mode = BTREE_INTERIOR_UPDATING_NODE;
as->b = b; as->b = b;
@ -975,6 +977,7 @@ static void bch2_btree_interior_update_will_free_node(struct btree_update *as,
clear_btree_node_dirty_acct(c, b); clear_btree_node_dirty_acct(c, b);
clear_btree_node_need_write(b); clear_btree_node_need_write(b);
clear_btree_node_write_blocked(b);
/* /*
* Does this node have unwritten data that has a pin on the journal? * Does this node have unwritten data that has a pin on the journal?
@ -2003,6 +2006,7 @@ struct async_btree_rewrite {
static int async_btree_node_rewrite_trans(struct btree_trans *trans, static int async_btree_node_rewrite_trans(struct btree_trans *trans,
struct async_btree_rewrite *a) struct async_btree_rewrite *a)
{ {
struct bch_fs *c = trans->c;
struct btree_iter iter; struct btree_iter iter;
struct btree *b; struct btree *b;
int ret; int ret;
@ -2014,8 +2018,18 @@ static int async_btree_node_rewrite_trans(struct btree_trans *trans,
if (ret) if (ret)
goto out; goto out;
if (!b || b->data->keys.seq != a->seq) if (!b || b->data->keys.seq != a->seq) {
struct printbuf buf = PRINTBUF;
if (b)
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
else
prt_str(&buf, "(null");
bch_info(c, "%s: node to rewrite not found:, searching for seq %llu, got\n%s",
__func__, a->seq, buf.buf);
printbuf_exit(&buf);
goto out; goto out;
}
ret = bch2_btree_node_rewrite(trans, &iter, b, 0); ret = bch2_btree_node_rewrite(trans, &iter, b, 0);
out: out:
@ -2029,9 +2043,12 @@ void async_btree_node_rewrite_work(struct work_struct *work)
struct async_btree_rewrite *a = struct async_btree_rewrite *a =
container_of(work, struct async_btree_rewrite, work); container_of(work, struct async_btree_rewrite, work);
struct bch_fs *c = a->c; struct bch_fs *c = a->c;
int ret;
bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
async_btree_node_rewrite_trans(&trans, a)); async_btree_node_rewrite_trans(&trans, a));
if (ret)
bch_err(c, "%s: error %s", __func__, bch2_err_str(ret));
bch2_write_ref_put(c, BCH_WRITE_REF_node_rewrite); bch2_write_ref_put(c, BCH_WRITE_REF_node_rewrite);
kfree(a); kfree(a);
} }
@ -2040,12 +2057,15 @@ void bch2_btree_node_rewrite_async(struct bch_fs *c, struct btree *b)
{ {
struct async_btree_rewrite *a; struct async_btree_rewrite *a;
if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_node_rewrite)) if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_node_rewrite)) {
bch_err(c, "%s: error getting c->writes ref", __func__);
return; return;
}
a = kmalloc(sizeof(*a), GFP_NOFS); a = kmalloc(sizeof(*a), GFP_NOFS);
if (!a) { if (!a) {
bch2_write_ref_put(c, BCH_WRITE_REF_node_rewrite); bch2_write_ref_put(c, BCH_WRITE_REF_node_rewrite);
bch_err(c, "%s: error allocating memory", __func__);
return; return;
} }

View File

@ -307,7 +307,7 @@ static inline void btree_insert_entry_checks(struct btree_trans *trans,
} }
static noinline int static noinline int
bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned u64s, bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned flags,
unsigned long trace_ip) unsigned long trace_ip)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
@ -316,7 +316,9 @@ bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned u64s,
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
ret = bch2_journal_preres_get(&c->journal, ret = bch2_journal_preres_get(&c->journal,
&trans->journal_preres, u64s, 0); &trans->journal_preres,
trans->journal_preres_u64s,
(flags & JOURNAL_WATERMARK_MASK));
if (ret) if (ret)
return ret; return ret;
@ -857,8 +859,7 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags
&trans->journal_preres, trans->journal_preres_u64s, &trans->journal_preres, trans->journal_preres_u64s,
(flags & JOURNAL_WATERMARK_MASK)|JOURNAL_RES_GET_NONBLOCK); (flags & JOURNAL_WATERMARK_MASK)|JOURNAL_RES_GET_NONBLOCK);
if (unlikely(ret == -BCH_ERR_journal_preres_get_blocked)) if (unlikely(ret == -BCH_ERR_journal_preres_get_blocked))
ret = bch2_trans_journal_preres_get_cold(trans, ret = bch2_trans_journal_preres_get_cold(trans, flags, trace_ip);
trans->journal_preres_u64s, trace_ip);
if (unlikely(ret)) if (unlikely(ret))
return ret; return ret;
@ -937,7 +938,9 @@ int bch2_trans_commit_error(struct btree_trans *trans, unsigned flags,
break; break;
} }
ret = bch2_trans_journal_res_get(trans, JOURNAL_RES_GET_CHECK); ret = bch2_trans_journal_res_get(trans,
(flags & JOURNAL_WATERMARK_MASK)|
JOURNAL_RES_GET_CHECK);
if (ret) if (ret)
break; break;