Commit 50b13bee authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Improve an error message

When inserting a key type that's not valid for a given btree, we should
print out which btree we were inserting into.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 2ed6248a
......@@ -207,8 +207,8 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
}
if (!(bch2_key_types_allowed[type] & (1U << k.k->type))) {
prt_printf(err, "invalid key type for this btree (%s)",
bch2_bkey_types[type]);
prt_printf(err, "invalid key type for btree %s (%s)",
bch2_btree_ids[type], bch2_bkey_types[k.k->type]);
return -EINVAL;
}
......
......@@ -3257,6 +3257,7 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
memset(trans, 0, sizeof(*trans));
trans->c = c;
trans->fn = fn;
trans->task = current;
trans->journal_replay_not_finished =
!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags);
......@@ -3277,9 +3278,17 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG_TRANSACTIONS)) {
trans->pid = current->pid;
struct btree_trans *pos;
mutex_lock(&c->btree_trans_lock);
list_add(&trans->list, &c->btree_trans_list);
list_for_each_entry(pos, &c->btree_trans_list, list) {
if (trans->task->pid < pos->task->pid) {
list_add_tail(&trans->list, &pos->list);
goto list_add_done;
}
}
list_add_tail(&trans->list, &c->btree_trans_list);
list_add_done:
mutex_unlock(&c->btree_trans_lock);
}
}
......@@ -3371,77 +3380,57 @@ bch2_btree_path_node_to_text(struct printbuf *out,
}
#ifdef CONFIG_BCACHEFS_DEBUG_TRANSACTIONS
static bool trans_has_locks(struct btree_trans *trans)
void bch2_btree_trans_to_text(struct printbuf *out, struct btree_trans *trans)
{
struct btree_path *path;
trans_for_each_path(trans, path)
if (path->nodes_locked)
return true;
return false;
}
#endif
void bch2_btree_trans_to_text(struct printbuf *out, struct bch_fs *c)
{
#ifdef CONFIG_BCACHEFS_DEBUG_TRANSACTIONS
struct btree_trans *trans;
struct btree_path *path;
struct btree *b;
static char lock_types[] = { 'r', 'i', 'w' };
unsigned l;
mutex_lock(&c->btree_trans_lock);
list_for_each_entry(trans, &c->btree_trans_list, list) {
if (!trans_has_locks(trans))
continue;
prt_printf(out, "%i %s\n", trans->pid, trans->fn);
prt_printf(out, "%i %s\n", trans->task->pid, trans->fn);
trans_for_each_path(trans, path) {
if (!path->nodes_locked)
continue;
trans_for_each_path(trans, path) {
if (!path->nodes_locked)
continue;
prt_printf(out, " path %u %c l=%u %s:",
path->idx,
path->cached ? 'c' : 'b',
path->level,
bch2_btree_ids[path->btree_id]);
bch2_bpos_to_text(out, path->pos);
prt_printf(out, "\n");
for (l = 0; l < BTREE_MAX_DEPTH; l++) {
if (btree_node_locked(path, l)) {
prt_printf(out, " %s l=%u ",
btree_node_intent_locked(path, l) ? "i" : "r", l);
bch2_btree_path_node_to_text(out,
(void *) path->l[l].b,
path->cached);
prt_printf(out, "\n");
}
prt_printf(out, " path %u %c l=%u %s:",
path->idx,
path->cached ? 'c' : 'b',
path->level,
bch2_btree_ids[path->btree_id]);
bch2_bpos_to_text(out, path->pos);
prt_printf(out, "\n");
for (l = 0; l < BTREE_MAX_DEPTH; l++) {
if (btree_node_locked(path, l)) {
prt_printf(out, " %s l=%u ",
btree_node_intent_locked(path, l) ? "i" : "r", l);
bch2_btree_path_node_to_text(out,
(void *) path->l[l].b,
path->cached);
prt_printf(out, "\n");
}
}
}
b = READ_ONCE(trans->locking);
if (b) {
path = &trans->paths[trans->locking_path_idx];
prt_printf(out, " locking path %u %c l=%u %c %s:",
trans->locking_path_idx,
path->cached ? 'c' : 'b',
trans->locking_level,
lock_types[trans->locking_lock_type],
bch2_btree_ids[trans->locking_btree_id]);
bch2_bpos_to_text(out, trans->locking_pos);
prt_printf(out, " node ");
bch2_btree_path_node_to_text(out,
(void *) b, path->cached);
prt_printf(out, "\n");
}
b = READ_ONCE(trans->locking);
if (b) {
path = &trans->paths[trans->locking_path_idx];
prt_printf(out, " locking path %u %c l=%u %c %s:",
trans->locking_path_idx,
path->cached ? 'c' : 'b',
trans->locking_level,
lock_types[trans->locking_lock_type],
bch2_btree_ids[trans->locking_btree_id]);
bch2_bpos_to_text(out, trans->locking_pos);
prt_printf(out, " node ");
bch2_btree_path_node_to_text(out,
(void *) b, path->cached);
prt_printf(out, "\n");
}
mutex_unlock(&c->btree_trans_lock);
#endif
}
#endif
void bch2_fs_btree_iter_exit(struct bch_fs *c)
{
......
......@@ -440,7 +440,7 @@ void bch2_trans_exit(struct btree_trans *);
#define bch2_trans_init(...) __bch2_trans_init(__VA_ARGS__, __func__)
void bch2_btree_trans_to_text(struct printbuf *, struct bch_fs *);
void bch2_btree_trans_to_text(struct printbuf *, struct btree_trans *);
void bch2_fs_btree_iter_exit(struct bch_fs *);
int bch2_fs_btree_iter_init(struct bch_fs *);
......
......@@ -386,7 +386,7 @@ struct btree_trans {
u8 locking_btree_id;
u8 locking_level;
u8 locking_lock_type;
pid_t pid;
struct task_struct *task;
int srcu_idx;
u8 nr_sorted;
......
......@@ -529,6 +529,78 @@ static const struct file_operations cached_btree_nodes_ops = {
.read = bch2_cached_btree_nodes_read,
};
#ifdef CONFIG_BCACHEFS_DEBUG_TRANSACTIONS
static int prt_backtrace(struct printbuf *out, struct task_struct *task)
{
unsigned long entries[32];
unsigned i, nr_entries;
int ret;
ret = down_read_killable(&task->signal->exec_update_lock);
if (ret)
return ret;
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]);
prt_newline(out);
}
up_read(&task->signal->exec_update_lock);
return 0;
}
static ssize_t bch2_btree_transactions_read(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
struct dump_iter *i = file->private_data;
struct bch_fs *c = i->c;
struct btree_trans *trans;
int err;
i->ubuf = buf;
i->size = size;
i->ret = 0;
mutex_lock(&c->btree_trans_lock);
list_for_each_entry(trans, &c->btree_trans_list, list) {
if (trans->task->pid <= i->iter)
continue;
err = flush_buf(i);
if (err)
return err;
if (!i->size)
break;
bch2_btree_trans_to_text(&i->buf, trans);
prt_printf(&i->buf, "backtrace:");
prt_newline(&i->buf);
printbuf_indent_add(&i->buf, 2);
prt_backtrace(&i->buf, trans->task);
printbuf_indent_sub(&i->buf, 2);
prt_newline(&i->buf);
i->iter = trans->task->pid;
}
mutex_unlock(&c->btree_trans_lock);
if (i->buf.allocation_failure)
return -ENOMEM;
return i->ret;
}
static const struct file_operations btree_transactions_ops = {
.owner = THIS_MODULE,
.open = bch2_dump_open,
.release = bch2_dump_release,
.read = bch2_btree_transactions_read,
};
#endif /* CONFIG_BCACHEFS_DEBUG_TRANSACTIONS */
static ssize_t bch2_journal_pins_read(struct file *file, char __user *buf,
size_t size, loff_t *ppos)
{
......@@ -588,6 +660,11 @@ void bch2_fs_debug_init(struct bch_fs *c)
debugfs_create_file("cached_btree_nodes", 0400, c->fs_debug_dir,
c->btree_debug, &cached_btree_nodes_ops);
#ifdef CONFIG_BCACHEFS_DEBUG_TRANSACTIONS
debugfs_create_file("btree_transactions", 0400, c->fs_debug_dir,
c->btree_debug, &btree_transactions_ops);
#endif
debugfs_create_file("journal_pins", 0400, c->fs_debug_dir,
c->btree_debug, &journal_pins_ops);
......
......@@ -33,6 +33,7 @@ const char * const bch2_sb_compat[] = {
const char * const bch2_btree_ids[] = {
BCH_BTREE_IDS()
"interior btree node",
NULL
};
......
......@@ -181,7 +181,6 @@ read_attribute(journal_debug);
read_attribute(btree_updates);
read_attribute(btree_cache);
read_attribute(btree_key_cache);
read_attribute(btree_transactions);
read_attribute(stripes_heap);
read_attribute(open_buckets);
read_attribute(write_points);
......@@ -420,9 +419,6 @@ SHOW(bch2_fs)
if (attr == &sysfs_btree_key_cache)
bch2_btree_key_cache_to_text(out, &c->btree_key_cache);
if (attr == &sysfs_btree_transactions)
bch2_btree_trans_to_text(out, c);
if (attr == &sysfs_stripes_heap)
bch2_stripes_heap_to_text(out, c);
......@@ -621,7 +617,6 @@ struct attribute *bch2_fs_internal_files[] = {
&sysfs_btree_updates,
&sysfs_btree_cache,
&sysfs_btree_key_cache,
&sysfs_btree_transactions,
&sysfs_new_stripes,
&sysfs_stripes_heap,
&sysfs_open_buckets,
......
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