From 1b2d60826974e31b9894b6d5aa59b0e7e62823cd Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 13 Feb 2023 15:51:27 -0500 Subject: [PATCH] Update bcachefs sources to 8dbfede1d9 fixup! bcachefs: More info on check_bucket_ref() error --- .bcachefs_revision | 2 +- libbcachefs/btree_iter.c | 25 ++++++++++++----- libbcachefs/btree_iter.h | 4 +++ libbcachefs/btree_locking.c | 9 +++++- libbcachefs/btree_types.h | 5 +++- libbcachefs/buckets.c | 2 +- libbcachefs/debug.c | 2 +- libbcachefs/move.c | 11 ++++---- libbcachefs/super-io.c | 55 +++++++++++++++---------------------- libbcachefs/util.c | 44 +++++++++++++++++++++++------ libbcachefs/util.h | 8 +++++- 11 files changed, 106 insertions(+), 61 deletions(-) diff --git a/.bcachefs_revision b/.bcachefs_revision index f6330b4..bfcbcf5 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -3e0c5b0722d7fccf0ba83435c5da8892b00c0fe0 +8dbfede1d9e6483c682956c7c8a4900a65f98dde diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c index dc2b2a0..3977bb1 100644 --- a/libbcachefs/btree_iter.c +++ b/libbcachefs/btree_iter.c @@ -1174,10 +1174,17 @@ int bch2_btree_path_traverse_one(struct btree_trans *trans, path->uptodate = BTREE_ITER_UPTODATE; out: - if (bch2_err_matches(ret, BCH_ERR_transaction_restart) != !!trans->restarted) - panic("ret %s (%i) trans->restarted %s (%i)\n", - bch2_err_str(ret), ret, - bch2_err_str(trans->restarted), trans->restarted); + if (bch2_err_matches(ret, BCH_ERR_transaction_restart) != !!trans->restarted) { + struct printbuf buf = PRINTBUF; + + prt_printf(&buf, "ret %s (%i) trans->restarted %s (%i)\n", + bch2_err_str(ret), ret, + bch2_err_str(trans->restarted), trans->restarted); +#ifdef CONFIG_BCACHEFS_DEBUG + bch2_prt_backtrace(&buf, &trans->last_restarted); +#endif + panic("%s", buf.buf); + } bch2_btree_path_verify(trans, path); return ret; } @@ -1360,14 +1367,14 @@ void bch2_trans_restart_error(struct btree_trans *trans, u32 restart_count) { panic("trans->restart_count %u, should be %u, last restarted by %pS\n", trans->restart_count, restart_count, - (void *) trans->last_restarted_ip); + (void *) trans->last_begin_ip); } void bch2_trans_in_restart_error(struct btree_trans *trans) { panic("in transaction restart: %s, last restarted by %pS\n", bch2_err_str(trans->restarted), - (void *) trans->last_restarted_ip); + (void *) trans->last_begin_ip); } noinline __cold @@ -2865,7 +2872,7 @@ u32 bch2_trans_begin(struct btree_trans *trans) if (unlikely(time_after(jiffies, trans->srcu_lock_time + msecs_to_jiffies(10)))) bch2_trans_reset_srcu_lock(trans); - trans->last_restarted_ip = _RET_IP_; + trans->last_begin_ip = _RET_IP_; if (trans->restarted) { bch2_btree_path_traverse_all(trans); trans->notrace_relock_fail = false; @@ -3046,6 +3053,10 @@ void bch2_trans_exit(struct btree_trans *trans) if (trans->paths) mempool_free(trans->paths, &c->btree_paths_pool); +#ifdef CONFIG_BCACHEFS_DEBUG + darray_exit(&trans->last_restarted); +#endif + trans->mem = (void *) 0x1; trans->paths = (void *) 0x1; } diff --git a/libbcachefs/btree_iter.h b/libbcachefs/btree_iter.h index 0ede02c..bbbbe52 100644 --- a/libbcachefs/btree_iter.h +++ b/libbcachefs/btree_iter.h @@ -251,6 +251,10 @@ static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int er BUG_ON(err <= 0); BUG_ON(!bch2_err_matches(err, BCH_ERR_transaction_restart)); +#ifdef CONFIG_BCACHEFS_DEBUG + bch2_save_backtrace(&trans->last_restarted, current); +#endif + trans->restarted = err; return -err; } diff --git a/libbcachefs/btree_locking.c b/libbcachefs/btree_locking.c index 1ddac23..80398e4 100644 --- a/libbcachefs/btree_locking.c +++ b/libbcachefs/btree_locking.c @@ -191,7 +191,7 @@ static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle) prt_printf(&buf, "backtrace:"); prt_newline(&buf); printbuf_indent_add(&buf, 2); - bch2_prt_backtrace(&buf, trans->locking_wait.task); + bch2_prt_task_backtrace(&buf, trans->locking_wait.task); printbuf_indent_sub(&buf, 2); prt_newline(&buf); } @@ -225,6 +225,10 @@ static int lock_graph_descend(struct lock_graph *g, struct btree_trans *trans, while (g->nr) lock_graph_up(g); + + if (cycle) + return 0; + trace_and_count(trans->c, trans_restart_would_deadlock_recursion_limit, trans, _RET_IP_); return btree_trans_restart(orig_trans, BCH_ERR_transaction_restart_deadlock_recursion_limit); } @@ -247,6 +251,9 @@ int bch2_check_for_deadlock(struct btree_trans *trans, struct printbuf *cycle) int ret; if (trans->lock_must_abort) { + if (cycle) + return -1; + trace_and_count(trans->c, trans_restart_would_deadlock, trans, _RET_IP_); return btree_trans_restart(trans, BCH_ERR_transaction_restart_would_deadlock); } diff --git a/libbcachefs/btree_types.h b/libbcachefs/btree_types.h index ad73cd2..97ff267 100644 --- a/libbcachefs/btree_types.h +++ b/libbcachefs/btree_types.h @@ -442,7 +442,10 @@ struct btree_trans { bool notrace_relock_fail:1; enum bch_errcode restarted:16; u32 restart_count; - unsigned long last_restarted_ip; +#ifdef CONFIG_BCACHEFS_DEBUG + bch_stacktrace last_restarted; +#endif + unsigned long last_begin_ip; unsigned long srcu_lock_time; /* diff --git a/libbcachefs/buckets.c b/libbcachefs/buckets.c index ebfbfd9..fd3ba10 100644 --- a/libbcachefs/buckets.c +++ b/libbcachefs/buckets.c @@ -727,7 +727,7 @@ static int check_bucket_ref(struct btree_trans *trans, if (b_gen != ptr->gen) { ret = 1; - goto err; + goto out; } if (!data_type_is_empty(bucket_data_type) && diff --git a/libbcachefs/debug.c b/libbcachefs/debug.c index fcefd55..8f43581 100644 --- a/libbcachefs/debug.c +++ b/libbcachefs/debug.c @@ -527,7 +527,7 @@ static ssize_t bch2_btree_transactions_read(struct file *file, char __user *buf, prt_printf(&i->buf, "backtrace:"); prt_newline(&i->buf); printbuf_indent_add(&i->buf, 2); - bch2_prt_backtrace(&i->buf, trans->locking_wait.task); + bch2_prt_task_backtrace(&i->buf, trans->locking_wait.task); printbuf_indent_sub(&i->buf, 2); prt_newline(&i->buf); diff --git a/libbcachefs/move.c b/libbcachefs/move.c index 7e7e904..e7eb55b 100644 --- a/libbcachefs/move.c +++ b/libbcachefs/move.c @@ -584,7 +584,7 @@ int bch2_move_data(struct bch_fs *c, return ret; } -static int verify_bucket_evacuated(struct btree_trans *trans, struct bpos bucket, int gen) +static noinline void verify_bucket_evacuated(struct btree_trans *trans, struct bpos bucket, int gen) { struct bch_fs *c = trans->c; struct btree_iter iter; @@ -597,8 +597,8 @@ static int verify_bucket_evacuated(struct btree_trans *trans, struct bpos bucket bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, bucket, BTREE_ITER_CACHED); again: - k = bch2_btree_iter_peek_slot(&iter); - ret = bkey_err(k); + ret = lockrestart_do(trans, + bkey_err(k = bch2_btree_iter_peek_slot(&iter))); if (!ret && k.k->type == KEY_TYPE_alloc_v4) { struct bkey_s_c_alloc_v4 a = bkey_s_c_to_alloc_v4(k); @@ -615,7 +615,7 @@ again: } bch2_trans_iter_exit(trans, &iter); - return ret; + return; failed_to_evacuate: bch2_trans_iter_exit(trans, &iter); @@ -651,7 +651,6 @@ failed_to_evacuate: bch2_print_string_as_lines(KERN_ERR, buf.buf); printbuf_exit(&buf); - return 0; } int __bch2_evacuate_bucket(struct moving_context *ctxt, @@ -800,7 +799,7 @@ next: move_ctxt_wait_event(ctxt, NULL, list_empty(&ctxt->reads)); closure_sync(&ctxt->cl); if (!ctxt->write_error) - lockrestart_do(&trans, verify_bucket_evacuated(&trans, bucket, gen)); + verify_bucket_evacuated(&trans, bucket, gen); } err: bch2_trans_exit(&trans); diff --git a/libbcachefs/super-io.c b/libbcachefs/super-io.c index 00c1f69..b9af782 100644 --- a/libbcachefs/super-io.c +++ b/libbcachefs/super-io.c @@ -432,7 +432,7 @@ static void bch2_sb_update(struct bch_fs *c) ca->mi = bch2_mi_to_cpu(mi->members + i); } -static void __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src) +static int __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src) { struct bch_sb_field *src_f, *dst_f; struct bch_sb *dst = dst_handle->sb; @@ -457,42 +457,45 @@ static void __copy_super(struct bch_sb_handle *dst_handle, struct bch_sb *src) memcpy(dst->compat, src->compat, sizeof(dst->compat)); for (i = 0; i < BCH_SB_FIELD_NR; i++) { + int d; + if ((1U << i) & BCH_SINGLE_DEVICE_SB_FIELDS) continue; src_f = bch2_sb_field_get(src, i); dst_f = bch2_sb_field_get(dst, i); + + d = (src_f ? le32_to_cpu(src_f->u64s) : 0) - + (dst_f ? le32_to_cpu(dst_f->u64s) : 0); + if (d > 0) { + int ret = bch2_sb_realloc(dst_handle, le32_to_cpu(dst_handle->sb->u64s) + d); + if (ret) + return ret; + + dst = dst_handle->sb; + dst_f = bch2_sb_field_get(dst, i); + } + dst_f = __bch2_sb_field_resize(dst_handle, dst_f, src_f ? le32_to_cpu(src_f->u64s) : 0); if (src_f) memcpy(dst_f, src_f, vstruct_bytes(src_f)); } + + return 0; } int bch2_sb_to_fs(struct bch_fs *c, struct bch_sb *src) { - struct bch_sb_field_journal *journal_buckets = - bch2_sb_get_journal(src); - unsigned journal_u64s = journal_buckets - ? le32_to_cpu(journal_buckets->field.u64s) - : 0; int ret; lockdep_assert_held(&c->sb_lock); - ret = bch2_sb_realloc(&c->disk_sb, - le32_to_cpu(src->u64s) - journal_u64s); - if (ret) - return ret; - - __copy_super(&c->disk_sb, src); - - ret = bch2_sb_replicas_to_cpu_replicas(c); - if (ret) - return ret; - - ret = bch2_sb_disk_groups_to_cpu(c); + ret = bch2_sb_realloc(&c->disk_sb, 0) ?: + __copy_super(&c->disk_sb, src) ?: + bch2_sb_replicas_to_cpu_replicas(c) ?: + bch2_sb_disk_groups_to_cpu(c); if (ret) return ret; @@ -502,21 +505,7 @@ int bch2_sb_to_fs(struct bch_fs *c, struct bch_sb *src) int bch2_sb_from_fs(struct bch_fs *c, struct bch_dev *ca) { - struct bch_sb *src = c->disk_sb.sb, *dst = ca->disk_sb.sb; - struct bch_sb_field_journal *journal_buckets = - bch2_sb_get_journal(dst); - unsigned journal_u64s = journal_buckets - ? le32_to_cpu(journal_buckets->field.u64s) - : 0; - unsigned u64s = le32_to_cpu(src->u64s) + journal_u64s; - int ret; - - ret = bch2_sb_realloc(&ca->disk_sb, u64s); - if (ret) - return ret; - - __copy_super(&ca->disk_sb, src); - return 0; + return __copy_super(&ca->disk_sb, c->disk_sb.sb); } /* read superblock: */ diff --git a/libbcachefs/util.c b/libbcachefs/util.c index 9939bf2..a979095 100644 --- a/libbcachefs/util.c +++ b/libbcachefs/util.c @@ -296,22 +296,48 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines) console_unlock(); } -int bch2_prt_backtrace(struct printbuf *out, struct task_struct *task) +int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *task) { - unsigned long entries[32]; - unsigned i, nr_entries; + unsigned nr_entries = 0; + int ret = 0; + + stack->nr = 0; + ret = darray_make_room(stack, 32); + if (ret) + return ret; if (!down_read_trylock(&task->signal->exec_update_lock)) - return 0; + return -1; + + do { + nr_entries = stack_trace_save_tsk(task, stack->data, stack->size, 0); + } while (nr_entries == stack->size && + !(ret = darray_make_room(stack, stack->size * 2))); + + stack->nr = nr_entries; + up_read(&task->signal->exec_update_lock); - nr_entries = stack_trace_save_tsk(task, entries, ARRAY_SIZE(entries), 0); - for (i = 0; i < nr_entries; i++) { - prt_printf(out, "[<0>] %pB", (void *)entries[i]); + return ret; +} + +void bch2_prt_backtrace(struct printbuf *out, bch_stacktrace *stack) +{ + unsigned long *i; + + darray_for_each(*stack, i) { + prt_printf(out, "[<0>] %pB", (void *) *i); prt_newline(out); } +} - up_read(&task->signal->exec_update_lock); - return 0; +int bch2_prt_task_backtrace(struct printbuf *out, struct task_struct *task) +{ + bch_stacktrace stack = { 0 }; + int ret = bch2_save_backtrace(&stack, task); + + bch2_prt_backtrace(out, &stack); + darray_exit(&stack); + return ret; } /* time stats: */ diff --git a/libbcachefs/util.h b/libbcachefs/util.h index 09e2729..c3718d3 100644 --- a/libbcachefs/util.h +++ b/libbcachefs/util.h @@ -19,6 +19,8 @@ #include #include +#include "darray.h" + struct closure; #ifdef CONFIG_BCACHEFS_DEBUG @@ -360,7 +362,11 @@ u64 bch2_read_flag_list(char *, const char * const[]); void bch2_prt_u64_binary(struct printbuf *, u64, unsigned); void bch2_print_string_as_lines(const char *prefix, const char *lines); -int bch2_prt_backtrace(struct printbuf *, struct task_struct *); + +typedef DARRAY(unsigned long) bch_stacktrace; +int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *); +void bch2_prt_backtrace(struct printbuf *, bch_stacktrace *); +int bch2_prt_task_backtrace(struct printbuf *, struct task_struct *); #define NR_QUANTILES 15 #define QUANTILE_IDX(i) inorder_to_eytzinger0(i, NR_QUANTILES) -- 2.39.2