dlm: master - dlm_controld: new config handling

David Teigland teigland at fedoraproject.org
Thu Apr 5 18:51:03 UTC 2012


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=ff1f5c78203613a8e28be6d7de1d558d598f8ca9
Commit:        ff1f5c78203613a8e28be6d7de1d558d598f8ca9
Parent:        b8d1a03c2d23a42761216ac33dae6e42f87ec782
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Thu Apr 5 13:47:23 2012 -0500
Committer:     David Teigland <teigland at redhat.com>
CommitterDate: Thu Apr 5 13:47:23 2012 -0500

dlm_controld: new config handling

to handle both command line and config file options.

Signed-off-by: David Teigland <teigland at redhat.com>
---
 dlm_controld/action.c        |   45 ++--
 dlm_controld/config.c        |  127 ++++++-----
 dlm_controld/cpg.c           |   54 +++---
 dlm_controld/daemon_cpg.c    |   28 ++-
 dlm_controld/dlm_controld.h  |    1 +
 dlm_controld/dlm_daemon.h    |  119 +++++-----
 dlm_controld/lib.c           |    5 +
 dlm_controld/libdlmcontrol.h |    1 +
 dlm_controld/logging.c       |    6 +-
 dlm_controld/main.c          |  525 +++++++++++++++++++++++++++++------------
 dlm_controld/member.c        |    2 +-
 dlm_controld/plock.c         |   42 ++--
 dlm_tool/main.c              |   22 ++-
 13 files changed, 615 insertions(+), 362 deletions(-)

diff --git a/dlm_controld/action.c b/dlm_controld/action.c
index 6cb34f2..8ac05b6 100644
--- a/dlm_controld/action.c
+++ b/dlm_controld/action.c
@@ -50,9 +50,6 @@ static int detect_protocol(void)
 	return proto;
 }
 
-/* TODO: getting cluster_name will almost certainly change to either
-   a corosync lib api, or some cmap path other than cluster.name */
-
 static int detect_cluster_name(void)
 {
 	cmap_handle_t handle;
@@ -799,7 +796,8 @@ void clear_configfs(void)
 
 int setup_configfs_options(void)
 {
-	int rv;
+	char *proto_name;
+	int rv, proto_num;
 
 	clear_configfs();
 
@@ -808,24 +806,33 @@ int setup_configfs_options(void)
 		return rv;
 
 	/* the kernel has its own defaults for these values which we
-	   don't want to change unless these have been set; -1 means
-	   they have not been set on command line or config file */
+	   don't want to change unless these have been set explicitly
+	   on cli or config file */
 
-	if (cfgk_debug != -1)
-		set_configfs_cluster("log_debug", NULL, cfgk_debug);
-	if (cfgk_timewarn != -1)
-		set_configfs_cluster("timewarn_cs", NULL, cfgk_timewarn);
+	if (dlm_options[log_debug_ind].cli_set ||
+	    dlm_options[log_debug_ind].file_set)
+		set_configfs_cluster("log_debug", NULL, opt(log_debug_ind));
 
-	if (cfgk_protocol == PROTO_DETECT) {
-		rv = detect_protocol();
-		if (rv == PROTO_TCP || rv == PROTO_SCTP)
-			cfgk_protocol = rv;
-	}
+	if (dlm_options[timewarn_ind].cli_set ||
+	    dlm_options[timewarn_ind].file_set)
+		set_configfs_cluster("timewarn_cs", NULL, opt(timewarn_ind));
+
+	proto_name = opts(protocol_ind);
+	proto_num = -1;
+
+	if (!strcasecmp(proto_name, "detect") || !strcmp(proto_name, "2"))
+		proto_num = detect_protocol(); /* may be -1 */
+
+	else if (!strcasecmp(proto_name, "tcp") || !strcmp(proto_name, "0"))
+		proto_num = PROTO_TCP;
+
+	else if (!strcasecmp(proto_name, "sctp") || !strcmp(proto_name, "1"))
+		proto_num = PROTO_SCTP;
 
-	if (cfgk_protocol == PROTO_TCP || cfgk_protocol == PROTO_SCTP)
-		set_configfs_cluster("protocol", NULL, cfgk_protocol);
+	if (proto_num == PROTO_TCP || proto_num == PROTO_SCTP)
+		set_configfs_cluster("protocol", NULL, proto_num);
 
-	if (cfgk_protocol == PROTO_SCTP)
+	if (proto_num == PROTO_SCTP)
 		set_proc_rmem();
 
 	/* 
@@ -838,7 +845,7 @@ int setup_configfs_options(void)
 	 * go ahead without the monitor being open
 	 */
 
-	if (cfgd_enable_fscontrol) {
+	if (opt(enable_fscontrol_ind)) {
 		/* deprecated */
 		set_configfs_cluster("recover_callbacks", NULL, 0);
 	} else {
diff --git a/dlm_controld/config.c b/dlm_controld/config.c
index 040784b..1efea45 100644
--- a/dlm_controld/config.c
+++ b/dlm_controld/config.c
@@ -8,14 +8,18 @@
 
 #include "dlm_daemon.h"
 
-/* TODO:
- <dlm>
- <lockspace name="foo" nodir="1">
-   <master nodeid="1" weight="2"/>
-   <master nodeid="2" weight="3"/>
- </lockspace>
- </dlm>
-*/
+/*
+ * TODO: lockspace master/nodir/weight
+ *
+ * lockspace foo nodir=1
+ * master foo nodeid=1 weight=1
+ * master foo nodeid=2 weight=1
+ * master foo nodeid=3 weight=1
+ *
+ * lockspace bar nodir=1
+ * master bar nodeid=4 weight=2
+ * master bar nodeid=5 weight=1
+ */
 
 int get_weight(int nodeid, char *lockspace)
 {
@@ -23,20 +27,7 @@ int get_weight(int nodeid, char *lockspace)
 	return 1;
 }
 
-static void proto_val(char *str, int *val)
-{
-	if (!strncasecmp(str, "tcp", 3))
-		*val = PROTO_TCP;
-	else if (!strncasecmp(str, "sctp", 4))
-		*val = PROTO_SCTP;
-	else if (!strncasecmp(str, "detect", 6))
-		*val = PROTO_DETECT;
-	else {
-		log_error("invalid protocol value %s", str);
-	}
-}
-
-static void set_val(char *line, int *val_out)
+static void get_val_int(char *line, int *val_out)
 {
 	char key[PATH_MAX];
 	char val[PATH_MAX];
@@ -47,11 +38,9 @@ static void set_val(char *line, int *val_out)
 		return;
 
 	*val_out = atoi(val);
-
-	log_debug("config %s=%d", key, *val_out);
 }
 
-static void get_val(char *line, char *val_out)
+static void get_val_str(char *line, char *val_out)
 {
 	char key[PATH_MAX];
 	char val[PATH_MAX];
@@ -66,9 +55,11 @@ static void get_val(char *line, char *val_out)
 
 void setup_config(int update)
 {
+	struct dlm_option *o;
 	FILE *file;
 	char line[PATH_MAX];
 	char str[PATH_MAX];
+	int i, val;
 
 	if (!path_exists(CONF_FILE_PATH))
 		return;
@@ -83,59 +74,71 @@ void setup_config(int update)
 		if (line[0] == '\n')
 			continue;
 
-		if (!optk_debug && !strncmp(line, "log_debug", strlen("log_debug")))
-			set_val(line, &cfgk_debug);
+		memset(str, 0, sizeof(str));
+
+		for (i = 0; i < PATH_MAX; i++) {
+			if (line[i] == ' ')
+				break;
+			if (line[i] == '=')
+				break;
+			if (line[i] == '\0')
+				break;
+			if (line[i] == '\n')
+				break;
+			if (line[i] == '\t')
+				break;
+			str[i] = line[i];
+		}
 
-		else if (!optk_timewarn && !strncmp(line, "timewarn", strlen("timewarn")) && !update)
-			set_val(line, &cfgk_timewarn);
+		o = get_dlm_option(str);
+		if (!o)
+			continue;
 
-		else if (!optd_post_join_delay && !strncmp(line, "post_join_delay", strlen("post_join_delay")))
-			set_val(line, &cfgd_post_join_delay);
+		o->file_set++;
 
-		else if (!optd_enable_fencing && !strncmp(line, "enable_fencing", strlen("enable_fencing")) && !update)
-			set_val(line, &cfgd_enable_fencing);
+		if (!o->req_arg) {
+			/* ignore any = x */
 
-		else if (!optd_enable_startup_fencing && !strncmp(line, "enable_startup_fencing", strlen("enable_startup_fencing")) && !update)
-			set_val(line, &cfgd_enable_startup_fencing);
+			o->file_int = 1;
 
-		else if (!optd_enable_concurrent_fencing && !strncmp(line, "enable_concurrent_fencing", strlen("enable_concurrent_fencing")) && !update)
-			set_val(line, &cfgd_enable_concurrent_fencing);
+			if (!o->cli_set)
+				o->use_int = o->file_int;
 
-		else if (!optd_enable_quorum_fencing && !strncmp(line, "enable_quorum_fencing", strlen("enable_quorum_fencing")) && !update)
-			set_val(line, &cfgd_enable_quorum_fencing);
+			log_debug("config file %s = %d cli_set %d use %d",
+				  o->name, o->file_int, o->cli_set, o->use_int);
 
-		else if (!optd_enable_quorum_lockspace && !strncmp(line, "enable_quorum_lockspace", strlen("enable_quorum_lockspace")) && !update)
-			set_val(line, &cfgd_enable_quorum_lockspace);
+		} else if (o->req_arg == req_arg_int) {
+			get_val_int(line, &val);
 
-		else if (!optd_enable_fscontrol && !strncmp(line, "enable_fscontrol", strlen("enable_fscontrol")) && !update)
-			set_val(line, &cfgd_enable_fscontrol);
+			o->file_int = val;
 
-		else if (!optd_enable_plock && !strncmp(line, "enable_plock", strlen("enable_plock")) && !update)
-			set_val(line, &cfgd_enable_plock);
+			if (!o->cli_set)
+				o->use_int = o->file_int;
 
-		else if (!optd_plock_ownership && !strncmp(line, "plock_ownership", strlen("plock_ownership")) && !update)
-			set_val(line, &cfgd_plock_ownership);
+			log_debug("config file %s = %d cli_set %d use %d",
+				  o->name, o->file_int, o->cli_set, o->use_int);
 
-		else if (!optd_plock_debug && !strncmp(line, "plock_debug", strlen("plock_debug")))
-			set_val(line, &cfgd_plock_debug);
+		} else if (o->req_arg == req_arg_bool) {
+			get_val_int(line, &val);
 
-		else if (!optd_plock_rate_limit && !strncmp(line, "plock_rate_limit", strlen("plock_rate_limit")))
-			set_val(line, &cfgd_plock_rate_limit);
+			o->file_int = val ? 1 : 0;
 
-		else if (!optd_drop_resources_time && !strncmp(line, "drop_resources_time", strlen("drop_resources_time")))
-			set_val(line, &cfgd_drop_resources_time);
+			if (!o->cli_set)
+				o->use_int = o->file_int;
 
-		else if (!optd_drop_resources_count && !strncmp(line, "drop_resources_count", strlen("drop_resources_count")))
-			set_val(line, &cfgd_drop_resources_count);
+			log_debug("config file %s = %d cli_set %d use %d",
+				  o->name, o->file_int, o->cli_set, o->use_int);
+		} else if (o->req_arg == req_arg_str) {
+			memset(str, 0, sizeof(str));
+			get_val_str(line, str);
 
-		else if (!optd_drop_resources_age && !strncmp(line, "drop_resources_age", strlen("drop_resources_age")))
-			set_val(line, &cfgd_drop_resources_age);
+			o->file_str = strdup(str);
 
-		else if (!optk_protocol && !strncmp(line, "protocol", strlen("protocol")) && !update) {
-			memset(str, 0, sizeof(str));
-			get_val(line, str);
-			proto_val(str, &cfgk_protocol);
-			log_debug("config protocol = %d", cfgk_protocol);
+			if (!o->cli_set)
+				o->use_str = o->file_str;
+
+			log_debug("config file %s = %s cli_set %d use %s",
+				  o->name, o->file_str, o->cli_set, o->use_str);
 		}
 	}
 
diff --git a/dlm_controld/cpg.c b/dlm_controld/cpg.c
index 83e9b17..49fb06a 100644
--- a/dlm_controld/cpg.c
+++ b/dlm_controld/cpg.c
@@ -315,7 +315,7 @@ static void node_history_lockspace_fail(struct lockspace *ls, int nodeid,
 		return;
 	}
 
-	if (cfgd_enable_fencing && node->start_time) {
+	if (opt(enable_fencing_ind) && node->start_time) {
 		node->need_fencing = 1;
 		node->fence_queries = 0;
 	}
@@ -396,7 +396,7 @@ static int check_fencing_done(struct lockspace *ls)
 	int wait_count = 0;
 	int rv, in_progress;
 
-	if (!cfgd_enable_fencing) {
+	if (!opt(enable_fencing_ind)) {
 		log_group(ls, "check_fencing disabled");
 		return 1;
 	}
@@ -592,7 +592,7 @@ static int wait_conditions_done(struct lockspace *ls)
 		return 0;
 	}
 
-	if ((cfgd_enable_quorum_lockspace > 1) && !cluster_quorate) {
+	if (opt(enable_quorum_lockspace_ind) && !cluster_quorate) {
 		log_group(ls, "wait for quorum");
 		ls->wait_debug = DLMC_LS_WAIT_QUORUM;
 		return 0;
@@ -1097,7 +1097,7 @@ static void prepare_plocks(struct lockspace *ls)
 	struct member *memb;
 	uint32_t plocks_data;
 
-	if (!cfgd_enable_plock || ls->disable_plock)
+	if (!opt(enable_plock_ind) || ls->disable_plock)
 		return;
 
 	log_dlock(ls, "prepare_plocks");
@@ -1393,6 +1393,9 @@ static void deliver_cb(cpg_handle_t handle,
 	int ignore_plock;
 	int rv;
 
+	int enable_plock = opt(enable_plock_ind);
+	int plock_ownership = opt(plock_ownership_ind);
+
 	ls = find_ls_handle(handle);
 	if (!ls) {
 		log_error("deliver_cb no ls for cpg %s", group_name->value);
@@ -1425,11 +1428,11 @@ static void deliver_cb(cpg_handle_t handle,
 			ignore_plock = 1;
 			break;
 		}
-		if (cfgd_enable_plock)
+		if (enable_plock)
 			receive_plock(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_plock %d",
-				  hd->type, nodeid, cfgd_enable_plock);
+				  hd->type, nodeid, enable_plock);
 		break;
 
 	case DLM_MSG_PLOCK_OWN:
@@ -1439,12 +1442,11 @@ static void deliver_cb(cpg_handle_t handle,
 			ignore_plock = 1;
 			break;
 		}
-		if (cfgd_enable_plock && cfgd_plock_ownership)
+		if (enable_plock && plock_ownership)
 			receive_own(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_plock %d owner %d",
-				  hd->type, nodeid, cfgd_enable_plock,
-				  cfgd_plock_ownership);
+				  hd->type, nodeid, enable_plock, plock_ownership);
 		break;
 
 	case DLM_MSG_PLOCK_DROP:
@@ -1454,12 +1456,11 @@ static void deliver_cb(cpg_handle_t handle,
 			ignore_plock = 1;
 			break;
 		}
-		if (cfgd_enable_plock && cfgd_plock_ownership)
+		if (enable_plock && plock_ownership)
 			receive_drop(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_plock %d owner %d",
-				  hd->type, nodeid, cfgd_enable_plock,
-				  cfgd_plock_ownership);
+				  hd->type, nodeid, enable_plock, plock_ownership);
 		break;
 
 	case DLM_MSG_PLOCK_SYNC_LOCK:
@@ -1470,65 +1471,64 @@ static void deliver_cb(cpg_handle_t handle,
 			ignore_plock = 1;
 			break;
 		}
-		if (cfgd_enable_plock && cfgd_plock_ownership)
+		if (enable_plock && plock_ownership)
 			receive_sync(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_plock %d owner %d",
-				  hd->type, nodeid, cfgd_enable_plock,
-				  cfgd_plock_ownership);
+				  hd->type, nodeid, enable_plock, plock_ownership);
 		break;
 
 	case DLM_MSG_PLOCKS_DATA:
 		if (ls->disable_plock)
 			break;
-		if (cfgd_enable_plock)
+		if (enable_plock)
 			receive_plocks_data(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_plock %d",
-				  hd->type, nodeid, cfgd_enable_plock);
+				  hd->type, nodeid, enable_plock);
 		break;
 
 	case DLM_MSG_PLOCKS_DONE:
 		if (ls->disable_plock)
 			break;
-		if (cfgd_enable_plock)
+		if (enable_plock)
 			receive_plocks_done(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_plock %d",
-				  hd->type, nodeid, cfgd_enable_plock);
+				  hd->type, nodeid, enable_plock);
 		break;
 
 #if 0
 	case DLM_MSG_DEADLK_CYCLE_START:
-		if (cfgd_enable_deadlk)
+		if (opt(enable_deadlk))
 			receive_cycle_start(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_deadlk %d",
-				  hd->type, nodeid, cfgd_enable_deadlk);
+				  hd->type, nodeid, opt(enable_deadlk));
 		break;
 
 	case DLM_MSG_DEADLK_CYCLE_END:
-		if (cfgd_enable_deadlk)
+		if (opt(enable_deadlk))
 			receive_cycle_end(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_deadlk %d",
-				  hd->type, nodeid, cfgd_enable_deadlk);
+				  hd->type, nodeid, opt(enable_deadlk));
 		break;
 
 	case DLM_MSG_DEADLK_CHECKPOINT_READY:
-		if (cfgd_enable_deadlk)
+		if (opt(enable_deadlk))
 			receive_checkpoint_ready(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_deadlk %d",
-				  hd->type, nodeid, cfgd_enable_deadlk);
+				  hd->type, nodeid, opt(enable_deadlk));
 		break;
 
 	case DLM_MSG_DEADLK_CANCEL_LOCK:
-		if (cfgd_enable_deadlk)
+		if (opt(enable_deadlk))
 			receive_cancel_lock(ls, hd, len);
 		else
 			log_error("msg %d nodeid %d enable_deadlk %d",
-				  hd->type, nodeid, cfgd_enable_deadlk);
+				  hd->type, nodeid, opt(enable_deadlk));
 		break;
 #endif
 
diff --git a/dlm_controld/daemon_cpg.c b/dlm_controld/daemon_cpg.c
index a68de80..3e7ed74 100644
--- a/dlm_controld/daemon_cpg.c
+++ b/dlm_controld/daemon_cpg.c
@@ -457,7 +457,11 @@ static struct node_daemon *add_node_daemon(int nodeid)
 
 	/* explicit command line arg has first priority */
 
-	if (optd_fence_all_agent) {
+	if (dlm_options[fence_all_ind].cli_set) {
+		memset(&fence_all_device, 0, sizeof(struct fence_device));
+		strcpy(fence_all_device.name, "fence_all");
+		strcpy(fence_all_device.agent, dlm_options[fence_all_ind].cli_str);
+
 		fc->dev[0] = &fence_all_device;
 		goto out;
 	}
@@ -746,7 +750,7 @@ static void daemon_fence_work(void)
 
 	/* poll_fencing++; */
 
-	if (cfgd_enable_quorum_fencing && !cluster_quorate) {
+	if (opt(enable_quorum_fencing_ind) && !cluster_quorate) {
 		/* wait for quorum before doing any fencing, but if there
 		   is none, send_fence_clear below can unblock new nodes */
 		log_debug("fence work wait for quorum");
@@ -766,12 +770,12 @@ static void daemon_fence_work(void)
 			continue;
 		}
 
-		if (!cfgd_enable_startup_fencing)
+		if (!opt(enable_startup_fencing_ind))
 			continue;
 
-		if (monotime() - daemon_last_join_monotime < cfgd_post_join_delay) {
+		if (monotime() - daemon_last_join_monotime < opt(post_join_delay_ind)) {
 			log_debug("fence startup %d delay %d from %llu",
-				  node->nodeid, cfgd_post_join_delay,
+				  node->nodeid, opt(post_join_delay_ind),
 				  (unsigned long long)daemon_last_join_monotime);
 			poll_fencing++;
 			continue;
@@ -842,7 +846,7 @@ static void daemon_fence_work(void)
 			continue;
 		}
 
-		if (!cfgd_enable_concurrent_fencing && daemon_fence_pid) {
+		if (!opt(enable_concurrent_fencing_ind) && daemon_fence_pid) {
 			/* run one agent at a time in case they need the same switch */
 			log_debug("fence request %d delay for other pid %d",
 				  node->nodeid, daemon_fence_pid);
@@ -851,9 +855,9 @@ static void daemon_fence_work(void)
 			continue;
 		}
 
-		if (monotime() - cluster_last_join_monotime < cfgd_post_join_delay) {
+		if (monotime() - cluster_last_join_monotime < opt(post_join_delay_ind)) {
 			log_debug("fence request %d delay %d from %llu",
-				  node->nodeid, cfgd_post_join_delay,
+				  node->nodeid, opt(post_join_delay_ind),
 				  (unsigned long long)cluster_last_join_monotime);
 			node->delay_fencing = 1;
 			poll_fencing++;
@@ -1000,7 +1004,7 @@ static void daemon_fence_work(void)
 	 * clear fence_in_progress_unknown
 	 */
  out_fipu:
-	if (cfgd_enable_startup_fencing &&
+	if (opt(enable_startup_fencing_ind) &&
 	    fence_in_progress_unknown &&
 	    list_empty(&startup_nodes) &&
 	    !wait_clear_fipu &&
@@ -1063,7 +1067,7 @@ static void daemon_fence_work(void)
 		}
 	}
 
-	if (!cfgd_enable_startup_fencing && fence_in_progress_unknown) {
+	if (!opt(enable_startup_fencing_ind) && fence_in_progress_unknown) {
 		/*
 		 * case C in comment above
 		 * all nodes are starting and have fipu set.  All expect a
@@ -1872,7 +1876,7 @@ static void confchg_cb_daemon(cpg_handle_t handle,
 		reason = 0;
 		low = 0;
 
-		if (!cfgd_enable_fencing)
+		if (!opt(enable_fencing_ind))
 			continue;
 
 		if (node->need_fencing) {
@@ -1959,7 +1963,7 @@ int setup_cpg_daemon(void)
 
 	memset(&our_protocol, 0, sizeof(our_protocol));
 
-	if (cfgd_enable_fscontrol)
+	if (opt(enable_fscontrol_ind))
 		our_protocol.daemon_max[0] = 2;
 	else
 		our_protocol.daemon_max[0] = 3;
diff --git a/dlm_controld/dlm_controld.h b/dlm_controld/dlm_controld.h
index 84662eb..334408f 100644
--- a/dlm_controld/dlm_controld.h
+++ b/dlm_controld/dlm_controld.h
@@ -31,6 +31,7 @@
 #define DLMC_CMD_DUMP_LOG_PLOCK		11
 #define DLMC_CMD_FENCE_ACK		12
 #define DLMC_CMD_DUMP_STATUS		13
+#define DLMC_CMD_DUMP_CONFIG		14
 
 struct dlmc_header {
 	unsigned int magic;
diff --git a/dlm_controld/dlm_daemon.h b/dlm_controld/dlm_daemon.h
index 4f3e551..788f4e8 100644
--- a/dlm_controld/dlm_daemon.h
+++ b/dlm_controld/dlm_daemon.h
@@ -80,22 +80,65 @@
 #define DEFAULT_LOGFILE_PRIORITY LOG_INFO
 #define DEFAULT_LOGFILE          LOG_FILE_PATH
 
-#define DEFAULT_DEBUG_LOGFILE 0
-#define DEFAULT_POST_JOIN_DELAY 30
-#define DEFAULT_ENABLE_FENCING 1
-#define DEFAULT_ENABLE_STARTUP_FENCING 1
-#define DEFAULT_ENABLE_CONCURRENT_FENCING 0
-#define DEFAULT_ENABLE_QUORUM_FENCING 1
-#define DEFAULT_ENABLE_QUORUM_LOCKSPACE 0
-#define DEFAULT_ENABLE_FSCONTROL 0
-#define DEFAULT_ENABLE_PLOCK 1
-#define DEFAULT_PLOCK_DEBUG 0
-#define DEFAULT_PLOCK_RATE_LIMIT 0
-#define DEFAULT_PLOCK_OWNERSHIP 0
-#define DEFAULT_DROP_RESOURCES_TIME 10000 /* 10 sec */
-#define DEFAULT_DROP_RESOURCES_COUNT 10
-#define DEFAULT_DROP_RESOURCES_AGE 10000 /* 10 sec */
-#define DEFAULT_FENCE_ALL_AGENT "dlm_stonith"
+enum {
+        no_arg = 0,
+        req_arg_bool = 1,
+        req_arg_int = 2,
+        req_arg_str = 3,
+};
+
+enum {
+        daemon_debug_ind = 0,
+        log_debug_ind,
+        timewarn_ind,
+        protocol_ind,
+        debug_logfile_ind,
+        enable_fscontrol_ind,
+        enable_plock_ind,
+        plock_debug_ind,
+        plock_rate_limit_ind,
+        plock_ownership_ind,
+        drop_resources_time_ind,
+        drop_resources_count_ind,
+        drop_resources_age_ind,
+        post_join_delay_ind,
+        enable_fencing_ind,
+        enable_concurrent_fencing_ind,
+        enable_startup_fencing_ind,
+        enable_quorum_fencing_ind,
+        enable_quorum_lockspace_ind,
+        fence_all_ind,
+        unfence_all_ind,
+        help_ind,
+        version_ind,
+        dlm_options_max,
+};
+
+struct dlm_option {
+	const char *name;
+	char letter;
+	int req_arg;
+	const char *desc;
+
+	int use_int;
+	char *use_str;
+
+	int default_int;
+	const char *default_str;
+
+	int cli_set;
+	int cli_int;
+	char *cli_str;
+
+	int file_set;
+	int file_int;
+	char *file_str;
+};
+
+EXTERN struct dlm_option dlm_options[dlm_options_max];
+#define opt(x) dlm_options[x].use_int
+#define opts(x) dlm_options[x].use_str
+
 
 /* DLM_LOCKSPACE_LEN: maximum lockspace name length, from linux/dlmconstants.h.
    Copied in libdlm.h so apps don't need to include the kernel header.
@@ -116,13 +159,10 @@
 
 #define MAXLINE		256
 
-/* cfgk_protocol */
-
 #define PROTO_TCP  0
 #define PROTO_SCTP 1
 #define PROTO_DETECT 2
 
-EXTERN int daemon_debug_opt;
 EXTERN int daemon_quit;
 EXTERN int cluster_down;
 EXTERN int poll_lockspaces;
@@ -146,46 +186,6 @@ EXTERN uint32_t monitor_minor;
 EXTERN uint32_t plock_minor;
 EXTERN struct fence_device fence_all_device;
 
-EXTERN int optk_debug;
-EXTERN int optk_timewarn;
-EXTERN int optk_protocol;
-EXTERN int optd_debug_logfile;
-EXTERN int optd_post_join_delay;
-EXTERN int optd_enable_fencing;
-EXTERN int optd_enable_startup_fencing;
-EXTERN int optd_enable_concurrent_fencing;
-EXTERN int optd_enable_quorum_fencing;
-EXTERN int optd_enable_quorum_lockspace;
-EXTERN int optd_enable_fscontrol;
-EXTERN int optd_enable_plock;
-EXTERN int optd_plock_debug;
-EXTERN int optd_plock_rate_limit;
-EXTERN int optd_plock_ownership;
-EXTERN int optd_drop_resources_time;
-EXTERN int optd_drop_resources_count;
-EXTERN int optd_drop_resources_age;
-EXTERN int optd_fence_all_agent;
-
-EXTERN int cfgk_debug;
-EXTERN int cfgk_timewarn;
-EXTERN int cfgk_protocol;
-EXTERN int cfgd_debug_logfile;
-EXTERN int cfgd_post_join_delay;
-EXTERN int cfgd_enable_fencing;
-EXTERN int cfgd_enable_startup_fencing;
-EXTERN int cfgd_enable_concurrent_fencing;
-EXTERN int cfgd_enable_quorum_fencing;
-EXTERN int cfgd_enable_quorum_lockspace;
-EXTERN int cfgd_enable_fscontrol;
-EXTERN int cfgd_enable_plock;
-EXTERN int cfgd_plock_debug;
-EXTERN int cfgd_plock_rate_limit;
-EXTERN int cfgd_plock_ownership;
-EXTERN int cfgd_drop_resources_time;
-EXTERN int cfgd_drop_resources_count;
-EXTERN int cfgd_drop_resources_age;
-EXTERN char fence_all_agent[PATH_MAX];
-
 #define LOG_DUMP_SIZE DLMC_DUMP_SIZE
 
 #define LOG_PLOCK 0x00010000
@@ -384,6 +384,7 @@ struct lockspace *find_ls(char *name);
 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);
 
 /* member.c */
 int setup_cluster(void);
diff --git a/dlm_controld/lib.c b/dlm_controld/lib.c
index a7cd443..8b079b1 100644
--- a/dlm_controld/lib.c
+++ b/dlm_controld/lib.c
@@ -142,6 +142,11 @@ int dlmc_dump_debug(char *buf)
 	return do_dump(DLMC_CMD_DUMP_DEBUG, NULL, buf);
 }
 
+int dlmc_dump_config(char *buf)
+{
+	return do_dump(DLMC_CMD_DUMP_CONFIG, NULL, buf);
+}
+
 int dlmc_dump_log_plock(char *buf)
 {
 	return do_dump(DLMC_CMD_DUMP_LOG_PLOCK, NULL, buf);
diff --git a/dlm_controld/libdlmcontrol.h b/dlm_controld/libdlmcontrol.h
index 2af30de..436088b 100644
--- a/dlm_controld/libdlmcontrol.h
+++ b/dlm_controld/libdlmcontrol.h
@@ -79,6 +79,7 @@ struct dlmc_lockspace {
 #define DLMC_NODES_NEXT		3
 
 int dlmc_dump_debug(char *buf);
+int dlmc_dump_config(char *buf);
 int dlmc_dump_log_plock(char *buf);
 int dlmc_dump_plocks(char *name, char *buf);
 int dlmc_lockspace_info(char *lsname, struct dlmc_lockspace *ls);
diff --git a/dlm_controld/logging.c b/dlm_controld/logging.c
index 1f97df7..1b08c4f 100644
--- a/dlm_controld/logging.c
+++ b/dlm_controld/logging.c
@@ -24,7 +24,7 @@ void init_logging(void)
 	/* logfile_priority is the only one of these options that
 	   can be controlled from command line or environment variable */
 
-	if (cfgd_debug_logfile)
+	if (opt(debug_logfile_ind))
 		logfile_priority = LOG_DEBUG;
 
 	if (logfile[0]) {
@@ -167,10 +167,10 @@ void log_level(char *name_in, uint32_t level_in, const char *fmt, ...)
 		fflush(logfile_fp);
 	}
 
-	if (!daemon_debug_opt)
+	if (!dlm_options[daemon_debug_ind].use_int)
 		return;
 
-	if (level || (plock && cfgd_plock_debug))
+	if (level || (plock && opt(plock_debug_ind)))
 		fprintf(stderr, "%s", log_str);
 }
 
diff --git a/dlm_controld/main.c b/dlm_controld/main.c
index dcb01ec..872cdfd 100644
--- a/dlm_controld/main.c
+++ b/dlm_controld/main.c
@@ -8,6 +8,7 @@
 
 #define EXTERN
 #include "dlm_daemon.h"
+#include <ctype.h>
 #include <pthread.h>
 #include <linux/netlink.h>
 #include <linux/genetlink.h>
@@ -443,6 +444,46 @@ static void query_dump_debug(int fd)
 		send(fd, copy_buf, len, MSG_NOSIGNAL);
 }
 
+static void copy_options(char *buf, int *len)
+{
+	struct dlm_option *o;
+	char tmp[256];
+	int i, ret, pos = 0;
+
+	for (i = 0; i < dlm_options_max; i++) {
+		o = &dlm_options[i];
+
+		memset(tmp, 0, sizeof(tmp));
+
+		if (o->req_arg == req_arg_str)
+			snprintf(tmp, 255, "%s=%s\n", o->name, o->use_str);
+		else
+			snprintf(tmp, 255, "%s=%d\n", o->name, o->use_int);
+
+		if (pos + strlen(tmp) >= LOG_DUMP_SIZE)
+			break;
+
+		ret = sprintf(buf + pos, "%s", tmp);
+		pos += ret;
+	}
+
+	*len = pos;
+}
+
+static void query_dump_config(int fd)
+{
+	struct dlmc_header h;
+	int len = 0;
+
+	copy_options(copy_buf, &len);
+
+	init_header(&h, DLMC_CMD_DUMP_CONFIG, NULL, 0, len);
+	send(fd, &h, sizeof(h), MSG_NOSIGNAL);
+
+	if (len)
+		send(fd, copy_buf, len, MSG_NOSIGNAL);
+}
+
 static void query_dump_log_plock(int fd)
 {
 	struct dlmc_header h;
@@ -658,7 +699,7 @@ static void process_connection(int ci)
 		break;
 
 	case DLMC_CMD_FS_REGISTER:
-		if (cfgd_enable_fscontrol) {
+		if (opt(enable_fscontrol_ind)) {
 			rv = fs_register_add(h.name);
 			ls = find_ls(h.name);
 			if (ls)
@@ -805,6 +846,9 @@ static void *process_queries(void *arg)
 		case DLMC_CMD_DUMP_DEBUG:
 			query_dump_debug(f);
 			break;
+		case DLMC_CMD_DUMP_CONFIG:
+			query_dump_config(f);
+			break;
 		case DLMC_CMD_DUMP_LOG_PLOCK:
 			query_dump_log_plock(f);
 			break;
@@ -951,7 +995,7 @@ static void loop(void)
 		goto out;
 
 #if 0
-	if (cfgd_enable_deadlk) {
+	if (opt(enable_deadlk_ind)) {
 		rv = setup_netlink();
 		if (rv < 0)
 			goto out;
@@ -1114,174 +1158,367 @@ static void unlink_lockfile(int fd, const char *dir, const char *name)
 	close(fd);
 }
 
+static const char *req_arg_s(int a)
+{
+	switch (a) {
+	case no_arg:
+		return "";
+	case req_arg_bool:
+		return "0|1";
+	case req_arg_int:
+		return "<int>";
+	case req_arg_str:
+		return "<str>";
+	default:
+		return "<arg>";
+	}
+}
+
 static void print_usage(void)
 {
+	struct dlm_option *o;
+	int i;
+
 	printf("Usage:\n");
 	printf("\n");
 	printf("dlm_controld [options]\n");
 	printf("\n");
 	printf("Options:\n");
 	printf("\n");
-	printf("  -D		Enable debugging to stderr and don't fork\n");
-	printf("  -L		Enable debugging to log file\n");
-	printf("  -K		Enable kernel dlm debugging messages\n");
-	printf("  -r <num>      dlm kernel lowcomms protocol, 0 tcp, 1 sctp, 2 detect\n");
-	printf("                2 selects tcp if corosync rrp_mode is \"none\", otherwise sctp\n");
-	printf("                Default is 2\n");
-
-	printf("  -j <sec>      Seconds to delay fencing after cluster join\n");
-	printf("                Default is %d\n", DEFAULT_POST_JOIN_DELAY);
-	printf("  -f <num>	Enable (1) or disable (0) fencing\n");
-	printf("		Default is %d\n", DEFAULT_ENABLE_FENCING);
-	printf("  -s <num>	Enable (1) or disable (0) startup fencing\n");
-	printf("		Default is %d\n", DEFAULT_ENABLE_STARTUP_FENCING);
-	printf("  -q <num>	Enable (1) or disable (0) quorum wait before fencing\n");
-	printf("		Default is %d\n", DEFAULT_ENABLE_QUORUM_FENCING);
-
-	printf("  -p <num>	Enable (1) or disable (0) plock code for cluster fs\n");
-	printf("		Default is %d\n", DEFAULT_ENABLE_PLOCK);
-	printf("  -P		Enable plock debugging\n");
-	printf("  -l <limit>	Limit the rate of plock operations\n");
-	printf("		Default is %d, set to 0 for no limit\n", DEFAULT_PLOCK_RATE_LIMIT);
-	printf("  -o <n>	Enable (1) or disable (0) plock ownership\n");
-	printf("		Default is %d\n", DEFAULT_PLOCK_OWNERSHIP);
-	printf("  -t <ms>	plock ownership drop resources time (milliseconds)\n");
-	printf("		Default is %u\n", DEFAULT_DROP_RESOURCES_TIME);
-	printf("  -c <num>	plock ownership drop resources count\n");
-	printf("		Default is %u\n", DEFAULT_DROP_RESOURCES_COUNT);
-	printf("  -a <ms>	plock ownership drop resources age (milliseconds)\n");
-	printf("		Default is %u\n", DEFAULT_DROP_RESOURCES_AGE);
-
-	printf("  -h		Print this help, then exit\n");
-	printf("  -V		Print program version information, then exit\n");
-}
 
-#define OPTION_STRING "LDKf:q:p:Pl:o:t:c:a:hVr:s:e:j:"
+	for (i = 0; i < dlm_options_max; i++) {
+		o = &dlm_options[i];
 
-static void read_arguments(int argc, char **argv)
-{
-	int cont = 1;
-	int optchar;
+		/* don't advertise options with no description */
+		if (!strlen(o->desc))
+			continue;
 
-	while (cont) {
-		optchar = getopt(argc, argv, OPTION_STRING);
+		printf("  --%s", o->name);
 
-		switch (optchar) {
-		case 'D':
-			daemon_debug_opt = 1;
-			break;
+		if (o->letter) {
+			printf(" | -%c", o->letter);
+			if (o->req_arg)
+				printf(" %s", req_arg_s(o->req_arg));
+		} else {
+			if (o->req_arg)
+				printf(" %s", req_arg_s(o->req_arg));
+		}
 
-		case 'L':
-			optd_debug_logfile = 1;
-			cfgd_debug_logfile = 1;
-			break;
+		printf("\n");
 
-		case 'K':
-			optk_debug = 1;
-			cfgk_debug = 1;
-			break;
+		printf("        %s", o->desc);
 
-		case 'r':
-			optk_protocol = 1;
-			cfgk_protocol = atoi(optarg);
-			break;
+		if (o->req_arg == req_arg_str)
+			printf(" [%s]\n", o->default_str ? o->default_str : "");
+		else if (o->req_arg == req_arg_int)
+			printf(" [%d]\n", o->default_int);
+		else if (o->req_arg == req_arg_bool)
+			printf(" [%d]\n", o->default_int);
+		else
+			printf("\n");
+
+		printf("\n");
+	}
+}
 
-		/* fencing options */
+static void set_opt_default(int ind, const char *name, char letter, int arg_type,
+			    int default_int, const char *default_str, 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].default_int = default_int;
+	dlm_options[ind].default_str = default_str;
+	dlm_options[ind].use_int = default_int;
+	dlm_options[ind].use_str = (char *)default_str;
+}
 
-		case 'j':
-			optd_post_join_delay = 1;
-			cfgd_post_join_delay = atoi(optarg);
-			break;
+static void set_opt_defaults(void)
+{
+	set_opt_default(daemon_debug_ind,
+			"daemon_debug", 'D', no_arg,
+			0, NULL,
+			"enable debugging to stderr and don't fork");
+
+	set_opt_default(log_debug_ind,
+			"log_debug", 'K', no_arg,
+			0, NULL,
+			"enable kernel dlm debugging messages");
+
+	set_opt_default(timewarn_ind,
+			"timewarn", '\0', req_arg_int,
+			0, NULL,
+			""); /* do not advertise */
+
+	set_opt_default(protocol_ind,
+			"protocol", 'r', req_arg_str,
+			-1, "detect",
+			"dlm kernel lowcomms protocol: tcp, sctp, detect");
+
+	set_opt_default(debug_logfile_ind,
+			"debug_logfile", 'L', no_arg,
+			0, NULL,
+			"write debugging to log file");
+
+	set_opt_default(enable_fscontrol_ind,
+			"enable_fscontrol", '\0', req_arg_bool,
+			0, NULL,
+			"enable/disable recovery coordination with fs controld");
+
+	set_opt_default(enable_plock_ind,
+			"enable_plock", 'p', req_arg_bool,
+			1, NULL,
+			"enable/disable posix lock support for cluster fs");
+
+	set_opt_default(plock_debug_ind,
+			"plock_debug", 'P', no_arg,
+			0, NULL,
+			"enable plock debugging");
+
+	set_opt_default(plock_rate_limit_ind,
+			"plock_rate_limit", 'l', req_arg_int,
+			0, NULL,
+			"limit rate of plock operations (0 for none)");
+
+	set_opt_default(plock_ownership_ind,
+			"plock_ownership", 'o', req_arg_bool,
+			0, NULL,
+			"enable/disable plock ownership");
+
+	set_opt_default(drop_resources_time_ind,
+			"drop_resources_time", 't', req_arg_int,
+			10000, NULL,
+			"plock ownership drop resources time (milliseconds)");
+
+	set_opt_default(drop_resources_count_ind,
+			"drop_resources_count", 'c', req_arg_int,
+			10, NULL,
+			"plock ownership drop resources count");
+
+	set_opt_default(drop_resources_age_ind,
+			"drop_resources_age", 'a', req_arg_int,
+			10000, NULL,
+			"plock ownership drop resources age (milliseconds)");
+
+	set_opt_default(post_join_delay_ind,
+			"post_join_delay", 'j', req_arg_int,
+			30, NULL,
+			"seconds to delay fencing after cluster join");
+
+	set_opt_default(enable_fencing_ind,
+			"enable_fencing", 'f', req_arg_bool,
+			1, NULL,
+			"enable/disable fencing");
+
+	set_opt_default(enable_concurrent_fencing_ind,
+			"enable_concurrent_fencing", '\0', req_arg_bool,
+			0, NULL,
+			"enable/disable concurrent fencing");
+
+	set_opt_default(enable_startup_fencing_ind,
+			"enable_startup_fencing", 's', req_arg_bool,
+			1, NULL,
+			"enable/disable startup fencing");
+
+	set_opt_default(enable_quorum_fencing_ind,
+			"enable_quorum_fencing", 'q', req_arg_bool,
+			1, NULL,
+			"enable/disable quorum requirement for fencing");
+
+	set_opt_default(enable_quorum_lockspace_ind,
+			"enable_quorum_lockspace", '\0', req_arg_bool,
+			1, NULL,
+			"enable/disable quorum requirement for lockspace operations");
+
+	set_opt_default(fence_all_ind,
+			"fence_all", '\0', req_arg_str,
+			-1, "dlm_stonith",
+			"fence all nodes with this agent");
+
+	set_opt_default(unfence_all_ind,
+			"unfence_all", '\0', req_arg_str,
+			-1, NULL,
+			"unfence all nodes with this agent");
+
+	set_opt_default(help_ind,
+			"help", 'h', no_arg,
+			-1, NULL,
+			"print this help, then exit");
+
+	set_opt_default(version_ind,
+			"version", 'V', no_arg,
+			-1, NULL,
+			"Print program version information, then exit");
+}
 
-		case 'f':
-			optd_enable_fencing = 1;
-			cfgd_enable_fencing = atoi(optarg);
-			break;
+static int get_ind_name(char *s)
+{
+	char name[PATH_MAX];
+	char *p = s;
+	int i;
 
-		case 's':
-			optd_enable_startup_fencing = 1;
-			cfgd_enable_startup_fencing = atoi(optarg);
+	memset(name, 0, sizeof(name));
 
-		case 'q':
-			optd_enable_quorum_fencing = 1;
-			cfgd_enable_quorum_fencing = atoi(optarg);
+	for (i = 0; i < strlen(s); i++) {
+		if (*p == '=')
 			break;
-
-		case 'e':
-			optd_fence_all_agent = 1;
-			strcpy(fence_all_agent, optarg);
+		if (*p == ' ')
 			break;
+		name[i] = *p;
+		p++;
+	}
+
+	for (i = 0; i < dlm_options_max; i++) {
+		if (!strcmp(dlm_options[i].name, name))
+			return i;
+	}
+	return -1;
+}
 
+static int get_ind_letter(char c)
+{
+	int i;
 
-		/* plock options */
+	for (i = 0; i < dlm_options_max; i++) {
+		if (dlm_options[i].letter == c)
+			return i;
+	}
+	return -1;
+}
 
-		case 'p':
-			optd_enable_plock = 1;
-			cfgd_enable_plock = atoi(optarg);
-			break;
+struct dlm_option *get_dlm_option(char *name)
+{
+	int i;
+	i = get_ind_name(name);
+	if (i < 0)
+		return NULL;
+	return &dlm_options[i];
+}
 
-		case 'P':
-			optd_plock_debug = 1;
-			cfgd_plock_debug = 1;
-			break;
+static void set_opt_cli(int argc, char **argv)
+{
+	struct dlm_option *o;
+	char *arg1 = argv[1];
+	char *p, *arg_str;
+	char bundled_letters[8];
+	int b, blc = 0, blc_max = 8;
+	int debug_options = 0;
+	int i, ind;
+
+	if (argc < 2 || !strcmp(arg1, "help") || !strcmp(arg1, "--help") || !strcmp(arg1, "-h")) {
+		print_usage();
+		exit(EXIT_SUCCESS);
+	}
 
-		case 'l':
-			optd_plock_rate_limit = 1;
-			cfgd_plock_rate_limit = atoi(optarg);
-			break;
+	if (!strcmp(arg1, "version") || !strcmp(arg1, "--version") || !strcmp(arg1, "-V")) {
+		printf("dlm_controld %s (built %s %s)\n",
+			RELEASE_VERSION, __DATE__, __TIME__);
+			printf("%s\n", REDHAT_COPYRIGHT);
+		exit(EXIT_SUCCESS);
+	}
 
-		case 'o':
-			optd_plock_ownership = 1;
-			cfgd_plock_ownership = atoi(optarg);
-			break;
+	for (i = 1; i < argc; ) {
+		p = argv[i++];
 
-		case 't':
-			optd_drop_resources_time = 1;
-			cfgd_drop_resources_time = atoi(optarg);
-			break;
+		if (!strcmp(p, "--debug_options")) {
+			debug_options = 1;
+			continue;
+		}
 
-		case 'c':
-			optd_drop_resources_count = 1;
-			cfgd_drop_resources_count = atoi(optarg);
-			break;
+		if (p[0] == '-' && p[1] == '-')
+			ind = get_ind_name(p + 2);
+		else if (p[0] == '-')
+			ind = get_ind_letter(p[1]);
+		else {
+			fprintf(stderr, "unknown option arg %s\n", p);
+			exit(EXIT_FAILURE);
+		}
 
-		case 'a':
-			optd_drop_resources_age = 1;
-			cfgd_drop_resources_age = atoi(optarg);
-			break;
+		if (ind < 0) {
+			fprintf(stderr, "unknown option %s\n", p);
+			exit(EXIT_FAILURE);
+		}
 
-		case 'h':
-			print_usage();
-			exit(EXIT_SUCCESS);
-			break;
+		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;
+
+			/* save bundled, arg-less, single letters, e.g. -DKP */
+			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];
+				}
+			}
+			continue;
+		}
 
-		case 'V':
-			printf("dlm_controld %s (built %s %s)\n",
-				RELEASE_VERSION, __DATE__, __TIME__);
-			printf("%s\n", REDHAT_COPYRIGHT);
-			exit(EXIT_SUCCESS);
-			break;
+		arg_str = NULL;
+
+		if (strstr(p, "=")) {
+			/* arg starts after = for name or letter */
+			arg_str = strstr(p, "=") + 1;
+
+		} else if (strlen(p) > 2 && isalpha(p[1]) && isdigit(p[2])) {
+			/* arg with no space between letter and digits */
+			arg_str = p + 2;
+
+		} else {
+			/* space separates arg from name or letter */
+			if (i >= argc) {
+				fprintf(stderr, "option %s no arg", p);
+				exit(EXIT_FAILURE);
+			}
+			arg_str = argv[i++];
+		}
 
-		case ':':
-		case '?':
-			fprintf(stderr, "Please use '-h' for usage.\n");
+		if (!arg_str || arg_str[0] == '-' || arg_str[0] == '\0') {
+			fprintf(stderr, "option %s requires arg", p);
 			exit(EXIT_FAILURE);
-			break;
+		}
 
-		case EOF:
-			cont = 0;
-			break;
+		if (o->req_arg == req_arg_str) {
+			o->cli_str = strdup(arg_str);
+			o->use_str = o->cli_str;
+		} else if (o->req_arg == req_arg_int) {
+			o->cli_int = atoi(arg_str);
+			o->use_int = o->cli_int;
+		} else if (o->req_arg == req_arg_bool) {
+			o->cli_int = atoi(arg_str) ? 1 : 0;
+			o->use_int = o->cli_int;
+		}
+	}
 
-		default:
-			fprintf(stderr, "unknown option: %c\n", optchar);
+	/* process bundled letters saved above */
+
+	for (i = 0; i < blc; i++) {
+		ind = get_ind_letter(bundled_letters[i]);
+		if (ind < 0) {
+			fprintf(stderr, "unknown option char %c\n", bundled_letters[i]);
 			exit(EXIT_FAILURE);
-			break;
-		};
+		}
+		o = &dlm_options[ind];
+		o->cli_set++;
+		o->cli_int = 1;
+		o->use_int = 1;
+	}
+
+	if (debug_options && opt(daemon_debug_ind)) {
+		for (i = 0; i < dlm_options_max; i++) {
+			o = &dlm_options[i];
+			printf("%-25s cli_set %d cli_int %d cli_str %s use_int %d use_str %s\n",
+			       o->name, o->cli_set, o->cli_int, o->cli_str, o->use_int, o->use_str);
+		}
 	}
 
 	if (getenv("DLM_CONTROLD_DEBUG")) {
-		optd_debug_logfile = 1;
-		cfgd_debug_logfile = 1;
+		dlm_options[daemon_debug_ind].use_int = 1;
 	}
 }
 
@@ -1308,39 +1545,19 @@ int main(int argc, char **argv)
 	struct sigaction act;
 	int fd, rv;
 
-	cfgk_debug                  = -1;
-	cfgk_timewarn               = -1;
-	cfgk_protocol               = PROTO_DETECT;
-	cfgd_debug_logfile          = DEFAULT_DEBUG_LOGFILE;
-	cfgd_enable_fscontrol       = DEFAULT_ENABLE_FSCONTROL;
-
-	cfgd_enable_plock           = DEFAULT_ENABLE_PLOCK;
-	cfgd_plock_debug            = DEFAULT_PLOCK_DEBUG;
-	cfgd_plock_rate_limit       = DEFAULT_PLOCK_RATE_LIMIT;
-	cfgd_plock_ownership        = DEFAULT_PLOCK_OWNERSHIP;
-	cfgd_drop_resources_time    = DEFAULT_DROP_RESOURCES_TIME;
-	cfgd_drop_resources_count   = DEFAULT_DROP_RESOURCES_COUNT;
-	cfgd_drop_resources_age     = DEFAULT_DROP_RESOURCES_AGE;
-
-	cfgd_post_join_delay        = DEFAULT_POST_JOIN_DELAY;
-	cfgd_enable_fencing         = DEFAULT_ENABLE_FENCING;
-	cfgd_enable_startup_fencing = DEFAULT_ENABLE_STARTUP_FENCING;
-	cfgd_enable_quorum_fencing  = DEFAULT_ENABLE_QUORUM_FENCING;
-	cfgd_enable_quorum_lockspace= DEFAULT_ENABLE_QUORUM_LOCKSPACE;
-
-	strcpy(fence_all_agent, DEFAULT_FENCE_ALL_AGENT);
+	set_opt_defaults();
+
 	memset(&fence_all_device, 0, sizeof(struct fence_device));
 	strcpy(fence_all_device.name, "fence_all");
-	strcpy(fence_all_device.agent, fence_all_agent);
+	strcpy(fence_all_device.agent, dlm_options[fence_all_ind].default_str);
 
 	INIT_LIST_HEAD(&lockspaces);
 	INIT_LIST_HEAD(&fs_register_list);
-	
 	init_daemon();
 
-	read_arguments(argc, argv);
+	set_opt_cli(argc, argv);
 
-	if (!daemon_debug_opt) {
+	if (!opt(daemon_debug_ind)) {
 		if (daemon(0, 0) < 0) {
 			perror("daemon error");
 			exit(EXIT_FAILURE);
diff --git a/dlm_controld/member.c b/dlm_controld/member.c
index 7222b9e..d25ad42 100644
--- a/dlm_controld/member.c
+++ b/dlm_controld/member.c
@@ -356,7 +356,7 @@ int setup_node_config(void)
 
 		log_debug("node_config %d", nodeid);
 
-		if (cfgd_enable_fencing && cfgd_enable_startup_fencing)
+		if (opt(enable_fencing_ind) && opt(enable_startup_fencing_ind))
 			add_startup_node(nodeid);
 	}
 
diff --git a/dlm_controld/plock.c b/dlm_controld/plock.c
index ed98e9c..72bf6ea 100644
--- a/dlm_controld/plock.c
+++ b/dlm_controld/plock.c
@@ -293,7 +293,7 @@ static int find_resource(struct lockspace *ls, uint64_t number, int create,
 	INIT_LIST_HEAD(&r->waiters);
 	INIT_LIST_HEAD(&r->pending);
 
-	if (cfgd_plock_ownership)
+	if (opt(plock_ownership_ind))
 		r->owner = -1;
 	else
 		r->owner = 0;
@@ -310,7 +310,7 @@ static int find_resource(struct lockspace *ls, uint64_t number, int create,
 static void put_resource(struct lockspace *ls, struct resource *r)
 {
 	/* with ownership, resources are only freed via drop messages */
-	if (cfgd_plock_ownership)
+	if (opt(plock_ownership_ind))
 		return;
 
 	if (list_empty(&r->locks) && list_empty(&r->waiters)) {
@@ -877,11 +877,11 @@ static void _receive_plock(struct lockspace *ls, struct dlm_header *hd, int len)
 		return;
 	}
 
-	create = !cfgd_plock_ownership;
+	create = !opt(plock_ownership_ind);
 
 	rv = find_resource(ls, info.number, create, &r);
 
-	if (rv && cfgd_plock_ownership) {
+	if (rv && opt(plock_ownership_ind)) {
 		/* There must have been a race with a drop, so we need to
 		   ignore this plock op which will be resent.  If we're the one
 		   who sent the plock, we need to send_own() and put it on the
@@ -1420,7 +1420,7 @@ static int drop_resources(struct lockspace *ls)
 	struct timeval now;
 	int count = 0;
 
-	if (!cfgd_plock_ownership)
+	if (!opt(plock_ownership_ind))
 		return 0;
 
 	if (list_empty(&ls->plock_resources))
@@ -1429,7 +1429,7 @@ static int drop_resources(struct lockspace *ls)
 	gettimeofday(&now, NULL);
 
 	if (time_diff_ms(&ls->drop_resources_last, &now) <
-			 cfgd_drop_resources_time)
+			 opt(drop_resources_time_ind))
 		return 1;
 
 	ls->drop_resources_last = now;
@@ -1437,12 +1437,12 @@ static int drop_resources(struct lockspace *ls)
 	/* try to drop the oldest, unused resources */
 
 	list_for_each_entry_reverse(r, &ls->plock_resources, list) {
-		if (count >= cfgd_drop_resources_count)
+		if (count >= opt(drop_resources_count_ind))
 			break;
 		if (r->owner && r->owner != our_nodeid)
 			continue;
 		if (time_diff_ms(&r->last_access, &now) <
-		    cfgd_drop_resources_age)
+		    opt(drop_resources_age_ind))
 			continue;
 
 		if (list_empty(&r->locks) && list_empty(&r->waiters)) {
@@ -1478,18 +1478,18 @@ int limit_plocks(void)
 {
 	struct timeval now;
 
-	if (!cfgd_plock_rate_limit || !plock_read_count)
+	if (!opt(plock_rate_limit_ind) || !plock_read_count)
 		return 0;
 
 	gettimeofday(&now, NULL);
 
 	/* Every time a plock op is read from the kernel, we increment
-	   plock_read_count.  After every cfgd_plock_rate_limit (N) reads,
+	   plock_read_count.  After every plock_rate_limit (N) reads,
 	   we check the time it's taken to do those N; if the time is less than
 	   a second, then we delay reading any more until a second is up.
 	   This way we read a max of N ops from the kernel every second. */
 
-	if (!(plock_read_count % cfgd_plock_rate_limit)) {
+	if (!(plock_read_count % opt(plock_rate_limit_ind))) {
 		if (time_diff_ms(&plock_rate_last, &now) < 1000) {
 			plock_rate_delays++;
 			return 2;
@@ -1529,7 +1529,7 @@ void process_plocks(int ci)
 	/* kernel doesn't set the nodeid field */
 	info.nodeid = our_nodeid;
 
-	if (!cfgd_enable_plock) {
+	if (!opt(enable_plock_ind)) {
 		rv = -ENOSYS;
 		goto fail;
 	}
@@ -1586,7 +1586,7 @@ void process_plocks(int ci)
 		save_pending_plock(ls, r, &info);
 	}
 
-	if (cfgd_plock_ownership && !list_empty(&ls->plock_resources))
+	if (opt(plock_ownership_ind) && !list_empty(&ls->plock_resources))
 		poll_drop_plock = 1;
 	return;
 
@@ -1670,7 +1670,7 @@ static int pack_send_buf(struct lockspace *ls, struct resource *r, int owner,
 	}
 
 	/* plocks not replicated for owned resources */
-	if (cfgd_plock_ownership && (owner == our_nodeid))
+	if (opt(plock_ownership_ind) && (owner == our_nodeid))
 		goto done;
 
 	len = sizeof(struct dlm_header) + sizeof(struct resource_data);
@@ -1769,7 +1769,7 @@ void send_all_plocks_data(struct lockspace *ls, uint32_t seq, uint32_t *plocks_d
 	int owner, count, len, full;
 	uint32_t send_count = 0;
 
-	if (!cfgd_enable_plock || ls->disable_plock)
+	if (!opt(enable_plock_ind) || ls->disable_plock)
 		return;
 
 	log_dlock(ls, "send_all_plocks_data %d:%u", our_nodeid, seq);
@@ -1785,7 +1785,7 @@ void send_all_plocks_data(struct lockspace *ls, uint32_t seq, uint32_t *plocks_d
 	     (there should be no SYNCING plocks) */
 
 	list_for_each_entry(r, &ls->plock_resources, list) {
-		if (!cfgd_plock_ownership)
+		if (!opt(plock_ownership_ind))
 			owner = 0;
 		else if (r->owner == -1)
 			continue;
@@ -1861,7 +1861,7 @@ void receive_plocks_data(struct lockspace *ls, struct dlm_header *hd, int len)
 	int owner;
 	int i;
 
-	if (!cfgd_enable_plock || ls->disable_plock)
+	if (!opt(enable_plock_ind) || ls->disable_plock)
 		return;
 
 	if (!ls->need_plocks)
@@ -1907,7 +1907,7 @@ void receive_plocks_data(struct lockspace *ls, struct dlm_header *hd, int len)
 	INIT_LIST_HEAD(&r->waiters);
 	INIT_LIST_HEAD(&r->pending);
 
-	if (!cfgd_plock_ownership) {
+	if (!opt(plock_ownership_ind)) {
 		if (owner) {
 			log_elock(ls, "recv_plocks_data %d:%u n %llu bad owner %d",
 				  hd->nodeid, hd->msgdata, (unsigned long long)num,
@@ -1991,7 +1991,7 @@ void clear_plocks_data(struct lockspace *ls)
 	struct resource *r, *r2;
 	uint32_t count = 0;
 
-	if (!cfgd_enable_plock || ls->disable_plock)
+	if (!opt(enable_plock_ind) || ls->disable_plock)
 		return;
 
 	list_for_each_entry_safe(r, r2, &ls->plock_resources, list) {
@@ -2019,7 +2019,7 @@ void purge_plocks(struct lockspace *ls, int nodeid, int unmount)
 	struct resource *r, *r2;
 	int purged = 0;
 
-	if (!cfgd_enable_plock || ls->disable_plock)
+	if (!opt(enable_plock_ind) || ls->disable_plock)
 		return;
 
 	list_for_each_entry_safe(r, r2, &ls->plock_resources, list) {
@@ -2053,7 +2053,7 @@ void purge_plocks(struct lockspace *ls, int nodeid, int unmount)
 		if (!list_empty(&r->waiters))
 			do_waiters(ls, r);
 
-		if (!cfgd_plock_ownership &&
+		if (!opt(plock_ownership_ind) &&
 		    list_empty(&r->locks) && list_empty(&r->waiters)) {
 			rb_del_plock_resource(ls, r);
 			list_del(&r->list);
diff --git a/dlm_tool/main.c b/dlm_tool/main.c
index 5df5c59..1fb6b3e 100644
--- a/dlm_tool/main.c
+++ b/dlm_tool/main.c
@@ -40,6 +40,7 @@
 #define OP_LOG_PLOCK			10
 #define OP_FENCE_ACK			11
 #define OP_STATUS			12
+#define OP_DUMP_CONFIG			13
 
 static char *prog_name;
 static char *lsname;
@@ -183,7 +184,7 @@ static void print_usage(void)
 	printf("Usage:\n");
 	printf("\n");
 	printf("dlm_tool [options] [join | leave | lockdump | lockdebug |\n"
-	       "                    ls | dump | log_plock | plocks |\n"
+	       "                    ls | dump | dump_config | log_plock | plocks |\n"
 	       "                    fence_ack]\n");
 	printf("\n");
 	printf("Options:\n");
@@ -340,6 +341,12 @@ static void decode_arguments(int argc, char **argv)
 			opt_ind = optind + 1;
 			need_lsname = 0;
 			break;
+		} else if (!strncmp(argv[optind], "dump_config", 11) &&
+			   (strlen(argv[optind]) == 11)) {
+			operation = OP_DUMP_CONFIG;
+			opt_ind = optind + 1;
+			need_lsname = 0;
+			break;
 		} else if (!strncmp(argv[optind], "plocks", 6) &&
 			   (strlen(argv[optind]) == 6)) {
 			operation = OP_PLOCKS;
@@ -1273,13 +1280,16 @@ static void do_plocks(char *name)
 	do_write(STDOUT_FILENO, buf, strlen(buf));
 }
 
-static void do_dump(void)
+static void do_dump(int op)
 {
 	char buf[DLMC_DUMP_SIZE];
 
 	memset(buf, 0, sizeof(buf));
 
-	dlmc_dump_debug(buf);
+	if (op == OP_DUMP)
+		dlmc_dump_debug(buf);
+	else if (op == OP_DUMP_CONFIG)
+		dlmc_dump_config(buf);
 
 	buf[DLMC_DUMP_SIZE-1] = '\0';
 
@@ -1334,7 +1344,11 @@ int main(int argc, char **argv)
 		break;
 
 	case OP_DUMP:
-		do_dump();
+		do_dump(operation);
+		break;
+
+	case OP_DUMP_CONFIG:
+		do_dump(operation);
 		break;
 
 	case OP_LOG_PLOCK:


More information about the cluster-commits mailing list