mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-13 02:25:36 -04:00
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: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
committed by
Kent Overstreet
parent
2ed6248ab3
commit
50b13beef0
@@ -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))
|
||||
prt_printf(out, "%i %s\n", trans->task->pid, trans->fn);
|
||||
|
||||
trans_for_each_path(trans, path) {
|
||||
if (!path->nodes_locked)
|
||||
continue;
|
||||
|
||||
prt_printf(out, "%i %s\n", trans->pid, trans->fn);
|
||||
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");
|
||||
|
||||
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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
mutex_unlock(&c->btree_trans_lock);
|
||||
#endif
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
#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,
|
||||
|
||||
Reference in New Issue
Block a user