[DRBD-cvs] svn commit by phil - r2144 - trunk/user - Finally a _sane_ implementation of the "drbdadm adjust"

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Tue Apr 11 18:18:18 CEST 2006


Author: phil
Date: 2006-04-11 18:18:17 +0200 (Tue, 11 Apr 2006)
New Revision: 2144

Modified:
   trunk/user/drbdadm.h
   trunk/user/drbdadm_adjust.c
   trunk/user/drbdadm_main.c
   trunk/user/drbdadm_parser.c
   trunk/user/drbdadm_parser.h
   trunk/user/drbdadm_scanner.fl
   trunk/user/drbdsetup.c
Log:
Finally a _sane_ implementation of the "drbdadm adjust" command.


Modified: trunk/user/drbdadm.h
===================================================================
--- trunk/user/drbdadm.h	2006-04-07 16:21:02 UTC (rev 2143)
+++ trunk/user/drbdadm.h	2006-04-11 16:18:17 UTC (rev 2144)
@@ -53,9 +53,13 @@
   char* name;
   char* device;
   char* disk;
+  int disk_major;
+  int disk_minor;
   char* address;
   char* port;
   char* meta_disk;
+  int meta_major;
+  int meta_minor;
   char* meta_index;
 };
 
@@ -64,7 +68,8 @@
   char* name;
   char* value;
   struct d_option* next;
-  int mentioned; // for the adjust command.
+  unsigned int mentioned  :1 ; // for the adjust command.
+  unsigned int is_default :1 ; // for the adjust command.
 };
 
 struct d_resource
@@ -97,6 +102,8 @@
 
 extern void uc_node(enum usage_count_type type);
 extern int adm_create_md(struct d_resource* res ,const char* cmd);
+extern void convert_discard_opt(struct d_resource* res);
+extern void convert_after_option(struct d_resource* res);
 
 extern char* config_file;
 extern int config_valid;

Modified: trunk/user/drbdadm_adjust.c
===================================================================
--- trunk/user/drbdadm_adjust.c	2006-04-07 16:21:02 UTC (rev 2143)
+++ trunk/user/drbdadm_adjust.c	2006-04-11 16:18:17 UTC (rev 2144)
@@ -28,6 +28,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -36,312 +37,176 @@
 #include "drbdadm.h"
 #include "drbdtool_common.h"
 
-/******
- This is a bit uggly.
- If you think you are clever, then consider to contribute a nicer
- implementation of adm_adjust()
+extern FILE* yyin;
+extern struct d_resource* parse_resource(char*);
 
-*/
-
-FILE *m_popen(int *pid,char** argv)
+static FILE *m_popen(int *pid,char** argv)
 {
-  int mpid;
-  int pipes[2];
+	int mpid;
+	int pipes[2];
 
-  if(pipe(pipes)) {
-    perror("Creation of pipes failed");
-    exit(E_exec_error);
-  }
+	if(pipe(pipes)) {
+		perror("Creation of pipes failed");
+		exit(E_exec_error);
+	}
 
-  mpid = fork();
-  if(mpid == -1) {
-    fprintf(stderr,"Can not fork");
-    exit(E_exec_error);
-  }
-  if(mpid == 0) {
-    close(pipes[0]); // close reading end
-    dup2(pipes[1],1); // 1 = stdout
-    close(pipes[1]);
-    execvp(argv[0],argv);
-    fprintf(stderr,"Can not exec");
-    exit(E_exec_error);
-  }
+	mpid = fork();
+	if(mpid == -1) {
+		fprintf(stderr,"Can not fork");
+		exit(E_exec_error);
+	}
+	if(mpid == 0) {
+		close(pipes[0]); // close reading end
+		dup2(pipes[1],1); // 1 = stdout
+		close(pipes[1]);
+		execvp(argv[0],argv);
+		fprintf(stderr,"Can not exec");
+		exit(E_exec_error);
+	}
 
-  close(pipes[1]); // close writing end
-  *pid=mpid;
-  return fdopen(pipes[0],"r");
+	close(pipes[1]); // close writing end
+	*pid=mpid;
+	return fdopen(pipes[0],"r");
 }
 
-int check_opt_b(FILE *in,char* name,struct d_option* base)
+/* option value equal? */
+static int ov_eq(char* val1, char* val2)
 {
-  struct d_option* o;
-  char uu[2],scs[200],sn[50];
-  int l,rv=0;
+	unsigned long long v1,v2;
 
-  strcpy(sn,name);
-  l=strlen(sn)-1;
-  sn[l]=0;
-  sprintf(scs," %*s%%[%c]\n",l,sn,name[l]);
+	if(val1 == NULL && val2 == NULL) return 1;
+	if(val1 == NULL || val2 == NULL) return 0;
 
-  if(fscanf(in,scs,uu)>0) {
-    o=find_opt(base,name);
-    if(o) o->mentioned=1;
-    else rv=1;
-  } // else { unexpected input... }
+	if(isdigit(val1[0])) {
+		v1 = m_strtoll(val1,0);
+		v2 = m_strtoll(val2,0);
 
-  //printf("check_opt_b(%s)=%d\n",name,rv);
-  return rv;
+		return v1 == v2;
+	}
+
+	return !strcmp(val1,val2);
 }
 
-int check_opt_d(FILE *in,char* name,char du, char* unit,struct d_option* base)
+static int opts_equal(struct d_option* conf, struct d_option* running)
 {
-  unsigned long  ul;
-  struct d_option* o;
-  char uu[2];
-  char scs[200];
-  int rv=0;
+	struct d_option* opt;
 
-  sprintf(scs," %s = %%lu %s (%%[d]efault)\n",name,unit);
-  if(fscanf(in,scs,&ul,uu)>0) {
-    o=find_opt(base,name);
-    if(o) {
-      o->mentioned=1;
-      if(m_strtoll(o->value,du) != ul) rv=1;
-    } else {
-      if( uu[0] != 'd' ) rv=1;
-    }
-  }
-  //printf("check_opt_d(%s)=%d\n",name,rv);
+	while(running) {
+		if((opt=find_opt(conf,running->name))) {
+			if(!ov_eq(running->value,opt->value)) {
+				/*printf("Value of '%s' differs: r=%s c=%s\n",
+				  opt->name,running->value,opt->value);*/
+				return 0;
+			}
+			opt->mentioned=1;
+		} else {
+			if(!running->is_default) {
+				/*printf("Only in running config %s: %s\n",
+				  running->name,running->value);*/
+				return 0;
+			}
+		}
+		running=running->next;
+	}
 
-  return rv;
+	while(conf) {
+		if(conf->mentioned==0) {
+			/*printf("Only in config file %s: %s\n",
+			  conf->name,conf->value);*/
+			return 0;
+		}
+		conf=conf->next;
+	}
+	return 1;
 }
 
-int check_opt_s(FILE *in,char* name,struct d_option* base)
+static int addr_equal(struct d_resource* conf, struct d_resource* running)
 {
-  struct d_option* o;
-  char scs[200];
-  char value[200];
-  int rv=0;
+	if (conf->peer == NULL && running->peer == NULL) return 1;
+	if (conf->peer == NULL || running->peer == NULL) return 0;
 
-  sprintf(scs," %s = %%s\n",name);
-  if(fscanf(in,scs,value)>0) {
-    o=find_opt(base,name);
-    if(o) {
-      o->mentioned=1;
-      if(strcmp(o->value,value)) rv=1;
-    } else {
-      rv=1;
-    }
-  }
+	return !strcmp(conf->me->address,  running->me->address) &&
+		!strcmp(conf->me->port,     running->me->port) &&
+		!strcmp(conf->peer->address,running->peer->address) &&
+		!strcmp(conf->peer->port,   running->peer->port) ;
+}
 
-  //printf("check_opt_s(%s)=%d [value=%s]\n",name,rv,value);
+static int proto_equal(struct d_resource* conf, struct d_resource* running)
+{
+	if (conf->protocol == NULL && running->protocol == NULL) return 1;
+	if (conf->protocol == NULL || running->protocol == NULL) return 0;
 
-  return rv;
+	return !strcmp(conf->protocol, running->protocol);
 }
 
-int complete(struct d_option* base)
+static int dev_eq(char* device_name, int g_major, int g_minor)
 {
-  int rv=0;
+	struct stat sb;
+	
+	if(stat(device_name,&sb)) return 0;
 
-  while(base) {
-    if(base->mentioned == 0) {
-      //printf("complete(): '%s'\n",base->name);
-      rv=1;
-      break;
-    }
-    base=base->next;
-  }
+	return major(sb.st_rdev) == g_major && minor(sb.st_rdev) == g_minor;
+}
 
-  //printf("complete()=%d\n",rv);
-
-  return rv;
+/* Are both internal, or are both not internal. */
+static int int_eq(char* m_conf, char* m_running)
+{
+	return !strcmp(m_conf,"internal") == !strcmp(m_running,"internal");
 }
 
-int m_fscanf(FILE *stream,const char *fmt, ...)
+static int disk_equal(struct d_host_info* conf, struct d_host_info* running)
 {
-  va_list ap;
-  int rv;
+	int eq = 1;
 
-  va_start(ap, fmt);
-  rv=vfscanf(stream,fmt,ap);
-  va_end(ap);
+	eq &= dev_eq(conf->disk,running->disk_major,running->disk_minor);
+	eq &= int_eq(conf->meta_disk,running->meta_disk);
+	if(!strcmp(conf->meta_disk,"internal")) return eq;
+	eq &= dev_eq(conf->meta_disk,running->meta_major,running->meta_minor);
 
-  if(rv==0) {
-    fprintf(stderr,"fscanf() faild for fmt string: %s\n",fmt);
-  }
-
-  return rv;
+	return eq;
 }
 
-
-/* NOTE
- * return before waitpit is a BUG. "goto out;" instead!
- *
+/*
  * calling drbdsetup again before waitpid("drbdsetup show") has a race with
  * the next ioctl failing because of the zombie still holding an open_cnt on
  * the drbd device. so don't do that.
  */
 int adm_adjust(struct d_resource* res,char* unused __attribute((unused)))
 {
-  char* argv[20];
-  int rv,pid,argc=0;
-  FILE *in;
-  char str1[255],str2[255];
-  unsigned long  ul1,ul2;
-  struct d_option* o;
-  char uu[2];
-  int do_attach=0;
-  int do_resize=0;
-  int do_connect=0;
-  int do_syncer=0;
+	char* argv[20];
+	int pid,argc=0;
+	struct d_resource* running;
+	int do_attach=0;
+	int do_connect=0;
+	int do_syncer=0;
 
-  struct stat sb;
-  int c_major, c_minor;
-  int err = 10;
+	argv[argc++]=drbdsetup;
+	argv[argc++]=res->me->device;
+	argv[argc++]="show";
+	argv[argc++]=0;
 
-  argv[argc++]=drbdsetup;
-  argv[argc++]=res->me->device;
-  argv[argc++]="show";
-  argv[argc++]=0;
+	yyin = m_popen(&pid,argv);
+	line = 1;
+	running = parse_resource("drbdsetup/show");
+	fclose(yyin);
+	waitpid(pid,0,0);
 
-  in=m_popen(&pid,argv);
+	convert_discard_opt(res);
+	convert_after_option(res);
 
-  rv=fscanf(in,"%[Not] configured",str1);
-  if(rv==1 && !strcmp("Not",str1) ) {
-    do_attach=1;
-    do_connect=1;
-    do_syncer=1;
-    goto do_up;
-  }
+	do_attach  = !opts_equal(res->disk_options, running->disk_options);
+	do_attach |= strcmp(res->me->device, running->me->device);
+	do_attach |= !disk_equal(res->me, running->me);
 
-  if (stat(res->me->disk, &sb)) {
-    PERROR("stat '%s' failed:", res->me->device);
-    goto out;
-  }
-  if (!S_ISBLK(sb.st_mode)) {
-    fprintf(stderr, "'%s' not a block device!\n", res->me->disk);
-    goto out;
-  }
-  rv=m_fscanf(in,"Lower device: %d:%d (%*[^)])\n",&c_major,&c_minor);
-  if( (rv!=2) || makedev(c_major,c_minor) != sb.st_rdev) do_attach=1;
+	do_connect  = !opts_equal(res->net_options, running->net_options);
+	do_connect |= !addr_equal(res,running);
+	do_connect |= !proto_equal(res,running);
 
-  if (strcmp("internal", res->me->meta_disk)) {
-    if (stat(res->me->meta_disk, &sb)) {
-      PERROR("stat '%s' failed:", res->me->meta_disk);
-      goto out;
-    }
-    if (!S_ISBLK(sb.st_mode)) {
-      fprintf(stderr, "'%s' not a block device!\n", res->me->disk);
-      goto out;
-    }
-  } else {
-    sb.st_rdev = 0;
-  }
+	do_syncer = !opts_equal(res->sync_options, running->sync_options);
 
-  rv = m_fscanf(in, "Meta device: %s (%[^)])\n", str1, str2);
-  if (rv == 1) {
-    if (!strcmp("internal", str1)) {
-      if (strcmp("internal", res->me->meta_disk))
-	do_attach = 1;
-    } else {
-      fprintf(stderr, "parse error, '%s' read, 'internal' expected\n", str1);
-      goto out;
-    }
-  }
-  if (rv == 2) {
-    sscanf(str1, "%d:%d", &c_major, &c_minor);
-    if ((rv != 2) || makedev(c_major,c_minor) != sb.st_rdev)
-      do_attach = 1;
-    rv = m_fscanf(in, "Meta index: %[0-9]\n", str1);
-    if (rv == 1) {
-      if (strcmp(str1, res->me->meta_index))
-	do_attach = 1;
-    } else {
-      fprintf(stderr, "parse error\n");
-      goto out;
-    }
-  }
+	if(do_attach)  schedule_dcmd(adm_attach,res,0);
+	if(do_syncer)  schedule_dcmd(adm_syncer,res,1);
+	if(do_connect) schedule_dcmd(adm_connect,res,2);
 
-  rv=m_fscanf(in,"Disk options%[:]\n",uu);
-  if(rv==1) {
-    do_resize |= check_opt_d(in,"size",'K',"KB",res->disk_options);
-    do_attach |= check_opt_s(in,"on-io-error",res->disk_options);
-
-    // Check if every options is also present in drbdsetup show's output.
-    o=res->disk_options;
-    while(o) {
-      if(o->mentioned == 0) {
-	if(!strcmp(o->name,"size")) do_resize=1;
-	   else do_attach=1;
-      }
-      o=o->next;
-    }
-  }
-
-  rv=m_fscanf(in,"Local address: %[0-9.]:%s\n",str1,str2);
-  if(rv!=2 || strcmp(str1,res->me->address) || strcmp(str2,res->me->port) ) {
-    do_connect=1;
-  }
-
-  rv=m_fscanf(in,"Remote address: %[0-9.]:%s\n",str1,str2);
-  if(rv!=2 || strcmp(str1,res->peer->address) ||
-     strcmp(str2,res->peer->port) ) {
-    do_connect=1;
-  }
-
-  rv=m_fscanf(in,"Wire protocol: %1[ABC]\n",str1);
-  if(rv!=1 || strcmp(str1,res->protocol) ) {
-    do_connect=1;
-  }
-
-  rv=m_fscanf(in,"Net options%[:]\n",uu);
-  if(rv==1) {
-    rv=m_fscanf(in," timeout = %lu.%lu sec (%[d]efault)\n",&ul1,&ul2,uu);
-    o=find_opt(res->net_options,"timeout");
-    if(o) {
-      o->mentioned=1;
-      if(m_strtoll(o->value,1) != ul1*10 + ul2) do_connect=1;
-    } else {
-      if( uu[0] != 'd' ) do_connect=1;
-    }
-
-    do_connect |= check_opt_d(in,"connect-int",1,"sec",res->net_options);
-    do_connect |= check_opt_d(in,"ping-int",1,"sec",res->net_options);
-    do_connect |= check_opt_d(in,"max-epoch-size",1,"",res->net_options);
-    do_connect |= check_opt_d(in,"max-buffers",1,"",res->net_options);
-    do_connect |= check_opt_d(in,"sndbuf-size",1,"",res->net_options);
-    do_connect |= check_opt_d(in,"ko-count",1,"",res->net_options);
-    do_connect |= check_opt_s(in,"on-disconnect",res->net_options);
-    do_connect |= check_opt_b(in,"allow-two-primaries",res->net_options);
-    do_connect |= complete(res->net_options);
-  }
-
-  rv=m_fscanf(in,"Syncer options%[:]\n",uu);
-  if(rv==1) {
-    do_syncer |= check_opt_d(in,"rate",'K',"KB/sec",res->sync_options);
-    do_syncer |= check_opt_d(in,"group",1,"",res->sync_options);
-    do_syncer |= check_opt_d(in,"al-extents",1,"",res->sync_options);
-    do_syncer |= check_opt_b(in,"skip-sync",res->sync_options);
-    do_syncer |= check_opt_b(in,"use-csums",res->sync_options);
-    do_syncer |= complete(res->sync_options);
-  } else do_syncer=1;
-
- do_up:
-  err = 0;
- out:
-  // drain, close, wait for drbdsetup to "officially die".
-  { static char drain[1024]; while (fgets(drain,1024,in)); }
-  fclose(in);
-  waitpid(pid,0,0);
-  if (err) return err;
-
-  if(do_attach) {
-    schedule_dcmd(adm_attach,res,0);
-    do_resize=0;
-  }
-  if(do_resize)  schedule_dcmd(adm_resize,res,0);
-  if(do_syncer)  schedule_dcmd(adm_syncer,res,1);
-  if(do_connect) schedule_dcmd(adm_connect,res,2);
-
-  return 0;
+	return 0;
 }

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-04-07 16:21:02 UTC (rev 2143)
+++ trunk/user/drbdadm_main.c	2006-04-11 16:18:17 UTC (rev 2144)
@@ -728,6 +728,24 @@
   return rv;
 }
 
+// need to convert discard-node-nodename to discard-local or discard-remote.
+void convert_discard_opt(struct d_resource* res)
+{
+  struct d_option* opt;
+
+  if ( (opt = find_opt(res->net_options, "after-sb-0pri")) ) {
+    if(!strncmp(opt->value,"discard-node-",13)) {
+      if(!strcmp(nodeinfo.nodename,opt->value+13)) {
+	free(opt->value);
+	opt->value=strdup("discard-local");
+      } else {
+	free(opt->value);
+	opt->value=strdup("discard-remote");
+      }
+    }
+  }
+}
+
 int adm_connect(struct d_resource* res,const char* unused __attribute((unused)))
 {
   char* argv[20];
@@ -742,16 +760,7 @@
   ssprintf(argv[argc++],"%s:%s",res->peer->address,res->peer->port);
   argv[argc++]=res->protocol;
 
-  // need to convert discard-node-nodename to discard-local or discard-remote.
-  if ( (opt = find_opt(res->net_options, "after-sb-0pri")) ) {
-    if(!strncmp(opt->value,"discard-node-",13)) {
-      if(!strcmp(nodeinfo.nodename,opt->value+13)) {
-	opt->value=strdup("discard-local");
-      } else {
-	opt->value=strdup("discard-remote");
-      }
-    }
-  }
+  convert_discard_opt(res);
 
   opt=res->net_options;
   make_options(opt);
@@ -767,6 +776,19 @@
 
 struct d_resource* res_by_name(const char *name);
 
+// Need to convert after from resourcename to minor_number.
+void convert_after_option(struct d_resource* res)
+{
+  struct d_option* opt;
+
+  if ( (opt = find_opt(res->sync_options, "after")) ) {
+    char *ptr;
+    ssprintf(ptr,"%d",dt_minor_of_dev(res_by_name(opt->value)->me->device));
+    free(opt->value);
+    opt->value=strdup(ptr);
+  }
+}
+
 int adm_syncer(struct d_resource* res,const char* unused __attribute((unused)))
 {
   char* argv[20];
@@ -777,13 +799,7 @@
   argv[argc++]=res->me->device;
   argv[argc++]="syncer";
 
-  // Need to convert after from resourcename to minor_number.
-  if ( (opt = find_opt(res->sync_options, "after")) ) {
-    char *ptr;
-    ssprintf(ptr,"%d",dt_minor_of_dev(res_by_name(opt->value)->me->device));
-    free(opt->value);
-    opt->value=strdup(ptr);
-  }
+  convert_after_option(res);
 
   opt=res->sync_options;
   make_options(opt);

Modified: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c	2006-04-07 16:21:02 UTC (rev 2143)
+++ trunk/user/drbdadm_parser.c	2006-04-11 16:18:17 UTC (rev 2144)
@@ -157,6 +157,7 @@
 	cn->name=name;
 	cn->value=value;
 	cn->mentioned=0;
+	cn->is_default=0;
 
 	return cn;
 }
@@ -271,7 +272,7 @@
 	int token;
 	enum range_checks rc;
 
-	struct d_option* options = NULL;
+	struct d_option* options = NULL, *ro = NULL;
 
 	EXP('{');
 	while(1) {
@@ -283,40 +284,30 @@
 			rc = yylval.rc;
 			EXP2(TK_STRING,TK_INTEGER);
 			range_check(rc,opt_name,yylval.txt);
-			options = APPEND(options,new_opt(opt_name,yylval.txt));
+			ro = new_opt(opt_name,yylval.txt);
+			options = APPEND(options,ro);
 		} else if ( token == '}' ) {
 			return options;
 		} else {
 			pe_expected("An option keyword");
 		}
-		EXP(';');
+		switch(yylex()) {
+		case TK__IS_DEFAULT:
+			ro->is_default=1;
+			EXP(';');
+			break;
+		case ';':
+			break;
+		default:
+			pe_expected("_is_default | ;");
+		}
 	}
 }
 
-static void parse_host_section(struct d_resource* res)
+static void parse_host_body(struct d_host_info *host, 
+			    struct d_resource* res,
+			    int require_all) 
 {
-	struct d_host_info *host;
-
-	c_section_start = line;
-
-	host=calloc(1,sizeof(struct d_host_info));
-	EXP(TK_STRING);
-	host->name = yylval.txt;
-	if(strcmp(host->name, nodeinfo.nodename) == 0) {
-		res->me = host;
-	} else {
-		if (res->peer) {
-			config_valid = 0;
-			fprintf(stderr,
-		"%s:%d: in resource %s, on %s { ... } ... on %s { ... }:\n"
-		"\tThere are multiple host sections for the peer.\n"
-		"\tMaybe misspelled local host name '%s'?\n",
-				config_file, c_section_start, res->name,
-				res->peer->name, host->name, nodeinfo.nodename);
-		}
-		res->peer = host;
-	}
-
 	EXP('{');
 	while(1) {
 		switch(yylex()) {
@@ -325,12 +316,26 @@
 			host->disk = yylval.txt;
 			check_uniq("disk", "%s:%s:%s","disk",
 				   host->name,yylval.txt);
+			switch(yylex()) {
+			case TK__MAJOR:
+				EXP(TK_INTEGER);
+				host->disk_major = atoi(yylval.txt);
+				EXP(TK__MINOR);
+				EXP(TK_INTEGER);
+				host->disk_minor = atoi(yylval.txt);
+				EXP(';');
+			case ';':
+				break;
+			default:
+				pe_expected("_major | ;");
+			}
 			break;
 		case TK_DEVICE:
 			EXP(TK_STRING);
 			host->device = yylval.txt;
 			check_uniq("device", "%s:%s:%s","device",
 				   host->name,yylval.txt);
+			EXP(';');
 			break;
 		case TK_ADDRESS:
 			EXP(TK_IPADDR);
@@ -339,6 +344,7 @@
 			EXP(TK_INTEGER);
 			host->port = yylval.txt;
 			range_check(R_PORT, "port", yylval.txt);
+			EXP(';');
 			break;
 		case TK_META_DISK:
 			EXP(TK_STRING);
@@ -348,6 +354,21 @@
 				EXP(TK_INTEGER);
 				host->meta_index = yylval.txt;
 				EXP(']');
+				EXP(';');
+			} else {
+				switch(yylex()) {
+				case TK__MAJOR:
+					EXP(TK_INTEGER);
+					host->meta_major = atoi(yylval.txt);
+					EXP(TK__MINOR);
+					EXP(TK_INTEGER);
+					host->meta_minor = atoi(yylval.txt);
+					EXP(';');
+				case ';':
+					break;
+				default:
+					pe_expected("_major | ;");
+				}
 			}
 			check_meta_disk(host);
 			break;
@@ -356,6 +377,7 @@
 			host->meta_disk = yylval.txt;
 			host->meta_index = strdup("flexible");
 			check_meta_disk(host);
+			EXP(';');
 			break;
 		case '}':
 			goto break_loop;
@@ -363,26 +385,69 @@
 			pe_expected("disk | device | address | meta-disk "
 				    "| flex-meta-disk");
 		}
-		EXP(';');
 	}
  break_loop:
+	if (!require_all) return;
 	if (!host->device)	derror(host,res,"device");
 	if (!host->disk)	derror(host,res,"disk");
 	if (!host->address)	derror(host,res,"address");
 	if (!host->meta_disk)	derror(host,res,"meta-disk");
 }
 
+static void parse_host_section(struct d_resource* res)
+{
+	struct d_host_info *host;
+
+	c_section_start = line;
+
+	host=calloc(1,sizeof(struct d_host_info));
+	EXP(TK_STRING);
+	host->name = yylval.txt;
+	if(strcmp(host->name, nodeinfo.nodename) == 0) {
+		res->me = host;
+	} else {
+		if (res->peer) {
+			config_valid = 0;
+			fprintf(stderr,
+		"%s:%d: in resource %s, on %s { ... } ... on %s { ... }:\n"
+		"\tThere are multiple host sections for the peer.\n"
+		"\tMaybe misspelled local host name '%s'?\n",
+				config_file, c_section_start, res->name,
+				res->peer->name, host->name, nodeinfo.nodename);
+		}
+		res->peer = host;
+	}
+	parse_host_body(host,res,1);
+}
+
+static void parse_drbdsetup_host_dump(struct d_resource* res, int local)
+{
+	struct d_host_info *host;
+
+	c_section_start = line;
+
+	host=calloc(1,sizeof(struct d_host_info));
+
+	if(local) {
+		res->me = host;
+	} else {
+		res->peer = host;
+	}
+
+	parse_host_body(host,res,0);
+}
+
 struct d_resource* parse_resource(char* res_name)
 {
 	struct d_resource* res;
+	int token;
 
 	res=calloc(1,sizeof(struct d_resource));
 	res->name = res_name;
 	res->next = NULL;
 
-	EXP('{');
 	while(1) {
-		switch(yylex()) {
+		switch((token=yylex())) {
 		case TK_PROTOCOL:
 			EXP(TK_STRING);
 			res->protocol=yylval.txt;
@@ -391,6 +456,12 @@
 		case TK_ON:
 			parse_host_section(res);
 			break;
+		case TK__THIS_HOST:
+			parse_drbdsetup_host_dump(res, 1);
+			break;
+		case TK__REMOTE_HOST:
+			parse_drbdsetup_host_dump(res, 0);
+			break;
 		case TK_DISK:
 			res->disk_options = parse_options(TK_DISK_SWITCH,
 							  TK_DISK_OPTION);
@@ -411,10 +482,12 @@
 			res->handlers =  parse_options(0,
 						       TK_HANDLER_OPTION);
 			break;
-		case '}': return res;
+		case '}': 
+		case 0:	
+			return res;
 		default:
-			pe_expected("protocol | on | disk | net | syncer |"
-				    " startup | handler");
+			pe_expected_got("protocol | on | disk | net | syncer |"
+					" startup | handler",token);
 		}
 	}
 }
@@ -442,9 +515,13 @@
 	while(1) {
 		switch(yylex()) {
 		case TK_GLOBAL: parse_global(); break;
-		case TK_COMMON: common = parse_resource("common"); break;
+		case TK_COMMON: 
+			EXP('{');
+			common = parse_resource("common"); 
+			break;
 		case TK_RESOURCE: 
 			EXP(TK_STRING);
+			EXP('{');
 			config = APPEND( config , parse_resource(yylval.txt) );
 			break;
 		case TK_SKIP: parse_skip(); break;

Modified: trunk/user/drbdadm_parser.h
===================================================================
--- trunk/user/drbdadm_parser.h	2006-04-07 16:21:02 UTC (rev 2143)
+++ trunk/user/drbdadm_parser.h	2006-04-11 16:18:17 UTC (rev 2144)
@@ -83,7 +83,12 @@
 	TK_USAGE_COUNT,
 	TK_ASK,
 	TK_YES,
-	TK_NO
+	TK_NO,
+	TK__IS_DEFAULT,
+	TK__MAJOR,
+	TK__MINOR,
+	TK__THIS_HOST,
+	TK__REMOTE_HOST
 };
 
 typedef struct YYSTYPE {

Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl	2006-04-07 16:21:02 UTC (rev 2143)
+++ trunk/user/drbdadm_scanner.fl	2006-04-11 16:18:17 UTC (rev 2144)
@@ -31,7 +31,7 @@
 IPV4ADDR	({SNUMB}"."){3}{SNUMB}
 WS		[ \t]
 OPCHAR		[{};\[\]:]
-DQSTRING	\"[^\"\\\n]{1,255}\"
+DQSTRING	\"[^\"\\\n]{0,255}\"
 STRING		[a-zA-Z0-9/._-]{1,80}
 LONG_STRING	[a-zA-Z0-9/._-]{81}
 
@@ -66,6 +66,11 @@
 meta-disk		{ DP; return TK_META_DISK;		}
 flexible-meta-disk	{ DP; return TK_FLEX_META_DISK;		}
 usage-count 		{ DP; return TK_USAGE_COUNT;		}
+_is_default 		{ DP; return TK__IS_DEFAULT;		}
+_major	 		{ DP; return TK__MAJOR;			}
+_minor	 		{ DP; return TK__MINOR;			}
+_this_host 		{ DP; return TK__THIS_HOST;		}
+_remote_host 		{ DP; return TK__REMOTE_HOST;		}
 size			{ DP; CP; RC(DISK_SIZE); return TK_DISK_OPTION;	}
 on-io-error		{ DP; CP; return TK_DISK_OPTION;	}
 fencing			{ DP; CP; return TK_DISK_OPTION;	}

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2006-04-07 16:21:02 UTC (rev 2143)
+++ trunk/user/drbdsetup.c	2006-04-11 16:18:17 UTC (rev 2144)
@@ -1322,13 +1322,28 @@
 #define SHOW_I(T,U,M,D) \
 printf("\t" T "\t%d",M); \
 if(M==D) printf(" _is_default"); \
-printf(";   # " U "\n")
+printf(";  \t# " U "\n")
 
+#define SHOW_IU(T,U1,U2,M,D) \
+printf("\t" T "\t%d",M); \
+if(M==D) printf(" _is_default"); \
+printf(U1";  \t# " U2 "\n")
+
 #define SHOW_H(T,M,D,H) \
 printf("\t" T "\t%s",H[M]); \
 if(M==D) printf(" _is_default"); \
 printf(";\n")
 
+#define SHOW_S(T,M,D) \
+printf("\t" T "\t\"%s\"",M); \
+if(!strcmp(M,D)) printf(" _is_default"); \
+printf(";\n")
+
+  if( cn.state.disk == Diskless && cn.state.conn == StandAlone)
+    {
+      printf("# not configured.\n");
+    }
+
   if( cn.state.disk > Diskless)
     {
       printf("disk {\n");
@@ -1350,10 +1365,12 @@
       SHOW_I("max-buffers","pages", cn.nconf.max_buffers, DEF_MAX_BUFFERS);
       SHOW_I("sndbuf-size","byte", cn.nconf.sndbuf_size, DEF_SNDBUF_SIZE);
       SHOW_I("ko-count","1", cn.nconf.ko_count, DEF_KO_COUNT);
-      SHOW_H("on-disconnect",cn.nconf.on_disconnect,DEF_ON_DISCONNECT,dh_names);
+      // SHOW_H("on-disconnect",cn.nconf.on_disconnect,DEF_ON_DISCONNECT,dh_names);
       SHOW_H("after-sb-0pri",cn.nconf.after_sb_0p,DEF_AFTER_SB_0P,asb0p_names);
       SHOW_H("after-sb-1pri",cn.nconf.after_sb_1p,DEF_AFTER_SB_0P,asb1p_names);
       SHOW_H("after-sb-2pri",cn.nconf.after_sb_2p,DEF_AFTER_SB_0P,asb2p_names);
+      SHOW_S("cram-hmac-alg",cn.nconf.cram_hmac_alg,"");
+      SHOW_S("shared-secret",cn.nconf.shared_secret,"");
       if( cn.nconf.two_primaries ) printf("\tallow-two-primaries;\n");
       if( cn.nconf.want_lose ) printf("\tdiscard-my-data;\n");
       printf("}\n");
@@ -1362,7 +1379,7 @@
   if( cn.state.conn > StandAlone)
     {
       printf("syncer {\n");
-      SHOW_I("rate\t","KByte/second", cn.sconf.rate, DEF_SYNC_RATE);
+      SHOW_IU("rate\t","K","(K)Byte/second", cn.sconf.rate, DEF_SYNC_RATE);
       SHOW_I("after\t","minor", cn.sconf.after, DEF_SYNC_AFTER);
       SHOW_I("al-extents","4MByte", cn.sconf.al_extents, DEF_SYNC_AL_EXTENTS);
       if( cn.sconf.skip ) printf("\tskip-sync;\n");



More information about the drbd-cvs mailing list