File bug-1191734_0009-add-new-dlm_tool-command-reload_config.patch of Package libdlm
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