ubifs: Rework ubifs_assert()
authorRichard Weinberger <richard@nod.at>
Thu, 12 Jul 2018 11:01:58 +0000 (13:01 +0200)
committerRichard Weinberger <richard@nod.at>
Tue, 14 Aug 2018 22:25:21 +0000 (00:25 +0200)
With having access to struct ubifs_info in ubifs_assert() we can
give more information when an assert is failing.
By using ubifs_err() we can tell which UBIFS instance failed.

Also multiple actions can be taken now.
We support:
 - report: This is what UBIFS did so far, just report the failure and go
   on.
 - read-only: Switch to read-only mode.
 - panic: shoot the kernel in the head.

Signed-off-by: Richard Weinberger <richard@nod.at>
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/ubifs.h

index 1a626484f8aee28cfa7d3d3c37efded6cde7550f..564e330d05b146df6d8c848742b08f02820b14c3 100644 (file)
@@ -3081,6 +3081,28 @@ void dbg_debugfs_exit(void)
                debugfs_remove_recursive(dfs_rootdir);
 }
 
+void ubifs_assert_failed(struct ubifs_info *c, const char *expr,
+                        const char *file, int line)
+{
+       ubifs_err(c, "UBIFS assert failed: %s, in %s:%u", expr, file, line);
+
+       switch (c->assert_action) {
+               case ASSACT_PANIC:
+               BUG();
+               break;
+
+               case ASSACT_RO:
+               ubifs_ro_mode(c, -EINVAL);
+               break;
+
+               case ASSACT_REPORT:
+               default:
+               dump_stack();
+               break;
+
+       }
+}
+
 /**
  * ubifs_debugging_init - initialize UBIFS debugging.
  * @c: UBIFS file-system description object
index 981a3fa081f3b7d64a2faec6824e546650d1234d..64c6977c189b932494f282a708a04101e4849878 100644 (file)
@@ -148,18 +148,20 @@ struct ubifs_global_debug_info {
        unsigned int tst_rcvry:1;
 };
 
+void ubifs_assert_failed(struct ubifs_info *c, const char *expr,
+       const char *file, int line);
+
 #define ubifs_assert(c, expr) do {                                             \
        if (unlikely(!(expr))) {                                               \
-               pr_crit("UBIFS assert failed in %s at %u (pid %d)\n",          \
-                      __func__, __LINE__, current->pid);                      \
-               dump_stack();                                                  \
+               ubifs_assert_failed((struct ubifs_info *)c, #expr, __FILE__,   \
+                __LINE__);                                                    \
        }                                                                      \
 } while (0)
 
 #define ubifs_assert_cmt_locked(c) do {                                        \
        if (unlikely(down_write_trylock(&(c)->commit_sem))) {                  \
                up_write(&(c)->commit_sem);                                    \
-               pr_crit("commit lock is not locked!\n");                       \
+               ubifs_err(c, "commit lock is not locked!\n");                  \
                ubifs_assert(c, 0);                                            \
        }                                                                      \
 } while (0)
index d17e895ee87f938243182d05a0d9dda4b640f2c6..4368cde476b0fa4360ab942790fb70ff62937530 100644 (file)
@@ -258,6 +258,18 @@ enum {
        LEB_RETAINED,
 };
 
+/*
+ * Action taken upon a failed ubifs_assert().
+ * @ASSACT_REPORT: just report the failed assertion
+ * @ASSACT_RO: switch to read-only mode
+ * @ASSACT_PANIC: call BUG() and possible panic the kernel
+ */
+enum {
+       ASSACT_REPORT = 0,
+       ASSACT_RO,
+       ASSACT_PANIC,
+};
+
 /**
  * struct ubifs_old_idx - index node obsoleted since last commit start.
  * @rb: rb-tree node
@@ -1015,6 +1027,7 @@ struct ubifs_debug_info;
  * @bulk_read: enable bulk-reads
  * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
  * @rw_incompat: the media is not R/W compatible
+ * @assert_action: action to take when a ubifs_assert() fails
  *
  * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
  *             @calc_idx_sz
@@ -1256,6 +1269,7 @@ struct ubifs_info {
        unsigned int bulk_read:1;
        unsigned int default_compr:2;
        unsigned int rw_incompat:1;
+       unsigned int assert_action:2;
 
        struct mutex tnc_mutex;
        struct ubifs_zbranch zroot;