]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Safer debugging and assertion macros.
authorTim Chase <tim@chase2k.com>
Wed, 18 Jun 2014 20:22:50 +0000 (15:22 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 1 Jul 2014 22:14:43 +0000 (15:14 -0700)
Spl's debugging and assertion macros macro used the typical do/while(0)
form for if/else friendliness, however, this limits their use in contexts
where a do loop is not valid; such as within another multi-statement
style macro.

The following macros have been converted to not use do/while(0):
PANIC, ASSERT, ASSERTF, VERIFY, VERIFY3_IMPL

PANIC has been converted to a wrapper around the new spl_PANIC() function.

The other macros have been converted to use the "&&" operator for the
branch-predicition conditional and also to use spl_PANIC().

The __ASSERT() macro was not touched.  It is only used by the debugging
infrastructure and that code, including this macro, will be retired when
the tracepoint patches are merged.

Signed-off-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #367

include/sys/debug.h
module/spl/spl-err.c

index 9fa2653d4d3b61f614a22bddf471e220c3d65e61..3a4b1352fbfd915521d87268fa2bf323893b10fa 100644 (file)
 #define SPL_DEBUG_STR  ""
 
 #define PANIC(fmt, a...)                                               \
-do {                                                                   \
-       printk(KERN_EMERG fmt, ## a);                                   \
-       spl_debug_bug(__FILE__, __FUNCTION__, __LINE__, 0);             \
-} while (0)
+       spl_PANIC(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
 
 #define __ASSERT(x)                    ((void)0)
 #define ASSERT(x)                      ((void)0)
 #define ASSERTF(x, y, z...)            ((void)0)
 #define ASSERTV(x)
 #define VERIFY(cond)                                                   \
-do {                                                                   \
-       if (unlikely(!(cond)))                                          \
-               PANIC("VERIFY(" #cond ") failed\n");                    \
-} while (0)
+       (void)(unlikely(!(cond)) &&                                     \
+               spl_PANIC(__FILE__, __FUNCTION__, __LINE__,             \
+               "%s", "VERIFY(" #cond ") failed\n"))
 
 #define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE, FMT, CAST)                 \
-do {                                                                   \
-       if (!((TYPE)(LEFT) OP (TYPE)(RIGHT)))                           \
-               PANIC("VERIFY3(" #LEFT " " #OP " " #RIGHT ") "          \
+       (void)((!((TYPE)(LEFT) OP (TYPE)(RIGHT))) &&                    \
+               spl_PANIC(__FILE__, __FUNCTION__, __LINE__,             \
+               "VERIFY3(" #LEFT " " #OP " " #RIGHT ") "                \
                    "failed (" FMT " " #OP " " FMT ")\n",               \
-                   CAST (LEFT), CAST (RIGHT));                         \
-} while (0)
+                   CAST (LEFT), CAST (RIGHT)))
 
 #define VERIFY3S(x,y,z)        VERIFY3_IMPL(x, y, z, int64_t, "%lld", (long long))
 #define VERIFY3U(x,y,z)        VERIFY3_IMPL(x, y, z, uint64_t, "%llu",         \
@@ -94,11 +89,7 @@ do {                                                                 \
 #define SPL_DEBUG_STR  " (DEBUG mode)"
 
 #define PANIC(fmt, a...)                                               \
-do {                                                                   \
-       spl_debug_msg(NULL, 0, 0,                                       \
-            __FILE__, __FUNCTION__, __LINE__,  fmt, ## a);             \
-       spl_debug_bug(__FILE__, __FUNCTION__, __LINE__, 0);             \
-} while (0)
+       spl_PANIC(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
 
 /* ASSERTION that is safe to use within the debug system */
 #define __ASSERT(cond)                                                 \
@@ -111,24 +102,21 @@ do {                                                                      \
 
 /* ASSERTION that will debug log used outside the debug sysytem */
 #define ASSERT(cond)                                                   \
-do {                                                                   \
-       if (unlikely(!(cond)))                                          \
-               PANIC("ASSERTION(" #cond ") failed\n");                 \
-} while (0)
+       (void)(unlikely(!(cond)) &&                                     \
+               spl_PANIC(__FILE__, __FUNCTION__, __LINE__,             \
+               "%s", "ASSERTION(" #cond ") failed\n"))
 
 #define ASSERTF(cond, fmt, a...)                                       \
-do {                                                                   \
-       if (unlikely(!(cond)))                                          \
-               PANIC("ASSERTION(" #cond ") failed: " fmt, ## a);       \
-} while (0)
+       (void)(unlikely(!(cond)) &&                                     \
+               spl_PANIC(__FILE__, __FUNCTION__, __LINE__,             \
+               "ASSERTION(" #cond ") failed: " fmt, ## a))
 
 #define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE, FMT, CAST)                 \
-do {                                                                   \
-       if (!((TYPE)(LEFT) OP (TYPE)(RIGHT)))                           \
-               PANIC("VERIFY3(" #LEFT " " #OP " " #RIGHT ") "          \
+       (void)((!((TYPE)(LEFT) OP (TYPE)(RIGHT))) &&                    \
+               spl_PANIC(__FILE__, __FUNCTION__, __LINE__,             \
+               "VERIFY3(" #LEFT " " #OP " " #RIGHT ") "                \
                    "failed (" FMT " " #OP " " FMT ")\n",               \
-                   CAST (LEFT), CAST (RIGHT));                         \
-} while (0)
+                   CAST (LEFT), CAST (RIGHT)))
 
 #define VERIFY3S(x,y,z)        VERIFY3_IMPL(x, y, z, int64_t, "%lld", (long long))
 #define VERIFY3U(x,y,z)        VERIFY3_IMPL(x, y, z, uint64_t, "%llu",         \
@@ -146,6 +134,12 @@ do {                                                                       \
 
 #endif /* NDEBUG */
 
+/*
+ * Helpers for the Solaris debug macros above
+ */
+extern int spl_PANIC(char *filename, const char *functionname,
+       int lineno, const char *fmt, ...);
+
 /*
  * Compile-time assertion. The condition 'x' must be constant.
  */
index b6d15f01918f1ff68e25f0150a0939a0c504c9d6..2706f9bd13996fc0955d0f69aeb85538fcd905ec 100644 (file)
@@ -39,6 +39,27 @@ static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
 static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
 #endif
 
+int
+spl_PANIC(char *filename, const char *functionname,
+    int lineno, const char *fmt, ...) {
+       char msg[MAXMSGLEN];
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (vsnprintf(msg, sizeof (msg), fmt, ap) == sizeof (msg))
+               msg[sizeof (msg) - 1] = '\0';
+       va_end(ap);
+#ifdef NDEBUG
+       printk(KERN_EMERG "%s", msg);
+#else
+       spl_debug_msg(NULL, 0, 0,
+            filename, functionname, lineno, "%s", msg);
+#endif
+       spl_debug_bug(filename, functionname, lineno, 0);
+       return 1;
+}
+EXPORT_SYMBOL(spl_PANIC);
+
 void
 vpanic(const char *fmt, va_list ap)
 {