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, ...@@ -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))) { if (!(bch2_key_types_allowed[type] & (1U << k.k->type))) {
prt_printf(err, "invalid key type for this btree (%s)", prt_printf(err, "invalid key type for btree %s (%s)",
bch2_bkey_types[type]); bch2_btree_ids[type], bch2_bkey_types[k.k->type]);
return -EINVAL; return -EINVAL;
} }
......
...@@ -3257,6 +3257,7 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, ...@@ -3257,6 +3257,7 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c,
memset(trans, 0, sizeof(*trans)); memset(trans, 0, sizeof(*trans));
trans->c = c; trans->c = c;
trans->fn = fn; trans->fn = fn;
trans->task = current;
trans->journal_replay_not_finished = trans->journal_replay_not_finished =
!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags); !test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags);
...@@ -3277,9 +3278,17 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, ...@@ -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); trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG_TRANSACTIONS)) { if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG_TRANSACTIONS)) {
trans->pid = current->pid; struct btree_trans *pos;
mutex_lock(&c->btree_trans_lock); 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); mutex_unlock(&c->btree_trans_lock);
} }
} }
...@@ -3371,77 +3380,57 @@ bch2_btree_path_node_to_text(struct printbuf *out, ...@@ -3371,77 +3380,57 @@ bch2_btree_path_node_to_text(struct printbuf *out,
} }
#ifdef CONFIG_BCACHEFS_DEBUG_TRANSACTIONS #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; 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; struct btree *b;
static char lock_types[] = { 'r', 'i', 'w' }; static char lock_types[] = { 'r', 'i', 'w' };
unsigned l; unsigned l;
mutex_lock(&c->btree_trans_lock); prt_printf(out, "%i %s\n", trans->task->pid, trans->fn);
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);
trans_for_each_path(trans, path) { trans_for_each_path(trans, path) {
if (!path->nodes_locked) if (!path->nodes_locked)
continue; continue;
prt_printf(out, " path %u %c l=%u %s:", prt_printf(out, " path %u %c l=%u %s:",
path->idx, path->idx,
path->cached ? 'c' : 'b', path->cached ? 'c' : 'b',
path->level, path->level,
bch2_btree_ids[path->btree_id]); bch2_btree_ids[path->btree_id]);
bch2_bpos_to_text(out, path->pos); bch2_bpos_to_text(out, path->pos);
prt_printf(out, "\n"); prt_printf(out, "\n");
for (l = 0; l < BTREE_MAX_DEPTH; l++) { for (l = 0; l < BTREE_MAX_DEPTH; l++) {
if (btree_node_locked(path, l)) { if (btree_node_locked(path, l)) {
prt_printf(out, " %s l=%u ", prt_printf(out, " %s l=%u ",
btree_node_intent_locked(path, l) ? "i" : "r", l); btree_node_intent_locked(path, l) ? "i" : "r", l);
bch2_btree_path_node_to_text(out, bch2_btree_path_node_to_text(out,
(void *) path->l[l].b, (void *) path->l[l].b,
path->cached); path->cached);
prt_printf(out, "\n"); prt_printf(out, "\n");
}
} }
} }
}
b = READ_ONCE(trans->locking); b = READ_ONCE(trans->locking);
if (b) { if (b) {
path = &trans->paths[trans->locking_path_idx]; path = &trans->paths[trans->locking_path_idx];
prt_printf(out, " locking path %u %c l=%u %c %s:", prt_printf(out, " locking path %u %c l=%u %c %s:",
trans->locking_path_idx, trans->locking_path_idx,
path->cached ? 'c' : 'b', path->cached ? 'c' : 'b',
trans->locking_level, trans->locking_level,
lock_types[trans->locking_lock_type], lock_types[trans->locking_lock_type],
bch2_btree_ids[trans->locking_btree_id]); bch2_btree_ids[trans->locking_btree_id]);
bch2_bpos_to_text(out, trans->locking_pos); bch2_bpos_to_text(out, trans->locking_pos);
prt_printf(out, " node "); prt_printf(out, " node ");
bch2_btree_path_node_to_text(out, bch2_btree_path_node_to_text(out,
(void *) b, path->cached); (void *) b, path->cached);
prt_printf(out, "\n"); prt_printf(out, "\n");
}
} }
mutex_unlock(&c->btree_trans_lock);
#endif
} }
#endif
void bch2_fs_btree_iter_exit(struct bch_fs *c) void bch2_fs_btree_iter_exit(struct bch_fs *c)
{ {
......
...@@ -440,7 +440,7 @@ void bch2_trans_exit(struct btree_trans *); ...@@ -440,7 +440,7 @@ void bch2_trans_exit(struct btree_trans *);
#define bch2_trans_init(...) __bch2_trans_init(__VA_ARGS__, __func__) #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 *); void bch2_fs_btree_iter_exit(struct bch_fs *);
int bch2_fs_btree_iter_init(struct bch_fs *); int bch2_fs_btree_iter_init(struct bch_fs *);
......
...@@ -386,7 +386,7 @@ struct btree_trans { ...@@ -386,7 +386,7 @@ struct btree_trans {
u8 locking_btree_id; u8 locking_btree_id;
u8 locking_level; u8 locking_level;
u8 locking_lock_type; u8 locking_lock_type;
pid_t pid; struct task_struct *task;
int srcu_idx; int srcu_idx;
u8 nr_sorted; u8 nr_sorted;
......
...@@ -529,6 +529,78 @@ static const struct file_operations cached_btree_nodes_ops = { ...@@ -529,6 +529,78 @@ static const struct file_operations cached_btree_nodes_ops = {
.read = bch2_cached_btree_nodes_read, .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, static ssize_t bch2_journal_pins_read(struct file *file, char __user *buf,
size_t size, loff_t *ppos) size_t size, loff_t *ppos)
{ {
...@@ -588,6 +660,11 @@ void bch2_fs_debug_init(struct bch_fs *c) ...@@ -588,6 +660,11 @@ void bch2_fs_debug_init(struct bch_fs *c)
debugfs_create_file("cached_btree_nodes", 0400, c->fs_debug_dir, debugfs_create_file("cached_btree_nodes", 0400, c->fs_debug_dir,
c->btree_debug, &cached_btree_nodes_ops); 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, debugfs_create_file("journal_pins", 0400, c->fs_debug_dir,
c->btree_debug, &journal_pins_ops); c->btree_debug, &journal_pins_ops);
......
...@@ -33,6 +33,7 @@ const char * const bch2_sb_compat[] = { ...@@ -33,6 +33,7 @@ const char * const bch2_sb_compat[] = {
const char * const bch2_btree_ids[] = { const char * const bch2_btree_ids[] = {
BCH_BTREE_IDS() BCH_BTREE_IDS()
"interior btree node",
NULL NULL
}; };
......
...@@ -181,7 +181,6 @@ read_attribute(journal_debug); ...@@ -181,7 +181,6 @@ read_attribute(journal_debug);
read_attribute(btree_updates); read_attribute(btree_updates);
read_attribute(btree_cache); read_attribute(btree_cache);
read_attribute(btree_key_cache); read_attribute(btree_key_cache);
read_attribute(btree_transactions);
read_attribute(stripes_heap); read_attribute(stripes_heap);
read_attribute(open_buckets); read_attribute(open_buckets);
read_attribute(write_points); read_attribute(write_points);
...@@ -420,9 +419,6 @@ SHOW(bch2_fs) ...@@ -420,9 +419,6 @@ SHOW(bch2_fs)
if (attr == &sysfs_btree_key_cache) if (attr == &sysfs_btree_key_cache)
bch2_btree_key_cache_to_text(out, &c->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) if (attr == &sysfs_stripes_heap)
bch2_stripes_heap_to_text(out, c); bch2_stripes_heap_to_text(out, c);
...@@ -621,7 +617,6 @@ struct attribute *bch2_fs_internal_files[] = { ...@@ -621,7 +617,6 @@ struct attribute *bch2_fs_internal_files[] = {
&sysfs_btree_updates, &sysfs_btree_updates,
&sysfs_btree_cache, &sysfs_btree_cache,
&sysfs_btree_key_cache, &sysfs_btree_key_cache,
&sysfs_btree_transactions,
&sysfs_new_stripes, &sysfs_new_stripes,
&sysfs_stripes_heap, &sysfs_stripes_heap,
&sysfs_open_buckets, &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