[DRBD-cvs] svn commit by phil - r2387 - trunk/user - Moved drbdsetup to its final name

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Fri Aug 25 11:01:55 CEST 2006


Author: phil
Date: 2006-08-25 11:01:54 +0200 (Fri, 25 Aug 2006)
New Revision: 2387

Added:
   trunk/user/drbdsetup.c
Removed:
   trunk/user/drbdsetup_nl.c
Modified:
   trunk/user/Makefile
Log:
Moved drbdsetup to its final name


Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile	2006-08-25 08:50:47 UTC (rev 2386)
+++ trunk/user/Makefile	2006-08-25 09:01:54 UTC (rev 2387)
@@ -29,7 +29,7 @@
 
 drbdmeta-obj = drbdmeta.o drbdmeta_scanner.o drbdtool_common.o ../drbd/drbd_buildtag.o
 
-all: drbdadm drbdmeta drbdsetup_nl
+all: drbdadm drbdmeta drbdsetup
 
 drbdadm: $(drbdadm-obj)
 	$(CC) -o $@ $^ 
@@ -42,12 +42,9 @@
 
 # for debug:	flex -d -s -odrbdadm_scanner.c drbdadm_scanner.fl
 
-drbdsetup_nl: drbdsetup_nl.o drbdtool_common.o ../drbd/drbd_strings.o
+drbdsetup: $(drbdsetup-obj)
 	$(CC) -o $@ $^ 
 
-#drbdsetup: $(drbdsetup-obj)
-#	$(CC) -o $@ $^ 
-
 drbdmeta: $(drbdmeta-obj)
 	$(CC) -o $@ $^ 
 

Copied: trunk/user/drbdsetup.c (from rev 2386, trunk/user/drbdsetup_nl.c)
===================================================================
--- trunk/user/drbdsetup_nl.c	2006-08-25 08:50:47 UTC (rev 2386)
+++ trunk/user/drbdsetup.c	2006-08-25 09:01:54 UTC (rev 2387)
@@ -0,0 +1,1136 @@
+/*
+   drbdsetup.c
+
+   This file is part of drbd by Philipp Reisner.
+
+   Copyright (C) 1999-2006, Philipp Reisner <philipp.reisner at linbit.com>.
+   Copyright (C) 2002-2006, Lars Ellenberg <lars.ellenberg at linbit.com>.
+   Copyright (C) 2001-2006, LINBIT Information Technologies GmbH.
+
+   Copyright (C) 2000, Fábio Olivé Leite <olive at conectiva.com.br>.
+        Added sanity checks before using the device.
+
+   drbd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   drbd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with drbd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <mntent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+
+#include <linux/netlink.h>
+#include <linux/connector.h>
+
+#include <linux/drbd.h>
+#include <linux/drbd_config.h>
+#include <linux/drbd_tag_magic.h>
+#include <linux/drbd_limits.h>
+
+#include "drbdtool_common.h"
+
+#ifndef __CONNECTOR_H
+#error "You need to set KDIR while building drbdsetup."
+#endif
+
+struct drbd_tag_list {
+	struct nlmsghdr *nl_header;
+	struct cn_msg   *cn_header;
+	struct drbd_nl_cfg_req* drbd_p_header;
+	unsigned short *tag_list_start;
+	unsigned short *tag_list_cpos;
+	int    tag_size;
+};
+
+struct drbd_argument {
+	const char* name;
+	const enum drbd_tags tag;
+	int (*convert_function)(struct drbd_argument *,
+				struct drbd_tag_list *, 
+				char *);
+};
+
+struct drbd_option {
+	const char* name;
+	const char short_name;
+	const enum drbd_tags tag;
+	int (*convert_function)(struct drbd_option *,
+				struct drbd_tag_list *,
+				char *);
+	void (*show_function)(struct drbd_option *,unsigned short*);
+	union {
+		struct {
+			const unsigned long long min;
+			const unsigned long long max;
+			const unsigned long long def;
+			const unsigned char default_unit;
+		} numeric_param;
+		struct {
+			const char** handler_names;
+			const int number_of_handlers;
+			const int def;
+		} handler_param;
+	};
+};
+
+struct drbd_cmd {
+	const char* cmd;
+	const int packet_id;
+	int (*function)(struct drbd_cmd *, int, int, char **);
+	struct drbd_argument *args;
+	struct drbd_option *options;
+};
+
+
+// Connector functions
+int open_cn();
+int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size);
+int send_tag_list_cn(int, struct drbd_tag_list *, const int, int, int);
+int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size);
+void close_cn(int sk_nl);
+
+// other functions
+void print_command_usage(int i, const char *addinfo);
+// command functions
+int generic_config_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
+int show_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
+// convert functions for arguments
+int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+int conv_address(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
+// convert functions for options
+int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
+// show functions for options
+void show_numeric(struct drbd_option *od, unsigned short* tp);
+void show_handler(struct drbd_option *od, unsigned short* tp);
+void show_bit(struct drbd_option *od, unsigned short* tp);
+void show_string(struct drbd_option *od, unsigned short* tp);
+
+
+const char *on_error[] = {
+	[PassOn] = "pass_on",
+	[Panic]  = "panic",
+	[Detach] = "detach",
+};
+
+const char *fencing_n[] = {
+	[DontCare] = "dont-care",
+	[Resource] = "resource-only",
+	[Stonith]  = "resource-and-stonith",
+};
+
+const char *asb0p_n[] = {
+        [Disconnect]        = "disconnect",
+	[DiscardYoungerPri] = "discard-younger-primary",
+	[DiscardOlderPri]   = "discard-older-primary",
+	[DiscardLeastChg]   = "discard-least-changes",
+	[DiscardLocal]      = "discard-local",
+	[DiscardRemote]     = "discard-remote"
+};
+
+const char *asb1p_n[] = {
+	[Disconnect]        = "disconnect",
+	[Consensus]         = "consensus",
+	[DiscardSecondary]  = "discard-secondary",
+	[PanicPrimary]      = "panic-primary"
+};
+
+const char *asb2p_n[] = {
+	[Disconnect]        = "disconnect",
+	[PanicPrimary]      = "panic"
+};
+
+#define EN(N) \
+	conv_numeric, show_numeric, \
+	{ .numeric_param = { DRBD_ ## N ## _MIN, DRBD_ ## N ## _MAX, \
+		DRBD_ ## N ## _DEF ,0  } }
+#define EH(N,D) \
+	conv_handler, show_handler, { .handler_param = { N, ARRY_SIZE(N), \
+	DRBD_ ## D ## _DEF } }
+#define EB      conv_bit, show_bit, { } 
+#define ES      conv_string, show_string, { } 
+
+struct drbd_cmd commands[] = {
+	{"primary", P_primary, generic_config_cmd, NULL,
+	 (struct drbd_option[]) {
+		 { "overwrite-data-of-peer",'o',T_overwrite_peer, EB   },
+		 { NULL,0,0,NULL,NULL, { } }, }, },
+
+	{"secondary", P_secondary, generic_config_cmd, NULL, NULL },
+
+	{"disk", P_disk_conf, generic_config_cmd,
+	 (struct drbd_argument[]) {
+		 { "lower_dev",		T_backing_dev,	conv_block_dev },
+		 { "meta_data_dev",	T_meta_dev,	conv_block_dev },
+		 { "meta_data_index",	T_meta_dev_idx,	conv_md_idx },
+		 { NULL,                0,           	NULL}, },
+	 (struct drbd_option[]) {
+		 { "size",'d',		T_disk_size,	EN(DISK_SIZE_SECT) },
+		 { "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, { } }, }, },
+
+	{"detach", P_detach, generic_config_cmd, NULL, NULL },
+
+	{"net", P_net_conf, generic_config_cmd,
+	 (struct drbd_argument[]) {
+		 { "local_addr",	T_my_addr,	conv_address },
+		 { "remote_addr",	T_peer_addr,	conv_address },
+		 { "protocol",		T_wire_protocol,conv_protocol },
+ 		 { NULL,                0,           	NULL}, },
+	 (struct drbd_option[]) {
+		 { "timeout",'t',	T_timeout,	EN(TIMEOUT) },
+		 { "max-epoch-size",'e',T_max_epoch_size,EN(MAX_EPOCH_SIZE) },
+		 { "max-buffers",'b',	T_max_buffers,	EN(MAX_BUFFERS) },
+		 { "unplug-watermark",'u',T_unplug_watermark, EN(UNPLUG_WATERMARK) },
+		 { "connect-int",'c',	T_try_connect_int, EN(CONNECT_INT) },
+		 { "ping-int",'i',	T_ping_int,	   EN(PING_INT) },
+		 { "sndbuf-size",'S',	T_sndbuf_size,	   EN(SNDBUF_SIZE) },
+		 { "ko-count",'k',	T_ko_count,	   EN(KO_COUNT) },
+		 { "allow-two-primaries",'m',T_two_primaries, EB },
+		 { "cram-hmac-alg",'a',	T_cram_hmac_alg,   ES },
+		 { "shared-secret",'x',	T_shared_secret,   ES },
+		 { "after-sb-0pri",'A',	T_after_sb_0p,EH(asb0p_n,AFTER_SB_0P) },
+		 { "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, { } }, }, },
+
+	{"disconnect", P_disconnect, generic_config_cmd, NULL, NULL },
+
+	{"resize", P_resize, generic_config_cmd, NULL,
+	 (struct drbd_option[]) {
+		 { "size",'s',T_resize_size,		EN(DISK_SIZE_SECT) },
+		 { NULL,0,0,NULL,NULL, { } }, }, },
+
+	{"syncer", P_syncer_conf, generic_config_cmd, NULL,
+	 (struct drbd_option[]) {
+		 { "rate",'r',T_rate,			EN(RATE) },
+		 { "after",'a',T_after,			EN(AFTER) },
+		 { "al-extents",'e',T_al_extents,	EN(AL_EXTENTS) },
+		 { NULL,0,0,NULL,NULL, { } }, }, },
+
+	{"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", cmd_state,               0, 0, },
+	{"cstate", cmd_cstate,             0, 0, },
+	{"dstate", cmd_dstate,             0, 0, },
+	{"show-gi", cmd_show_gi,           0, 0, },
+	{"get-gi", cmd_get_gi,             0, 0, }, */
+	{"show", P_get_config, show_cmd, NULL, NULL },
+};
+
+#define EM(C) [ C - RetCodeBase ]
+
+static const char *error_messages[] = {
+	EM(NoError) = "No further Information available.",
+	EM(LAAlreadyInUse) = "Local address(port) already in use.",
+	EM(OAAlreadyInUse) = "Remote address(port) already in use.",
+	EM(LDNameInvalid) = "Can not open backing device.",
+	EM(MDNameInvalid) = "Can not open meta device.",
+	EM(LDAlreadyInUse) = "Lower device already in use.",
+	EM(LDNoBlockDev) = "Lower device is not a block device.",
+	EM(MDNoBlockDev) = "Meta device is not a block device.",
+	EM(LDOpenFailed) = "Open of lower device failed.",
+	EM(MDOpenFailed) = "Open of meta device failed.",
+	EM(LDDeviceTooSmall) = "Low.dev. smaller than requested DRBD-dev. size.",
+	EM(MDDeviceTooSmall) = "Meta device too small.",
+	EM(LDNoConfig) = "You have to use the disk command first.",
+	EM(LDMounted) = "Lower device is already mounted.",
+	EM(MDMounted) = "Meta device is already mounted.",
+	EM(LDMDInvalid) = "Lower device / meta device / index combination invalid.",
+	EM(LDDeviceTooLarge) = "Currently we only support devices up to 3.998TB.\n"
+	"(up to 2TB in case you do not have CONFIG_LBD set)"
+	"Contact office at linbit.com, if you need more.",
+	EM(MDIOError) = "IO error(s) orruced during initial access to meta-data.\n",
+	EM(MDInvalid) = "No valid meta-data signature found.\n)"
+	"Use 'drbdadm create-md res' to initialize meta-data area.\n",
+	EM(CRAMAlgNotAvail) = "The 'cram-hmac-alg' you specified is not known in )"
+	"the kernel.\n",
+	EM(CRAMAlgNotDigest) = "The 'cram-hmac-alg' you specified is not a digest.",
+	EM(KMallocFailed) = "kmalloc() failed. Out of memory?",
+	EM(DiscardNotAllowed) = "--discard-my-data not allowed when primary.",
+	EM(HaveDiskConfig) = "HaveDiskConfig",
+	EM(UnknownMandatoryTag) = "UnknownMandatoryTag",
+	EM(MinorNotKnown) = "MinorNotKnown",
+	EM(StateNotAllowed) = "StateNotAllowed",
+	EM(GotSignal) = "GotSignal",
+	EM(NoResizeDuringResync) = "Resize not allowed during resync.",
+	EM(APrimaryNodeNeeded) = "Need the a primary node to resize.",
+	EM(SyncAfterInvalid) = "The sync after minor number is invalid",
+	EM(SyncAfterCycle-) = "This would cause a sync-after dependency cycle",
+	EM(PauseFlagAlreadySet) = "PauseFlagAlreadySet",
+	EM(PauseFlagAlreadyClear) = "PauseFlagAlreadyClear",
+	EM(DiskLowerThanOutdated) = "DiskLowerThanOutdated",
+	EM(FailedToClaimMyself) = "FailedToClaimMyself",
+};
+
+char* cmdname = 0;
+
+int dump_tag_list(unsigned short *tlc)
+{
+	enum drbd_tags tag;
+	unsigned int tag_nr;
+	int len;
+	int integer;
+	char bit;
+	__u64 int64;
+	char* string;
+	int found_unknown=0;
+
+	while( (tag = *tlc++ ) != TT_END) {
+		len = *tlc++;
+		if(tag == TT_REMOVED) goto skip;
+
+		tag_nr = tag_number(tag);
+		if(tag_nr<ARRY_SIZE(tag_descriptions)) {
+			string = tag_descriptions[tag_nr].name;
+		} else {
+			string = "unknown tag";
+			found_unknown=1;
+		}
+		printf("# (%2d) %16s = ",tag_nr,string);
+		switch(tag_type(tag)) {
+		case TT_INTEGER: 
+			integer = *(int*)tlc;
+			printf("(integer) %d",integer);
+			break;
+		case TT_INT64:
+			int64 = *(__u64*)tlc;
+			printf("(int64) %lld",(long long)int64);
+			break;
+		case TT_BIT:
+			bit = *(char*)tlc;
+			printf("(bit) %s", bit ? "on" : "off");
+			break;
+		case TT_STRING:
+			string = (char*)tlc;
+			printf("(string)'%s'",string);
+			break;
+		}
+		printf(" \t[len: %u]\n",len);
+	skip:
+		tlc = (unsigned short*)((char*)tlc + len);
+	}
+
+	return found_unknown;
+}
+
+struct drbd_tag_list *create_tag_list(int size)
+{
+	struct drbd_tag_list *tl;
+	
+	tl = malloc(sizeof(struct drbd_tag_list));
+	tl->nl_header  = malloc(NLMSG_SPACE( sizeof(struct cn_msg) +
+					     sizeof(struct drbd_nl_cfg_req) + 
+					     size) );
+	tl->cn_header = NLMSG_DATA(tl->nl_header);
+	tl->drbd_p_header = (struct drbd_nl_cfg_req*) tl->cn_header->data;
+	tl->tag_list_start = tl->drbd_p_header->tag_list;
+	tl->tag_list_cpos = tl->tag_list_start;
+	tl->tag_size = size;
+
+	return tl;
+}
+
+void add_tag(struct drbd_tag_list *tl, int tag, void *data, int data_len)
+{
+	if( (tl->tag_list_cpos - tl->tag_list_start) + data_len 
+	    > tl->tag_size ) {
+		fprintf(stderr, "Tag list size exceeded!\n");
+		exit(20);
+	}
+	*tl->tag_list_cpos++ = tag;
+	*tl->tag_list_cpos++ = data_len;
+	memcpy(tl->tag_list_cpos,data,data_len);
+	tl->tag_list_cpos = (unsigned short*)((char*)tl->tag_list_cpos + data_len);
+}
+
+void free_tag_list(struct drbd_tag_list *tl)
+{
+	free(tl->nl_header);
+	free(tl);
+}
+
+int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
+{
+	struct stat sb;
+	int device_fd;
+	int err;
+
+	if ((device_fd = open(arg,O_RDWR))==-1) {
+		PERROR("Can not open device '%s'", arg);
+		return 20;
+	}
+
+	if ( (err=fstat(device_fd, &sb)) ) {
+		PERROR("fstat(%s) failed", arg);
+		return 20;
+	}
+
+	if(!S_ISBLK(sb.st_mode)) {
+		fprintf(stderr, "%s is not a block device!\n", arg);
+		return 20;
+	}
+	
+	close(device_fd);
+
+	add_tag(tl,ad->tag,arg,strlen(arg)+1); // include the null byte. 
+
+	return 0;
+}
+
+int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
+{
+	int idx;
+
+	if(!strcmp(arg,"internal")) idx = DRBD_MD_INDEX_FLEX_INT;
+	else if(!strcmp(arg,"flex")) idx = DRBD_MD_INDEX_FLEX_EXT;
+	else idx = m_strtoll(arg,1);
+
+	add_tag(tl,ad->tag,&idx,sizeof(idx));
+
+	return 0;
+}
+
+const char* addr_part(const char* s)
+{
+	static char buffer[200];
+	char *b;
+
+	b=strchr(s,':');
+	if(b) {
+		strncpy(buffer,s,b-s);
+		buffer[b-s]=0;
+		return buffer;
+	}
+	return s;
+}
+
+int port_part(const char* s)
+{
+	char *b;
+
+	b=strchr(s,':');
+
+	// m_strtoll_range(b+1,1, "port", DRBD_PORT_MIN, DRBD_PORT_MAX);
+	if(b) return m_strtoll(b+1,1);
+	return 7788;
+}
+
+unsigned long resolv(const char* name)
+{
+	unsigned long retval;
+
+	if((retval = inet_addr(name)) == INADDR_NONE ) {
+		struct hostent *he;
+		he = gethostbyname(name);
+		if (!he) {
+			PERROR("can not resolv the hostname");
+			exit(20);
+		}
+		retval = ((struct in_addr *)(he->h_addr_list[0]))->s_addr;
+	}
+	return retval;
+}
+
+int conv_address(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
+{
+	struct sockaddr_in addr;
+	int addr_len = sizeof(struct sockaddr_in);
+
+	addr.sin_port = htons(port_part(arg));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = resolv(addr_part(arg));
+
+	add_tag(tl,ad->tag,&addr,addr_len);
+
+	return 0;
+}
+
+int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
+{
+	int prot;
+
+	if(!strcmp(arg,"A") || !strcmp(arg,"a")) {
+		prot=DRBD_PROT_A;
+	} else if (!strcmp(arg,"B") || !strcmp(arg,"b")) {
+		prot=DRBD_PROT_B;
+	} else if (!strcmp(arg,"C") || !strcmp(arg,"c")) {
+		prot=DRBD_PROT_C;
+	} else {
+		fprintf(stderr, "'%s' is no valid protocol.\n", arg);
+		return 20;
+	}
+
+	add_tag(tl,ad->tag,&prot,sizeof(prot));
+
+	return 0;
+}
+
+int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
+{
+	char bit=1;
+
+	add_tag(tl,od->tag,&bit,sizeof(bit));
+
+	return 0;
+}
+
+int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
+{
+	const unsigned long long min = od->numeric_param.min;
+	const unsigned long long max = od->numeric_param.max;
+	const unsigned char default_unit = od->numeric_param.default_unit;
+	unsigned long long l;
+	int i;
+	char unit[] = {0,0};
+
+	l = m_strtoll(arg, default_unit);
+
+	if (min > l || l > max) {
+		unit[0] = default_unit > 1 ? default_unit : 0;
+		fprintf(stderr,"%s %s => %llu%s out of range [%llu..%llu]%s\n",
+			od->name, arg, l, unit, min, max, unit);
+		return(20);
+	}
+
+	switch(tag_type(od->tag)) {
+	case TT_INT64:
+		add_tag(tl,od->tag,&l,sizeof(l));
+		break;
+	case TT_INTEGER:
+		i=l;
+		add_tag(tl,od->tag,&i,sizeof(i));
+		break;
+	default:
+		fprintf(stderr, "internal error in conv_numeric()\n");
+	}
+	return 0;
+
+}
+
+int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
+{
+	const char** handler_names = od->handler_param.handler_names;
+	const int number_of_handlers = od->handler_param.number_of_handlers;
+	int i,nr;
+
+	for(i=0;i<number_of_handlers;i++) {
+		if(strcmp(arg,handler_names[i])==0) {
+			nr = i;
+			break;
+		}
+	}
+
+	add_tag(tl,od->tag,&nr,sizeof(nr));
+
+	return 0;
+}
+
+int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
+{
+	add_tag(tl,od->tag,arg,strlen(arg)+1);
+
+	return 0;
+}
+
+struct option *	make_longoptions(struct drbd_option* od)
+{
+	static struct option buffer[20];
+	int i=0;
+
+	while(od && od->name) {
+		buffer[i].name = od->name;
+		buffer[i].has_arg = tag_type(od->tag) == TT_BIT ? 
+			no_argument : required_argument ;
+		buffer[i].flag = NULL;
+		buffer[i].val = od->short_name;
+		if(i++ == 20) {
+			fprintf(stderr,"buffer in make_longoptions to small.\n");
+		}
+		od++;
+	}
+	
+	// The two omnipresent options:
+	buffer[i].name = "set-defaults";
+	buffer[i].has_arg = 0;
+	buffer[i].flag = NULL;
+	buffer[i].val = '(';
+	i++;
+
+	buffer[i].name = "create-device";
+	buffer[i].has_arg = 0;
+	buffer[i].flag = NULL;
+	buffer[i].val = ')';
+	i++;
+
+	buffer[i].name = NULL;
+	buffer[i].has_arg = 0;
+	buffer[i].flag = NULL;
+	buffer[i].val = 0;
+
+	return buffer;
+}
+
+struct drbd_option *find_opt_by_short_name(struct drbd_option *od, int c)
+{
+	while(od->name) {
+		if(od->short_name == c) return od;
+		od++;
+	}
+
+	return NULL;
+}
+
+void print_config_error( struct drbd_nl_cfg_reply *reply)
+{
+	int err_no = reply->ret_code;
+
+	if (err_no == NoError) return;
+	if (err_no == SS_Success) return;
+
+	if ( ( err_no >= AfterLastRetCode || err_no <= RetCodeBase ) &&
+	     ( err_no > SS_TowPrimaries || err_no < SS_CW_FailedByPeer) ) {
+		fprintf(stderr,"Error code %d unknown.\n"
+			"You should updated the drbd userland tools.\n",err_no);
+	} else {
+		if(err_no > RetCodeBase ) {
+			fprintf(stderr,"Failure: (%d) %s\n",err_no,
+				error_messages[err_no-RetCodeBase]);
+		} else {
+			fprintf(stderr,"State change failed: (%d) %s\n",
+				err_no, set_st_err_name(err_no));
+		}
+	}
+}
+
+#define RCV_SIZE NLMSG_SPACE(sizeof(struct cn_msg)+sizeof(struct drbd_nl_cfg_reply))
+
+int generic_config_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv)
+{
+	char buffer[ RCV_SIZE ];
+	struct drbd_nl_cfg_reply *reply;
+	struct drbd_argument *ad = cm->args;
+	struct drbd_option *od;
+	static struct option *lo;
+	struct drbd_tag_list *tl;
+	int c,i=0,rv=0,sk_nl;
+	int flags=0;
+
+	tl = create_tag_list(4096);
+
+	while(ad && ad->name) {
+		if(argc < i+1) {
+			fprintf(stderr,"Missing argument '%s'\n", ad->name);
+			print_command_usage(cm-commands, "");
+			rv=20;
+			break;
+		}
+		rv |= ad->convert_function(ad,tl,argv[i++]);
+		if(rv) break;
+		ad++;
+	}
+
+	lo = make_longoptions(cm->options);
+	opterr=0;
+	while( (c=getopt_long(argc,argv,make_optstring(lo,0),lo,0)) != -1 ) {
+		od = find_opt_by_short_name(cm->options,c);
+		if(od) rv |= od->convert_function(od,tl,optarg);
+		else {
+			if(c=='(') flags |= DRBD_NL_SET_DEFAULTS;
+			else if(c==')') flags |= DRBD_NL_CREATE_DEVICE;
+			else {
+				fprintf(stderr,
+					"%s: unrecognized option '%s'\n",
+					cmdname, argv[optind-1]);
+				rv=20;
+			}
+		}
+		if(rv) break;
+	}
+
+	add_tag(tl,TT_END,NULL,0); // close the tag list
+
+	if(rv == 0) {
+		// dump_tag_list(tl->tag_list_start);
+		sk_nl = open_cn();
+		if(sk_nl < 0) return 20;
+
+		send_tag_list_cn(sk_nl,tl,cm->packet_id,minor,flags);
+
+		receive_cn(sk_nl, (struct nlmsghdr*)buffer, RCV_SIZE );
+		close_cn(sk_nl);
+		reply = (struct drbd_nl_cfg_reply *)
+			((struct cn_msg *)NLMSG_DATA(buffer))->data;
+		print_config_error(reply);
+	}
+	free_tag_list(tl);
+
+	return rv;
+}
+
+#define ASSERT(exp) if (!(exp)) \
+		fprintf(stderr,"ASSERT( " #exp " ) in %s:%d\n", __FILE__,__LINE__);
+
+void show_numeric(struct drbd_option *od, unsigned short* tp)
+{
+	long long val;
+
+	switch(tag_type(*tp++)) {
+	case TT_INTEGER: 
+		ASSERT( *tp++ == sizeof(int) );
+		val = *(int*)tp;
+		break;
+	case TT_INT64:
+		ASSERT( *tp++ == sizeof(__u64) );
+		val = *(__u64*)tp;
+		break;
+	default: 
+		ASSERT(0);
+		val=0;
+	}
+
+	printf("\t%s\t\t%lld",od->name,val);
+	if(val == (long long) od->numeric_param.def) printf(" _is_default");
+	printf(";\n");
+}
+
+void show_handler(struct drbd_option *od, unsigned short* tp)
+{
+	const char** handler_names = od->handler_param.handler_names;
+	int i;
+
+	ASSERT( tag_type(*tp++) == TT_INTEGER );
+	ASSERT( *tp++ == sizeof(int) );
+	i = *(int*)tp;
+	printf("\t%s\t\t%s",od->name,handler_names[i]);
+	if( i == (long long)od->numeric_param.def) printf(" _is_default");
+	printf(";\n");
+}
+
+void show_bit(struct drbd_option *od, unsigned short* tp)
+{
+	ASSERT( tag_type(*tp++) == TT_BIT );
+	ASSERT( *tp++ == sizeof(char) );
+	if(*(char*)tp) printf("\t%s;\n",od->name);
+}
+
+void show_string(struct drbd_option *od, unsigned short* tp)
+{
+	ASSERT( tag_type(*tp++) == TT_STRING );
+	if( *tp++ > 0) printf("\t%s\t\t\"%s\";\n",od->name,(char*)tp);
+}
+
+unsigned short *look_for_tag(unsigned short *tlc, unsigned short tag)
+{
+	enum drbd_tags t;
+	int len;
+
+	while( (t = *tlc) != TT_END ) {
+		if(t == tag) return tlc;
+		tlc++;
+		len = *tlc++;
+		tlc = (unsigned short*)((char*)tlc + len);
+	}
+	return NULL;
+}
+
+void print_options(struct drbd_option *od, unsigned short *tlc, const char* sect_name)
+{
+	unsigned short *tp;
+	int opened = 0;
+
+	while(od->name) {
+		tp = look_for_tag(tlc,od->tag);
+		if(tp) {
+			if(!opened) {
+				opened=1;
+				printf("%s {\n",sect_name);
+			}
+			od->show_function(od,tp);
+			*tp = TT_REMOVED;
+		}
+		od++;
+	}
+	if(opened) {
+		printf("}\n");
+	}
+}
+
+char* consume_tag_string(enum drbd_tags tag, unsigned short *tlc)
+{
+	unsigned short *tp;
+	tp = look_for_tag(tlc,tag);
+	if(tp) {
+		*tp++ = TT_REMOVED;
+		if( *tp++ > 0) return (char*)tp;
+	}
+	return "";
+}
+
+int consume_tag_int(enum drbd_tags tag, unsigned short *tlc)
+{
+	unsigned short *tp;
+	tp = look_for_tag(tlc,tag);
+	if(tp) {
+		*tp++ = TT_REMOVED;
+		tp++;
+		return *(int *)tp;
+	}
+	return 0;
+}
+
+int show_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv)
+{
+	char buffer[ 4096 ];
+	struct drbd_tag_list *tl;
+	struct drbd_nl_cfg_reply *reply;
+	struct sockaddr_in *addr;
+	int sk_nl;
+	unsigned short *rtl;
+
+	int idx;
+	char* str;
+
+	ASSERT(cm->packet_id == P_get_config);
+
+	if(argc > 1) {
+		fprintf(stderr,"Ignoring excess arguments\n");
+	
+	}
+
+	tl = create_tag_list(2);
+	add_tag(tl,TT_END,NULL,0); // close the tag list
+
+	sk_nl = open_cn();
+	if(sk_nl < 0) return 20;
+
+	send_tag_list_cn(sk_nl,tl,cm->packet_id,minor,0);
+
+	receive_cn(sk_nl, (struct nlmsghdr*)buffer, 4096 );
+	close_cn(sk_nl);
+	reply = (struct drbd_nl_cfg_reply *)
+		((struct cn_msg *)NLMSG_DATA(buffer))->data;
+
+	rtl = reply->tag_list;
+
+	// find all commands that have options and print those...
+	for ( cm = commands ; cm < commands + ARRY_SIZE(commands) ; cm++ ) {
+		if(cm->options)
+			print_options(cm->options, rtl, cm->cmd);
+	}
+
+	// start of spagethi code...
+	idx = consume_tag_int(T_wire_protocol,rtl);
+	if(idx) printf("protocol %c;\n",'A'+idx-1);
+	str = consume_tag_string(T_backing_dev,rtl);
+	if(str) {
+		printf("_this_host {\n");
+		printf("\tdevice\t\t\"/dev/drbd%d\";\n",minor);
+		printf("\tdisk\t\t\"%s\";\n",str);
+		idx=consume_tag_int(T_meta_dev_idx,rtl);
+		switch(idx) {
+		case DRBD_MD_INDEX_INTERNAL:
+		case DRBD_MD_INDEX_FLEX_INT:
+			printf("\tmeta-disk\tinternal;\n");
+			consume_tag_string(T_meta_dev,rtl);
+			break;
+		case DRBD_MD_INDEX_FLEX_EXT:
+			printf("\tflexible-meta-disk\t\"%s\";\n",
+			       consume_tag_string(T_meta_dev,rtl));
+			break;
+		default:
+			printf("\tmeta-disk\t\"%s\" [ %d ];\n",
+			       consume_tag_string(T_meta_dev,rtl),idx);
+		}
+		str = consume_tag_string(T_my_addr,rtl);
+		if(str) {
+			addr = (struct sockaddr_in *)str;
+			printf("\taddress\t\t%s:%d;\n",
+			       inet_ntoa(addr->sin_addr),
+			       ntohs(addr->sin_port));
+		}
+		printf("}\n");
+	}
+
+	str = consume_tag_string(T_peer_addr,rtl);
+	if(str) {
+		printf("_remote_host {\n");
+		addr = (struct sockaddr_in *)str;
+		printf("\taddress\t\t%s:%d;\n",
+		       inet_ntoa(addr->sin_addr),
+		       ntohs(addr->sin_port));
+		printf("}\n");
+	}
+
+	if(dump_tag_list(reply->tag_list)) {
+		printf("# Found unknown tags, you should update your\n"
+		       "# userland tools\n");
+	}
+
+	return 0;
+}
+
+void print_command_usage(int i, const char *addinfo)
+    // CAUTION no range check for i
+{
+	struct drbd_argument *args;
+	struct drbd_option *options;
+#define  maxcol 100 // plus initial tab ...
+	static char line[maxcol+1];
+	int col,prevcol;
+
+	prevcol=col=0;
+
+	col += snprintf(line+col, maxcol-col, " %s", commands[i].cmd);
+	if ((args = commands[i].args)) {
+		while (args->name) {
+			col += snprintf(line+col, maxcol-col, " %s", args->name);
+			args++;
+		}
+					
+	}
+	if (col > maxcol) {
+		printf("%s\n\t",line);
+		col=0;
+	}
+	prevcol=col;
+	if ((options = commands[i].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);
+			}
+			if (col >= maxcol) {
+				line[prevcol]=0;
+				printf("%s\n\t",line);
+				prevcol=col=0;
+			} else {
+				prevcol=col;
+				options++;
+			}
+		}
+	}
+	line[col]=0;
+	printf("%s\n",line);
+	if (addinfo) {
+		printf("%s\n",addinfo);
+		exit(20);
+	}
+}
+
+void print_handler(const char* info, const char** handlers, unsigned int size)
+{
+	unsigned int i;
+
+	printf(info);
+
+	for(i=0;i<size;i++) {
+		if(handlers[i]) {
+			printf(" %s",handlers[i]);
+			if(i < size-1) printf(",");
+		}
+	}
+}
+
+void print_usage(const char* addinfo)
+{
+	size_t i;
+
+	printf("\nUSAGE: %s device command arguments options\n\n"
+	       "Device is usually /dev/drbdX or /dev/drbd/X.\n"
+	       "Commands, arguments and options are:\n",cmdname);
+
+
+	for (i = 0; i < ARRY_SIZE(commands); i++)
+		print_command_usage(i, 0);
+
+	printf("\nGeneral options: --create-device, --set-defaults\n");
+
+	print_handler("\non-io-error handlers:",on_error,ARRY_SIZE(on_error));
+	print_handler("\nfencing policies:",fencing_n,ARRY_SIZE(fencing_n));
+	print_handler("\nafter-sb-0pri handler:",asb0p_n,ARRY_SIZE(asb0p_n));
+	print_handler("\nafter-sb-1pri handler:",asb1p_n,ARRY_SIZE(asb1p_n));
+	print_handler("\nafter-sb-2pri handler:",asb2p_n,ARRY_SIZE(asb2p_n));
+
+	printf("\n\n");
+	/*
+	printf("\n\nVersion: "REL_VERSION" (api:%d)\n%s\n",
+	       API_VERSION, drbd_buildtag());
+	*/
+	if (addinfo)
+		printf("\n%s\n",addinfo);
+
+	exit(20);
+}
+
+int open_cn()
+{
+	int sk_nl;
+	int err;
+	struct sockaddr_nl my_nla;
+
+	sk_nl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+	if (sk_nl == -1) {
+		perror("socket() failed");
+		return -1;
+	}
+
+	my_nla.nl_family = AF_NETLINK;
+	my_nla.nl_groups = -1; //CN_IDX_DRBD; 
+	my_nla.nl_pid = getpid();
+
+	err = bind(sk_nl, (struct sockaddr *)&my_nla, sizeof(my_nla));
+	if (err == -1) {
+		err = errno;
+		perror("bind() failed");
+		if(err == ENOENT) {
+			fprintf(stderr,"DRBD driver not present in the kernel?\n");
+		}
+		return -1;
+	}
+
+	return sk_nl;
+}
+
+
+int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size)
+{
+	struct cn_msg *cn_hdr;
+	cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr);
+	int rr;
+
+	/* fill the netlink header */
+	nl_hdr->nlmsg_len = NLMSG_LENGTH(size - sizeof(struct nlmsghdr));
+	nl_hdr->nlmsg_type = NLMSG_DONE;
+	nl_hdr->nlmsg_flags = 0;
+	nl_hdr->nlmsg_seq = 0;
+	nl_hdr->nlmsg_pid = getpid();
+	/* fill the connector header */
+	cn_hdr->id.idx = CN_IDX_DRBD;
+	cn_hdr->seq = 0;
+	cn_hdr->ack = 0;
+	cn_hdr->len = size - sizeof(struct nlmsghdr) - sizeof(struct cn_msg);
+
+	rr = send(sk_nl,nl_hdr,nl_hdr->nlmsg_len,0);
+	if( rr != (ssize_t)nl_hdr->nlmsg_len) {
+		perror("send() failed");
+		return -1;
+	}
+	return rr;
+}
+
+int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size)
+{
+	int rr;
+
+	rr = recv(sk_nl,nl_hdr,size,0);
+
+	if( rr < 0 ) {
+		perror("recv() failed");
+		return -1;
+	}
+	return rr;
+}
+
+int send_tag_list_cn(int sk_nl, struct drbd_tag_list *tl, const int packet_id, int minor, int flags)
+{
+	tl->cn_header->id.val = packet_id;
+	tl->drbd_p_header->drbd_minor = minor;
+	tl->drbd_p_header->flags = flags;
+
+	return send_cn(sk_nl, tl->nl_header, (char*)tl->tag_list_cpos - 
+		       (char*)tl->nl_header);
+}
+
+void close_cn(int sk_nl)
+{
+	close(sk_nl);
+}
+
+int main(int argc, char** argv)
+{
+	int help = 0;
+	unsigned int i;
+	int minor;
+	int drbd_fd,lock_fd;
+	struct drbd_cmd *cmd;
+
+	chdir("/");
+
+	if ( (cmdname = strrchr(argv[0],'/')) )
+		argv[0] = ++cmdname;
+	else
+		cmdname = argv[0];
+
+	/* == '-' catches -h, --help, and similar */
+	if (argc > 1 && (!strcmp(argv[1],"help") || argv[1][0] == '-'))
+		help = 1;
+
+	if (argc < 3) print_usage(argc==1 ? 0 : " Insufficient arguments");
+
+	cmd=NULL;
+	for(i=0;i<ARRY_SIZE(commands);i++) {
+		if(strcmp(argv[2],commands[i].cmd)==0) {
+			cmd = commands+i;
+			break;
+		}
+	}
+
+	if(cmd) {
+		drbd_fd = dt_lock_open_drbd(argv[1], &lock_fd, 1 );
+		minor=dt_minor_of_dev(argv[1]);
+		commands[i].function(commands+i,minor,argc-3,argv+3);
+		dt_close_drbd_unlock(drbd_fd,lock_fd);
+	} else {
+		print_usage("invalid command");
+	}
+
+	return 0;
+}

Deleted: trunk/user/drbdsetup_nl.c
===================================================================
--- trunk/user/drbdsetup_nl.c	2006-08-25 08:50:47 UTC (rev 2386)
+++ trunk/user/drbdsetup_nl.c	2006-08-25 09:01:54 UTC (rev 2387)
@@ -1,1134 +0,0 @@
-/*
-   drbdsetup.c
-
-   This file is part of drbd by Philipp Reisner.
-
-   Copyright (C) 1999-2006, Philipp Reisner <philipp.reisner at linbit.com>.
-   Copyright (C) 2002-2006, Lars Ellenberg <lars.ellenberg at linbit.com>.
-   Copyright (C) 2001-2006, LINBIT Information Technologies GmbH.
-
-   Copyright (C) 2000, Fábio Olivé Leite <olive at conectiva.com.br>.
-        Added sanity checks before using the device.
-
-   drbd is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   drbd is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with drbd; see the file COPYING.  If not, write to
-   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-#define _GNU_SOURCE
-
-#include <errno.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <mntent.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <stdlib.h>
-
-#include <linux/netlink.h>
-#include <linux/connector.h>
-
-#include <linux/drbd.h>
-#include <linux/drbd_config.h>
-#include <linux/drbd_tag_magic.h>
-#include <linux/drbd_limits.h>
-
-#include "drbdtool_common.h"
-
-
-
-struct drbd_tag_list {
-	struct nlmsghdr *nl_header;
-	struct cn_msg   *cn_header;
-	struct drbd_nl_cfg_req* drbd_p_header;
-	unsigned short *tag_list_start;
-	unsigned short *tag_list_cpos;
-	int    tag_size;
-};
-
-struct drbd_argument {
-	const char* name;
-	const enum drbd_tags tag;
-	int (*convert_function)(struct drbd_argument *,
-				struct drbd_tag_list *, 
-				char *);
-};
-
-struct drbd_option {
-	const char* name;
-	const char short_name;
-	const enum drbd_tags tag;
-	int (*convert_function)(struct drbd_option *,
-				struct drbd_tag_list *,
-				char *);
-	void (*show_function)(struct drbd_option *,unsigned short*);
-	union {
-		struct {
-			const unsigned long long min;
-			const unsigned long long max;
-			const unsigned long long def;
-			const unsigned char default_unit;
-		} numeric_param;
-		struct {
-			const char** handler_names;
-			const int number_of_handlers;
-			const int def;
-		} handler_param;
-	};
-};
-
-struct drbd_cmd {
-	const char* cmd;
-	const int packet_id;
-	int (*function)(struct drbd_cmd *, int, int, char **);
-	struct drbd_argument *args;
-	struct drbd_option *options;
-};
-
-
-// Connector functions
-int open_cn();
-int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size);
-int send_tag_list_cn(int, struct drbd_tag_list *, const int, int, int);
-int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size);
-void close_cn(int sk_nl);
-
-// other functions
-void print_command_usage(int i, const char *addinfo);
-// command functions
-int generic_config_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
-int show_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv);
-// convert functions for arguments
-int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-int conv_address(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg);
-// convert functions for options
-int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
-int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
-int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
-int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg);
-// show functions for options
-void show_numeric(struct drbd_option *od, unsigned short* tp);
-void show_handler(struct drbd_option *od, unsigned short* tp);
-void show_bit(struct drbd_option *od, unsigned short* tp);
-void show_string(struct drbd_option *od, unsigned short* tp);
-
-
-const char *on_error[] = {
-	[PassOn] = "pass_on",
-	[Panic]  = "panic",
-	[Detach] = "detach",
-};
-
-const char *fencing_n[] = {
-	[DontCare] = "dont-care",
-	[Resource] = "resource-only",
-	[Stonith]  = "resource-and-stonith",
-};
-
-const char *asb0p_n[] = {
-        [Disconnect]        = "disconnect",
-	[DiscardYoungerPri] = "discard-younger-primary",
-	[DiscardOlderPri]   = "discard-older-primary",
-	[DiscardLeastChg]   = "discard-least-changes",
-	[DiscardLocal]      = "discard-local",
-	[DiscardRemote]     = "discard-remote"
-};
-
-const char *asb1p_n[] = {
-	[Disconnect]        = "disconnect",
-	[Consensus]         = "consensus",
-	[DiscardSecondary]  = "discard-secondary",
-	[PanicPrimary]      = "panic-primary"
-};
-
-const char *asb2p_n[] = {
-	[Disconnect]        = "disconnect",
-	[PanicPrimary]      = "panic"
-};
-
-#define EN(N) \
-	conv_numeric, show_numeric, \
-	{ .numeric_param = { DRBD_ ## N ## _MIN, DRBD_ ## N ## _MAX, \
-		DRBD_ ## N ## _DEF ,0  } }
-#define EH(N,D) \
-	conv_handler, show_handler, { .handler_param = { N, ARRY_SIZE(N), \
-	DRBD_ ## D ## _DEF } }
-#define EB      conv_bit, show_bit, { } 
-#define ES      conv_string, show_string, { } 
-
-struct drbd_cmd commands[] = {
-	{"primary", P_primary, generic_config_cmd, NULL,
-	 (struct drbd_option[]) {
-		 { "overwrite-data-of-peer",'o',T_overwrite_peer, EB   },
-		 { NULL,0,0,NULL,NULL, { } }, }, },
-
-	{"secondary", P_secondary, generic_config_cmd, NULL, NULL },
-
-	{"disk", P_disk_conf, generic_config_cmd,
-	 (struct drbd_argument[]) {
-		 { "lower_dev",		T_backing_dev,	conv_block_dev },
-		 { "meta_data_dev",	T_meta_dev,	conv_block_dev },
-		 { "meta_data_index",	T_meta_dev_idx,	conv_md_idx },
-		 { NULL,                0,           	NULL}, },
-	 (struct drbd_option[]) {
-		 { "size",'d',		T_disk_size,	EN(DISK_SIZE_SECT) },
-		 { "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, { } }, }, },
-
-	{"detach", P_detach, generic_config_cmd, NULL, NULL },
-
-	{"net", P_net_conf, generic_config_cmd,
-	 (struct drbd_argument[]) {
-		 { "local_addr",	T_my_addr,	conv_address },
-		 { "remote_addr",	T_peer_addr,	conv_address },
-		 { "protocol",		T_wire_protocol,conv_protocol },
- 		 { NULL,                0,           	NULL}, },
-	 (struct drbd_option[]) {
-		 { "timeout",'t',	T_timeout,	EN(TIMEOUT) },
-		 { "max-epoch-size",'e',T_max_epoch_size,EN(MAX_EPOCH_SIZE) },
-		 { "max-buffers",'b',	T_max_buffers,	EN(MAX_BUFFERS) },
-		 { "unplug-watermark",'u',T_unplug_watermark, EN(UNPLUG_WATERMARK) },
-		 { "connect-int",'c',	T_try_connect_int, EN(CONNECT_INT) },
-		 { "ping-int",'i',	T_ping_int,	   EN(PING_INT) },
-		 { "sndbuf-size",'S',	T_sndbuf_size,	   EN(SNDBUF_SIZE) },
-		 { "ko-count",'k',	T_ko_count,	   EN(KO_COUNT) },
-		 { "allow-two-primaries",'m',T_two_primaries, EB },
-		 { "cram-hmac-alg",'a',	T_cram_hmac_alg,   ES },
-		 { "shared-secret",'x',	T_shared_secret,   ES },
-		 { "after-sb-0pri",'A',	T_after_sb_0p,EH(asb0p_n,AFTER_SB_0P) },
-		 { "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, { } }, }, },
-
-	{"disconnect", P_disconnect, generic_config_cmd, NULL, NULL },
-
-	{"resize", P_resize, generic_config_cmd, NULL,
-	 (struct drbd_option[]) {
-		 { "size",'s',T_resize_size,		EN(DISK_SIZE_SECT) },
-		 { NULL,0,0,NULL,NULL, { } }, }, },
-
-	{"syncer", P_syncer_conf, generic_config_cmd, NULL,
-	 (struct drbd_option[]) {
-		 { "rate",'r',T_rate,			EN(RATE) },
-		 { "after",'a',T_after,			EN(AFTER) },
-		 { "al-extents",'e',T_al_extents,	EN(AL_EXTENTS) },
-		 { NULL,0,0,NULL,NULL, { } }, }, },
-
-	{"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", cmd_state,               0, 0, },
-	{"cstate", cmd_cstate,             0, 0, },
-	{"dstate", cmd_dstate,             0, 0, },
-	{"show-gi", cmd_show_gi,           0, 0, },
-	{"get-gi", cmd_get_gi,             0, 0, }, */
-	{"show", P_get_config, show_cmd, NULL, NULL },
-};
-
-#define EM(C) [ C - RetCodeBase ]
-
-static const char *error_messages[] = {
-	EM(NoError) = "No further Information available.",
-	EM(LAAlreadyInUse) = "Local address(port) already in use.",
-	EM(OAAlreadyInUse) = "Remote address(port) already in use.",
-	EM(LDNameInvalid) = "Can not open backing device.",
-	EM(MDNameInvalid) = "Can not open meta device.",
-	EM(LDAlreadyInUse) = "Lower device already in use.",
-	EM(LDNoBlockDev) = "Lower device is not a block device.",
-	EM(MDNoBlockDev) = "Meta device is not a block device.",
-	EM(LDOpenFailed) = "Open of lower device failed.",
-	EM(MDOpenFailed) = "Open of meta device failed.",
-	EM(LDDeviceTooSmall) = "Low.dev. smaller than requested DRBD-dev. size.",
-	EM(MDDeviceTooSmall) = "Meta device too small.",
-	EM(LDNoConfig) = "You have to use the disk command first.",
-	EM(LDMounted) = "Lower device is already mounted.",
-	EM(MDMounted) = "Meta device is already mounted.",
-	EM(LDMDInvalid) = "Lower device / meta device / index combination invalid.",
-	EM(LDDeviceTooLarge) = "Currently we only support devices up to 3.998TB.\n"
-	"(up to 2TB in case you do not have CONFIG_LBD set)"
-	"Contact office at linbit.com, if you need more.",
-	EM(MDIOError) = "IO error(s) orruced during initial access to meta-data.\n",
-	EM(MDInvalid) = "No valid meta-data signature found.\n)"
-	"Use 'drbdadm create-md res' to initialize meta-data area.\n",
-	EM(CRAMAlgNotAvail) = "The 'cram-hmac-alg' you specified is not known in )"
-	"the kernel.\n",
-	EM(CRAMAlgNotDigest) = "The 'cram-hmac-alg' you specified is not a digest.",
-	EM(KMallocFailed) = "kmalloc() failed. Out of memory?",
-	EM(DiscardNotAllowed) = "--discard-my-data not allowed when primary.",
-	EM(HaveDiskConfig) = "HaveDiskConfig",
-	EM(UnknownMandatoryTag) = "UnknownMandatoryTag",
-	EM(MinorNotKnown) = "MinorNotKnown",
-	EM(StateNotAllowed) = "StateNotAllowed",
-	EM(GotSignal) = "GotSignal",
-	EM(NoResizeDuringResync) = "Resize not allowed during resync.",
-	EM(APrimaryNodeNeeded) = "Need the a primary node to resize.",
-	EM(SyncAfterInvalid) = "The sync after minor number is invalid",
-	EM(SyncAfterCycle-) = "This would cause a sync-after dependency cycle",
-	EM(PauseFlagAlreadySet) = "PauseFlagAlreadySet",
-	EM(PauseFlagAlreadyClear) = "PauseFlagAlreadyClear",
-	EM(DiskLowerThanOutdated) = "DiskLowerThanOutdated",
-	EM(FailedToClaimMyself) = "FailedToClaimMyself",
-};
-
-char* cmdname = 0;
-
-int dump_tag_list(unsigned short *tlc)
-{
-	enum drbd_tags tag;
-	unsigned int tag_nr;
-	int len;
-	int integer;
-	char bit;
-	__u64 int64;
-	char* string;
-	int found_unknown=0;
-
-	while( (tag = *tlc++ ) != TT_END) {
-		len = *tlc++;
-		if(tag == TT_REMOVED) goto skip;
-
-		tag_nr = tag_number(tag);
-		if(tag_nr<ARRY_SIZE(tag_descriptions)) {
-			string = tag_descriptions[tag_nr].name;
-		} else {
-			string = "unknown tag";
-			found_unknown=1;
-		}
-		printf("# (%2d) %16s = ",tag_nr,string);
-		switch(tag_type(tag)) {
-		case TT_INTEGER: 
-			integer = *(int*)tlc;
-			printf("(integer) %d",integer);
-			break;
-		case TT_INT64:
-			int64 = *(__u64*)tlc;
-			printf("(int64) %lld",(long long)int64);
-			break;
-		case TT_BIT:
-			bit = *(char*)tlc;
-			printf("(bit) %s", bit ? "on" : "off");
-			break;
-		case TT_STRING:
-			string = (char*)tlc;
-			printf("(string)'%s'",string);
-			break;
-		}
-		printf(" \t[len: %u]\n",len);
-	skip:
-		tlc = (unsigned short*)((char*)tlc + len);
-	}
-
-	return found_unknown;
-}
-
-struct drbd_tag_list *create_tag_list(int size)
-{
-	struct drbd_tag_list *tl;
-	
-	tl = malloc(sizeof(struct drbd_tag_list));
-	tl->nl_header  = malloc(NLMSG_SPACE( sizeof(struct cn_msg) +
-					     sizeof(struct drbd_nl_cfg_req) + 
-					     size) );
-	tl->cn_header = NLMSG_DATA(tl->nl_header);
-	tl->drbd_p_header = (struct drbd_nl_cfg_req*) tl->cn_header->data;
-	tl->tag_list_start = tl->drbd_p_header->tag_list;
-	tl->tag_list_cpos = tl->tag_list_start;
-	tl->tag_size = size;
-
-	return tl;
-}
-
-void add_tag(struct drbd_tag_list *tl, int tag, void *data, int data_len)
-{
-	if( (tl->tag_list_cpos - tl->tag_list_start) + data_len 
-	    > tl->tag_size ) {
-		fprintf(stderr, "Tag list size exceeded!\n");
-		exit(20);
-	}
-	*tl->tag_list_cpos++ = tag;
-	*tl->tag_list_cpos++ = data_len;
-	memcpy(tl->tag_list_cpos,data,data_len);
-	tl->tag_list_cpos = (unsigned short*)((char*)tl->tag_list_cpos + data_len);
-}
-
-void free_tag_list(struct drbd_tag_list *tl)
-{
-	free(tl->nl_header);
-	free(tl);
-}
-
-int conv_block_dev(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
-{
-	struct stat sb;
-	int device_fd;
-	int err;
-
-	if ((device_fd = open(arg,O_RDWR))==-1) {
-		PERROR("Can not open device '%s'", arg);
-		return 20;
-	}
-
-	if ( (err=fstat(device_fd, &sb)) ) {
-		PERROR("fstat(%s) failed", arg);
-		return 20;
-	}
-
-	if(!S_ISBLK(sb.st_mode)) {
-		fprintf(stderr, "%s is not a block device!\n", arg);
-		return 20;
-	}
-	
-	close(device_fd);
-
-	add_tag(tl,ad->tag,arg,strlen(arg)+1); // include the null byte. 
-
-	return 0;
-}
-
-int conv_md_idx(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
-{
-	int idx;
-
-	if(!strcmp(arg,"internal")) idx = DRBD_MD_INDEX_FLEX_INT;
-	else if(!strcmp(arg,"flex")) idx = DRBD_MD_INDEX_FLEX_EXT;
-	else idx = m_strtoll(arg,1);
-
-	add_tag(tl,ad->tag,&idx,sizeof(idx));
-
-	return 0;
-}
-
-const char* addr_part(const char* s)
-{
-	static char buffer[200];
-	char *b;
-
-	b=strchr(s,':');
-	if(b) {
-		strncpy(buffer,s,b-s);
-		buffer[b-s]=0;
-		return buffer;
-	}
-	return s;
-}
-
-int port_part(const char* s)
-{
-	char *b;
-
-	b=strchr(s,':');
-
-	// m_strtoll_range(b+1,1, "port", DRBD_PORT_MIN, DRBD_PORT_MAX);
-	if(b) return m_strtoll(b+1,1);
-	return 7788;
-}
-
-unsigned long resolv(const char* name)
-{
-	unsigned long retval;
-
-	if((retval = inet_addr(name)) == INADDR_NONE ) {
-		struct hostent *he;
-		he = gethostbyname(name);
-		if (!he) {
-			PERROR("can not resolv the hostname");
-			exit(20);
-		}
-		retval = ((struct in_addr *)(he->h_addr_list[0]))->s_addr;
-	}
-	return retval;
-}
-
-int conv_address(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
-{
-	struct sockaddr_in addr;
-	int addr_len = sizeof(struct sockaddr_in);
-
-	addr.sin_port = htons(port_part(arg));
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = resolv(addr_part(arg));
-
-	add_tag(tl,ad->tag,&addr,addr_len);
-
-	return 0;
-}
-
-int conv_protocol(struct drbd_argument *ad, struct drbd_tag_list *tl, char* arg)
-{
-	int prot;
-
-	if(!strcmp(arg,"A") || !strcmp(arg,"a")) {
-		prot=DRBD_PROT_A;
-	} else if (!strcmp(arg,"B") || !strcmp(arg,"b")) {
-		prot=DRBD_PROT_B;
-	} else if (!strcmp(arg,"C") || !strcmp(arg,"c")) {
-		prot=DRBD_PROT_C;
-	} else {
-		fprintf(stderr, "'%s' is no valid protocol.\n", arg);
-		return 20;
-	}
-
-	add_tag(tl,ad->tag,&prot,sizeof(prot));
-
-	return 0;
-}
-
-int conv_bit(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
-{
-	char bit=1;
-
-	add_tag(tl,od->tag,&bit,sizeof(bit));
-
-	return 0;
-}
-
-int conv_numeric(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
-{
-	const unsigned long long min = od->numeric_param.min;
-	const unsigned long long max = od->numeric_param.max;
-	const unsigned char default_unit = od->numeric_param.default_unit;
-	unsigned long long l;
-	int i;
-	char unit[] = {0,0};
-
-	l = m_strtoll(arg, default_unit);
-
-	if (min > l || l > max) {
-		unit[0] = default_unit > 1 ? default_unit : 0;
-		fprintf(stderr,"%s %s => %llu%s out of range [%llu..%llu]%s\n",
-			od->name, arg, l, unit, min, max, unit);
-		return(20);
-	}
-
-	switch(tag_type(od->tag)) {
-	case TT_INT64:
-		add_tag(tl,od->tag,&l,sizeof(l));
-		break;
-	case TT_INTEGER:
-		i=l;
-		add_tag(tl,od->tag,&i,sizeof(i));
-		break;
-	default:
-		fprintf(stderr, "internal error in conv_numeric()\n");
-	}
-	return 0;
-
-}
-
-int conv_handler(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
-{
-	const char** handler_names = od->handler_param.handler_names;
-	const int number_of_handlers = od->handler_param.number_of_handlers;
-	int i,nr;
-
-	for(i=0;i<number_of_handlers;i++) {
-		if(strcmp(arg,handler_names[i])==0) {
-			nr = i;
-			break;
-		}
-	}
-
-	add_tag(tl,od->tag,&nr,sizeof(nr));
-
-	return 0;
-}
-
-int conv_string(struct drbd_option *od, struct drbd_tag_list *tl, char* arg)
-{
-	add_tag(tl,od->tag,arg,strlen(arg)+1);
-
-	return 0;
-}
-
-struct option *	make_longoptions(struct drbd_option* od)
-{
-	static struct option buffer[20];
-	int i=0;
-
-	while(od && od->name) {
-		buffer[i].name = od->name;
-		buffer[i].has_arg = tag_type(od->tag) == TT_BIT ? 
-			no_argument : required_argument ;
-		buffer[i].flag = NULL;
-		buffer[i].val = od->short_name;
-		if(i++ == 20) {
-			fprintf(stderr,"buffer in make_longoptions to small.\n");
-		}
-		od++;
-	}
-	
-	// The two omnipresent options:
-	buffer[i].name = "set-defaults";
-	buffer[i].has_arg = 0;
-	buffer[i].flag = NULL;
-	buffer[i].val = '(';
-	i++;
-
-	buffer[i].name = "create-device";
-	buffer[i].has_arg = 0;
-	buffer[i].flag = NULL;
-	buffer[i].val = ')';
-	i++;
-
-	buffer[i].name = NULL;
-	buffer[i].has_arg = 0;
-	buffer[i].flag = NULL;
-	buffer[i].val = 0;
-
-	return buffer;
-}
-
-struct drbd_option *find_opt_by_short_name(struct drbd_option *od, int c)
-{
-	while(od->name) {
-		if(od->short_name == c) return od;
-		od++;
-	}
-
-	return NULL;
-}
-
-void print_config_error( struct drbd_nl_cfg_reply *reply)
-{
-	int err_no = reply->ret_code;
-
-	if (err_no == NoError) return;
-	if (err_no == SS_Success) return;
-
-	if ( ( err_no >= AfterLastRetCode || err_no <= RetCodeBase ) &&
-	     ( err_no > SS_TowPrimaries || err_no < SS_CW_FailedByPeer) ) {
-		fprintf(stderr,"Error code %d unknown.\n"
-			"You should updated the drbd userland tools.\n",err_no);
-	} else {
-		if(err_no > RetCodeBase ) {
-			fprintf(stderr,"Failure: (%d) %s\n",err_no,
-				error_messages[err_no-RetCodeBase]);
-		} else {
-			fprintf(stderr,"State change failed: (%d) %s\n",
-				err_no, set_st_err_name(err_no));
-		}
-	}
-}
-
-#define RCV_SIZE NLMSG_SPACE(sizeof(struct cn_msg)+sizeof(struct drbd_nl_cfg_reply))
-
-int generic_config_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv)
-{
-	char buffer[ RCV_SIZE ];
-	struct drbd_nl_cfg_reply *reply;
-	struct drbd_argument *ad = cm->args;
-	struct drbd_option *od;
-	static struct option *lo;
-	struct drbd_tag_list *tl;
-	int c,i=0,rv=0,sk_nl;
-	int flags=0;
-
-	tl = create_tag_list(4096);
-
-	while(ad && ad->name) {
-		if(argc < i+1) {
-			fprintf(stderr,"Missing argument '%s'\n", ad->name);
-			print_command_usage(cm-commands, "");
-			rv=20;
-			break;
-		}
-		rv |= ad->convert_function(ad,tl,argv[i++]);
-		if(rv) break;
-		ad++;
-	}
-
-	lo = make_longoptions(cm->options);
-	opterr=0;
-	while( (c=getopt_long(argc,argv,make_optstring(lo,0),lo,0)) != -1 ) {
-		od = find_opt_by_short_name(cm->options,c);
-		if(od) rv |= od->convert_function(od,tl,optarg);
-		else {
-			if(c=='(') flags |= DRBD_NL_SET_DEFAULTS;
-			else if(c==')') flags |= DRBD_NL_CREATE_DEVICE;
-			else {
-				fprintf(stderr,
-					"%s: unrecognized option '%s'\n",
-					cmdname, argv[optind-1]);
-				rv=20;
-			}
-		}
-		if(rv) break;
-	}
-
-	add_tag(tl,TT_END,NULL,0); // close the tag list
-
-	if(rv == 0) {
-		// dump_tag_list(tl->tag_list_start);
-		sk_nl = open_cn();
-		if(sk_nl < 0) return 20;
-
-		send_tag_list_cn(sk_nl,tl,cm->packet_id,minor,flags);
-
-		receive_cn(sk_nl, (struct nlmsghdr*)buffer, RCV_SIZE );
-		close_cn(sk_nl);
-		reply = (struct drbd_nl_cfg_reply *)
-			((struct cn_msg *)NLMSG_DATA(buffer))->data;
-		print_config_error(reply);
-	}
-	free_tag_list(tl);
-
-	return rv;
-}
-
-#define ASSERT(exp) if (!(exp)) \
-		fprintf(stderr,"ASSERT( " #exp " ) in %s:%d\n", __FILE__,__LINE__);
-
-void show_numeric(struct drbd_option *od, unsigned short* tp)
-{
-	long long val;
-
-	switch(tag_type(*tp++)) {
-	case TT_INTEGER: 
-		ASSERT( *tp++ == sizeof(int) );
-		val = *(int*)tp;
-		break;
-	case TT_INT64:
-		ASSERT( *tp++ == sizeof(__u64) );
-		val = *(__u64*)tp;
-		break;
-	default: 
-		ASSERT(0);
-		val=0;
-	}
-
-	printf("\t%s\t\t%lld",od->name,val);
-	if(val == (long long) od->numeric_param.def) printf(" _is_default");
-	printf(";\n");
-}
-
-void show_handler(struct drbd_option *od, unsigned short* tp)
-{
-	const char** handler_names = od->handler_param.handler_names;
-	int i;
-
-	ASSERT( tag_type(*tp++) == TT_INTEGER );
-	ASSERT( *tp++ == sizeof(int) );
-	i = *(int*)tp;
-	printf("\t%s\t\t%s",od->name,handler_names[i]);
-	if( i == (long long)od->numeric_param.def) printf(" _is_default");
-	printf(";\n");
-}
-
-void show_bit(struct drbd_option *od, unsigned short* tp)
-{
-	ASSERT( tag_type(*tp++) == TT_BIT );
-	ASSERT( *tp++ == sizeof(char) );
-	if(*(char*)tp) printf("\t%s;\n",od->name);
-}
-
-void show_string(struct drbd_option *od, unsigned short* tp)
-{
-	ASSERT( tag_type(*tp++) == TT_STRING );
-	if( *tp++ > 0) printf("\t%s\t\t\"%s\";\n",od->name,(char*)tp);
-}
-
-unsigned short *look_for_tag(unsigned short *tlc, unsigned short tag)
-{
-	enum drbd_tags t;
-	int len;
-
-	while( (t = *tlc) != TT_END ) {
-		if(t == tag) return tlc;
-		tlc++;
-		len = *tlc++;
-		tlc = (unsigned short*)((char*)tlc + len);
-	}
-	return NULL;
-}
-
-void print_options(struct drbd_option *od, unsigned short *tlc, const char* sect_name)
-{
-	unsigned short *tp;
-	int opened = 0;
-
-	while(od->name) {
-		tp = look_for_tag(tlc,od->tag);
-		if(tp) {
-			if(!opened) {
-				opened=1;
-				printf("%s {\n",sect_name);
-			}
-			od->show_function(od,tp);
-			*tp = TT_REMOVED;
-		}
-		od++;
-	}
-	if(opened) {
-		printf("}\n");
-	}
-}
-
-char* consume_tag_string(enum drbd_tags tag, unsigned short *tlc)
-{
-	unsigned short *tp;
-	tp = look_for_tag(tlc,tag);
-	if(tp) {
-		*tp++ = TT_REMOVED;
-		if( *tp++ > 0) return (char*)tp;
-	}
-	return "";
-}
-
-int consume_tag_int(enum drbd_tags tag, unsigned short *tlc)
-{
-	unsigned short *tp;
-	tp = look_for_tag(tlc,tag);
-	if(tp) {
-		*tp++ = TT_REMOVED;
-		tp++;
-		return *(int *)tp;
-	}
-	return 0;
-}
-
-int show_cmd(struct drbd_cmd *cm, int minor, int argc, char **argv)
-{
-	char buffer[ 4096 ];
-	struct drbd_tag_list *tl;
-	struct drbd_nl_cfg_reply *reply;
-	struct sockaddr_in *addr;
-	int sk_nl;
-	unsigned short *rtl;
-
-	int idx;
-	char* str;
-
-	ASSERT(cm->packet_id == P_get_config);
-
-	if(argc > 1) {
-		fprintf(stderr,"Ignoring excess arguments\n");
-	
-	}
-
-	tl = create_tag_list(2);
-	add_tag(tl,TT_END,NULL,0); // close the tag list
-
-	sk_nl = open_cn();
-	if(sk_nl < 0) return 20;
-
-	send_tag_list_cn(sk_nl,tl,cm->packet_id,minor,0);
-
-	receive_cn(sk_nl, (struct nlmsghdr*)buffer, 4096 );
-	close_cn(sk_nl);
-	reply = (struct drbd_nl_cfg_reply *)
-		((struct cn_msg *)NLMSG_DATA(buffer))->data;
-
-	rtl = reply->tag_list;
-
-	// find all commands that have options and print those...
-	for ( cm = commands ; cm < commands + ARRY_SIZE(commands) ; cm++ ) {
-		if(cm->options)
-			print_options(cm->options, rtl, cm->cmd);
-	}
-
-	// start of spagethi code...
-	idx = consume_tag_int(T_wire_protocol,rtl);
-	if(idx) printf("protocol %c;\n",'A'+idx-1);
-	str = consume_tag_string(T_backing_dev,rtl);
-	if(str) {
-		printf("_this_host {\n");
-		printf("\tdevice\t\t\"/dev/drbd%d\";\n",minor);
-		printf("\tdisk\t\t\"%s\";\n",str);
-		idx=consume_tag_int(T_meta_dev_idx,rtl);
-		switch(idx) {
-		case DRBD_MD_INDEX_INTERNAL:
-		case DRBD_MD_INDEX_FLEX_INT:
-			printf("\tmeta-disk\tinternal;\n");
-			consume_tag_string(T_meta_dev,rtl);
-			break;
-		case DRBD_MD_INDEX_FLEX_EXT:
-			printf("\tflexible-meta-disk\t\"%s\";\n",
-			       consume_tag_string(T_meta_dev,rtl));
-			break;
-		default:
-			printf("\tmeta-disk\t\"%s\" [ %d ];\n",
-			       consume_tag_string(T_meta_dev,rtl),idx);
-		}
-		str = consume_tag_string(T_my_addr,rtl);
-		if(str) {
-			addr = (struct sockaddr_in *)str;
-			printf("\taddress\t\t%s:%d;\n",
-			       inet_ntoa(addr->sin_addr),
-			       ntohs(addr->sin_port));
-		}
-		printf("}\n");
-	}
-
-	str = consume_tag_string(T_peer_addr,rtl);
-	if(str) {
-		printf("_remote_host {\n");
-		addr = (struct sockaddr_in *)str;
-		printf("\taddress\t\t%s:%d;\n",
-		       inet_ntoa(addr->sin_addr),
-		       ntohs(addr->sin_port));
-		printf("}\n");
-	}
-
-	if(dump_tag_list(reply->tag_list)) {
-		printf("# Found unknown tags, you should update your\n"
-		       "# userland tools\n");
-	}
-
-	return 0;
-}
-
-void print_command_usage(int i, const char *addinfo)
-    // CAUTION no range check for i
-{
-	struct drbd_argument *args;
-	struct drbd_option *options;
-#define  maxcol 100 // plus initial tab ...
-	static char line[maxcol+1];
-	int col,prevcol;
-
-	prevcol=col=0;
-
-	col += snprintf(line+col, maxcol-col, " %s", commands[i].cmd);
-	if ((args = commands[i].args)) {
-		while (args->name) {
-			col += snprintf(line+col, maxcol-col, " %s", args->name);
-			args++;
-		}
-					
-	}
-	if (col > maxcol) {
-		printf("%s\n\t",line);
-		col=0;
-	}
-	prevcol=col;
-	if ((options = commands[i].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);
-			}
-			if (col >= maxcol) {
-				line[prevcol]=0;
-				printf("%s\n\t",line);
-				prevcol=col=0;
-			} else {
-				prevcol=col;
-				options++;
-			}
-		}
-	}
-	line[col]=0;
-	printf("%s\n",line);
-	if (addinfo) {
-		printf("%s\n",addinfo);
-		exit(20);
-	}
-}
-
-void print_handler(const char* info, const char** handlers, unsigned int size)
-{
-	unsigned int i;
-
-	printf(info);
-
-	for(i=0;i<size;i++) {
-		if(handlers[i]) {
-			printf(" %s",handlers[i]);
-			if(i < size-1) printf(",");
-		}
-	}
-}
-
-void print_usage(const char* addinfo)
-{
-	size_t i;
-
-	printf("\nUSAGE: %s device command arguments options\n\n"
-	       "Device is usually /dev/drbdX or /dev/drbd/X.\n"
-	       "Commands, arguments and options are:\n",cmdname);
-
-
-	for (i = 0; i < ARRY_SIZE(commands); i++)
-		print_command_usage(i, 0);
-
-	printf("\nGeneral options: --create-device, --set-defaults\n");
-
-	print_handler("\non-io-error handlers:",on_error,ARRY_SIZE(on_error));
-	print_handler("\nfencing policies:",fencing_n,ARRY_SIZE(fencing_n));
-	print_handler("\nafter-sb-0pri handler:",asb0p_n,ARRY_SIZE(asb0p_n));
-	print_handler("\nafter-sb-1pri handler:",asb1p_n,ARRY_SIZE(asb1p_n));
-	print_handler("\nafter-sb-2pri handler:",asb2p_n,ARRY_SIZE(asb2p_n));
-
-	printf("\n\n");
-	/*
-	printf("\n\nVersion: "REL_VERSION" (api:%d)\n%s\n",
-	       API_VERSION, drbd_buildtag());
-	*/
-	if (addinfo)
-		printf("\n%s\n",addinfo);
-
-	exit(20);
-}
-
-int open_cn()
-{
-	int sk_nl;
-	int err;
-	struct sockaddr_nl my_nla;
-
-	sk_nl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
-	if (sk_nl == -1) {
-		perror("socket() failed");
-		return -1;
-	}
-
-	my_nla.nl_family = AF_NETLINK;
-	my_nla.nl_groups = -1; //CN_IDX_DRBD; 
-	my_nla.nl_pid = getpid();
-
-	err = bind(sk_nl, (struct sockaddr *)&my_nla, sizeof(my_nla));
-	if (err == -1) {
-		err = errno;
-		perror("bind() failed");
-		if(err == ENOENT) {
-			fprintf(stderr,"DRBD driver not present in the kernel?\n");
-		}
-		return -1;
-	}
-
-	return sk_nl;
-}
-
-
-int send_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size)
-{
-	struct cn_msg *cn_hdr;
-	cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr);
-	int rr;
-
-	/* fill the netlink header */
-	nl_hdr->nlmsg_len = NLMSG_LENGTH(size - sizeof(struct nlmsghdr));
-	nl_hdr->nlmsg_type = NLMSG_DONE;
-	nl_hdr->nlmsg_flags = 0;
-	nl_hdr->nlmsg_seq = 0;
-	nl_hdr->nlmsg_pid = getpid();
-	/* fill the connector header */
-	cn_hdr->id.idx = CN_IDX_DRBD;
-	cn_hdr->seq = 0;
-	cn_hdr->ack = 0;
-	cn_hdr->len = size - sizeof(struct nlmsghdr) - sizeof(struct cn_msg);
-
-	rr = send(sk_nl,nl_hdr,nl_hdr->nlmsg_len,0);
-	if( rr != (ssize_t)nl_hdr->nlmsg_len) {
-		perror("send() failed");
-		return -1;
-	}
-	return rr;
-}
-
-int receive_cn(int sk_nl, struct nlmsghdr* nl_hdr, int size)
-{
-	int rr;
-
-	rr = recv(sk_nl,nl_hdr,size,0);
-
-	if( rr < 0 ) {
-		perror("recv() failed");
-		return -1;
-	}
-	return rr;
-}
-
-int send_tag_list_cn(int sk_nl, struct drbd_tag_list *tl, const int packet_id, int minor, int flags)
-{
-	tl->cn_header->id.val = packet_id;
-	tl->drbd_p_header->drbd_minor = minor;
-	tl->drbd_p_header->flags = flags;
-
-	return send_cn(sk_nl, tl->nl_header, (char*)tl->tag_list_cpos - 
-		       (char*)tl->nl_header);
-}
-
-void close_cn(int sk_nl)
-{
-	close(sk_nl);
-}
-
-int main(int argc, char** argv)
-{
-	int help = 0;
-	unsigned int i;
-	int minor;
-	int drbd_fd,lock_fd;
-	struct drbd_cmd *cmd;
-
-	chdir("/");
-
-	if ( (cmdname = strrchr(argv[0],'/')) )
-		argv[0] = ++cmdname;
-	else
-		cmdname = argv[0];
-
-	/* == '-' catches -h, --help, and similar */
-	if (argc > 1 && (!strcmp(argv[1],"help") || argv[1][0] == '-'))
-		help = 1;
-
-	if (argc < 3) print_usage(argc==1 ? 0 : " Insufficient arguments");
-
-	cmd=NULL;
-	for(i=0;i<ARRY_SIZE(commands);i++) {
-		if(strcmp(argv[2],commands[i].cmd)==0) {
-			cmd = commands+i;
-			break;
-		}
-	}
-
-	if(cmd) {
-		drbd_fd = dt_lock_open_drbd(argv[1], &lock_fd, 1 );
-		minor=dt_minor_of_dev(argv[1]);
-		commands[i].function(commands+i,minor,argc-3,argv+3);
-		dt_close_drbd_unlock(drbd_fd,lock_fd);
-	} else {
-		print_usage("invalid command");
-	}
-
-	return 0;
-}



More information about the drbd-cvs mailing list