summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2018-07-12 14:01:58 +0300
committerRichard Weinberger <richard@nod.at>2018-08-15 01:25:21 +0300
commit2e52eb74463f15c745d64948cedfaee722d6268c (patch)
tree28c0633e10d74d5e12ac3179108c1fed8c52e4f3
parent6eb61d587f4515e4be5669eff383c0185009954f (diff)
downloadlinux-2e52eb74463f15c745d64948cedfaee722d6268c.tar.xz
ubifs: Rework ubifs_assert()
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>
-rw-r--r--fs/ubifs/debug.c22
-rw-r--r--fs/ubifs/debug.h10
-rw-r--r--fs/ubifs/ubifs.h14
3 files changed, 42 insertions, 4 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 1a626484f8ae..564e330d05b1 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -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
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 981a3fa081f3..64c6977c189b 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -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)
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index d17e895ee87f..4368cde476b0 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -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;