[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