From 7d4a965aac1482411e7daabe2a646f97768fdc87 Mon Sep 17 00:00:00 2001
From: Heming Zhao <heming.zhao@suse.com>
Date: Fri, 8 Oct 2021 09:33:37 +0800
Subject: [PATCH 09/14] add new dlm_tool command reload_config

reload_config could help people to change dlm.conf settings on the fly.

Signed-off-by: Heming Zhao <heming.zhao@suse.com>
---
 dlm_controld/action.c        |   5 ++
 dlm_controld/config.c        | 119 +++++++++++++++++++++++++++++----
 dlm_controld/dlm_controld.h  |   1 +
 dlm_controld/dlm_daemon.h    |   4 ++
 dlm_controld/lib.c           |  19 ++++++
 dlm_controld/libdlmcontrol.h |   1 +
 dlm_controld/logging.c       |  18 +++--
 dlm_controld/main.c          | 126 ++++++++++++++++++++++-------------
 dlm_tool/main.c              |  21 +++++-
 9 files changed, 246 insertions(+), 68 deletions(-)

diff --git a/dlm_controld/action.c b/dlm_controld/action.c
index 0eff27997e1c..baddaf81cb4f 100644
--- a/dlm_controld/action.c
+++ b/dlm_controld/action.c
@@ -766,6 +766,11 @@ static int set_configfs_cluster(const char *name, char *str, int num)
 	return 0;
 }
 
+int set_configfs_opt(const char *name, char *str, int num)
+{
+	return set_configfs_cluster(name, str, num);
+}
+
 #define NET_RMEM_DEFAULT 4194304
 #define NET_RMEM_MAX 4194304
 
diff --git a/dlm_controld/config.c b/dlm_controld/config.c
index 947480dabe85..c60be8d47ef0 100644
--- a/dlm_controld/config.c
+++ b/dlm_controld/config.c
@@ -188,6 +188,55 @@ static void get_val_str(char *line, char *val_out)
 	strcpy(val_out, val);
 }
 
+inline static void reload_setting(int index)
+{
+	switch(index) {
+	case log_debug_ind:
+		set_configfs_opt("log_debug", NULL, opt(log_debug_ind));
+		break;
+	case debug_logfile_ind:
+		set_logfile_priority();
+		break;
+	default:
+		break;
+	}
+}
+
+static void reset_opt_value(int index)
+{
+	struct dlm_option *o = &dlm_options[index];
+
+	/* config priority: cli, config file, default */
+
+	if (o->cli_set) {
+		o->use_int = o->cli_int;
+		o->use_uint = o->cli_uint;
+		o->use_str = o->cli_str;
+
+	} else if (o->file_set) {
+		o->use_int = o->file_int;
+		o->use_uint = o->file_uint;
+		o->use_str = o->file_str;
+
+	} else {
+		o->use_int = o->default_int;
+		o->use_uint = o->default_uint;
+		o->use_str = (char *)o->default_str;
+	}
+
+	/*
+	 * We don't handle reset value same as legacy value.
+	 *
+	 * i.e.
+	 * 1. option abc default value is 0, while in dlm.conf abc=0.
+	 * 2. Then remove abc from dlm.conf.
+	 * 3. This function still call reload_setting(), and won't bypass this
+	 *    calling for no change.
+	 */
+	reload_setting(index);
+	return;
+}
+
 void set_opt_file(int update)
 {
 	unsigned int uval = 0;
@@ -195,7 +244,8 @@ void set_opt_file(int update)
 	FILE *file;
 	char line[MAX_LINE];
 	char str[MAX_LINE];
-	int i, val = 0;
+	int i, val = 0, ind;
+	char scanned_dlm_opt[dlm_options_max];
 
 	if (!path_exists(CONF_FILE_PATH))
 		return;
@@ -204,6 +254,12 @@ void set_opt_file(int update)
 	if (!file)
 		return;
 
+	/* In update mode, there is a little bit bother if one option ever set
+	 * but later be removed or commented out */
+	memset(scanned_dlm_opt, 0, sizeof(scanned_dlm_opt));
+	scanned_dlm_opt[help_ind] = 1;
+	scanned_dlm_opt[version_ind] = 1;
+
 	while (fgets(line, MAX_LINE, file)) {
 		if (line[0] == '#')
 			continue;
@@ -226,30 +282,31 @@ void set_opt_file(int update)
 			str[i] = line[i];
 		}
 
-		o = get_dlm_option(str);
+		ind = get_ind_name(str);
+		if (ind < 0)
+			continue;
+		o = &dlm_options[ind];
 		if (!o)
 			continue;
 
-		/* Doesn't make sense to set this in conf file. */
-		if (!strcmp(str, "daemon_debug"))
+		scanned_dlm_opt[ind] = 1;
+
+		/* In update flow, bypass the item which doesn't support reload. */
+		if (update && !o->reload)
 			continue;
 
 		o->file_set++;
 
 		if (!o->req_arg) {
-			/* ignore any = x */
-
-			o->file_int = 1;
-
-			if (!o->cli_set)
-				o->use_int = o->file_int;
-
-			log_debug("config file %s = %d cli_set %d use %d",
-				  o->name, o->file_int, o->cli_set, o->use_int);
+			/* current only "help" & "version" are no_arg type, ignore them */
+			continue;
 
 		} else if (o->req_arg == req_arg_int) {
 			get_val_int(line, &val);
 
+			if (update && (o->file_int == val))
+				continue;
+
 			o->file_int = val;
 
 			if (!o->cli_set)
@@ -261,6 +318,9 @@ void set_opt_file(int update)
 		} else if (o->req_arg == req_arg_uint) {
 			get_val_uint(line, &uval);
 
+			if (update && (o->file_uint == uval))
+				continue;
+
 			o->file_uint = uval;
 
 			if (!o->cli_set)
@@ -271,8 +331,12 @@ void set_opt_file(int update)
 
 		} else if (o->req_arg == req_arg_bool) {
 			get_val_int(line, &val);
+			val = val ? 1 : 0;
+
+			if (update && (o->file_int == val))
+				continue;
 
-			o->file_int = val ? 1 : 0;
+			o->file_int = val;
 
 			if (!o->cli_set)
 				o->use_int = o->file_int;
@@ -283,6 +347,11 @@ void set_opt_file(int update)
 			memset(str, 0, sizeof(str));
 			get_val_str(line, str);
 
+			if (update && !strcmp(o->file_str, str))
+				continue;
+
+			if (o->file_str)
+				free(o->file_str);
 			o->file_str = strdup(str);
 
 			if (!o->cli_set)
@@ -291,6 +360,28 @@ void set_opt_file(int update)
 			log_debug("config file %s = %s cli_set %d use %s",
 				  o->name, o->file_str, o->cli_set, o->use_str);
 		}
+
+		if (update)
+			reload_setting(ind);
+	}
+
+	if (update) {
+		/* handle commented out options  */
+		for (i=0; i<dlm_options_max; i++) {
+			if (scanned_dlm_opt[i])
+				continue;
+			if (!dlm_options[i].reload || !dlm_options[i].file_set)
+				continue;
+
+			dlm_options[i].file_set = 0;
+			dlm_options[i].file_int = 0;
+			dlm_options[i].file_uint = 0;
+			if(dlm_options[i].file_str) {
+				free(dlm_options[i].file_str);
+				dlm_options[i].file_str = NULL;
+			}
+			reset_opt_value(i);
+		}
 	}
 
 	fclose(file);
diff --git a/dlm_controld/dlm_controld.h b/dlm_controld/dlm_controld.h
index 649b2a5826f9..0ea3548fce7d 100644
--- a/dlm_controld/dlm_controld.h
+++ b/dlm_controld/dlm_controld.h
@@ -35,6 +35,7 @@
 #define DLMC_CMD_RUN_START		15
 #define DLMC_CMD_RUN_CHECK		16
 #define DLMC_CMD_DUMP_RUN		17
+#define DLMC_CMD_RELOAD_CONFIG	18
 
 struct dlmc_header {
 	unsigned int magic;
diff --git a/dlm_controld/dlm_daemon.h b/dlm_controld/dlm_daemon.h
index 436fc9109aa6..9e68f8257cb5 100644
--- a/dlm_controld/dlm_daemon.h
+++ b/dlm_controld/dlm_daemon.h
@@ -132,6 +132,7 @@ struct dlm_option {
 	const char *name;
 	char letter;
 	int req_arg;
+	char reload;
 	const char *desc;
 
 	int use_int;
@@ -383,6 +384,7 @@ int setup_configfs_members(void);
 int check_uncontrolled_lockspaces(void);
 int setup_misc_devices(void);
 int path_exists(const char *path);
+int set_configfs_opt(const char *name, char *str, int num);
 
 /* config.c */
 void set_opt_file(int update);
@@ -471,6 +473,7 @@ struct lockspace *find_ls_id(uint32_t id);
 const char *dlm_mode_str(int mode);
 void cluster_dead(int ci);
 struct dlm_option *get_dlm_option(char *name);
+int get_ind_name(char *s);
 struct run *find_run(char *uuid_str);
 void clear_run(struct run *run);
 void send_helper_run_request(struct run_request *req);
@@ -522,6 +525,7 @@ void init_logging(void);
 void close_logging(void);
 void copy_log_dump(char *buf, int *len);
 void copy_log_dump_plock(char *buf, int *len);
+void set_logfile_priority(void);
 
 /* crc.c */
 uint32_t cpgname_to_crc(const char *data, int len);
diff --git a/dlm_controld/lib.c b/dlm_controld/lib.c
index 53c11cf9f269..951eb6561ba9 100644
--- a/dlm_controld/lib.c
+++ b/dlm_controld/lib.c
@@ -174,6 +174,25 @@ int dlmc_dump_run(char *buf)
 	return do_dump(DLMC_CMD_DUMP_RUN, NULL, buf);
 }
 
+int dlmc_reload_config(void)
+{
+	struct dlmc_header h;
+	int fd, rv;
+
+	init_header(&h, DLMC_CMD_RELOAD_CONFIG, NULL, 0);
+
+	fd = do_connect(DLMC_SOCK_PATH);
+	if (fd < 0) {
+		rv = fd;
+		goto out;
+	}
+
+	rv = do_write(fd, &h, sizeof(h));
+	close(fd);
+ out:
+	return rv;
+}
+
 static int nodeid_compare(const void *va, const void *vb)
 {
 	const int *a = va;
diff --git a/dlm_controld/libdlmcontrol.h b/dlm_controld/libdlmcontrol.h
index ba603feeccf0..ac84e702fb58 100644
--- a/dlm_controld/libdlmcontrol.h
+++ b/dlm_controld/libdlmcontrol.h
@@ -91,6 +91,7 @@ int dlmc_lockspaces(int max, int *count, struct dlmc_lockspace *lss);
 int dlmc_lockspace_nodes(char *lsname, int type, int max, int *count,
 			 struct dlmc_node *nodes);
 int dlmc_print_status(uint32_t flags);
+int dlmc_reload_config(void);
 
 #define DLMC_RESULT_REGISTER	1
 #define DLMC_RESULT_NOTIFIED	2
diff --git a/dlm_controld/logging.c b/dlm_controld/logging.c
index d48b8aebc237..2c57138ce766 100644
--- a/dlm_controld/logging.c
+++ b/dlm_controld/logging.c
@@ -14,6 +14,18 @@ static int logfile_priority;
 static char logfile[PATH_MAX];
 static FILE *logfile_fp;
 
+/* logfile_priority is the only one of these options that
+   can be controlled from command line, environment variable
+   and dynamic setting.
+ */
+void set_logfile_priority(void)
+{
+	if (opt(debug_logfile_ind))
+		logfile_priority = LOG_DEBUG;
+	else
+		logfile_priority = DEFAULT_LOGFILE_PRIORITY;
+}
+
 void init_logging(void)
 {
 	mode_t old_umask;
@@ -24,11 +36,7 @@ void init_logging(void)
 	logfile_priority = DEFAULT_LOGFILE_PRIORITY;
 	strcpy(logfile, DEFAULT_LOGFILE);
 
-	/* logfile_priority is the only one of these options that
-	   can be controlled from command line or environment variable */
-
-	if (opt(debug_logfile_ind))
-		logfile_priority = LOG_DEBUG;
+	set_logfile_priority();
 
 	if (logfile[0]) {
 		old_umask = umask(0077);
diff --git a/dlm_controld/main.c b/dlm_controld/main.c
index 504cafa12ec6..8104d8f906ac 100644
--- a/dlm_controld/main.c
+++ b/dlm_controld/main.c
@@ -1230,6 +1230,10 @@ static void process_connection(int ci)
 		client_dead(ci);
 		break;
 #endif
+	case DLMC_CMD_RELOAD_CONFIG:
+		set_opt_file(1);
+		break;
+
 	default:
 		log_error("process_connection %d unknown command %d",
 			  ci, h.command);
@@ -1749,12 +1753,13 @@ static void print_usage(void)
 
 static void set_opt_default(int ind, const char *name, char letter, int arg_type,
 			    int default_int, const char *default_str,
-			    unsigned int default_uint, const char *desc)
+			    unsigned int default_uint, char reload, const char *desc)
 {
 	dlm_options[ind].name = name;
 	dlm_options[ind].letter = letter;
 	dlm_options[ind].req_arg = arg_type;
 	dlm_options[ind].desc = desc;
+	dlm_options[ind].reload = reload;
 	dlm_options[ind].default_int = default_int;
 	dlm_options[ind].default_str = default_str;
 	dlm_options[ind].default_uint = default_uint;
@@ -1766,142 +1771,142 @@ static void set_opt_default(int ind, const char *name, char letter, int arg_type
 static void set_opt_defaults(void)
 {
 	set_opt_default(daemon_debug_ind,
-			"daemon_debug", 'D', no_arg,
-			0, NULL, 0,
+			"daemon_debug", 'D', req_arg_bool,
+			0, NULL, 0, 1,
 			"enable debugging to stderr and don't fork");
 
 	set_opt_default(foreground_ind,
-			"foreground", '\0', no_arg,
-			0, NULL, 0,
+			"foreground", '\0', req_arg_bool,
+			0, NULL, 0, 0,
 			"don't fork");
 
 	set_opt_default(log_debug_ind,
-			"log_debug", 'K', no_arg,
-			0, NULL, 0,
+			"log_debug", 'K', req_arg_bool,
+			0, NULL, 0, 1,
 			"enable kernel dlm debugging messages");
 
 	set_opt_default(timewarn_ind,
 			"timewarn", '\0', req_arg_int,
-			0, NULL, 0,
+			0, NULL, 0, 0,
 			""); /* do not advertise */
 
 	set_opt_default(protocol_ind,
 			"protocol", 'r', req_arg_str,
-			-1, "detect", 0,
+			-1, "detect", 0, 0,
 			"dlm kernel lowcomms protocol: tcp, sctp, detect");
 
 	set_opt_default(port_ind,
 			"port", 'R', req_arg_uint,
-			-1, NULL, 21064,
+			-1, NULL, 21064, 0,
 			"dlm kernel lowcomms protocol port");
 
 	set_opt_default(bind_all_ind,
 			"bind_all", '\0', req_arg_int,
-			0, NULL, 0,
+			0, NULL, 0, 0,
 			""); /* do not advertise */
 
 	set_opt_default(mark_ind,
 			"mark", '\0', req_arg_uint,
-			0, NULL, 0,
+			0, NULL, 0, 0,
 			"set mark value for DLM if not explicit by nodeid specified");
 
 	set_opt_default(debug_logfile_ind,
-			"debug_logfile", 'L', no_arg,
-			0, NULL, 0,
+			"debug_logfile", 'L', req_arg_bool,
+			0, NULL, 0, 1,
 			"write debugging to log file");
 
 	set_opt_default(enable_fscontrol_ind,
 			"enable_fscontrol", '\0', req_arg_bool,
-			0, NULL, 0,
+			0, NULL, 0, 0,
 			""); /* do not advertise */
 
 	set_opt_default(enable_plock_ind,
 			"enable_plock", 'p', req_arg_bool,
-			1, NULL, 0,
+			1, NULL, 0, 0,
 			"enable/disable posix lock support for cluster fs");
 
 	set_opt_default(plock_debug_ind,
-			"plock_debug", 'P', no_arg,
-			0, NULL, 0,
+			"plock_debug", 'P', req_arg_bool,
+			0, NULL, 0, 1,
 			"enable plock debugging");
 
 	set_opt_default(plock_rate_limit_ind,
 			"plock_rate_limit", 'l', req_arg_int,
-			0, NULL, 0,
+			0, NULL, 0, 1,
 			"limit rate of plock operations (0 for none)");
 
 	set_opt_default(plock_ownership_ind,
 			"plock_ownership", 'o', req_arg_bool,
-			0, NULL, 0,
+			0, NULL, 0, 0,
 			"enable/disable plock ownership");
 
 	set_opt_default(drop_resources_time_ind,
 			"drop_resources_time", 't', req_arg_int,
-			10000, NULL, 0,
+			10000, NULL, 0, 1,
 			"plock ownership drop resources time (milliseconds)");
 
 	set_opt_default(drop_resources_count_ind,
 			"drop_resources_count", 'c', req_arg_int,
-			10, NULL, 0,
+			10, NULL, 0, 1,
 			"plock ownership drop resources count");
 
 	set_opt_default(drop_resources_age_ind,
 			"drop_resources_age", 'a', req_arg_int,
-			10000, NULL, 0,
+			10000, NULL, 0, 1,
 			"plock ownership drop resources age (milliseconds)");
 
 	set_opt_default(post_join_delay_ind,
 			"post_join_delay", 'j', req_arg_int,
-			30, NULL, 0,
+			30, NULL, 0, 1,
 			"seconds to delay fencing after cluster join");
 
 	set_opt_default(enable_fencing_ind,
 			"enable_fencing", 'f', req_arg_bool,
-			1, NULL, 0,
+			1, NULL, 0, 0,
 			"enable/disable fencing");
 
 	set_opt_default(enable_concurrent_fencing_ind,
 			"enable_concurrent_fencing", '\0', req_arg_bool,
-			0, NULL, 0,
+			0, NULL, 0, 0,
 			"enable/disable concurrent fencing");
 
 	set_opt_default(enable_startup_fencing_ind,
 			"enable_startup_fencing", 's', req_arg_bool,
-			1, NULL, 0,
+			1, NULL, 0, 0,
 			"enable/disable startup fencing");
 
 	set_opt_default(repeat_failed_fencing_ind,
 			"repeat_failed_fencing", '\0', req_arg_bool,
-			1, NULL, 0,
+			1, NULL, 0, 1,
 			"enable/disable retrying after fencing fails");
 
 	set_opt_default(enable_quorum_fencing_ind,
 			"enable_quorum_fencing", 'q', req_arg_bool,
-			1, NULL, 0,
+			1, NULL, 0, 1,
 			"enable/disable quorum requirement for fencing");
 
 	set_opt_default(enable_quorum_lockspace_ind,
 			"enable_quorum_lockspace", '\0', req_arg_bool,
-			1, NULL, 0,
+			1, NULL, 0, 1,
 			"enable/disable quorum requirement for lockspace operations");
 
 	set_opt_default(enable_helper_ind,
 			"enable_helper", '\0', req_arg_bool,
-			1, NULL, 0,
+			1, NULL, 0, 0,
 			"enable/disable helper process for running commands");
 
 	set_opt_default(help_ind,
 			"help", 'h', no_arg,
-			-1, NULL, 0,
+			-1, NULL, 0, 0,
 			"print this help, then exit");
 
 	set_opt_default(version_ind,
 			"version", 'V', no_arg,
-			-1, NULL, 0,
+			-1, NULL, 0, 0,
 			"Print program version information, then exit");
 }
 
-static int get_ind_name(char *s)
+int get_ind_name(char *s)
 {
 	char name[PATH_MAX];
 	char *p = s;
@@ -1948,11 +1953,12 @@ struct dlm_option *get_dlm_option(char *name)
 static void set_opt_cli(int argc, char **argv)
 {
 	struct dlm_option *o;
-	char *arg1, *p, *arg_str;
+	char *arg1, *p, *arg_str, *endptr;
+	char bool_str[] = "1";
 	char bundled_letters[8];
 	int b, blc = 0, blc_max = 8;
 	int debug_options = 0;
-	int i, ind;
+	int i, ind, bundled;
 
 	if (argc < 2)
 		return;
@@ -1996,20 +2002,26 @@ static void set_opt_cli(int argc, char **argv)
 		o = &dlm_options[ind];
 		o->cli_set++;
 
-		if (!o->req_arg) {
-			/* "-x" has same effect as "-x 1" */
-			o->cli_int = 1;
-			o->use_int = 1;
+		if (!o->req_arg || (o->req_arg == req_arg_bool)) {
+			bundled = 0;
 
-			/* save bundled, arg-less, single letters, e.g. -DKP */
+			/* current for no_arg type, there is not possible to have bundled options.
+			 * for req_arg_bool, bundled options, e.g. -DKP. all treat as "true".
+			 * below code save bundled, arg-less, single letters */
 			if ((p[0] == '-') && isalpha(p[1]) && (strlen(p) > 2)) {
 				for (b = 2; b < strlen(p) && blc < blc_max; b++) {
 					if (!isalpha(p[b]))
 						break;
 					bundled_letters[blc++] = p[b];
+					bundled = 1;
 				}
 			}
-			continue;
+			if (bundled) {
+				/* "-x" has same effect as "-x 1" */
+				o->cli_int = 1;
+				o->use_int = 1;
+				continue;
+			}
 		}
 
 		arg_str = NULL;
@@ -2024,17 +2036,31 @@ static void set_opt_cli(int argc, char **argv)
 
 		} else {
 			/* space separates arg from name or letter */
-			if (i >= argc) {
-				fprintf(stderr, "option %s no arg", p);
-				exit(EXIT_FAILURE);
+			if (o->req_arg == req_arg_bool) {
+				/* bool type treat empty arg as true */
+				if (i >= argc || argv[i][0] == '-')
+					arg_str = bool_str;
+				else
+					arg_str = argv[i++];
+			} else {
+				if (i >= argc) {
+					fprintf(stderr, "option %s no arg\n", p);
+					exit(EXIT_FAILURE);
+				}
+				arg_str = argv[i++];
 			}
-			arg_str = argv[i++];
 		}
 
 		if (!arg_str || arg_str[0] == '-' || arg_str[0] == '\0') {
-			fprintf(stderr, "option %s requires arg", p);
+			fprintf(stderr, "option %s requires arg\n", p);
 			exit(EXIT_FAILURE);
 		}
+		if ((o->req_arg != req_arg_str) && !strtol(arg_str, &endptr, 10)) {
+			if (endptr == arg_str) {
+				fprintf(stderr, "option %s requires digit number\n", p);
+				exit(EXIT_FAILURE);
+			}
+		}
 
 		if (o->req_arg == req_arg_str) {
 			o->cli_str = strdup(arg_str);
@@ -2059,6 +2085,7 @@ static void set_opt_cli(int argc, char **argv)
 			fprintf(stderr, "unknown option char %c\n", bundled_letters[i]);
 			exit(EXIT_FAILURE);
 		}
+		/* bundled letter must be bool type, treat it with "true" value */
 		o = &dlm_options[ind];
 		o->cli_set++;
 		o->cli_int = 1;
@@ -2109,8 +2136,11 @@ int main(int argc, char **argv)
 	 * - explicit cli setting will override default,
 	 * - explicit file setting will override default
 	 * - explicit file setting will not override explicit cli setting
+	 *
+	 * "dlm reload_config" will trigger to reload config file, and
+	 * reload action also follows the rule: not override explicit
+	 * cli setting
 	 */
-
 	set_opt_defaults();
 	set_opt_cli(argc, argv);
 	set_opt_file(0);
diff --git a/dlm_tool/main.c b/dlm_tool/main.c
index 53d9336d59c6..774835192bbf 100644
--- a/dlm_tool/main.c
+++ b/dlm_tool/main.c
@@ -47,6 +47,7 @@
 #define OP_RUN_CANCEL			17
 #define OP_RUN_LIST			18
 #define OP_DUMP_RUN			19
+#define OP_RELOAD_CONFIG	20
 
 static char *prog_name;
 static char *lsname;
@@ -196,7 +197,7 @@ static void print_usage(void)
 	printf("dlm_tool [command] [options] [name]\n");
 	printf("\n");
 	printf("Commands:\n");
-	printf("ls, status, dump, dump_config, fence_ack\n");
+	printf("ls, status, dump, dump_config, reload_config, fence_ack\n");
 	printf("log_plock, plocks\n");
 	printf("join, leave, lockdebug\n");
 	printf("run, run_start, run_check, run_cancel, run_list\n");
@@ -363,6 +364,12 @@ static void decode_arguments(int argc, char **argv)
 			opt_ind = optind + 1;
 			need_lsname = 0;
 			break;
+		} else if (!strncmp(argv[optind], "reload_config", 13) &&
+			   (strlen(argv[optind]) == 13)) {
+			operation = OP_RELOAD_CONFIG;
+			opt_ind = optind + 1;
+			need_lsname = 0;
+			break;
 		} else if (!strncmp(argv[optind], "plocks", 6) &&
 			   (strlen(argv[optind]) == 6)) {
 			operation = OP_PLOCKS;
@@ -1472,6 +1479,14 @@ static void do_dump(int op)
 	printf("\n");
 }
 
+static void do_reload_config(void)
+{
+	if (dlmc_reload_config() < 0)
+		printf("reload_config failed\n");
+	else
+		printf("reload_config done\n");
+}
+
 static void do_log_plock(void)
 {
 	char buf[DLMC_DUMP_SIZE];
@@ -1570,6 +1585,10 @@ int main(int argc, char **argv)
 		do_dump(operation);
 		break;
 
+	case OP_RELOAD_CONFIG:
+		do_reload_config();
+		break;
+
 	case OP_LOG_PLOCK:
 		do_log_plock();
 		break;
-- 
2.33.0

