[patch 3/5] Make the dprintk() macro record information about the callsite

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Change the definition of dprintk() to generate an array of records in
a special new .dprintk section, which describe the module, filename,
line number, function, and printk format of each dprintk.

Signed-off-by: Greg Banks <gnb@xxxxxxx>
---

 include/linux/dprintk.h        |   91 ++++++++++++++++++++++++++++++
 include/linux/lockd/debug.h    |    6 -
 include/linux/nfs_fs.h         |   18 -----
 include/linux/nfsd/debug.h     |   12 +--
 include/linux/sunrpc/debug.h   |   29 +++++++--
 net/sunrpc/cache.c             |    2 
 net/sunrpc/xprtrdma/rpc_rdma.c |    2 
 7 files changed, 124 insertions(+), 36 deletions(-)

Index: bfields/include/linux/dprintk.h
===================================================================
--- /dev/null
+++ bfields/include/linux/dprintk.h
@@ -0,0 +1,91 @@
+/*
+ * dprintk.h - a generic /proc interface for enabling individual debugging printks.
+ *
+ * By Greg Banks <gnb@xxxxxxxxxxxxxxxxx>
+ * Copyright (c) 2008 Silicon Graphics Inc.  All Rights Reserved.
+ * $Id: dprintk.h,v 1.1 2008/09/04 04:46:06 gnb Exp $
+ */
+#ifndef _LINUX_DPRINTK_H_
+#define _LINUX_DPRINTK_H_ 1
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+/*
+ * An instance of this structure is created in a special
+ * ELF section at every dprintk() callsite.  At runtime,
+ * the special section is treated as an array of these.
+ */
+struct _dprintk
+{
+	/*
+	 * These fields are used to drive the /proc user interface
+	 * for selecting and displaying dprintk() callsites.
+	 */
+	const char *function;
+	const char *filename;
+	const char *format;
+	unsigned int lineno;
+	/*
+	 * This magic number helps finding the bound of the special
+	 * ELF section (for various stupid reasons we don't have an
+	 * accurate idea of the end of the loaded section).
+	 */
+#define _DPRINTK_MAGIC		0xc0ffee
+	unsigned int magic:24;
+	/*
+	 * The flags field controls the behaviour at the callsite.
+	 * The bits here are changed dynamically when the user
+	 * writes commands to /proc/dprintk.
+	 */
+#define _DPRINTK_FLAGS_PRINT	(1<<0)	/* printk() a message using the format */
+#define _DPRINTK_FLAGS_STACK	(1<<1)	/* print a kernel stack using dump_stack() */
+#define _DPRINTK_FLAGS_CRASH	(1<<2)	/* cause a kernel crash for debugging */
+#define _DPRINTK_FLAGS_DEFAULT	0
+	unsigned int flags:8;
+};
+
+
+/*
+ * Basic callsite functionality.  The `cond' argument allows
+ * the caller to add an extra logical condition to the check
+ * for printk().  The NFS code uses that to implement a
+ * dfprintk() macro which is dprintk() with an additional
+ * check of the NFS global debug bitmasks.
+ */
+#define __dprintk(cond, fmt, ...)				\
+do {								\
+	static struct _dprintk					\
+		__attribute__((section(".dprintk"))) _dp = {	\
+		.function = __FUNCTION__,			\
+		.filename = __FILE__,				\
+		.format = fmt,					\
+		.lineno = __LINE__,				\
+		.magic = _DPRINTK_MAGIC,			\
+		.flags = _DPRINTK_FLAGS_DEFAULT			\
+	};							\
+	if (unlikely(_dp.flags || (cond)))			\
+		printk(_dp.format, ## __VA_ARGS__);		\
+	if (unlikely(_dp.flags & _DPRINTK_FLAGS_STACK))		\
+		dump_stack();					\
+	BUG_ON(_dp.flags & _DPRINTK_FLAGS_CRASH);		\
+} while(0)
+
+/*
+ * Default definition of dprintk_check.  This macro exists
+ * only to allow calling code to redefine it to add extra
+ * logic which enables dprintk() callsites in ways other
+ * than the individual callsite flags.  For example, NFS
+ * uses this to implement backwards-compatible global debug
+ * bitmasks.
+ */
+#ifndef dprintk_check
+#define dprintk_check   0
+#endif
+
+/*
+ * This is the macro that most calling code should be using.
+ */
+#define dprintk(fmt, ...)   __dprintk(dprintk_check, fmt, ## __VA_ARGS__)
+
+#endif /* _LINUX_DPRINTK_H_ */
Index: bfields/include/linux/lockd/debug.h
===================================================================
--- bfields.orig/include/linux/lockd/debug.h
+++ bfields/include/linux/lockd/debug.h
@@ -21,11 +21,9 @@
 # define LOCKD_DEBUG		1
 #endif
 
-#undef ifdebug
 #if defined(RPC_DEBUG) && defined(LOCKD_DEBUG)
-# define ifdebug(flag)		if (unlikely(nlm_debug & NLMDBG_##flag))
-#else
-# define ifdebug(flag)		if (0)
+# undef debugcheck
+# define debugcheck(fac)	(nlm_debug & NLMDBG_##fac)
 #endif
 
 #endif /* __KERNEL__ */
Index: bfields/include/linux/nfsd/debug.h
===================================================================
--- bfields.orig/include/linux/nfsd/debug.h
+++ bfields/include/linux/nfsd/debug.h
@@ -36,13 +36,9 @@
 #define NFSDDBG_NOCHANGE	0xFFFF
 
 
-#ifdef __KERNEL__
-# undef ifdebug
-# ifdef NFSD_DEBUG
-#  define ifdebug(flag)		if (nfsd_debug & NFSDDBG_##flag)
-# else
-#  define ifdebug(flag)		if (0)
-# endif
-#endif /* __KERNEL__ */
+#if defined(__KERNEL__) && defined(NFSD_DEBUG)
+# undef debugcheck
+# define debugcheck(fac)	(nfsd_debug & NFSDDBG_##fac)
+#endif
 
 #endif /* LINUX_NFSD_DEBUG_H */
Index: bfields/include/linux/nfs_fs.h
===================================================================
--- bfields.orig/include/linux/nfs_fs.h
+++ bfields/include/linux/nfs_fs.h
@@ -598,22 +598,10 @@ extern void * nfs_root_data(void);
 #define NFSDBG_FSCACHE		0x0800
 #define NFSDBG_ALL		0xFFFF
 
-#ifdef __KERNEL__
-
-/*
- * Enable debugging support for nfs client.
- * Requires RPC_DEBUG.
- */
-#ifdef RPC_DEBUG
+#if defined(__KERNEL__) && defined(RPC_DEBUG)
 # define NFS_DEBUG
+# undef debugcheck
+# define debugcheck(fac)	(nfs_debug & NFSDBG_##fac)
 #endif
 
-# undef ifdebug
-# ifdef NFS_DEBUG
-#  define ifdebug(fac)		if (unlikely(nfs_debug & NFSDBG_##fac))
-# else
-#  define ifdebug(fac)		if (0)
-# endif
-#endif /* __KERNEL */
-
 #endif
Index: bfields/include/linux/sunrpc/debug.h
===================================================================
--- bfields.orig/include/linux/sunrpc/debug.h
+++ bfields/include/linux/sunrpc/debug.h
@@ -30,6 +30,7 @@
 
 #include <linux/timer.h>
 #include <linux/workqueue.h>
+#include <linux/dprintk.h>
 
 /*
  * Enable RPC debugging/profiling.
@@ -41,6 +42,20 @@
 
 /*
  * Debugging macros etc
+ *
+ * The RPC (and NFS etc) code can do the following:
+ *
+ * a) at the start of a .c file set up the default
+ *    debug bit to be used for all dprintk()s, e.g.
+ *   #define RPCDBG_FACILITY  RPCDBG_MISC
+ *
+ * b) call dprintk(), to do a debug print conditional
+ *    on the default debug bit, e.g.
+ *   dprintk("nfsd: write complete err=%d\n", err);
+ *
+ * c) call dfprintk(), to do a debug print conditional
+ *    on a specified non-default debug bit, e.g.
+ *   dfprintk(VFS, "NFS: find_dirent_index() returns %d\n", status);
  */
 #ifdef RPC_DEBUG
 extern unsigned int		rpc_debug;
@@ -49,15 +64,15 @@ extern unsigned int		nfsd_debug;
 extern unsigned int		nlm_debug;
 #endif
 
-#define dprintk(args...)	dfprintk(FACILITY, ## args)
-
-#undef ifdebug
-#ifdef RPC_DEBUG			
-# define ifdebug(fac)		if (unlikely(rpc_debug & RPCDBG_##fac))
-# define dfprintk(fac, args...)	do { ifdebug(fac) printk(args); } while(0)
+#ifdef RPC_DEBUG
+# define debugcheck(fac)	(rpc_debug & RPCDBG_##fac)
+# undef dprintk_check
+# define dprintk_check		debugcheck(FACILITY)
+# define dfprintk(fac, args...)	__dprintk(debugcheck(fac), args)
 # define RPC_IFDEBUG(x)		x
 #else
-# define ifdebug(fac)		if (0)
+# undef dprintk
+# define dprintk(args...)	do ; while (0)
 # define dfprintk(fac, args...)	do ; while (0)
 # define RPC_IFDEBUG(x)
 #endif
Index: bfields/net/sunrpc/cache.c
===================================================================
--- bfields.orig/net/sunrpc/cache.c
+++ bfields/net/sunrpc/cache.c
@@ -1236,7 +1236,7 @@ static int c_show(struct seq_file *m, vo
 	if (p == SEQ_START_TOKEN)
 		return cd->cache_show(m, cd, NULL);
 
-	ifdebug(CACHE)
+	if (unlikely(debugcheck(CACHE)))
 		seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
 			   h->expiry_time, atomic_read(&h->ref.refcount), h->flags);
 	cache_get(h);
Index: bfields/net/sunrpc/xprtrdma/rpc_rdma.c
===================================================================
--- bfields.orig/net/sunrpc/xprtrdma/rpc_rdma.c
+++ bfields/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -568,7 +568,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep 
 	total_len = 0;
 	while (i--) {
 		struct rpcrdma_segment *seg = &cur_wchunk->wc_target;
-		ifdebug(FACILITY) {
+		if (unlikely(debugcheck(FACILITY))) {
 			u64 off;
 			xdr_decode_hyper((__be32 *)&seg->rs_offset, &off);
 			dprintk("RPC:       %s: chunk %d@0x%llx:0x%x\n",

--
-- 
Greg Banks, P.Engineer, SGI Australian Software Group.
the brightly coloured sporks of revolution.
I don't speak for SGI.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux