bcachefs: Improve an error message
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 18 Jun 2022 00:12:02 +0000 (20:12 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:34 +0000 (17:09 -0400)
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>
fs/bcachefs/bkey_methods.c
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_iter.h
fs/bcachefs/btree_types.h
fs/bcachefs/debug.c
fs/bcachefs/opts.c
fs/bcachefs/sysfs.c

index 390ea41414bc40b1f3a285dc09a0af2929e95958..f2351e5ee7c1ddc827d777e6a479ab080f382e0b 100644 (file)
@@ -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;
        }
 
index a2219c13aee5609bb4e3352d176b87ca67786ecf..fc989b46b67ea1853826af794db79df58a1621f6 100644 (file)
@@ -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)
 {
index 83587383a41ff822a4e937ca418e22340e9faf28..39f241e2588142e561fae4f587ad28e1b263dabd 100644 (file)
@@ -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 *);
index ede5661b62a5525c13dd4ea1ebc23118339c9390..4f3e1086a86b3d233af1dfec1165cf7384a49dff 100644 (file)
@@ -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;
index 878f4e541f8381254c057a160189b89c838a22fe..0f25b75e3de7474efccfb8f537b0d403bf6c7572 100644 (file)
@@ -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);
 
index 5540d5d98d845e54d058b7b2bddca56ac7c25479..98568f21d6d07407169e50a4195f0482753ef7cc 100644 (file)
@@ -33,6 +33,7 @@ const char * const bch2_sb_compat[] = {
 
 const char * const bch2_btree_ids[] = {
        BCH_BTREE_IDS()
+       "interior btree node",
        NULL
 };
 
index b2d6a5c49a4d5f94e66794de9e11a0e071bd3ba7..173289c34de0f9a3cb4913efc47a32f467475def 100644 (file)
@@ -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,