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

[lvm-devel] master - logging: add debug classes



Gitweb:        http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7f747a0d739c08eadf319da9c3973f83c97c82af
Commit:        7f747a0d739c08eadf319da9c3973f83c97c82af
Parent:        b617109fff859a5b970554b38852fc61deb29f77
Author:        Alasdair G Kergon <agk redhat com>
AuthorDate:    Mon Jan 7 22:25:19 2013 +0000
Committer:     Alasdair G Kergon <agk redhat com>
CommitterDate: Mon Jan 7 22:25:19 2013 +0000

logging: add debug classes

Add log/debug_classes to lvm.conf to allow debug messages to be
classified and filtered at runtime.

The dm_errno field is only used by log_error(), so I've redefined it
for log_debug() messages to hold the message class.

By default, all existing messages appear, but we can add categories that
generate high volumes of data, such as logging all traffic to/from
lvmetad.
---
 WHATS_NEW                  |    1 +
 doc/example.conf.in        |    9 ++++++++
 lib/commands/toolcontext.c |   46 ++++++++++++++++++++++++++++++++++++++++++++
 lib/commands/toolcontext.h |    1 +
 lib/config/defaults.h      |    4 +++
 lib/log/log.c              |   27 +++++++++++++++----------
 lib/log/log.h              |   23 ++++++++++++++++++++++
 lib/log/lvm-logging.h      |    7 ++++-
 lib/misc/lvm-globals.c     |   15 ++++++++++++++
 lib/misc/lvm-globals.h     |    2 +
 libdm/libdevmapper.h       |    4 ++-
 libdm/libdm-common.c       |    6 ++--
 libdm/misc/dm-logging.h    |    3 ++
 13 files changed, 131 insertions(+), 17 deletions(-)

diff --git a/WHATS_NEW b/WHATS_NEW
index 5b81d52..d7e8c7d 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.99 - 
 ===================================
+  Add log/debug_classes to lvm.conf to control debug log messages.
   Synchronize with udev in pvscan --cache and fix dangling udev_sync cookies.
   Fix autoactivation to not autoactivate VG/LV on each change of the PVs used.
   Limit RAID device replacement to repair only if LV is not in-sync.
diff --git a/doc/example.conf.in b/doc/example.conf.in
index 872d6ef..256e012 100644
--- a/doc/example.conf.in
+++ b/doc/example.conf.in
@@ -307,6 +307,15 @@ log {
     # Set this if you want log messages during activation.
     # Don't use this in low memory situations (can deadlock).
     # activation = 0
+
+    # Some debugging messages are assigned to a class and only appear
+    # in debug output if the class is listed here.
+    # Classes currently available:
+    #   memory, devices, activation, allocation, lvmetad, metadata, cache,
+    #   locking
+    # Use "all" to see everything.
+    debug_classes = [ "memory", "devices", "activation", "allocation",
+		      "lvmetad", "metadata", "cache", "locking" ]
 }
 
 # Configuration of metadata backups and archiving.  In LVM2 when we
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 14152b7..d5dd430 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -122,6 +122,48 @@ static void _get_sysfs_dir(struct cmd_context *cmd)
 	strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir));
 }
 
+static int _parse_debug_classes(struct cmd_context *cmd)
+{
+	const struct dm_config_node *cn;
+	const struct dm_config_value *cv;
+	int debug_classes = 0;
+
+	if (!(cn = find_config_tree_node(cmd, "log/debug_classes")))
+		return DEFAULT_LOGGED_DEBUG_CLASSES;
+
+	for (cv = cn->v; cv; cv = cv->next) {
+		if (cv->type != DM_CFG_STRING) {
+			log_verbose("log/debug_classes contains a value "
+				    "which is not a string.  Ignoring.");
+			continue;
+		}
+
+		if (!strcasecmp(cv->v.str, "all"))
+			return -1;
+
+		if (!strcasecmp(cv->v.str, "memory"))
+			debug_classes |= LOG_CLASS_MEM;
+		else if (!strcasecmp(cv->v.str, "devices"))
+			debug_classes |= LOG_CLASS_DEVS;
+		else if (!strcasecmp(cv->v.str, "activation"))
+			debug_classes |= LOG_CLASS_ACTIVATION;
+		else if (!strcasecmp(cv->v.str, "allocation"))
+			debug_classes |= LOG_CLASS_ALLOC;
+		else if (!strcasecmp(cv->v.str, "lvmetad"))
+			debug_classes |= LOG_CLASS_LVMETAD;
+		else if (!strcasecmp(cv->v.str, "metadata"))
+			debug_classes |= LOG_CLASS_METADATA;
+		else if (!strcasecmp(cv->v.str, "cache"))
+			debug_classes |= LOG_CLASS_CACHE;
+		else if (!strcasecmp(cv->v.str, "locking"))
+			debug_classes |= LOG_CLASS_LOCKING;
+		else
+			log_verbose("Unrecognised value for log/debug_classes: %s", cv->v.str);
+	}
+
+	return debug_classes;
+}
+
 static void _init_logging(struct cmd_context *cmd)
 {
 	int append = 1;
@@ -198,6 +240,10 @@ static void _init_logging(struct cmd_context *cmd)
 	init_log_while_suspended(find_config_tree_int(cmd,
 						 "log/activation", 0));
 
+	cmd->default_settings.debug_classes = _parse_debug_classes(cmd);
+	log_debug("Setting log debug classes to %d", cmd->default_settings.debug_classes);
+	init_debug_classes_logged(cmd->default_settings.debug_classes);
+
 	t = time(NULL);
 	ctime_r(&t, &timebuf[0]);
 	timebuf[24] = '\0';
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 6e5803f..c21ec13 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -26,6 +26,7 @@
  */
 struct config_info {
 	int debug;
+	int debug_classes;
 	int verbose;
 	int silent;
 	int test;
diff --git a/lib/config/defaults.h b/lib/config/defaults.h
index 348fa75..3518240 100644
--- a/lib/config/defaults.h
+++ b/lib/config/defaults.h
@@ -112,6 +112,10 @@
 #  define DEFAULT_LOG_FACILITY LOG_USER
 #endif
 
+#define DEFAULT_LOGGED_DEBUG_CLASSES (LOG_CLASS_MEM | LOG_CLASS_DEVS | \
+    LOG_CLASS_ACTIVATION | LOG_CLASS_ALLOC | LOG_CLASS_LVMETAD | \
+    LOG_CLASS_METADATA | LOG_CLASS_CACHE | LOG_CLASS_LOCKING)
+
 #define DEFAULT_SYSLOG 1
 #define DEFAULT_VERBOSE 0
 #define DEFAULT_SILENT 0
diff --git a/lib/log/log.c b/lib/log/log.c
index 3c357f1..3b038f5 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -179,7 +179,7 @@ void reset_log_duplicated(void) {
 	}
 }
 
-void print_log(int level, const char *file, int line, int dm_errno,
+void print_log(int level, const char *file, int line, int dm_errno_or_class,
 	       const char *format, ...)
 {
 	va_list ap;
@@ -212,8 +212,8 @@ void print_log(int level, const char *file, int line, int dm_errno,
 
 	trformat = _(format);
 
-	if (dm_errno && !_lvm_errno)
-		_lvm_errno = dm_errno;
+	if (level < _LOG_DEBUG && dm_errno_or_class && !_lvm_errno)
+		_lvm_errno = dm_errno_or_class;
 
 	if (_lvm2_log_fn ||
 	    (_store_errmsg && (level <= _LOG_ERR)) ||
@@ -285,14 +285,16 @@ void print_log(int level, const char *file, int line, int dm_errno,
 			if (!strcmp("<backtrace>", format) &&
 			    verbose_level() <= _LOG_DEBUG)
 				break;
-			if (verbose_level() >= _LOG_DEBUG) {
-				fprintf(stderr, "%s%s%s", locn, log_command_name(),
-					_msg_prefix);
-				if (_indent)
-					fprintf(stderr, "      ");
-				vfprintf(stderr, trformat, ap);
-				fputc('\n', stderr);
-			}
+			if (verbose_level() < _LOG_DEBUG)
+				break;
+			if (!debug_class_is_logged(dm_errno_or_class))
+				break;
+			fprintf(stderr, "%s%s%s", locn, log_command_name(),
+				_msg_prefix);
+			if (_indent)
+				fprintf(stderr, "      ");
+			vfprintf(stderr, trformat, ap);
+			fputc('\n', stderr);
 			break;
 
 		case _LOG_INFO:
@@ -347,6 +349,9 @@ void print_log(int level, const char *file, int line, int dm_errno,
 	if (level > debug_level())
 		return;
 
+	if (level >= _LOG_DEBUG && !debug_class_is_logged(dm_errno_or_class))
+		return;
+
 	if (_log_to_file && (_log_while_suspended || !critical_section())) {
 		fprintf(_log_file, "%s:%d %s%s", file, line, log_command_name(),
 			_msg_prefix);
diff --git a/lib/log/log.h b/lib/log/log.h
index f0da64f..2e1c515 100644
--- a/lib/log/log.h
+++ b/lib/log/log.h
@@ -54,7 +54,30 @@
 #define _LOG_FATAL 2
 #define INTERNAL_ERROR "Internal error: "
 
+/*
+ * Classes available for debug log messages.
+ * These are also listed in doc/example.conf
+ * and lib/commands/toolcontext.c:_parse_debug_classes()
+ */
+#define LOG_CLASS_MEM		0x0001	/* "memory" */
+#define LOG_CLASS_DEVS		0x0002	/* "devices" */
+#define LOG_CLASS_ACTIVATION	0x0004	/* "activation" */
+#define LOG_CLASS_ALLOC		0x0008	/* "allocation" */
+#define LOG_CLASS_LVMETAD	0x0010	/* "lvmetad" */
+#define LOG_CLASS_METADATA	0x0020	/* "metadata" */
+#define LOG_CLASS_CACHE		0x0040	/* "cache" */
+#define LOG_CLASS_LOCKING	0x0080	/* "locking" */
+
 #define log_debug(x...) LOG_LINE(_LOG_DEBUG, x)
+#define log_debug_mem(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_MEM, x)
+#define log_debug_devs(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_DEVS, x)
+#define log_debug_activation(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_ACTIVATION, x)
+#define log_debug_alloc(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_ALLOC, x)
+#define log_debug_lvmetad(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_LVMETAD, x)
+#define log_debug_metadata(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_METADATA, x)
+#define log_debug_cache(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_CACHE, x)
+#define log_debug_locking(x...) LOG_LINE_WITH_CLASS(_LOG_DEBUG, LOG_CLASS_LOCKING, x)
+
 #define log_info(x...) LOG_LINE(_LOG_INFO, x)
 #define log_notice(x...) LOG_LINE(_LOG_NOTICE, x)
 #define log_warn(x...) LOG_LINE(_LOG_WARN | _LOG_STDERR, x)
diff --git a/lib/log/lvm-logging.h b/lib/log/lvm-logging.h
index 1c0a580..52cd895 100644
--- a/lib/log/lvm-logging.h
+++ b/lib/log/lvm-logging.h
@@ -16,7 +16,7 @@
 #ifndef _LVM_LOGGING_H
 #define _LVM_LOGGING_H
 
-void print_log(int level, const char *file, int line, int dm_errno,
+void print_log(int level, const char *file, int line, int dm_errno_or_class,
 	       const char *format, ...)
     __attribute__ ((format(printf, 5, 6)));
 
@@ -26,10 +26,13 @@ void print_log(int level, const char *file, int line, int dm_errno,
 #define LOG_LINE_WITH_ERRNO(l, e, x...) \
     print_log(l, __FILE__, __LINE__ , e, ## x)
 
+#define LOG_LINE_WITH_CLASS(l, c, x...) \
+    print_log(l, __FILE__, __LINE__ , c, ## x)
+
 #include "log.h"
 
 typedef void (*lvm2_log_fn_t) (int level, const char *file, int line,
-			       int dm_errno, const char *message);
+			       int dm_errno_or_class, const char *message);
 
 void init_log_fn(lvm2_log_fn_t log_fn);
 
diff --git a/lib/misc/lvm-globals.c b/lib/misc/lvm-globals.c
index fe38008..35d87ff 100644
--- a/lib/misc/lvm-globals.c
+++ b/lib/misc/lvm-globals.c
@@ -31,6 +31,7 @@ static int _full_scan_done = 0;	/* Restrict to one full scan during each cmd */
 static int _obtain_device_list_from_udev = DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV;
 static int _trust_cache = 0; /* Don't scan when incomplete VGs encountered */
 static int _debug_level = 0;
+static int _debug_classes_logged = DEFAULT_LOGGED_DEBUG_CLASSES;
 static int _log_cmd_name = 0;
 static int _ignorelockingfailure = 0;
 static int _security_level = SECURITY_LEVEL;
@@ -263,6 +264,20 @@ void init_debug(int level)
 	_debug_level = level;
 }
 
+void init_debug_classes_logged(int classes)
+{
+	_debug_classes_logged = classes;
+}
+
+int debug_class_is_logged(int class)
+{
+	/* If no class given, log it */
+	if (!class)
+		return 1;
+
+	return (_debug_classes_logged & class) ? 1 : 0;
+}
+
 int verbose_level(void)
 {
 	return _verbose_level;
diff --git a/lib/misc/lvm-globals.h b/lib/misc/lvm-globals.h
index 7fe3288..f590fd6 100644
--- a/lib/misc/lvm-globals.h
+++ b/lib/misc/lvm-globals.h
@@ -29,6 +29,7 @@ void init_full_scan_done(int level);
 void init_obtain_device_list_from_udev(int device_list_from_udev);
 void init_trust_cache(int trustcache);
 void init_debug(int level);
+void init_debug_classes_logged(int classes);
 void init_cmd_name(int status);
 void init_ignorelockingfailure(int level);
 void init_lockingfailed(int level);
@@ -58,6 +59,7 @@ int trust_cache(void);
 int verbose_level(void);
 int silent_mode(void);
 int debug_level(void);
+int debug_class_is_logged(int class);
 int ignorelockingfailure(void);
 int lockingfailed(void);
 int security_level(void);
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index c853ab4..3963022 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -49,10 +49,12 @@ extern "C" {
  * The library user may wish to register their own
  * logging function.  By default errors go to stderr.
  * Use dm_log_with_errno_init(NULL) to restore the default log fn.
+ * Error messages may have a non-zero errno.
+ * Debug messages may have a non-zero class.
  */
 
 typedef void (*dm_log_with_errno_fn) (int level, const char *file, int line,
-				      int dm_errno, const char *f, ...)
+				      int dm_errno_or_class, const char *f, ...)
     __attribute__ ((format(printf, 5, 6)));
 
 void dm_log_with_errno_init(dm_log_with_errno_fn fn);
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index 4a0ada8..3d95093 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -110,7 +110,7 @@ void dm_lib_init(void)
 __attribute__((format(printf, 5, 0)))
 static void _default_log_line(int level,
 	    const char *file __attribute__((unused)),
-	    int line __attribute__((unused)), int dm_errno, 
+	    int line __attribute__((unused)), int dm_errno_or_class, 
 	    const char *f, va_list ap)
 {
 	int use_stderr = level & _LOG_STDERR;
@@ -134,13 +134,13 @@ static void _default_log_line(int level,
 __attribute__((format(printf, 5, 6)))
 static void _default_log_with_errno(int level,
 	    const char *file __attribute__((unused)),
-	    int line __attribute__((unused)), int dm_errno, 
+	    int line __attribute__((unused)), int dm_errno_or_class, 
 	    const char *f, ...)
 {
 	va_list ap;
 
 	va_start(ap, f);
-	_default_log_line(level, file, line, dm_errno, f, ap);
+	_default_log_line(level, file, line, dm_errno_or_class, f, ap);
 	va_end(ap);
 }
 
diff --git a/libdm/misc/dm-logging.h b/libdm/misc/dm-logging.h
index 13ab804..ed3adfd 100644
--- a/libdm/misc/dm-logging.h
+++ b/libdm/misc/dm-logging.h
@@ -32,6 +32,9 @@ extern dm_log_with_errno_fn dm_log_with_errno;
 #define LOG_LINE(l, x...) LOG_MESG(l, __FILE__, __LINE__, 0, ## x)
 #define LOG_LINE_WITH_ERRNO(l, e, x...) LOG_MESG(l, __FILE__, __LINE__, e, ## x)
 
+/* Debug messages may have a type instead of an errno */
+#define LOG_LINE_WITH_CLASS(l, c, x...) LOG_MESG(l, __FILE__, __LINE__, c, ## x)
+
 #include "log.h"
 
 #endif


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