[DRBD-cvs] svn commit by phil - r2393 - in trunk: . drbd scripts user - Finished the new drbdsetup. Implemented the commands: e

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Sat Sep 9 12:42:18 CEST 2006


Author: phil
Date: 2006-09-09 12:42:16 +0200 (Sat, 09 Sep 2006)
New Revision: 2393

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_nl.c
   trunk/scripts/drbd
   trunk/scripts/drbd.gentoo
   trunk/user/drbdadm_main.c
   trunk/user/drbdsetup.c
Log:
Finished the new drbdsetup. 

Implemented the commands:
  events
  wait-connect
  wait-sync
  
./drbdsetup /dev/drbd0 events --all-devices might be usefull for 
all sorts for more intelligent cluster managers.

* The timeout parameters of wait-connect and wait-sync are still
  missing. (I will do them in my next session.)


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/ROADMAP	2006-09-09 10:42:16 UTC (rev 2393)
@@ -442,8 +442,9 @@
   Things to do:
   
   * Locking in userspace, to prevent multiple instances of drbdsetup
+  * The timeout options of wait-connect and wait-sync are still missing.
 
-  50% DONE
+  80% DONE
 
 15 Accept BIOs bigger than one page, probabely up to 32k (8 pages) 
   currently.

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/drbd/drbd_int.h	2006-09-09 10:42:16 UTC (rev 2393)
@@ -1222,6 +1222,7 @@
 
 void drbd_nl_cleanup(void);
 int __init drbd_nl_init(void);
+void drbd_bcast_state(drbd_dev *mdev);
 
 /*
  * inline helper functions

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/drbd/drbd_main.c	2006-09-09 10:42:16 UTC (rev 2393)
@@ -956,6 +956,9 @@
 		}
 	}
 
+	/* Inform userspace about the change... */
+	drbd_bcast_state(mdev);
+
 	/* Here we have the actions that are performed after a
 	   state change. This function might sleep */
 

Modified: trunk/drbd/drbd_nl.c
===================================================================
--- trunk/drbd/drbd_nl.c	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/drbd/drbd_nl.c	2006-09-09 10:42:16 UTC (rev 2393)
@@ -1487,6 +1487,36 @@
 	module_put(THIS_MODULE);
 }
 
+void drbd_bcast_state(drbd_dev *mdev)
+{
+	char buffer[sizeof(struct cn_msg)+
+		    sizeof(struct drbd_nl_cfg_reply)+
+		    sizeof(struct get_state_tag_len_struct)];
+	struct cn_msg *cn_reply = (struct cn_msg *) buffer;
+	struct drbd_nl_cfg_reply* reply = (struct drbd_nl_cfg_reply*)cn_reply->data;
+	unsigned short *tl = reply->tag_list;
+	static atomic_t seq = ATOMIC_INIT(2); // two.
+
+	WARN("drbd_bcast_state() got called\n");
+
+	tl = get_state_to_tags(mdev,(struct get_state*)&mdev->state,tl);
+	*tl++ = TT_END; /* Close the tag list */
+
+	cn_reply->id.idx = CN_IDX_DRBD;
+	cn_reply->id.val = CN_VAL_DRBD;
+
+	cn_reply->seq = atomic_add_return(1,&seq);
+	cn_reply->ack = 0; // not used here.
+	cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + 
+		(int)((char*)tl - (char*)reply->tag_list);
+	cn_reply->flags = 0;
+
+	reply->minor = mdev_to_minor(mdev);
+	reply->ret_code = NoError;
+
+	cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL);
+}
+
 int __init drbd_nl_init()
 {
 	static struct cb_id cn_id_drbd = { CN_IDX_DRBD, CN_VAL_DRBD };
@@ -1503,13 +1533,9 @@
 
 void drbd_nl_cleanup()
 {
-	static struct cb_id cn_id_drbd = { CN_IDX_DRBD, 0 };
-	int i;
+	static struct cb_id cn_id_drbd = { CN_IDX_DRBD, CN_VAL_DRBD };
 
-	for(i=0;i<P_nl_after_last_packet;i++) {
-		cn_id_drbd.val = i;
-		cn_del_callback(&cn_id_drbd);
-	}
+	cn_del_callback(&cn_id_drbd);
 }
 
 void drbd_nl_send_reply( struct cn_msg *req, 

Modified: trunk/scripts/drbd
===================================================================
--- trunk/scripts/drbd	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/scripts/drbd	2006-09-09 10:42:16 UTC (rev 2393)
@@ -95,7 +95,7 @@
 	adjust_with_progress
 	[ -d /var/lock/subsys ] && touch /var/lock/subsys/drbd  # for RedHat
 	echo "."
-	$DRBDADM wait_con_int # User interruptible version of wait_connect all
+	$DRBDADM wait-con-int # User interruptible version of wait-connect all
 	;;
     stop)
 	echo -n "Stopping all DRBD resources"

Modified: trunk/scripts/drbd.gentoo
===================================================================
--- trunk/scripts/drbd.gentoo	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/scripts/drbd.gentoo	2006-09-09 10:42:16 UTC (rev 2393)
@@ -23,7 +23,7 @@
 	    test -b /dev/drbd$i || mknod -m 0660 /dev/drbd$i b 147 $i; 
 	done
 	${DRBDADM} up all
-#	/sbin/drbdadm wait_connect all
+#	/sbin/drbdadm wait-connect all
 	eend $ret
 }
 

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/user/drbdadm_main.c	2006-09-09 10:42:16 UTC (rev 2393)
@@ -202,7 +202,7 @@
   { "pause-sync",        adm_generic_s, 1,1,1 },
   { "resume-sync",       adm_generic_s, 1,1,1 },
   { "adjust",            adm_adjust,    1,1,1 },
-  { "wait_connect",      adm_wait_c,    1,1,1 },
+  { "wait-connect",      adm_wait_c,    1,1,1 },
   { "state",             adm_generic_s, 1,1,0 },
   { "cstate",            adm_generic_s, 1,1,1 },
   { "dstate",            adm_generic_b, 1,1,1 },
@@ -211,7 +211,7 @@
   { "show-gi",           adm_generic_b, 1,1,0 },
   { "get-gi",            adm_generic_b, 1,1,0 },
   { "dump-md",           admm_generic,  1,1,0 },
-  { "wait_con_int",      adm_wait_ci,   1,0,1 },
+  { "wait-con-int",      adm_wait_ci,   1,0,1 },
   { "hidden-commands",   hidden_cmds,   1,0,0 },
   { "sh-nop",            sh_nop,        2,0,0 },
   { "sh-resources",      sh_resources,  2,0,0 },
@@ -863,7 +863,7 @@
 
   argv[argc++]=drbdsetup;
   argv[argc++]=res->me->device;
-  argv[argc++]="wait_connect";
+  argv[argc++]="wait-connect";
   opt=res->startup_options;
   make_options(opt);
   argv[argc++]=0;
@@ -1054,7 +1054,7 @@
     argc=0;
     argv[argc++]=drbdsetup;
     argv[argc++]=res->me->device;
-    argv[argc++]="wait_connect";
+    argv[argc++]="wait-connect";
     opt=res->startup_options;
     make_options(opt);
     argv[argc++]=0;

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2006-08-31 19:06:56 UTC (rev 2392)
+++ trunk/user/drbdsetup.c	2006-09-09 10:42:16 UTC (rev 2393)
@@ -45,6 +45,7 @@
 #include <string.h>
 #include <getopt.h>
 #include <stdlib.h>
+#include <time.h>
 
 #include <linux/netlink.h>
 #include <linux/connector.h>
@@ -85,18 +86,19 @@
 				struct drbd_tag_list *,
 				char *);
 	void (*show_function)(struct drbd_option *,unsigned short*);
+	int (*usage_function)(struct drbd_option *, char*, int);
 	union {
 		struct {
 			const long long min;
 			const long long max;
 			const long long def;
 			const unsigned char default_unit;
-		} numeric_param;
+		} numeric_param; // for conv_numeric
 		struct {
 			const char** handler_names;
 			const int number_of_handlers;
 			const int def;
-		} handler_param;
+		} handler_param; // conv_handler
 	};
 };
 
@@ -104,15 +106,20 @@
 	const char* cmd;
 	const int packet_id;
 	int (*function)(struct drbd_cmd *, int, int, char **);
+	void (*usage)(struct drbd_cmd *, int );
 	union {
 		struct {
 			struct drbd_argument *args;
 			struct drbd_option *options;
-		} cp;
+		} cp; // for generic_config_cmd, config_usage
 		struct {
 			int (*show_function)(struct drbd_cmd *, int, 
 					     unsigned short* );
-		} gp;
+		} gp; // for generic_get_cmd, get_usage
+		struct {
+			struct option *options;
+			int (*proc_event)();
+		} ep; // for events_cmd, events_usage
 	};
 };
 
@@ -131,7 +138,19 @@
 int generic_config_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
 int down_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
 int generic_get_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
+int events_cmd(struct drbd_cmd *cm, int minor, int argc,char **argv);
 
+// usage functions 
+void config_usage(struct drbd_cmd *cm, int);
+void get_usage(struct drbd_cmd *cm, int);
+void events_usage(struct drbd_cmd *cm, int);
+
+// sub usage functions for config_usage
+int numeric_opt_usage(struct drbd_option *option, char* str, int strlen);
+int handler_opt_usage(struct drbd_option *option, char* str, int strlen);
+int bit_opt_usage(struct drbd_option *option, char* str, int strlen);
+int string_opt_usage(struct drbd_option *option, char* str, int strlen);
+
 // sub commands for generic_get_cmd
 int show_scmd(struct drbd_cmd *cm, int minor, unsigned short *rtl);
 int state_scmd(struct drbd_cmd *cm, int minor, unsigned short *rtl);
@@ -157,6 +176,10 @@
 void show_bit(struct drbd_option *od, unsigned short* tp);
 void show_string(struct drbd_option *od, unsigned short* tp);
 
+// sub functions for events_cmd
+int print_state(unsigned int seq, int minor, drbd_state_t ns);
+int w_connected_state(unsigned int seq, int minor, drbd_state_t ns);
+int w_synced_state(unsigned int seq, int minor, drbd_state_t ns);
 
 const char *on_error[] = {
 	[PassOn] = "pass_on",
@@ -192,24 +215,30 @@
 };
 
 #define EN(N,U) \
-	conv_numeric, show_numeric, \
+	conv_numeric, show_numeric, numeric_opt_usage, \
 	{ .numeric_param = { DRBD_ ## N ## _MIN, DRBD_ ## N ## _MAX, \
 		DRBD_ ## N ## _DEF ,U  } }
 #define EH(N,D) \
-	conv_handler, show_handler, { .handler_param = { N, ARRY_SIZE(N), \
+	conv_handler, show_handler, handler_opt_usage, \
+	{ .handler_param = { N, ARRY_SIZE(N), \
 	DRBD_ ## D ## _DEF } }
-#define EB      conv_bit, show_bit, { } 
-#define ES      conv_string, show_string, { } 
+#define EB      conv_bit, show_bit, bit_opt_usage, { } 
+#define ES      conv_string, show_string, string_opt_usage, { } 
+#define CLOSE_OPTIONS  { NULL,0,0,NULL,NULL,NULL, { } }, }} }, },
 
+#define F_CONFIG_CMD	generic_config_cmd, config_usage
+#define F_GET_CMD	generic_get_cmd, get_usage
+#define F_EVENTS_CMD	events_cmd, events_usage
+
 struct drbd_cmd commands[] = {
-	{"primary", P_primary, generic_config_cmd, {{ NULL,
+	{"primary", P_primary, F_CONFIG_CMD, {{ NULL,
 	 (struct drbd_option[]) {
 		 { "overwrite-data-of-peer",'o',T_overwrite_peer, EB   },
-		 { NULL,0,0,NULL,NULL, { } }, }} }, },
+                 CLOSE_OPTIONS
 
-	{"secondary", P_secondary, generic_config_cmd, {{NULL, NULL}} },
+	{"secondary", P_secondary, F_CONFIG_CMD, {{NULL, NULL}} },
 
-	{"disk", P_disk_conf, generic_config_cmd, {{
+	{"disk", P_disk_conf, F_CONFIG_CMD, {{
 	 (struct drbd_argument[]) {
 		 { "lower_dev",		T_backing_dev,	conv_block_dev },
 		 { "meta_data_dev",	T_meta_dev,	conv_block_dev },
@@ -219,11 +248,11 @@
 		 { "size",'d',		T_disk_size,	EN(DISK_SIZE_SECT,'s') },
 		 { "on-io-error",'e',	T_on_io_error,	EH(on_error,ON_IO_ERROR) },
 		 { "fencing",'f',	T_fencing,      EH(fencing_n,FENCING) },
-		 { NULL,0,0,NULL,NULL, { } }, }, }} },
+		 CLOSE_OPTIONS
 
-	{"detach", P_detach, generic_config_cmd, {{NULL, NULL}} },
+	{"detach", P_detach, F_CONFIG_CMD, {{NULL, NULL}} },
 
-	{"net", P_net_conf, generic_config_cmd, {{
+	{"net", P_net_conf, F_CONFIG_CMD, {{
 	 (struct drbd_argument[]) {
 		 { "local_addr",	T_my_addr,	conv_address },
 		 { "remote_addr",	T_peer_addr,	conv_address },
@@ -245,36 +274,44 @@
 		 { "after-sb-1pri",'B',	T_after_sb_1p,EH(asb1p_n,AFTER_SB_1P) },
 		 { "after-sb-2pri",'C',	T_after_sb_2p,EH(asb2p_n,AFTER_SB_2P) },
 		 { "discard-my-data",'D', T_want_lose,     EB },
-		 { NULL,0,0,NULL,NULL, { } }, }, }} },
+		 CLOSE_OPTIONS
 
-	{"disconnect", P_disconnect, generic_config_cmd, {{NULL, NULL}} },
+	{"disconnect", P_disconnect, F_CONFIG_CMD, {{NULL, NULL}} },
 
-	{"resize", P_resize, generic_config_cmd, {{ NULL,
+	{"resize", P_resize, F_CONFIG_CMD, {{ NULL,
 	 (struct drbd_option[]) {
 		 { "size",'s',T_resize_size,		EN(DISK_SIZE_SECT,'s') },
-		 { NULL,0,0,NULL,NULL, { } }, }, }} },
+		 CLOSE_OPTIONS
 
-	{"syncer", P_syncer_conf, generic_config_cmd, {{ NULL,
+	{"syncer", P_syncer_conf, F_CONFIG_CMD, {{ NULL,
 	 (struct drbd_option[]) {
 		 { "rate",'r',T_rate,			EN(RATE,'k') },
 		 { "after",'a',T_after,			EN(AFTER,1) },
 		 { "al-extents",'e',T_al_extents,	EN(AL_EXTENTS,1) },
-		 { NULL,0,0,NULL,NULL, { } }, }, }} },
+		 CLOSE_OPTIONS
 
-	{"invalidate", P_invalidate, generic_config_cmd, {{ NULL, NULL }} },
-	{"invalidate-remote", P_invalidate_peer, generic_config_cmd, {{NULL, NULL}} },
-	{"pause-sync", P_pause_sync, generic_config_cmd, {{ NULL, NULL }} },
-	{"resume-sync", P_resume_sync, generic_config_cmd, {{ NULL, NULL }} },
-	{"suspend-io", P_suspend_io, generic_config_cmd, {{ NULL, NULL }} },
-	{"resume-io", P_resume_io, generic_config_cmd, {{ NULL, NULL }} },
-	{"outdate", P_outdate, generic_config_cmd, {{ NULL, NULL }} },
-	{"down",            0, down_cmd,  { {NULL, NULL }} },
-	{"state", P_get_state, generic_get_cmd, { .gp={ state_scmd} } },
-	{"cstate", P_get_state, generic_get_cmd, {.gp={ cstate_scmd} } },
-	{"dstate", P_get_state, generic_get_cmd, {.gp={ dstate_scmd} } },
-	{"show-gi", P_get_uuids, generic_get_cmd, {.gp={ uuids_scmd} }},
-	{"get-gi", P_get_uuids, generic_get_cmd, {.gp={ uuids_scmd} } },
-	{"show", P_get_config, generic_get_cmd, {.gp={ show_scmd} } },
+	{"invalidate", P_invalidate, F_CONFIG_CMD, {{ NULL, NULL }} },
+	{"invalidate-remote", P_invalidate_peer, F_CONFIG_CMD, {{NULL, NULL}} },
+	{"pause-sync", P_pause_sync, F_CONFIG_CMD, {{ NULL, NULL }} },
+	{"resume-sync", P_resume_sync, F_CONFIG_CMD, {{ NULL, NULL }} },
+	{"suspend-io", P_suspend_io, F_CONFIG_CMD, {{ NULL, NULL }} },
+	{"resume-io", P_resume_io, F_CONFIG_CMD, {{ NULL, NULL }} },
+	{"outdate", P_outdate, F_CONFIG_CMD, {{ NULL, NULL }} },
+	{"down",            0, down_cmd, get_usage, { {NULL, NULL }} },
+	{"state", P_get_state, F_GET_CMD, { .gp={ state_scmd} } },
+	{"cstate", P_get_state, F_GET_CMD, {.gp={ cstate_scmd} } },
+	{"dstate", P_get_state, F_GET_CMD, {.gp={ dstate_scmd} } },
+	{"show-gi", P_get_uuids, F_GET_CMD, {.gp={ uuids_scmd} }},
+	{"get-gi", P_get_uuids, F_GET_CMD, {.gp={ uuids_scmd} } },
+	{"show", P_get_config, F_GET_CMD, {.gp={ show_scmd} } },
+	{"events",          0, F_EVENTS_CMD, { .ep = {
+		(struct option[]) {
+			{ "unfiltered", no_argument, 0, 'u' },
+			{ "all-devices",no_argument, 0, 'd' },
+			{ 0,            0,           0,  0  } },
+		print_state } } },
+	{"wait-connect", 0, F_EVENTS_CMD, {.ep = {NULL,w_connected_state} } },
+	{"wait-sync", 0, F_EVENTS_CMD, {.ep = {NULL,w_synced_state} } },
 };
 
 #define EM(C) [ C - RetCodeBase ]
@@ -676,9 +713,9 @@
 	struct drbd_nl_cfg_reply *reply;
 	struct drbd_argument *ad = cm->cp.args;
 	struct drbd_option *od;
-	static struct option *lo;
+	struct option *lo;
 	struct drbd_tag_list *tl;
-	int c,i=0,rv=0,sk_nl;
+	int c,i=1,rv=0,sk_nl;
 	int flags=0;
 
 	tl = create_tag_list(4096);
@@ -1041,9 +1078,138 @@
 	return rv;
 }
 
-void print_command_usage(int i, const char *addinfo)
-    // CAUTION no range check for i
+int print_state(unsigned int seq, int minor, drbd_state_t ns)
 {
+	/*
+	char stime[20];
+	time_t now;
+	time(&now);
+	strftime(stime,20,"%a %e %T",gmtime(&now));
+	*/
+
+	printf("%u ST %d { cs:%s st:%s/%s ds:%s/%s %c%c%c%c }\n",
+	       seq,
+	       minor,
+	       conns_to_name(ns.conn),
+	       roles_to_name(ns.role),
+	       roles_to_name(ns.peer),
+	       disks_to_name(ns.disk),
+	       disks_to_name(ns.pdsk),
+	       ns.susp ? 's' : 'r',
+	       ns.aftr_isp ? 'a' : '-',
+	       ns.peer_isp ? 'p' : '-',
+	       ns.user_isp ? 'u' : '-' );
+
+	return 1;
+}
+
+int w_connected_state(unsigned int seq __attribute((unused)), 
+		      int minor __attribute((unused)), 
+		      drbd_state_t ns)
+{
+	if(ns.conn >= Connected) return 0;
+	return 1;
+}
+
+int w_synced_state(unsigned int seq __attribute((unused)), 
+		   int minor __attribute((unused)), 
+		   drbd_state_t ns)
+{
+	if(ns.conn == Connected || ns.conn < Unconnected ) return 0;
+	return 1;
+}
+
+int events_cmd(struct drbd_cmd *cm, int minor, int argc ,char **argv)
+{
+	char buffer[ 4096 ];
+	struct cn_msg *cn_reply;
+	struct drbd_nl_cfg_reply *reply;
+	struct drbd_tag_list *tl;
+	struct option *lo;
+	unsigned int seq=0;
+	int sk_nl,c,cont=1;
+	drbd_state_t state;
+	int unfiltered=0, all_devices=0;
+	
+	lo = cm->ep.options;
+
+	while( (c=getopt_long(argc,argv,make_optstring(lo,0),lo,0)) != -1 ) {
+		// This code block is actually only relevant for the "events" 
+		// command. not for wait-connect, or wait-sync.
+		switch(c) {
+		case 'u': unfiltered=1; break;
+		case 'd': all_devices=1; break;
+		}
+	}
+
+	if(optind > argc) {
+		fprintf(stderr,"Ignoring excess arguments\n");
+	}
+
+	sk_nl = open_cn();
+	if(sk_nl < 0) return 20;
+
+	// ask for the current state before waiting for state updates...
+	tl = create_tag_list(2);
+	add_tag(tl,TT_END,NULL,0); // close the tag list
+	send_tag_list_cn(sk_nl,tl,P_get_state,minor,0);
+
+	do {
+		receive_cn(sk_nl, (struct nlmsghdr*)buffer, 4096 );
+
+		cn_reply = (struct cn_msg *)NLMSG_DATA(buffer);
+		reply = (struct drbd_nl_cfg_reply *)cn_reply->data;
+
+		// dump_tag_list(reply->tag_list);
+		
+		if(!unfiltered && cn_reply->seq <= seq) continue;
+		seq = cn_reply->seq;
+
+		state.i = consume_tag_int(T_state_i,reply->tag_list);
+		
+		if(dump_tag_list(reply->tag_list)) {
+			printf("# Found unknown tags, you should update your\n"
+			       "# userland tools\n");
+		}
+
+		if( all_devices || minor == reply->minor ) {
+			cont=cm->ep.proc_event(cn_reply->seq, reply->minor, state);
+		}
+	} while(cont);
+
+	close_cn(sk_nl);
+
+	return 0;
+}
+
+int numeric_opt_usage(struct drbd_option *option, char* str, int strlen)
+{
+	return snprintf(str,strlen," [{--%s|-%c} %lld ... %lld]",
+			option->name, option->short_name,
+			option->numeric_param.min,
+			option->numeric_param.max);
+}
+
+int handler_opt_usage(struct drbd_option *option, char* str, int strlen)
+{
+	return snprintf(str,strlen," [{--%s|-%c} hdlr]",
+			option->name, option->short_name);
+}
+
+int bit_opt_usage(struct drbd_option *option, char* str, int strlen)
+{
+	return snprintf(str,strlen," [{--%s|-%c}]",
+			option->name, option->short_name);
+}
+
+int string_opt_usage(struct drbd_option *option, char* str, int strlen)
+{
+	return snprintf(str,strlen," [{--%s|-%c} <str>]",
+			option->name, option->short_name);
+}
+
+void config_usage(struct drbd_cmd *cm, int brief __attribute((unused)))
+{
 	struct drbd_argument *args;
 	struct drbd_option *options;
 #define  maxcol 100 // plus initial tab ...
@@ -1052,12 +1218,9 @@
 
 	prevcol=col=0;
 
-	col += snprintf(line+col, maxcol-col, " %s", commands[i].cmd);
+	col += snprintf(line+col, maxcol-col, " %s", cm->cmd);
 
-	// Only those config commands have arguments and options...
-	if(commands[i].function != generic_config_cmd) goto out;
-
-	if ((args = commands[i].cp.args)) {
+	if ((args = cm->cp.args)) {
 		while (args->name) {
 			col += snprintf(line+col, maxcol-col, " %s", args->name);
 			args++;
@@ -1069,17 +1232,9 @@
 		col=0;
 	}
 	prevcol=col;
-	if ((options = commands[i].cp.options)) {
+	if ((options = cm->cp.options)) {
 		while (options->name) {
-			if (tag_type(options->tag) == TT_BIT) {
-				col += snprintf(line+col, maxcol-col,
-						" [{--%s|-%c}]",
-						options->name, options->short_name);
-			} else {
-				col += snprintf(line+col, maxcol-col,
-						" [{--%s|-%c} val]",
-						options->name, options->short_name);
-			}
+			col += options->usage_function(options,line+col,maxcol-col);
 			if (col >= maxcol) {
 				line[prevcol]=0;
 				printf("%s\n\t",line);
@@ -1092,8 +1247,31 @@
 	}
 	line[col]=0;
 
- out:
 	printf("%s\n",line);
+}
+
+void get_usage(struct drbd_cmd *cm, int brief __attribute((unused)))
+{
+	printf(" %s\n", cm->cmd);
+}
+
+void events_usage(struct drbd_cmd *cm, int brief __attribute((unused)))
+{
+	struct option *lo;
+	printf(" %s", cm->cmd);
+
+	lo = cm->ep.options;
+	while(lo && lo->name) {
+		printf(" [{--%s|-%c}]",lo->name,lo->val);
+		lo++;
+	}
+	printf("\n");
+}
+
+void print_command_usage(int i, const char *addinfo)
+{
+	commands[i].usage(commands+i,0);
+
 	if (addinfo) {
 		printf("%s\n",addinfo);
 		exit(20);
@@ -1189,7 +1367,7 @@
 	nl_hdr->nlmsg_pid = getpid();
 	/* fill the connector header */
 	cn_hdr->id.idx = CN_IDX_DRBD;
-	cn_hdr->seq = 0;
+	cn_hdr->seq = 1;
 	cn_hdr->ack = 0;
 	cn_hdr->len = size - sizeof(struct nlmsghdr) - sizeof(struct cn_msg);
 
@@ -1252,10 +1430,12 @@
 	cmd=find_cmd_by_name(argv[2]);
 
 	if(cmd) {
-		drbd_fd = dt_lock_open_drbd(argv[1], &lock_fd, 1 );
+		//drbd_fd = dt_lock_open_drbd(argv[1], &lock_fd, 1 );
 		minor=dt_minor_of_dev(argv[1]);
-		rv = cmd->function(cmd,minor,argc-3,argv+3);
-		dt_close_drbd_unlock(drbd_fd,lock_fd);
+		rv = cmd->function(cmd,minor,argc-2,argv+2);
+		// by passing argc-2, argv+2 the function has the command name
+		// in argv[0], e.g. "syncer"
+		//dt_close_drbd_unlock(drbd_fd,lock_fd);
 	} else {
 		print_usage("invalid command");
 	}



More information about the drbd-cvs mailing list