From c27b54c522543bc44030a0c1ecd414dc2523d331 Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Tue, 19 Mar 2019 16:43:16 +0800
Subject: [PATCH] add dfx log when error occur, or lvm resource change, it will
 print the cmdline and ppid

Signed-off-by: wangjufeng<wangjufeng@huawei.com>
---
 conf/example.conf.in         |  5 +++++
 lib/commands/toolcontext.c   | 16 ++++++++++++++++
 lib/commands/toolcontext.h   |  4 ++++
 lib/config/config_settings.h |  5 +++++
 lib/log/log.c                | 21 +++++++++++++++++++--
 lib/log/log.h                |  4 +++-
 lib/misc/lvm-globals.c       | 11 +++++++++++
 lib/misc/lvm-globals.h       |  2 ++
 tools/lvmcmdline.c           |  1 +
 9 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/conf/example.conf.in b/conf/example.conf.in
index a60b595..09200ab 100644
--- a/conf/example.conf.in
+++ b/conf/example.conf.in
@@ -862,6 +862,11 @@ log {
 	# This configuration option has an automatic default value.
 	level = 3
 
+        #When the level of log messages is set as 2 or 3, set log_unless_silent
+        #to 1, it will also log some important warning level messages, such as,
+        #create/delete/change a lv/vg/pv, 0 is close this option.
+        log_unless_silent = 1
+ 
 	# Configuration option log/indent.
 	# Indent messages according to their severity.
 	# This configuration option has an automatic default value.
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 105aecd..2a9618a 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -51,6 +51,8 @@
 
 static const size_t _linebuffer_size = 4096;
 
+char *global_cmdline = NULL;
+
 /*
  * Copy the input string, removing invalid characters.
  */
@@ -397,6 +399,9 @@ static void _init_logging(struct cmd_context *cmd)
 	    find_config_tree_bool(cmd, log_silent_CFG, NULL);
 	init_silent(cmd->default_settings.silent);
 
+        cmd->default_settings.log_unless_silent = find_config_tree_bool(cmd, log_unless_silent_CFG, NULL);
+        init_log_unless_silent(cmd->default_settings.log_unless_silent);
+
 	/* Verbose level for tty output */
 	cmd->default_settings.verbose = find_config_tree_int(cmd, log_verbose_CFG, NULL);
 	init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
@@ -2045,6 +2050,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
 	_destroy_segtypes(&cmd->segtypes);
 	_destroy_formats(cmd, &cmd->formats);
 	_destroy_filters(cmd);
+	set_global_cmdline(NULL);
 	if (cmd->mem)
 		dm_pool_destroy(cmd->mem);
 	devices_file_exit(cmd);
@@ -2098,3 +2104,13 @@ void destroy_toolcontext(struct cmd_context *cmd)
 	fin_syslog();
 	reset_lvm_errno(0);
 }
+
+char *get_global_cmdline()
+{
+    return global_cmdline;
+}
+
+void set_global_cmdline(char *cmdline)
+{
+    global_cmdline = cmdline;
+}
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index 701b7a7..957ab7f 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -50,6 +50,7 @@ struct config_info {
 	mode_t umask;
 	char unit_type;
 	char _padding[1];
+	int log_unless_silent;
 };
 
 struct dm_config_tree;
@@ -299,4 +300,7 @@ struct format_type *get_format_by_name(struct cmd_context *cmd, const char *form
 
 const char *system_id_from_string(struct cmd_context *cmd, const char *str);
 
+char *get_global_cmdline();
+
+void set_global_cmdline(char *cmdline);
 #endif
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index ab7d0d5..a83c034 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -887,6 +887,11 @@ cfg(log_level_CFG, "level", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT
 	"There are 6 syslog-like log levels currently in use: 2 to 7 inclusive.\n"
 	"7 is the most verbose (LOG_DEBUG).\n")
 
+cfg(log_unless_silent_CFG, "log_unless_silent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 178), NULL, 0, NULL,
+        "When the level of log messages is set as 2 or 3, set log_unless_silent\n"
+        "to 1, it will also log some important warning level messages, such as,\n"
+        "create/delete/change a lv/vg/pv, 0 is close this option.\n")
+
 cfg(log_indent_CFG, "indent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_INDENT, vsn(1, 0, 0), NULL, 0, NULL,
 	"Indent messages according to their severity.\n")
 
diff --git a/lib/log/log.c b/lib/log/log.c
index 7b4d537..e8a16e0 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -19,6 +19,7 @@
 #include "lib/config/defaults.h"
 #include "lib/report/report.h"
 #include "lib/misc/lvm-file.h"
+#include "lib/commands/toolcontext.h"
 
 #include <stdio.h>
 #include <stdarg.h>
@@ -509,6 +510,7 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
 	const char *trformat;		/* Translated format string */
 	char *newbuf;
 	int use_stderr = log_stderr(level);
+	int force_syslog = (level & _LOG_IMPORTANT_TO_SYSLOG) ? 1 : 0;
 	int log_once = log_once(level);
 	int log_bypass_report = log_bypass_report(level);
 	int fatal_internal_error = 0;
@@ -521,7 +523,9 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
 	struct dm_report *orig_report;
 	int logged_via_report = 0;
 
+	static int printcmdline = 1;
 	level = log_level(level);
+	force_syslog = (level!=0 && get_log_unless_silent()) ? force_syslog : 0;
 
 	if (_abort_on_internal_errors_env_present < 0) {
 		if ((env_str = getenv("DM_ABORT_ON_INTERNAL_ERRORS"))) {
@@ -714,8 +718,8 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
 		va_end(ap);
 	}
 
-	if ((level > debug_level()) ||
-	    (level >= _LOG_DEBUG && !debug_class_is_logged(dm_errno_or_class))) {
+	if (!force_syslog && ((level > debug_level()) ||
+	    (level >= _LOG_DEBUG && !debug_class_is_logged(dm_errno_or_class)))) {
 		if (fatal_internal_error)
 			abort();
 		return;
@@ -758,6 +762,19 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
 
 	if (_syslog && (_log_while_suspended || !critical_section())) {
 		va_copy(ap, orig_ap);
+
+                if (level <= _LOG_WARN && printcmdline) {
+                    char *cmdline = get_global_cmdline();
+                    if (cmdline) {
+                        printcmdline = 0;
+                        char msg_addcmd[4096] = {0};
+
+                        snprintf(msg_addcmd, sizeof(msg_addcmd),
+                                 "ppid=%lu, cmdline:%s", getppid(), cmdline);
+                        syslog(level, "%s", msg_addcmd);
+                    }
+                }
+
 		vsyslog(level, trformat, ap);
 		va_end(ap);
 	}
diff --git a/lib/log/log.h b/lib/log/log.h
index b5f05f2..fc5d589 100644
--- a/lib/log/log.h
+++ b/lib/log/log.h
@@ -50,6 +50,8 @@
 #define _LOG_STDERR        0x0080 /* force things to go to stderr, even if loglevel would make them go to stdout */
 #define _LOG_ONCE          0x0100 /* downgrade to NOTICE if this has been already logged */
 #define _LOG_BYPASS_REPORT 0x0200 /* do not log through report even if report available */
+#define _LOG_IMPORTANT_TO_SYSLOG     0x10000 /*log to syslog even if loglevel number is bigger than _debug_level configuration,
+                                               unless _debug_level is 0*/
 #define log_level(x)  ((x) & 0x0f)			/* obtain message level */
 #define log_stderr(x)  ((x) & _LOG_STDERR)		/* obtain stderr bit */
 #define log_once(x)  ((x) & _LOG_ONCE)			/* obtain once bit */
@@ -111,7 +113,7 @@
 #define log_very_verbose(args...) log_info(args)
 #define log_verbose(args...) log_notice(args)
 #define log_print(args...) LOG_LINE(_LOG_WARN, args)
-#define log_print_unless_silent(args...) LOG_LINE(silent_mode() ? _LOG_NOTICE : _LOG_WARN, args)
+#define log_print_unless_silent(args...) LOG_LINE(silent_mode() ? _LOG_NOTICE : _LOG_WARN | _LOG_IMPORTANT_TO_SYSLOG, args)
 #define log_error(args...) log_err(args)
 #define log_error_suppress(s, args...) log_err_suppress(s, args)
 #define log_error_once(args...) log_err_once(args)
diff --git a/lib/misc/lvm-globals.c b/lib/misc/lvm-globals.c
index 06855ff..37d2fae 100644
--- a/lib/misc/lvm-globals.c
+++ b/lib/misc/lvm-globals.c
@@ -54,12 +54,23 @@ static char _sysfs_dir_path[PATH_MAX] = "";
 static uint64_t _pv_min_size = (DEFAULT_PV_MIN_SIZE_KB * 1024L >> SECTOR_SHIFT);
 static const char *_unknown_device_name = DEFAULT_UNKNOWN_DEVICE_NAME;
 static int _io_memory_size_kb = DEFAULT_IO_MEMORY_SIZE_KB;
+static int _log_unless_silent = 1;
 
 void init_verbose(int level)
 {
 	_verbose_level = level;
 }
 
+void init_log_unless_silent(int unless_silent)
+{
+	_log_unless_silent = unless_silent;
+}
+
+int get_log_unless_silent(void)
+{
+	return _log_unless_silent;
+}
+
 void init_silent(int silent)
 {
 	_silent = silent;
diff --git a/lib/misc/lvm-globals.h b/lib/misc/lvm-globals.h
index a54001c..8ae55f6 100644
--- a/lib/misc/lvm-globals.h
+++ b/lib/misc/lvm-globals.h
@@ -89,4 +89,6 @@ int io_memory_size(void);
 #define DMEVENTD_MONITOR_IGNORE -1
 int dmeventd_monitor_mode(void);
 
+void init_log_unless_silent(int unless_silent);
+int get_log_unless_silent(void);
 #endif
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 1e12bed..ee9288b 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -3116,6 +3116,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
 	/* The cmd_line string is only used for logging, not processing. */
 	if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv)))
 		return_ECMD_FAILED;
+	set_global_cmdline(cmd->cmd_line);
 
 	/* Look up command - will be NULL if not recognised */
 	if (!(cmd->cname = find_command_name(cmd->name)))
-- 
1.8.3.1

