xfs: define bug_on_assert debug mode sysfs tunable
authorBrian Foster <bfoster@redhat.com>
Thu, 15 Jun 2017 04:29:12 +0000 (21:29 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 19 Jun 2017 15:59:10 +0000 (08:59 -0700)
In DEBUG mode, assert failures unconditionally trigger a kernel BUG.
This is useful in diagnostic situations to panic a system and
collect detailed state information at the time of a failure.

This can also cause problems in cases where DEBUG mode code is
desired but it is preferable not trigger kernel BUGs on assert
failure. For example, during development of new code or during
certain xfstests tests that intentionally cause corruption and test
the kernel for survival (but otherwise may expect to trigger assert
failures).

To provide additional flexibility, create the
<sysfs>/fs/xfs/debug/bug_on_assert tunable to configure assert
failure behavior at runtime. This tunable is only available in DEBUG
mode and is enabled by default to preserve existing default
behavior. When disabled, assert failures in DEBUG mode result in
kernel warnings.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_globals.c
fs/xfs/xfs_message.c
fs/xfs/xfs_sysctl.h
fs/xfs/xfs_sysfs.c

index 687a4b01fc53e842e6a686895631b5f0d159f3f3..673adf0a40ccf5851a95572cbaf30fc7d3a32b51 100644 (file)
@@ -47,4 +47,6 @@ xfs_param_t xfs_params = {
 
 struct xfs_globals xfs_globals = {
        .log_recovery_delay     =       0,      /* no delay by default */
+       .bug_on_assert          =       true,   /* historical default in DEBUG
+                                                * mode */
 };
index 11792d888e4e707b91a528390deadbf212417e8e..e68bd1050eab53fca672d8afd5444d7b62cfcfbf 100644 (file)
@@ -110,7 +110,10 @@ assfail(char *expr, char *file, int line)
 {
        xfs_emerg(NULL, "Assertion failed: %s, file: %s, line: %d",
                expr, file, line);
-       BUG();
+       if (xfs_globals.bug_on_assert)
+               BUG();
+       else
+               WARN_ON(1);
 }
 
 void
index 984a3499cfe3870c4e8f0c02e3c3c48a2b18fad9..82afee005140a93353c178e0ce9c86056873978f 100644 (file)
@@ -95,6 +95,7 @@ extern xfs_param_t    xfs_params;
 
 struct xfs_globals {
        int     log_recovery_delay;     /* log recovery delay (secs) */
+       bool    bug_on_assert;          /* BUG() the kernel on assert failure */
 };
 extern struct xfs_globals      xfs_globals;
 
index 80ac15fb96381c5cbb8a7f89432a05c4b4a0f5a8..ec6e0e2f95d66dff0d11eced92abf54a1880ff27 100644 (file)
@@ -145,6 +145,38 @@ struct kobj_type xfs_mp_ktype = {
 #ifdef DEBUG
 /* debug */
 
+STATIC ssize_t
+bug_on_assert_store(
+       struct kobject          *kobject,
+       const char              *buf,
+       size_t                  count)
+{
+       int                     ret;
+       int                     val;
+
+       ret = kstrtoint(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (val == 1)
+               xfs_globals.bug_on_assert = true;
+       else if (val == 0)
+               xfs_globals.bug_on_assert = false;
+       else
+               return -EINVAL;
+
+       return count;
+}
+
+STATIC ssize_t
+bug_on_assert_show(
+       struct kobject          *kobject,
+       char                    *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", xfs_globals.bug_on_assert ? 1 : 0);
+}
+XFS_SYSFS_ATTR_RW(bug_on_assert);
+
 STATIC ssize_t
 log_recovery_delay_store(
        struct kobject  *kobject,
@@ -176,6 +208,7 @@ log_recovery_delay_show(
 XFS_SYSFS_ATTR_RW(log_recovery_delay);
 
 static struct attribute *xfs_dbg_attrs[] = {
+       ATTR_LIST(bug_on_assert),
        ATTR_LIST(log_recovery_delay),
        NULL,
 };