aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-02-13 15:51:27 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-02-13 15:51:27 -0500
commit1b2d60826974e31b9894b6d5aa59b0e7e62823cd (patch)
treeb0843bde9b859eab87520b88f7ddb8a4ccfe6cb8
parent4697efb7a01affe650dbc9a4e81a8203d0316d96 (diff)
downloadbcachefs-tools-1b2d60826974e31b9894b6d5aa59b0e7e62823cd.tar.gz
Update bcachefs sources to 8dbfede1d9 fixup! bcachefs: More info on check_bucket_ref() error
-rw-r--r--.bcachefs_revision2
-rw-r--r--libbcachefs/btree_iter.c25
-rw-r--r--libbcachefs/btree_iter.h4
-rw-r--r--libbcachefs/btree_locking.c9
-rw-r--r--libbcachefs/btree_types.h5
-rw-r--r--libbcachefs/buckets.c2
-rw-r--r--libbcachefs/debug.c2
-rw-r--r--libbcachefs/move.c11
-rw-r--r--libbcachefs/super-io.c55
-rw-r--r--libbcachefs/util.c44
-rw-r--r--libbcachefs/util.h8
11 files changed, 106 insertions, 61 deletions
diff --git a/.bcachefs_revision b/.bcachefs_revision
index f6330b43..bfcbcf58 100644
--- a/.bcachefs_revision
+++ b/.bcachefs_revision
@@ -1 +1 @@
-3e0c5b0722d7fccf0ba83435c5da8892b00c0fe0
+8dbfede1d9e6483c682956c7c8a4900a65f98dde
diff --git a/libbcachefs/btree_iter.c b/libbcachefs/btree_iter.c
index dc2b2a08..3977bb1f 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 0ede02c3..bbbbe52b 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 1ddac23c..80398e49 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 ad73cd2e..97ff267c 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 ebfbfd97..fd3ba10b 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 fcefd55a..8f43581f 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 7e7e9042..e7eb55bd 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 00c1f69b..b9af7820 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 9939bf2a..a9790954 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 09e27293..c3718d36 100644
--- a/libbcachefs/util.h
+++ b/libbcachefs/util.h
@@ -19,6 +19,8 @@
#include <linux/workqueue.h>
#include <linux/mean_and_variance.h>
+#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)