From drbd-cvs at lists.linbit.com  Mon Jul  3 17:38:38 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul  3 17:38:40 2006
Subject: [DRBD-cvs] svn commit by phil - r2254 - trunk/user - Thanks to the
	report of Simon Graham... 
Message-ID: <20060703153839.1664E2CDC4D9@mail.linbit.com>

Author: phil
Date: 2006-07-03 17:38:37 +0200 (Mon, 03 Jul 2006)
New Revision: 2254

Modified:
   trunk/user/drbdadm_adjust.c
   trunk/user/drbdadm_main.c
Log:
Thanks to the report of Simon Graham...



Modified: trunk/user/drbdadm_adjust.c
===================================================================
--- trunk/user/drbdadm_adjust.c	2006-06-30 13:03:02 UTC (rev 2253)
+++ trunk/user/drbdadm_adjust.c	2006-07-03 15:38:37 UTC (rev 2254)
@@ -191,9 +191,6 @@
 	fclose(yyin);
 	waitpid(pid,0,0);
 
-	convert_discard_opt(res);
-	convert_after_option(res);
-
 	do_attach  = !opts_equal(res->disk_options, running->disk_options);
 	if(running->me) {
 		do_attach |= strcmp(res->me->device, running->me->device);

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-06-30 13:03:02 UTC (rev 2253)
+++ trunk/user/drbdadm_main.c	2006-07-03 15:38:37 UTC (rev 2254)
@@ -775,8 +775,6 @@
   ssprintf(argv[argc++],"%s:%s",res->peer->address,res->peer->port);
   argv[argc++]=res->protocol;
 
-  convert_discard_opt(res);
-
   opt=res->net_options;
   make_options(opt);
 
@@ -816,8 +814,6 @@
   argv[argc++]=res->me->device;
   argv[argc++]="syncer";
 
-  convert_after_option(res);
-
   opt=res->sync_options;
   make_options(opt);
   argv[argc++]=0;
@@ -1291,6 +1287,7 @@
   const char *my_ip;
 
   my_ip = res->me->address;
+  sin_addr.s_addr = inet_addr(my_ip);
 
   /* does DRBD support inet6? */
   family = AF_INET;
@@ -1314,7 +1311,7 @@
 
   if (valid == 0) {
     fprintf(stderr, "OOPS, the IP address %s isn't configure/up on your system!\n", my_ip);
-#ifdef INVALID_IP_IS_INVALID_CONF
+#if INVALID_IP_IS_INVALID_CONF
     config_valid = 0;
 #endif
   }
@@ -1666,15 +1663,22 @@
       if (optind + 1 > argc && !is_dump)
         print_usage_and_exit("missing arguments"); // arguments missing.
 
-      if(!is_dump) expand_common();
+      if(!is_dump) {
+	expand_common();
 
+	global_validate(); 
+	if(!config_valid) exit(E_config_invalid);
+
+        for_each_resource(res,tmp,config) {
+	  convert_after_option(res);
+	  convert_discard_opt(res);
+	}
+      }
+
       if ( optind==argc || !strcmp(argv[optind],"all") ) {
         if (is_dump) {
 	  dump_global_info();
 	  dump_common_info();
-	} else {
-	  global_validate(); 
-	  if(!config_valid) exit(E_config_invalid);
 	}
         for_each_resource(res,tmp,config) {
 	  if( (rv |= cmd->function(res,cmd->name)) >= 10 ) {

From drbd-cvs at lists.linbit.com  Tue Jul  4 11:33:32 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul  4 11:33:33 2006
Subject: [DRBD-cvs] svn commit by lars - r2255 - branches/drbd-0.7/benchmark
	- pipe dm.c through Lindent, make it actually work with 6
Message-ID: <20060704093332.695D82DEACCF@mail.linbit.com>

Author: lars
Date: 2006-07-04 11:33:31 +0200 (Tue, 04 Jul 2006)
New Revision: 2255

Modified:
   branches/drbd-0.7/benchmark/dm.c
Log:
pipe dm.c through Lindent, make it actually work with 64 bit file offsets, and get the line wrap right

Modified: branches/drbd-0.7/benchmark/dm.c
===================================================================
--- branches/drbd-0.7/benchmark/dm.c	2006-07-03 15:38:37 UTC (rev 2254)
+++ branches/drbd-0.7/benchmark/dm.c	2006-07-04 09:33:31 UTC (rev 2255)
@@ -22,16 +22,16 @@
 
  */
 
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
 #include <fcntl.h>
-#define __USE_LARGEFILE64
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/time.h>
-#define _GNU_SOURCE
 #include <getopt.h>
 #include <string.h>
 
@@ -39,292 +39,280 @@
 
 unsigned long long fsize(int in_fd)
 {
-  struct stat dm_stat;
-  unsigned long long size;
-  
-  if(fstat(in_fd, &dm_stat))
-    {
-      fprintf(stderr,"Can not fstat\n");
-      exit(20);
-    }
-  if(S_ISBLK(dm_stat.st_mode))
-    {
-      unsigned long ls;
-      if( ioctl(in_fd,BLKGETSIZE,&ls) )
-	{
-	  fprintf(stderr,"Can not ioctl(BLKGETSIZE)\n");
-	  exit(20);
+	struct stat dm_stat;
+	unsigned long long size;
+
+	if (fstat(in_fd, &dm_stat)) {
+		fprintf(stderr, "Can not fstat\n");
+		exit(20);
 	}
-      size=((unsigned long long)ls)*512;
-    }
-  else if(S_ISREG(dm_stat.st_mode))
-    {
-      size=dm_stat.st_size;
-    }
-  else size=-1;
+	if (S_ISBLK(dm_stat.st_mode)) {
+		unsigned long ls;
+		if (ioctl(in_fd, BLKGETSIZE, &ls)) {
+			fprintf(stderr, "Can not ioctl(BLKGETSIZE)\n");
+			exit(20);
+		}
+		size = ((unsigned long long)ls) * 512;
+	} else if (S_ISREG(dm_stat.st_mode)) {
+		size = dm_stat.st_size;
+	} else
+		size = -1;
 
-  return size;
+	return size;
 }
 
-unsigned long long m_strtol(const char* s)
+unsigned long long m_strtol(const char *s)
 {
-  char *e = (char*)s;
-  unsigned long long r;
+	char *e = (char *)s;
+	unsigned long long r;
 
-  r = strtol(s,&e,0);
-  switch(*e)
-    {
-    case 0:
-      return r;
-    case 'K':
-    case 'k':
-      return r*1024;
-    case 'M':
-    case 'm':
-      return r*1024*1024;
-    case 'G':
-    case 'g':      
-      return r*1024*1024*1024;
-    default:
-      fprintf(stderr,"%s is not a valid number\n",s);
-      exit(20);
-    }
+	r = strtol(s, &e, 0);
+	switch (*e) {
+	case 0:
+		return r;
+	case 'K':
+	case 'k':
+		return r * 1024;
+	case 'M':
+	case 'm':
+		return r * 1024 * 1024;
+	case 'G':
+	case 'g':
+		return r * 1024 * 1024 * 1024;
+	default:
+		fprintf(stderr, "%s is not a valid number\n", s);
+		exit(20);
+	}
 }
 
-void usage(char* prgname)
+void usage(char *prgname)
 {
-  fprintf(stderr,"USAGE: %s [options] \n"
-	  "  Available options:\n"
-          "   --input-pattern val -a val \n"
-	  "   --input-file val    -i val \n"
-	  "   --output-file val   -o val\n"
-	  "   --buffer-size val   -b val\n"
-	  "   --seek-input val    -k val\n"
-	  "   --seek-output val   -l val\n"
-	  "   --size val          -s val\n"
-	  "   --sync              -y\n"
-	  "   --progress          -m\n"
-	  "   --performance       -p\n"
-	  "   --dialog            -d\n"
-	  "   --help              -h\n",
-	  prgname);
-  exit(20);
+	fprintf(stderr, "USAGE: %s [options] \n"
+		"  Available options:\n"
+		"   --input-pattern val -a val \n"
+		"   --input-file val    -i val \n"
+		"   --output-file val   -o val\n"
+		"   --buffer-size val   -b val\n"
+		"   --seek-input val    -k val\n"
+		"   --seek-output val   -l val\n"
+		"   --size val          -s val\n"
+		"   --sync              -y\n"
+		"   --progress          -m\n"
+		"   --performance       -p\n"
+		"   --dialog            -d\n"
+		"   --help              -h\n", prgname);
+	exit(20);
 
 }
 
-int main(int argc, char** argv)
+int main(int argc, char **argv)
 {
-  char* buffer;
-  size_t rr,ww;
-  unsigned long long seek_offs_i=0;
-  unsigned long long seek_offs_o=0;
-  unsigned long long size=-1,rsize;
-  int in_fd=0, out_fd=1;
-  unsigned long buffer_size=65536;
-  int do_sync=0;
-  int show_progress=0;
-  int show_performance=0;
-  struct timeval tv1,tv2;
-  int use_pattern=0;
-  int pattern;
-  int dialog=0,show_input_size=0;
-  int last_percentage=0;
+	char *buffer;
+	size_t rr, ww;
+	unsigned long long seek_offs_i = 0;
+	unsigned long long seek_offs_o = 0;
+	unsigned long long size = -1, rsize;
+	int in_fd = 0, out_fd = 1;
+	unsigned long buffer_size = 65536;
+	int do_sync = 0;
+	int show_progress = 0;
+	int show_performance = 0;
+	struct timeval tv1, tv2;
+	int use_pattern = 0;
+	int pattern;
+	int dialog = 0, show_input_size = 0;
+	int last_percentage = 0;
 
-  int c;
-  static struct option options[] = {        
-    { "input-pattern",required_argument, 0, 'a' },
-    { "input-file",   required_argument, 0, 'i' },
-    { "output-file",  required_argument, 0, 'o' },
-    { "buffer-size",  required_argument, 0, 'b' },
-    { "seek-input",   required_argument, 0, 'k' },
-    { "seek-output",  required_argument, 0, 'l' },
-    { "size"       ,  required_argument, 0, 's' },
-    { "sync",         no_argument,       0, 'y' },
-    { "progress",     no_argument,       0, 'm' },
-    { "performance",  no_argument,       0, 'p' },
-    { "dialog",       no_argument,       0, 'd' },
-    { "help",         no_argument,       0, 'h' },
-    { "show-input-size", no_argument,    0, 'w' },
-    { 0,              0,                 0, 0   }
-  };
+	int c;
+	static struct option options[] = {
+		{"input-pattern", required_argument, 0, 'a'},
+		{"input-file", required_argument, 0, 'i'},
+		{"output-file", required_argument, 0, 'o'},
+		{"buffer-size", required_argument, 0, 'b'},
+		{"seek-input", required_argument, 0, 'k'},
+		{"seek-output", required_argument, 0, 'l'},
+		{"size", required_argument, 0, 's'},
+		{"sync", no_argument, 0, 'y'},
+		{"progress", no_argument, 0, 'm'},
+		{"performance", no_argument, 0, 'p'},
+		{"dialog", no_argument, 0, 'd'},
+		{"help", no_argument, 0, 'h'},
+		{"show-input-size", no_argument, 0, 'w'},
+		{0, 0, 0, 0}
+	};
 
-  while(1)
-    {
-      c = getopt_long(argc,argv,"i:o:b:k:l:s:ympha:dw",options,0);
-      if(c == -1) break;
-      switch(c)
-	{
-	case 'i': 
-	  in_fd = open(optarg,O_RDONLY);
-	  if(in_fd==-1)
-	    {
-	      fprintf(stderr,"Can not open input file/device\n");
-	      exit(20);
-	    }
-	  break;
-	case 'o':
-	  out_fd = open(optarg,O_WRONLY|O_CREAT|O_TRUNC,0664);
-	  if(out_fd==-1)
-	    {
-	      fprintf(stderr,"Can not open output file/device\n");
-	      exit(20);
-	    }
-	  break;
-	case 'b':
-	  buffer_size = m_strtol(optarg);
-	  break;
-	case 'k':
-	  seek_offs_i = m_strtol(optarg);
-	  break;
-	case 'l':
-	  seek_offs_o = m_strtol(optarg);
-	  break;
-	case 's':
-	  size = m_strtol(optarg);
-	  break;
-	case 'y':
-	  do_sync = 1;
-	  break;
-	case 'm':
-	  show_progress = 1;
-	  break;
-	case 'p':
-	  show_performance = 1;
-	  break;
-	case 'h':
-	  usage(argv[0]);
-	  break;
-	case 'a':
-	  use_pattern = 1;
-	  pattern = m_strtol(optarg);
-	  break;
-	case 'd':
-	  dialog=1;
-	  break;
-	case 'w':
-	  show_input_size=1;
-	  break;
+	while (1) {
+		c = getopt_long(argc, argv, "i:o:b:k:l:s:ympha:dw", options, 0);
+		if (c == -1)
+			break;
+		switch (c) {
+		case 'i':
+			in_fd = open(optarg, O_RDONLY);
+			if (in_fd == -1) {
+				fprintf(stderr,
+					"Can not open input file/device\n");
+				exit(20);
+			}
+			break;
+		case 'o':
+			out_fd =
+			    open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0664);
+			if (out_fd == -1) {
+				fprintf(stderr,
+					"Can not open output file/device\n");
+				exit(20);
+			}
+			break;
+		case 'b':
+			buffer_size = m_strtol(optarg);
+			break;
+		case 'k':
+			seek_offs_i = m_strtol(optarg);
+			break;
+		case 'l':
+			seek_offs_o = m_strtol(optarg);
+			break;
+		case 's':
+			size = m_strtol(optarg);
+			break;
+		case 'y':
+			do_sync = 1;
+			break;
+		case 'm':
+			show_progress = 1;
+			break;
+		case 'p':
+			show_performance = 1;
+			break;
+		case 'h':
+			usage(argv[0]);
+			break;
+		case 'a':
+			use_pattern = 1;
+			pattern = m_strtol(optarg);
+			break;
+		case 'd':
+			dialog = 1;
+			break;
+		case 'w':
+			show_input_size = 1;
+			break;
+		}
 	}
-    }
-  
-  buffer=malloc(buffer_size);
-  if(!buffer)
-    {
-      fprintf(stderr,"Can not allocate the Buffer memory\n");
-      exit(20);
-    }
-  
-  if(seek_offs_i)
-    {
-      if(lseek64(in_fd,seek_offs_i,SEEK_SET) == -1)
-	{
-	  fprintf(stderr,"Can not lseek(2) in input file/device\n");
-	  exit(20);
-	}
-    }
 
-  if(seek_offs_o)
-    {
-      if(lseek64(out_fd,seek_offs_o,SEEK_SET) == -1)
-	{
-	  fprintf(stderr,"Can not lseek(2) in output file/device\n");
-	  exit(20);
+	buffer = malloc(buffer_size);
+	if (!buffer) {
+		fprintf(stderr, "Can not allocate the Buffer memory\n");
+		exit(20);
 	}
-    }
 
-  if(use_pattern)
-    {
-      memset(buffer,pattern,buffer_size);
-    }
-
-  if( dialog && size == -1)
-    {
-      size = min(fsize(in_fd),fsize(out_fd));
-      if(size == -1) 
-	{
-	  fprintf(stderr,"Can not determine the size\n");
-	  exit(20);	
+	if (seek_offs_i) {
+		if (lseek(in_fd, seek_offs_i, SEEK_SET) == -1) {
+			fprintf(stderr,
+				"Can not lseek(2) in input file/device\n");
+			exit(20);
+		}
 	}
-    }
 
-  if( show_input_size )
-    {
-      size = fsize(in_fd);
-      if(size == -1) 
-	{
-	  fprintf(stderr,"Can not determine the size\n");
-	  exit(20);	
+	if (seek_offs_o) {
+		if (lseek(out_fd, seek_offs_o, SEEK_SET) == -1) {
+			fprintf(stderr,
+				"Can not lseek(2) in output file/device\n");
+			exit(20);
+		}
 	}
-      printf("%lldK\n",size/1024);
-      exit(0);
-    }
 
-  rsize = size;
-  gettimeofday(&tv1,NULL);
-  while(1)
-    {      
-      if(use_pattern) rr=min(buffer_size,rsize);
-      else rr=read(in_fd,buffer,(size_t)min(buffer_size,rsize));
-
-      if(rr==0) break;
-      if(rr==-1)
-	{
-	  perror("Read failed");
-	  break;
+	if (use_pattern) {
+		memset(buffer, pattern, buffer_size);
 	}
 
-      if(show_progress)
-	{
-	  printf( rr==buffer_size ? "R" : "r" );
-	  fflush(stdout);
+	if (dialog && size == -1) {
+		size = min(fsize(in_fd), fsize(out_fd));
+		if (size == -1) {
+			fprintf(stderr, "Can not determine the size\n");
+			exit(20);
+		}
 	}
 
-      ww=write(out_fd,buffer,rr);
-      if(ww==-1)
-	{
-	  perror("Write failed");
-	  break;
+	if (show_input_size) {
+		size = fsize(in_fd);
+		if (size == -1) {
+			fprintf(stderr, "Can not determine the size\n");
+			exit(20);
+		}
+		printf("%lldK\n", size / 1024);
+		exit(0);
 	}
-      rsize = rsize - ww;
-      if( dialog )
-	{
-	  int new_percentage=(int)(100.0*(size-rsize)/size);
-	  if( new_percentage != last_percentage)
-	    {
-	      printf("%2d\n",(int)(100.0*(size-rsize)/size));
-	      fflush(stdout);
-	      last_percentage = new_percentage;
-	    }
-	}
-      if( ww!=rr) break;
-    }
-      
-  if(do_sync) fsync(out_fd);
 
-  gettimeofday(&tv2,NULL);
+	rsize = size;
+	gettimeofday(&tv1, NULL);
+	while (1) {
+		if (use_pattern)
+			rr = min(buffer_size, rsize);
+		else
+			rr = read(in_fd, buffer,
+				  (size_t) min(buffer_size, rsize));
 
-  if(show_performance)
-    {
-      long sec = tv2.tv_sec - tv1.tv_sec;
-      long usec = tv2.tv_usec-tv1.tv_usec;
-      double mps;
+		if (rr == 0)
+			break;
+		if (rr == -1) {
+			perror("Read failed");
+			break;
+		}
 
-      if(usec<0)
-	{
-	  sec--;
-	  usec+=1000000;
+		if (show_progress) {
+			printf(rr == buffer_size ? "R" : "r");
+			fflush(stdout);
+		}
+
+		ww = write(out_fd, buffer, rr);
+		if (ww == -1) {
+			perror("Write failed");
+			break;
+		}
+		rsize = rsize - ww;
+		if (dialog) {
+			int new_percentage =
+			    (int)(100.0 * (size - rsize) / size);
+			if (new_percentage != last_percentage) {
+				printf("%2d\n",
+				       (int)(100.0 * (size - rsize) / size));
+				fflush(stdout);
+				last_percentage = new_percentage;
+			}
+		}
+		if (ww != rr)
+			break;
 	}
 
-      mps = (((double)(size-rsize)) / (1<<20)) / 
-	(sec+((double)usec)/1000000);
+	if (do_sync)
+		fsync(out_fd);
 
-      printf("%.2f MB/sec (%llu B / ",mps,size-rsize);
-      printf("%02ld:%02ld.%06ld)\n",sec/60,sec%60,usec);
-    }
+	gettimeofday(&tv2, NULL);
 
-  if(size != -1 && rsize)
-    fprintf(stderr,"Could transfer only %lld Byte.\n",(size - rsize)); 
+	if (show_progress)
+		printf("\n");
 
-  return 0;
-}
+	if (show_performance) {
+		long sec = tv2.tv_sec - tv1.tv_sec;
+		long usec = tv2.tv_usec - tv1.tv_usec;
+		double mps;
 
+		if (usec < 0) {
+			sec--;
+			usec += 1000000;
+		}
+
+		mps = (((double)(size - rsize)) / (1 << 20)) /
+		    (sec + ((double)usec) / 1000000);
+
+		printf("%.2f MB/sec (%llu B / ", mps, size - rsize);
+		printf("%02ld:%02ld.%06ld)\n", sec / 60, sec % 60, usec);
+	}
+
+	if (size != -1 && rsize)
+		fprintf(stderr, "Could transfer only %lld Byte.\n",
+			(size - rsize));
+
+	return 0;
+}

From drbd-cvs at lists.linbit.com  Tue Jul  4 11:34:04 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul  4 11:34:06 2006
Subject: [DRBD-cvs] svn commit by lars - r2256 - trunk/benchmark - make it
	actually work with 64 bit file offsets
Message-ID: <20060704093404.D410A2CDC4FA@mail.linbit.com>

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: lars
Date: 2006-07-04 11:34:04 +0200 (Tue, 04 Jul 2006)
New Revision: 2256

Modified:
   trunk/benchmark/dm.c
Log:
make it actually work with 64 bit file offsets

Modified: trunk/benchmark/dm.c
===================================================================
--- trunk/benchmark/dm.c	2006-07-04 09:33:31 UTC (rev 2255)
+++ trunk/benchmark/dm.c	2006-07-04 09:34:04 UTC (rev 2256)
@@ -22,16 +22,16 @@
 
  */
 
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
-#define __USE_LARGEFILE64
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/time.h>
-#define _GNU_SOURCE
 #include <getopt.h>
 #include <string.h>
 
@@ -147,7 +147,7 @@
 			break;
 		switch (c) {
 		case 'i':
-			in_fd = open(optarg, O_RDONLY | O_LARGEFILE);
+			in_fd = open(optarg, O_RDONLY);
 			if (in_fd == -1) {
 				fprintf(stderr,
 					"Can not open input file/device\n");
@@ -207,7 +207,7 @@
 	}
 
 	if (seek_offs_i) {
-		if (lseek64(in_fd, seek_offs_i, SEEK_SET) == -1) {
+		if (lseek(in_fd, seek_offs_i, SEEK_SET) == -1) {
 			fprintf(stderr,
 				"Can not lseek(2) in input file/device\n");
 			exit(20);
@@ -215,7 +215,7 @@
 	}
 
 	if (seek_offs_o) {
-		if (lseek64(out_fd, seek_offs_o, SEEK_SET) == -1) {
+		if (lseek(out_fd, seek_offs_o, SEEK_SET) == -1) {
 			fprintf(stderr,
 				"Can not lseek(2) in output file/device\n");
 			exit(20);

From drbd-cvs at lists.linbit.com  Tue Jul  4 12:31:16 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul  4 12:31:16 2006
Subject: [DRBD-cvs] svn commit by lars - r2257 - branches/drbd-0.7/drbd -
	thanks for the headsup on drbd-user:
Message-ID: <20060704103116.685F92DF625D@mail.linbit.com>

/ 2006-07-03 19:47
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: lars
Date: 2006-07-04 12:31:11 +0200 (Tue, 04 Jul 2006)
New Revision: 2257

Modified:
   branches/drbd-0.7/drbd/drbd_fs.c
Log:

thanks for the headsup on drbd-user:
/ 2006-07-03 19:47:55 +0200
\ Guido Guenther:
> according to block/ioctl.c drbd_ioctl() is supposed to return -ENOCTLCMD
> instead of -EINVAL when it doesn't handle that specific ioctl:
>
> /* Most of the generic ioctls are handled in the normal fallback path.
>    This assumes the blkdev's low level compat_ioctl always returns
>    ENOIOCTLCMD for unknown ioctls. */

well, he is right, even though his proposed patch did not quite work generically.
this patch should do it, for all architechtures and even still be mostly correct
(not worse than before) for 2.4 kernels.


Modified: branches/drbd-0.7/drbd/drbd_fs.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_fs.c	2006-07-04 09:34:04 UTC (rev 2256)
+++ branches/drbd-0.7/drbd/drbd_fs.c	2006-07-04 10:31:11 UTC (rev 2257)
@@ -1069,9 +1069,10 @@
 long drbd_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
 {
 	int ret;
-	// lock_kernel(); Not needed, since we have mdev->device_mutex
 	ret = drbd_ioctl(f->f_dentry->d_inode, f, cmd, arg);
-	// unlock_kernel();
+	/* need to map "unknown" to ENOIOCTLCMD
+	 * to get the generic fallback path going */
+	if (ret == -ENOTTY) ret = -ENOIOCTLCMD;
 	return ret;
 }
 #endif
@@ -1123,7 +1124,9 @@
 		switch (cmd) {
 		default:
 			/* oops, unknown IOCTL ?? */
-			err = -EINVAL;
+			/* Sorry, 2.4 kernel will get "no such ioctl" for BLK* ioctls
+			 * on an unconfigured DRBD.  I don't care right now. */
+			err = -ENOTTY;
 			goto out_unlocked;
 
 		case DRBD_IOCTL_GET_CONFIG:
@@ -1176,6 +1179,10 @@
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 /* see how sys_ioctl and blkdev_ioctl handle it in 2.6 .
  * If I understand correctly, only "private" ioctl end up here.
+ *
+ * unless, of course, we are called by the compat_ioctl, in which case our
+ * drbd_compat_ioctl wrapper will convert ENOTTY into ENOIOCTLCMD, which in
+ * turn will cause the fallback path in the generic compat_sys_ioctl.
  */
 	case BLKGETSIZE:
 		err = put_user(drbd_get_capacity(mdev->this_bdev),(long *)arg);
@@ -1452,7 +1459,7 @@
 		break;
 
 	default:
-		err = -EINVAL;
+		err = -ENOTTY;
 	}
  /* out: */
 	up(&mdev->device_mutex);

From drbd-cvs at lists.linbit.com  Tue Jul  4 14:57:30 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul  4 14:57:31 2006
Subject: [DRBD-cvs] svn commit by lars - r2258 - branches/drbd-0.7/user -
	short option for unplug-watermark is 'u' not 'l'
Message-ID: <20060704125730.673C92CDC28C@mail.linbit.com>

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: lars
Date: 2006-07-04 14:57:29 +0200 (Tue, 04 Jul 2006)
New Revision: 2258

Modified:
   branches/drbd-0.7/user/drbdsetup.c
Log:
short option for unplug-watermark is 'u' not 'l'

Modified: branches/drbd-0.7/user/drbdsetup.c
===================================================================
--- branches/drbd-0.7/user/drbdsetup.c	2006-07-04 10:31:11 UTC (rev 2257)
+++ branches/drbd-0.7/user/drbdsetup.c	2006-07-04 12:57:29 UTC (rev 2258)
@@ -156,7 +156,7 @@
      { "timeout",    required_argument, 0, 't' },
      { "max-epoch-size", required_argument, 0, 'e' },
      { "max-buffers",required_argument, 0, 'b' },
-     { "unplug-watermark",required_argument, 0, 'l' },
+     { "unplug-watermark",required_argument, 0, 'u' },
      { "connect-int",required_argument, 0, 'c' },
      { "ping-int",   required_argument, 0, 'i' },
      { "sndbuf-size",required_argument, 0, 'S' },
@@ -589,7 +589,7 @@
 	  cn->config.max_buffers = m_strtoll_range(optarg,1, "max-buffers",
 			  DRBD_MAX_BUFFERS_MIN, DRBD_MAX_BUFFERS_MAX);
 	  break;
-	case 'l':
+	case 'u':
 	  cn->config.unplug_watermark = m_strtoll_range(optarg,1, "unplug-watermark",
 			  DRBD_UNPLUG_WATERMARK_MIN, DRBD_UNPLUG_WATERMARK_MAX);
 	  break;

From drbd-cvs at lists.linbit.com  Tue Jul  4 14:58:31 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul  4 14:58:38 2006
Subject: [DRBD-cvs] svn commit by lars - r2259 -
	branches/drbd-0.7/documentation - short option for
	unplug-watermark is 'u' not 'l'
Message-ID: <20060704125836.A14DA2CDC290@mail.linbit.com>

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: lars
Date: 2006-07-04 14:58:30 +0200 (Tue, 04 Jul 2006)
New Revision: 2259

Modified:
   branches/drbd-0.7/documentation/drbdsetup.sgml
Log:
short option for unplug-watermark is 'u' not 'l'

Modified: branches/drbd-0.7/documentation/drbdsetup.sgml
===================================================================
--- branches/drbd-0.7/documentation/drbdsetup.sgml	2006-07-04 12:57:29 UTC (rev 2258)
+++ branches/drbd-0.7/documentation/drbdsetup.sgml	2006-07-04 12:58:30 UTC (rev 2259)
@@ -313,7 +313,7 @@
 	  </listitem>
 	</varlistentry>
 	<varlistentry>
-	  <term><option>-l</option>,
+	  <term><option>-u</option>,
 	  <option>--unplug-watermark <replaceable>val</replaceable></option></term>
 	  <listitem>
 	    <para>

From drbd-cvs at lists.linbit.com  Tue Jul  4 15:16:15 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul  4 15:16:17 2006
Subject: [DRBD-cvs] svn commit by phil - r2260 - in branches/drbd-0.7: .
	debian drbd/linux - Preparing drbd-0.7.20 
Message-ID: <20060704131615.8EE2F2CDC28E@mail.linbit.com>

Author: phil
Date: 2006-07-04 15:15:53 +0200 (Tue, 04 Jul 2006)
New Revision: 2260

Modified:
   branches/drbd-0.7/ChangeLog
   branches/drbd-0.7/debian/changelog
   branches/drbd-0.7/drbd.spec.in
   branches/drbd-0.7/drbd/linux/drbd_config.h
Log:
Preparing drbd-0.7.20


Modified: branches/drbd-0.7/ChangeLog
===================================================================
--- branches/drbd-0.7/ChangeLog	2006-07-04 12:58:30 UTC (rev 2259)
+++ branches/drbd-0.7/ChangeLog	2006-07-04 13:15:53 UTC (rev 2260)
@@ -6,6 +6,17 @@
  Cumulative changes since last tarball.
  For even more detail, use "svn log" and "svn diff".
 
+0.7.20 (api:79/proto:74)
+-----
+ * The GC comparison code failed to start a resync in case the two
+   cluster node failed simultaniously (common power failure).
+ * Fixed DRBD's code to start kernel threads to work on 2.6.17 also.
+ * IOCTL return codes fixed for 32bit userland - 64 bit kernel
+   setups.
+ * New config option "unplug-watermark".
+ * Released the drbd_alloc_ee() / drbd_free_ee() implementation from 
+   the DRBD+ branch to the main branch.
+
 0.7.19 (api:78/proto:74)
 -----
  * Fixed a bug where lc_del() left a list poison in an LRU chache's

Modified: branches/drbd-0.7/debian/changelog
===================================================================
--- branches/drbd-0.7/debian/changelog	2006-07-04 12:58:30 UTC (rev 2259)
+++ branches/drbd-0.7/debian/changelog	2006-07-04 13:15:53 UTC (rev 2260)
@@ -1,3 +1,9 @@
+drbd (0.7.20-0) unstable; urgency=low
+
+  * New upstream release
+
+ -- Philipp Reisner <phil@linbit.com>  Tue, 04 Jul 2006 15:13:15 +0200
+
 drbd (0.7.19-0) unstable; urgency=low
 
   * New upstream release

Modified: branches/drbd-0.7/drbd/linux/drbd_config.h
===================================================================
--- branches/drbd-0.7/drbd/linux/drbd_config.h	2006-07-04 12:58:30 UTC (rev 2259)
+++ branches/drbd-0.7/drbd/linux/drbd_config.h	2006-07-04 13:15:53 UTC (rev 2260)
@@ -22,7 +22,7 @@
 
 extern const char * drbd_buildtag(void);
 
-#define REL_VERSION "0.7.19"
+#define REL_VERSION "0.7.20"
 #define API_VERSION 79
 #define PRO_VERSION 74
 

Modified: branches/drbd-0.7/drbd.spec.in
===================================================================
--- branches/drbd-0.7/drbd.spec.in	2006-07-04 12:58:30 UTC (rev 2259)
+++ branches/drbd-0.7/drbd.spec.in	2006-07-04 13:15:53 UTC (rev 2260)
@@ -190,6 +190,17 @@
 /sbin/depmod -a -F /boot/System.map-%{kernelversion} %{kernelversion} >/dev/null 2>&1 || true
 
 %changelog
+* Tue Jul  4 2006 15:13:15 +0200 Philipp Reisner <phil@linbit.com>
+- drbd (0.7.20-1)
+ * The GC comparison code failed to start a resync in case the two
+   cluster node failed simultaniously (common power failure).
+ * Fixed DRBD's code to start kernel threads to work on 2.6.17 also.
+ * IOCTL return codes fixed for 32bit userland - 64 bit kernel
+   setups.
+ * New config option "unplug-watermark".
+ * Released the drbd_alloc_ee() / drbd_free_ee() implementation from 
+   the DRBD+ branch to the main branch.
+
 * Mon May 24 2006 14:03:07 +0200 Philipp Reisner <phil@linbit.com>
 - drbd (0.7.19-1)
  * Fixed a bug where lc_del() left a list poison in an LRU chache's

From drbd-cvs at lists.linbit.com  Tue Jul  4 15:27:28 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul  4 15:27:29 2006
Subject: [DRBD-cvs] svn commit by phil - r2261 - tags - Tagging drbd-0.7.20 
Message-ID: <20060704132729.0353F2CDC3FB@mail.linbit.com>

Author: phil
Date: 2006-07-04 15:27:26 +0200 (Tue, 04 Jul 2006)
New Revision: 2261

Added:
   tags/drbd-0.7.20/
Log:
Tagging drbd-0.7.20


Copied: tags/drbd-0.7.20 (from rev 2260, branches/drbd-0.7)

From drbd-cvs at lists.linbit.com  Thu Jul  6 16:29:54 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul  6 16:29:55 2006
Subject: [DRBD-cvs] svn commit by phil - r2264 - in trunk/drbd: . linux -
	Imlemented item 34 of the ROADMAP 
Message-ID: <20060706142954.D13202D99FAD@mail.linbit.com>

Author: phil
Date: 2006-07-06 16:29:52 +0200 (Thu, 06 Jul 2006)
New Revision: 2264

Modified:
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/linux/drbd_config.h
Log:
Imlemented item 34 of the ROADMAP



Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-05 11:51:12 UTC (rev 2263)
+++ trunk/drbd/drbd_int.h	2006-07-06 14:29:52 UTC (rev 2264)
@@ -315,7 +315,9 @@
 	MayIgnore = 0x100, // Flag only to test if (cmd > MayIgnore) ...
 	MAX_OPT_CMD,
 
-	HandShake = 0xfffe // FIXED for the next century!
+	HandShakeM = 0xfff1, // First Packet on the MetaSock
+	HandShakeS = 0xfff2, // First Packet on the Socket
+	HandShake  = 0xfffe  // FIXED for the next century!
 } Drbd_Packet_Cmd;
 
 static inline const char* cmdname(Drbd_Packet_Cmd cmd)

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-05 11:51:12 UTC (rev 2263)
+++ trunk/drbd/drbd_main.c	2006-07-06 14:29:52 UTC (rev 2264)
@@ -1823,7 +1823,6 @@
 	int rv,sent=0;
 
 	if (!sock) return -1000;
-	if ((volatile int)mdev->state.conn < WFReportParams) return -1001;
 
 	// THINK  if (signal_pending) return ... ?
 

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-05 11:51:12 UTC (rev 2263)
+++ trunk/drbd/drbd_receiver.c	2006-07-06 14:29:52 UTC (rev 2264)
@@ -448,7 +448,8 @@
 	return 0;
 }
 
-STATIC int drbd_recv_short(drbd_dev *mdev, void *buf, size_t size)
+STATIC int drbd_recv_short(drbd_dev *mdev, struct socket *sock,
+			   void *buf, size_t size)
 {
 	mm_segment_t oldfs;
 	struct iovec iov;
@@ -472,7 +473,7 @@
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
 
-	rv = sock_recvmsg(mdev->meta.socket, &msg, size, msg.msg_flags);
+	rv = sock_recvmsg(sock, &msg, size, msg.msg_flags);
 
 	set_fs(oldfs);
 
@@ -628,6 +629,27 @@
 STATIC int drbd_do_handshake(drbd_dev *mdev);
 STATIC int drbd_do_auth(drbd_dev *mdev);
 
+STATIC int drbd_send_fp(drbd_dev *mdev,struct socket *sock,Drbd_Packet_Cmd cmd)
+{
+	Drbd_Header *h = (Drbd_Header *) &mdev->data.sbuf.head;
+
+	return _drbd_send_cmd(mdev,sock,cmd,h,sizeof(*h),0);
+}
+
+STATIC Drbd_Packet_Cmd drbd_recv_fp(drbd_dev *mdev,struct socket *sock)
+{
+	Drbd_Header *h = (Drbd_Header *) &mdev->data.sbuf.head;
+	int rr;
+
+	rr = drbd_recv_short(mdev, sock, h, sizeof(*h));
+
+	if( rr==sizeof(*h) && h->magic==BE_DRBD_MAGIC ) {
+		return be16_to_cpu(h->command);
+	}
+
+	return 0xffff;
+}
+
 /*
  * return values:
  *   1 yess, we have a valid connection
@@ -637,55 +659,80 @@
  */
 int drbd_connect(drbd_dev *mdev)
 {
-	struct socket *sock,*msock;
-	int h;
+	struct socket *s, *sock,*msock;
+	int try,h;
 
 	D_ASSERT(mdev->state.conn > StandAlone);
 	D_ASSERT(!mdev->data.socket);
 
 	if(drbd_request_state(mdev,NS(conn,WFConnection)) < SS_Success ) return 0;
-
 	clear_bit(UNIQUE, &mdev->flags);
 
-	/* Break out of unknown connect loops by random wait here. */
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(net_random()%((mdev->net_conf->try_connect_int*HZ)/4));
+	sock  = NULL;
+	msock = NULL;
 
-	while(1) {
-		sock=drbd_try_connect(mdev);
-		if(sock) {
-			msock=drbd_wait_for_connect(mdev);
-			if(msock) {
-				set_bit(UNIQUE, &mdev->flags);
-				break;
-			}
-			else sock_release(sock);
-		} else {
-			sock=drbd_wait_for_connect(mdev);
-			if(sock) {
-				int retry;
-				for (retry=1; retry <= 10; retry++) {
-					// give the other side time to call
-					// bind() & listen()
-					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ / 10);
-					msock=drbd_try_connect(mdev);
-					if(msock) goto connected;
-					ERR("msock try_connect %d\n",retry);
+	do {
+		for(try=0;;) { // 3 tries, this should take less than a second!
+			s=drbd_try_connect(mdev);
+			if(s || ++try >= 3 ) break;
+			// give the other side time to call bind() & listen()
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(HZ / 10);
+		}
+
+		if(s) {
+			if( !sock ) {
+				if( drbd_send_fp(mdev, s, HandShakeS) ) {
+					sock = s;
+					s = NULL;
 				}
-				sock_release(sock);
+			} else if( !msock ) {
+				if( drbd_send_fp(mdev, s, HandShakeM) ) {
+					msock = s;
+					s = NULL;
+				}
+			} else {
+				ERR("Logic error in drbd_connect()\n");
+				return -1;
 			}
+			if(s) {
+				ERR("Error during sending initial packet.\n");
+				sock_release(s);
+			}
 		}
+
+		if(sock && msock) break;
+
+		s=drbd_wait_for_connect(mdev);		
+		if(s) {
+			switch(drbd_recv_fp(mdev,s)) {
+			case HandShakeS:
+				if(sock) sock_release(sock);
+				sock = s;
+				break;
+			case HandShakeM:
+				if(msock) sock_release(msock);
+				msock = s;
+				if(sock) set_bit(UNIQUE, &mdev->flags);
+				break;
+			default:
+				WARN("Error receiving initial packet\n");
+				sock_release(s);
+			}
+		}
+
 		if(mdev->state.conn == Unconnected) return -1;
 		if(signal_pending(current)) {
 			flush_signals(current);
 			smp_rmb();
-			if (get_t_state(&mdev->receiver) == Exiting)
+			if (get_t_state(&mdev->receiver) == Exiting) {
+				if(sock) sock_release(sock);
+				if(msock) sock_release(msock);
 				return -1;
+			}
 		}
-	}
 
- connected:
+	} while( !sock || !msock );
 
 	msock->sk->sk_reuse=1; /* SO_REUSEADDR */
 	sock->sk->sk_reuse=1; /* SO_REUSEADDR */
@@ -3057,7 +3104,8 @@
 		if (!drbd_process_done_ee(mdev)) goto err;
 		set_bit(SIGNAL_ASENDER, &mdev->flags);
 
-		rv = drbd_recv_short(mdev,buf,expect-received);
+		rv = drbd_recv_short(mdev, mdev->meta.socket,
+				     buf,expect-received);
 		clear_bit(SIGNAL_ASENDER, &mdev->flags);
 
 		flush_signals(current);

Modified: trunk/drbd/linux/drbd_config.h
===================================================================
--- trunk/drbd/linux/drbd_config.h	2006-07-05 11:51:12 UTC (rev 2263)
+++ trunk/drbd/linux/drbd_config.h	2006-07-06 14:29:52 UTC (rev 2264)
@@ -24,7 +24,7 @@
 
 #define REL_VERSION "8.0pre3"
 #define API_VERSION 82
-#define PRO_VERSION 80
+#define PRO_VERSION 81
 
 // undef if you need the workaround in drbd_receiver
 #define HAVE_UML_TO_VIRT 1

From drbd-cvs at lists.linbit.com  Thu Jul  6 16:32:00 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul  6 16:32:02 2006
Subject: [DRBD-cvs] svn commit by phil - r2265 - trunk - update ROADMAP txt
	file 
Message-ID: <20060706143200.B1B172CDC262@mail.linbit.com>

Author: phil
Date: 2006-07-06 16:31:48 +0200 (Thu, 06 Jul 2006)
New Revision: 2265

Modified:
   trunk/ROADMAP
Log:
update ROADMAP txt file


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-06 14:29:52 UTC (rev 2264)
+++ trunk/ROADMAP	2006-07-06 14:31:48 UTC (rev 2265)
@@ -787,6 +787,8 @@
 34 Improve the initial hand-shake, to identify the sockets (and TCP-
    links) by an initial message, and not only by the connection timming.
 
+   99% DONE   
+
 35 Bigger AL-extents (e.g. 16MB)
 
 36 Increase the number of UUID history slots.

From drbd-cvs at lists.linbit.com  Thu Jul  6 16:45:13 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul  6 16:45:14 2006
Subject: [DRBD-cvs] svn commit by phil - r2266 - trunk - Added Graham
	Simon's idea to the ROADMAP. 
Message-ID: <20060706144513.F1A092CDC267@mail.linbit.com>

Author: phil
Date: 2006-07-06 16:45:13 +0200 (Thu, 06 Jul 2006)
New Revision: 2266

Modified:
   trunk/ROADMAP
Log:
Added Graham Simon's idea to the ROADMAP.


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-06 14:31:48 UTC (rev 2265)
+++ trunk/ROADMAP	2006-07-06 14:45:13 UTC (rev 2266)
@@ -798,6 +798,10 @@
    Currently we habe a problem is when heartbeat's dead time is smaller 
    than DRBD's network timeout.
 
+38 Create an other on-io-error hander, that does retry failed read
+   operations on the peer, but does not detach from the local disk.
+   And it sets that block in the bitmap as out-of-date.
+
 Maybe:
 
 *  Switch to protocol C in case we are running without a local 

From drbd-cvs at lists.linbit.com  Fri Jul  7 15:22:40 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Fri Jul  7 15:22:41 2006
Subject: [DRBD-cvs] svn commit by phil - r2267 - in trunk: . drbd - * Fixed
	a few bugs in regard to freezing of IO. Looks g
Message-ID: <20060707132240.3FFB32D99ECA@mail.linbit.com>

Author: phil
Date: 2006-07-07 15:22:38 +0200 (Fri, 07 Jul 2006)
New Revision: 2267

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_req.c
Log:
* Fixed a few bugs in regard to freezing of IO. Looks good now.
* Started to fix bugs in regard to this usage pattern:
    create-md
    attach
    --overwrite-data-of-peer primary
    adccess device
		


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-06 14:45:13 UTC (rev 2266)
+++ trunk/ROADMAP	2006-07-07 13:22:38 UTC (rev 2267)
@@ -802,6 +802,8 @@
    operations on the peer, but does not detach from the local disk.
    And it sets that block in the bitmap as out-of-date.
 
+   Simon works on this. 
+
 Maybe:
 
 *  Switch to protocol C in case we are running without a local 

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-06 14:45:13 UTC (rev 2266)
+++ trunk/drbd/drbd_fs.c	2006-07-07 13:22:38 UTC (rev 2267)
@@ -827,6 +827,8 @@
 		dec_local(mdev);
 	}
 
+	if( fp == Stonith ) drbd_request_state(mdev,NS(susp,1));
+
 	r=drbd_khelper(mdev,"outdate-peer");
 
 	switch( (r>>8) & 0xff ) {
@@ -896,7 +898,8 @@
 	while (try++ < 3) {
 		r = _drbd_request_state(mdev,mask,val,0);
 		if( r == SS_NoConsistentDisk && (newstate & DontBlameDrbd) && 
-		    mdev->state.disk < UpToDate) {
+		    ( mdev->state.disk == Inconsistent || 
+		      mdev->state.disk == Outdated ) ) {
 			mask.disk = disk_mask;
 			val.disk  = UpToDate;
 			forced = 1;

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-06 14:45:13 UTC (rev 2266)
+++ trunk/drbd/drbd_main.c	2006-07-07 13:22:38 UTC (rev 2267)
@@ -822,11 +822,10 @@
 	}
 
 	if( fp == Stonith ) {
-		if( !(os.role == Primary && os.conn < Connected) &&
-		     (ns.role == Primary && ns.conn < Connected) ) {
+		if(ns.role == Primary &&
+		   ns.conn < Connected &&
+		   ns.pdsk > Outdated ) {
 			ns.susp = 1;
-			ERR("ap_pending_cnt = %d while suspending IO.\n",
-			    atomic_read(&mdev->ap_pending_cnt));
 		}
 	}
 	
@@ -959,7 +958,7 @@
 	/* Here we have the actions that are performed after a
 	   state change. This function might sleep */
 
-	if( fp == Stonith && ns.susp && os.susp ) {
+	if( fp == Stonith && ns.susp ) {
 		// case1: The outdate peer handler is successfull:
 		// case2: The connection was established again:
 		if ( (os.pdsk > Outdated  && ns.pdsk <= Outdated) || // case1

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-06 14:45:13 UTC (rev 2266)
+++ trunk/drbd/drbd_req.c	2006-07-07 13:22:38 UTC (rev 2267)
@@ -298,8 +298,11 @@
 	if (rw == WRITE && local)
 		drbd_al_begin_io(mdev, sector);
 
-	remote = remote && (mdev->state.pdsk >= Inconsistent);
+	remote = remote && (mdev->state.pdsk == Inconsistent ||
+			    mdev->state.pdsk == UpToDate);
 
+	D_ASSERT( (rw != WRITE) || (remote == (mdev->state.conn >= Connected)) );
+
 	if (!(local || remote)) {
 		ERR("IO ERROR: neither local nor remote disk\n");
 		goto fail_and_free_req;

From drbd-cvs at lists.linbit.com  Mon Jul 10 15:58:43 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 10 15:58:44 2006
Subject: [DRBD-cvs] svn commit by phil - r2268 - trunk/user - Fixed the
	set-gi sub command of drbdmeta 
Message-ID: <20060710135843.29EBD2CDC293@mail.linbit.com>

Author: phil
Date: 2006-07-10 15:58:42 +0200 (Mon, 10 Jul 2006)
New Revision: 2268

Modified:
   trunk/user/drbdmeta.c
Log:
Fixed the set-gi sub command of drbdmeta


Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2006-07-07 13:22:38 UTC (rev 2267)
+++ trunk/user/drbdmeta.c	2006-07-10 13:58:42 UTC (rev 2268)
@@ -1056,7 +1056,7 @@
 	int d;
 	int rv;
 
-	d = *val & mask;
+	d = *val & mask ? 1 : 0;
 
 	rv = m_strsep_u32(s, &d);
 

From drbd-cvs at lists.linbit.com  Mon Jul 10 18:09:51 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 10 18:09:53 2006
Subject: [DRBD-cvs] svn commit by phil - r2269 - in trunk: drbd drbd/linux
	user - Made my mind clear about the different meanings of disk
Message-ID: <20060710160951.DC4942DF653D@mail.linbit.com>

Author: phil
Date: 2006-07-10 18:09:49 +0200 (Mon, 10 Jul 2006)
New Revision: 2269

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_strings.c
   trunk/drbd/linux/drbd.h
   trunk/user/drbdsetup.c
Log:
Made my mind clear about the different meanings of disk the states:
UpToDate                               -> app IO allowed
Consistent (and all other DiskStates)  -> no app IO

Changed the code in the following places to follow that finding:
* The attach code now may mark the disk as UpToDate.
* Renamed the SS_NoConsistentDisk enum to SS_NoUpToDateDisk 



Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-10 13:58:42 UTC (rev 2268)
+++ trunk/drbd/drbd_fs.c	2006-07-10 16:09:49 UTC (rev 2269)
@@ -561,6 +561,11 @@
 		if(drbd_md_test_flag(mdev->bc,MDF_PeerOutDated)) {
 			ns.pdsk = Outdated;
 		}
+
+		if( ns.disk == Consistent && 
+		    ( ns.pdsk == Outdated || nbc->fencing == DontCare ) ) {
+			ns.disk = UpToDate;
+		}
 		
 		/* All tests on MDF_PrimaryInd, MDF_ConnectedInd, 
 		   MDF_Consistent and MDF_WasUpToDate must happen before 
@@ -827,6 +832,8 @@
 		dec_local(mdev);
 	}
 
+	D_ASSERT( fp > DontCare );
+
 	if( fp == Stonith ) drbd_request_state(mdev,NS(susp,1));
 
 	r=drbd_khelper(mdev,"outdate-peer");
@@ -897,7 +904,7 @@
 
 	while (try++ < 3) {
 		r = _drbd_request_state(mdev,mask,val,0);
-		if( r == SS_NoConsistentDisk && (newstate & DontBlameDrbd) && 
+		if( r == SS_NoUpToDateDisk && (newstate & DontBlameDrbd) && 
 		    ( mdev->state.disk == Inconsistent || 
 		      mdev->state.disk == Outdated ) ) {
 			mask.disk = disk_mask;

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-10 13:58:42 UTC (rev 2268)
+++ trunk/drbd/drbd_main.c	2006-07-10 16:09:49 UTC (rev 2269)
@@ -711,14 +711,14 @@
 
 	if( rv <= 0 ) /* already found a reason to abort */;
 	else if( ns.role == Primary && ns.conn < Connected &&
-		 ns.disk <= Outdated ) rv=SS_NoConsistentDisk;
+		 ns.disk < UpToDate ) rv=SS_NoUpToDateDisk;
 
 	else if( fp >= Resource &&
 		 ns.role == Primary && ns.conn < Connected &&
 		 ns.pdsk >= DUnknown ) rv=SS_PrimaryNOP;
 
 	else if( ns.role == Primary && ns.disk <= Inconsistent &&
-		 ns.pdsk <= Inconsistent ) rv=SS_NoConsistentDisk;
+		 ns.pdsk <= Inconsistent ) rv=SS_NoUpToDateDisk;
 	
 	else if( ns.conn > Connected &&
 		 ns.disk < UpToDate && ns.pdsk < UpToDate ) 

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-10 13:58:42 UTC (rev 2268)
+++ trunk/drbd/drbd_req.c	2006-07-10 16:09:49 UTC (rev 2269)
@@ -175,8 +175,9 @@
 	sector_t esector, nr_sectors;
 
 	if (mdev->state.disk == UpToDate) return 1;
+	if (mdev->state.disk >= Outdated) return 0;
 	if (mdev->state.disk <  Inconsistent) return 0;
-	// We will have a look at the BitMap
+	// state.disk == Inconsistent   We will have a look at the BitMap
 	nr_sectors = drbd_get_capacity(mdev->this_bdev);
 	esector = sector + (size>>9) -1;
 

Modified: trunk/drbd/drbd_strings.c
===================================================================
--- trunk/drbd/drbd_strings.c	2006-07-10 13:58:42 UTC (rev 2268)
+++ trunk/drbd/drbd_strings.c	2006-07-10 16:09:49 UTC (rev 2269)
@@ -62,8 +62,8 @@
 
 static const char *drbd_state_sw_errors[] = {
 	[-SS_TowPrimaries] = "Multiple primaries now allowed by config",
-	[-SS_NoConsistentDisk] = 
-		"Refusing to be Primary without at least one consistent disk",
+	[-SS_NoUpToDateDisk] = 
+		"Refusing to be Primary without at least one UpToDate disk",
 	[-SS_BothInconsistent] = "Refusing to be inconsistent on both nodes",
 	[-SS_SyncingDiskless] = "Refusing to be syncing and diskless",
 	[-SS_ConnectedOutdates] = "Refusing to be Outdated while Connected",

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2006-07-10 13:58:42 UTC (rev 2268)
+++ trunk/drbd/linux/drbd.h	2006-07-10 16:09:49 UTC (rev 2269)
@@ -241,7 +241,7 @@
 	Outdated,
 	DUnknown,       /* Only used for the peer, never for myself */
 	Consistent,     /* Might be Outdated, might be UpToDate ... */
-	UpToDate,
+	UpToDate,       /* Only this disk state allows applications' IO ! */
 	disk_mask=15
 } drbd_disks_t;
 
@@ -268,7 +268,7 @@
 	SS_Success=1,
 	SS_UnknownError=0, // Used to sleep longer in _drbd_request_state
 	SS_TowPrimaries=-1,
-	SS_NoConsistentDisk=-2,
+	SS_NoUpToDateDisk=-2,
 	SS_BothInconsistent=-4,
 	SS_SyncingDiskless=-5,
 	SS_ConnectedOutdates=-6,

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2006-07-10 13:58:42 UTC (rev 2268)
+++ trunk/user/drbdsetup.c	2006-07-10 16:09:49 UTC (rev 2269)
@@ -1087,7 +1087,7 @@
       if(err==EIO) 
 	{
 	  fprintf(stderr,"%s\n",set_st_err_name(reason));
-	  if(reason == SS_NoConsistentDisk) return 17;
+	  if(reason == SS_NoUpToDateDisk) return 17;
 	}
       return 20;
     }

From drbd-cvs at lists.linbit.com  Tue Jul 11 16:17:52 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul 11 16:17:53 2006
Subject: [DRBD-cvs] svn commit by phil - r2270 - in trunk: . drbd drbd/linux
	- Made the "drbdadm invalidate" and "invalidate_remote" c
Message-ID: <20060711141752.8A2BA2CDC880@mail.linbit.com>

Author: phil
Date: 2006-07-11 16:17:49 +0200 (Tue, 11 Jul 2006)
New Revision: 2270

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_strings.c
   trunk/drbd/drbd_worker.c
   trunk/drbd/linux/drbd.h
Log:
Made the "drbdadm invalidate" and "invalidate_remote" commands
to work right in regard to:

* concurrent calls on both nodes
* calls an disconnected nodes


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/ROADMAP	2006-07-11 14:17:49 UTC (rev 2270)
@@ -781,8 +781,9 @@
     Evaluate if it is possible to use it for starting resync. (invalidate)
     Evaluate it for the other cases...
 
-  60 % Is implemented. Changing the role to primary already uses this 
-       mechanism. Seems to work.
+  80 % Is implemented. Changing the role to primary already uses this 
+       mechanism. Starting resync with invalidate and invalidate_remote
+       now also uses this method.
 
 34 Improve the initial hand-shake, to identify the sockets (and TCP-
    links) by an initial message, and not only by the connection timming.

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/drbd/drbd_fs.c	2006-07-11 14:17:49 UTC (rev 2270)
@@ -575,7 +575,7 @@
 		rv = _drbd_set_state(mdev, ns, ChgStateVerbose);
 		ns = mdev->state;
 		spin_unlock_irq(&mdev->req_lock);
-		after_state_ch(mdev,os,ns);
+		after_state_ch(mdev,os,ns,ChgStateVerbose);
 
 		if(rv >= SS_Success ) {
 			drbd_thread_start(&mdev->worker);
@@ -1100,7 +1100,7 @@
 	lc_free(mdev->resync);  mdev->resync = NULL;
 	lc_free(mdev->act_log); mdev->act_log = NULL;
 
-	after_state_ch(mdev, os, ns);
+	after_state_ch(mdev, os, ns, ChgStateVerbose);
 
 	return 0;
 }
@@ -1119,7 +1119,7 @@
 	}
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
-	after_state_ch(mdev,os,ns);
+	after_state_ch(mdev,os,ns, ChgStateVerbose);
 
 	if( r == SS_NothingToDo ) return 0;
 	if( r == -999 ) {
@@ -1173,7 +1173,7 @@
 	r = _drbd_set_state(mdev, _NS(conn,StandAlone), 0);
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
-	after_state_ch(mdev,os,ns);
+	after_state_ch(mdev,os,ns,0);
 
 	if ( r == SS_NothingToDo )  return 0;
 	if ( r == SS_PrimaryNOP ) {
@@ -1392,87 +1392,15 @@
 		goto out_unlocked;
 
 	case DRBD_IOCTL_INVALIDATE:
-		/* TODO
-		 * differentiate between different error cases,
-		 * or report the current connection state and flags back
-		 * to userspace */
-
-		/* disallow "invalidation" of local replica
-		 * when currently in primary state (would be a Bad Idea),
-		 * or during a running sync (won't make any sense) */
-
-		/* PRE TODO disallow invalidate if we are primary */
-		r = drbd_request_state(mdev,NS2(disk,Inconsistent,
-					        conn,WFBitMapT));
-
-		if( r == SS_NothingToDo ) { break; }
-		if( r < SS_Success ) {
-			err = -EINPROGRESS;
-			break;
-		}
-
-		/* avoid races with set_in_sync
-		 * for successfull mirrored writes
-		 */
-		wait_event(mdev->cstate_wait,
-			   atomic_read(&mdev->ap_bio_cnt)==0);
-
-		drbd_bm_lock(mdev); // racy...
-
-		drbd_md_set_flag(mdev,MDF_FullSync);
-		drbd_md_sync(mdev);
-
-		drbd_bm_set_all(mdev);
-		drbd_bm_write(mdev);
-
-		drbd_md_clear_flag(mdev,MDF_FullSync);
-		drbd_md_sync(mdev);
-
-		if (drbd_send_short_cmd(mdev,BecomeSyncSource)) {
-			int ok;
-			ok = drbd_request_state(mdev,NS(conn,WFSyncUUID));
-			D_ASSERT( ok == 1 );
-		}
-
-		drbd_bm_unlock(mdev);
-
+		r = drbd_request_state(mdev,NS2(conn,StartingSyncT,
+						disk,Inconsistent));
+		if ( r != SS_Success) err = -EINPROGRESS;
 		break;
 
 	case DRBD_IOCTL_INVALIDATE_REM:
-
-		/* PRE TODO disallow invalidate if we peer is primary */
-		/* remove EINVAL from error output... */
-		r = drbd_request_state(mdev,NS2(pdsk,Inconsistent,
-					        conn,WFBitMapS));
-
-		if( r == SS_NothingToDo ) { break; }
-		if( r < SS_Success ) {
-			err = -EINPROGRESS;
-			break;
-		}
-
-		drbd_md_set_flag(mdev,MDF_FullSync);
-		drbd_md_sync(mdev);
-
-		/* avoid races with set_in_sync
-		 * for successfull mirrored writes
-		 */
-		wait_event(mdev->cstate_wait,
-		     atomic_read(&mdev->ap_bio_cnt)==0);
-
-		drbd_bm_lock(mdev); // racy...
-
-		drbd_bm_set_all(mdev);
-		drbd_bm_write(mdev);
-
-		drbd_md_clear_flag(mdev,MDF_FullSync);
-
-		drbd_send_uuids(mdev);
-		drbd_send_short_cmd(mdev,BecomeSyncTarget);
-		drbd_start_resync(mdev,SyncSource);
-
-		drbd_bm_unlock(mdev);
-
+		r = drbd_request_state(mdev,NS2(conn,StartingSyncS,
+						pdsk,Inconsistent));
+		if ( r != SS_Success) err = -EINPROGRESS;
 		break;
 
 	case DRBD_IOCTL_OUTDATE_DISK:

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/drbd/drbd_int.h	2006-07-11 14:17:49 UTC (rev 2270)
@@ -842,7 +842,8 @@
 			       enum chg_state_flags);
 extern int _drbd_set_state(drbd_dev*, drbd_state_t, enum chg_state_flags );
 extern void print_st_err(drbd_dev*, drbd_state_t, drbd_state_t, int );
-extern void after_state_ch(drbd_dev* mdev, drbd_state_t os, drbd_state_t ns);
+extern void after_state_ch(drbd_dev* mdev, drbd_state_t os, drbd_state_t ns,
+			   enum chg_state_flags);
 extern void drbd_thread_start(struct Drbd_thread *thi);
 extern void _drbd_thread_stop(struct Drbd_thread *thi, int restart, int wait);
 extern void drbd_free_resources(drbd_dev *mdev);

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/drbd/drbd_main.c	2006-07-11 14:17:49 UTC (rev 2270)
@@ -79,6 +79,7 @@
 	struct drbd_work w;
 	drbd_state_t os;
 	drbd_state_t ns;
+	enum chg_state_flags flags;
 };
 
 int drbdd_init(struct Drbd_thread*);
@@ -531,14 +532,14 @@
 /** 
  * cl_wide_st_chg:
  * Returns TRUE if this state change should be preformed as a cluster wide
- * transaction. Of courese it returns 0 as soon as the connection is lost.
+ * transaction. Of course it returns 0 as soon as the connection is lost.
  */ 
 STATIC int cl_wide_st_chg(drbd_dev* mdev, drbd_state_t os, drbd_state_t ns)
 {
-	return ( ns.conn >= Connected &&
+	return ( os.conn >= Connected && ns.conn >= Connected &&
 		 ( ( os.role != Primary && ns.role == Primary ) ||
-		   // ( os.conn != SyncSource && ns.role == SyncSource ) ||
-		   // ( os.conn != SyncTarget && ns.role == SyncTarget ) ||
+		   ( os.conn != StartingSyncT && ns.conn == StartingSyncT ) ||
+		   ( os.conn != StartingSyncS && ns.conn == StartingSyncS ) ||
 		   // ( os.disk != Diskless && ns.role == Diskless ) ||
 		   // ( os.conn != TearDown && ns.conn == TearDown ) ||
 		   0
@@ -558,7 +559,7 @@
 	rv = _drbd_set_state(mdev, ns, f);
 	ns = mdev->state;
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
-	after_state_ch(mdev,os,ns);
+	if (rv == SS_Success) after_state_ch(mdev,os,ns,f);
 
 	return rv;
 }
@@ -624,7 +625,10 @@
 		}
 
 		drbd_state_lock(mdev);
-		drbd_send_state_req(mdev,mask,val);
+		if( !drbd_send_state_req(mdev,mask,val) ) {
+			drbd_state_unlock(mdev);
+			return SS_CW_FailedByPeer;
+		}
 
 		wait_event(mdev->cstate_wait,(rv=_req_st_cond(mdev,mask,val)));
 
@@ -644,7 +648,7 @@
 	ns = mdev->state;
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
 
-	if (rv == SS_Success) after_state_ch(mdev,os,ns);
+	if (rv == SS_Success) after_state_ch(mdev,os,ns,f);
 
 	return rv;
 }
@@ -748,6 +752,13 @@
 
 	os = mdev->state;
 
+	/* Early state sanitising. Dissalow the invalidate ioctl to connect  */
+	if( (ns.conn == StartingSyncS || ns.conn == StartingSyncT) &&
+		os.conn < Connected ) {
+		ns.conn = os.conn;
+		ns.pdsk = os.pdsk;
+	}
+
 	if( ns.i == os.i ) return SS_NothingToDo;
 
 	fp = DontCare;
@@ -901,6 +912,7 @@
 		if(ascw) {
 			ascw->os = os;
 			ascw->ns = ns;
+			ascw->flags = flags;
 			ascw->w.cb = w_after_state_ch;
 			_drbd_queue_work_front(&mdev->data.work,&ascw->w);
 		} else {
@@ -916,13 +928,14 @@
 	struct after_state_chg_work* ascw;
 
 	ascw = (struct after_state_chg_work*) w;
-	after_state_ch(mdev, ascw->os, ascw->ns);
+	after_state_ch(mdev, ascw->os, ascw->ns, ascw->flags);
 	kfree(ascw);
 
 	return 1;
 }
 
-void after_state_ch(drbd_dev* mdev, drbd_state_t os, drbd_state_t ns)
+void after_state_ch(drbd_dev* mdev, drbd_state_t os, drbd_state_t ns,
+		    enum chg_state_flags flags)
 {
 	enum fencing_policy fp;
 	u32 mdf;
@@ -1021,6 +1034,57 @@
 		drbd_send_short_cmd(mdev,ResumeResync);
 	}
 
+	/* We are in the progress to start a full sync... */
+	if ( ( os.conn != StartingSyncT && ns.conn == StartingSyncT ) ||
+	     ( os.conn != StartingSyncS && ns.conn == StartingSyncS ) ) {
+
+		/* avoid races with set_in_sync
+		 * for successfull mirrored writes
+		 */
+		wait_event(mdev->cstate_wait,
+			   atomic_read(&mdev->ap_bio_cnt)==0);
+
+		drbd_bm_lock(mdev); // racy...
+
+		drbd_md_set_flag(mdev,MDF_FullSync);
+		drbd_md_sync(mdev);
+
+		drbd_bm_set_all(mdev);
+		drbd_bm_write(mdev);
+
+		drbd_md_clear_flag(mdev,MDF_FullSync);
+		drbd_md_sync(mdev);
+
+		drbd_bm_unlock(mdev);
+
+		if (ns.conn == StartingSyncT) {
+			spin_lock_irq(&mdev->req_lock);
+			_drbd_set_state(mdev,_NS(conn,WFSyncUUID), 
+					ChgStateVerbose | ScheduleAfter );
+			spin_unlock_irq(&mdev->req_lock);
+		} else /* StartingSyncS */ {
+			drbd_start_resync(mdev,SyncSource);
+		}
+	}
+
+	/* We are invalidating our self... */
+	if ( os.conn < Connected && ns.conn < Connected &&
+	       os.disk > Inconsistent && ns.disk == Inconsistent ) {
+		drbd_bm_lock(mdev); // racy...
+
+		drbd_md_set_flag(mdev,MDF_FullSync);
+		drbd_md_sync(mdev);
+
+		drbd_bm_set_all(mdev);
+		drbd_bm_write(mdev);
+
+		drbd_md_clear_flag(mdev,MDF_FullSync);
+		drbd_md_sync(mdev);
+
+		drbd_bm_unlock(mdev);		
+	}
+
+
 	/* it feels better to have the module_put last ... */
 	if ( (os.disk > Diskless || os.conn > StandAlone) &&
 	     ns.disk == Diskless && ns.conn == StandAlone ) {

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/drbd/drbd_receiver.c	2006-07-11 14:17:49 UTC (rev 2270)
@@ -1696,7 +1696,8 @@
 /* drbd_sync_handshake() returns the new conn state on success, or
    conn_mask (-1) on failure.
  */
-STATIC drbd_conns_t drbd_sync_handshake(drbd_dev *mdev, drbd_role_t peer_role)
+STATIC drbd_conns_t drbd_sync_handshake(drbd_dev *mdev, drbd_role_t peer_role,
+					drbd_disks_t peer_disk)
 {
 	int hg;
 	drbd_conns_t rv = conn_mask;
@@ -1734,6 +1735,13 @@
 			WARN("Split-Brain detected, manually solved.\n");
 		}
 	}
+	
+	if (hg == 0) {
+		// This is needed in case someone does an invalidate on an
+		// disconnected node.
+		if(mdev->state.disk==Inconsistent && peer_disk>Inconsistent) hg=-1;
+		if(mdev->state.disk>Inconsistent && peer_disk==Inconsistent) hg= 1;
+	}
 
 	if (hg == -1000) {
 		ALERT("Unrelated data, dropping connection!\n");
@@ -1955,7 +1963,7 @@
 	drbd_bm_unlock(mdev); // }
 
 	if (mdev->p_uuid && mdev->state.conn <= Connected && inc_local(mdev)) {
-		nconn=drbd_sync_handshake(mdev,mdev->state.peer);
+		nconn=drbd_sync_handshake(mdev,mdev->state.peer,mdev->state.pdsk);
 		dec_local(mdev);
 
 		if(nconn == conn_mask) return FALSE;
@@ -2018,15 +2026,10 @@
 
 	static drbd_conns_t c_tab[] = {
 		[Connected] = Connected,
-		[SkippedSyncS] = SkippedSyncT,
-		[SkippedSyncT] = SkippedSyncS,
-		[WFBitMapS] = WFBitMapT,
-		[WFBitMapT] = WFBitMapS,
-		[WFSyncUUID] = SyncSource,
-		[SyncSource] = SyncTarget,
-		[SyncTarget] = WFSyncUUID,
-		[PausedSyncS] = PausedSyncT,
-		[PausedSyncT] = PausedSyncS,
+
+		[StartingSyncS] = StartingSyncT,
+		[StartingSyncT] = StartingSyncS,
+
 		[conn_mask]   = conn_mask,
 	};
 
@@ -2087,7 +2090,7 @@
 
 	if (mdev->p_uuid && mdev->state.conn <= Connected && 
 	    inc_md_only(mdev,Attaching) ) {
-		nconn=drbd_sync_handshake(mdev,peer_state.role);
+		nconn=drbd_sync_handshake(mdev,peer_state.role,peer_state.disk);
 		dec_local(mdev);
 
 		if(nconn == conn_mask) return FALSE;
@@ -2117,7 +2120,7 @@
 	if(nconn == Connected && ns.disk == Attaching) ns.disk = UpToDate;
 	rv = _drbd_set_state(mdev,ns,ChgStateVerbose);
 	spin_unlock_irq(&mdev->req_lock);
-	after_state_ch(mdev,os,ns);
+	after_state_ch(mdev,os,ns,ChgStateVerbose);
 
 	if(rv < SS_Success) {
 		drbd_force_state(mdev,NS(conn,StandAlone));
@@ -2137,8 +2140,11 @@
 {
 	Drbd_SyncUUID_Packet *p = (Drbd_SyncUUID_Packet*)h;
 
-	D_ASSERT( mdev->state.conn == WFSyncUUID );
+	wait_event( mdev->cstate_wait, 
+		    mdev->state.conn < Connected || mdev->state.conn == WFSyncUUID);
 
+	// D_ASSERT( mdev->state.conn == WFSyncUUID );
+
 	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
 	if (drbd_recv(mdev, h->payload, h->length) != h->length)
 		return FALSE;
@@ -2270,32 +2276,6 @@
 	return (size == 0);
 }
 
-STATIC int receive_BecomeSyncTarget(drbd_dev *mdev, Drbd_Header *h)
-{
-	int ok;
-
-	ERR_IF(!mdev->bitmap) return FALSE;
-	D_ASSERT(mdev->p_uuid);
-	drbd_bm_lock(mdev);
-	drbd_bm_set_all(mdev);
-	drbd_bm_write(mdev);
-	ok = drbd_request_state(mdev,NS(conn,WFSyncUUID));
-	D_ASSERT( ok == SS_Success );
-	drbd_bm_unlock(mdev);
-	return ok == SS_Success ? TRUE : FALSE;
-}
-
-STATIC int receive_BecomeSyncSource(drbd_dev *mdev, Drbd_Header *h)
-{
-	drbd_send_uuids(mdev);
-	drbd_bm_lock(mdev);
-	drbd_bm_set_all(mdev);
-	drbd_bm_write(mdev);
-	drbd_start_resync(mdev,SyncSource);
-	drbd_bm_unlock(mdev);
-	return TRUE;
-}
-
 STATIC int receive_pause_resync(drbd_dev *mdev, Drbd_Header *h)
 {
 	drbd_resync_pause(mdev, PeerImposed);
@@ -2331,7 +2311,7 @@
 	}
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
-	after_state_ch(mdev,os,ns);
+	after_state_ch(mdev,os,ns,ChgStateVerbose);
 
 	if( r >= 0 ) {
 		drbd_md_sync(mdev);
@@ -2367,8 +2347,6 @@
 	[ReportBitMap]     = receive_bitmap,
 	[Ping]             = NULL, // via msock: got_Ping,
 	[PingAck]          = NULL, // via msock: got_PingAck,
-	[BecomeSyncTarget] = receive_BecomeSyncTarget,
-	[BecomeSyncSource] = receive_BecomeSyncSource,
 	[UnplugRemote]     = receive_UnplugRemote,
 	[DataRequest]      = receive_DataRequest,
 	[RSDataRequest]    = receive_DataRequest, //receive_RSDataRequest,

Modified: trunk/drbd/drbd_strings.c
===================================================================
--- trunk/drbd/drbd_strings.c	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/drbd/drbd_strings.c	2006-07-11 14:17:49 UTC (rev 2270)
@@ -34,6 +34,8 @@
 	[Connected]      = "Connected",
 	[SkippedSyncS]   = "SkippedSyncS",
 	[SkippedSyncT]   = "SkippedSyncT",
+	[StartingSyncS]  = "StartingSyncS",
+	[StartingSyncT]  = "StartingSyncT",
 	[WFBitMapS]      = "WFBitMapS",
 	[WFBitMapT]      = "WFBitMapT",
 	[WFSyncUUID]     = "WFSyncUUID",

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/drbd/drbd_worker.c	2006-07-11 14:17:49 UTC (rev 2270)
@@ -759,7 +759,7 @@
  * @side: Either SyncSource or SyncTarget
  * Start the resync process. Called from process context only,
  * either ioctl or drbd_receiver.
- * Note, this function might bring your directly into one of the
+ * Note, this function might bring you directly into one of the
  * PausedSync* states.
  */
 void drbd_start_resync(drbd_dev *mdev, drbd_conns_t side)
@@ -809,7 +809,7 @@
 	drbd_global_unlock();
 
 	if ( r == SS_Success ) {
-		after_state_ch(mdev,os,ns);
+		after_state_ch(mdev,os,ns,ChgStateVerbose);
 
 		INFO("Began resync as %s (will sync %lu KB [%lu bits set]).\n",
 		     conns_to_name(ns.conn),

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2006-07-10 16:09:49 UTC (rev 2269)
+++ trunk/drbd/linux/drbd.h	2006-07-11 14:17:49 UTC (rev 2270)
@@ -223,6 +223,8 @@
 	Connected,      // we have introduced each other
 	SkippedSyncS,   // we should have synced, but user said no
 	SkippedSyncT,
+	StartingSyncS,  // starting full sync by IOCTL.
+	StartingSyncT,  // stariing full sync by IOCTL.
 	WFBitMapS,
 	WFBitMapT,
 	WFSyncUUID,

From drbd-cvs at lists.linbit.com  Wed Jul 12 10:08:57 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 12 10:08:58 2006
Subject: [DRBD-cvs] svn commit by phil - r2271 - in trunk: . drbd - Now
	detach uses the "cluster wide" state change as well
Message-ID: <20060712080857.76E692D99F34@mail.linbit.com>

Author: phil
Date: 2006-07-12 10:08:55 +0200 (Wed, 12 Jul 2006)
New Revision: 2271

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
Log:
Now detach uses the "cluster wide" state change as well...


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-11 14:17:49 UTC (rev 2270)
+++ trunk/ROADMAP	2006-07-12 08:08:55 UTC (rev 2271)
@@ -727,14 +727,11 @@
    Connected -> SyncSource in the cluster.
 
       role <- primary
-      disk <- inconsistent (conn <- SyncTarget) **
-      pdsk <- inconsistent (conn <- SyncSource)
+      conn <- StartingSyncT (disk <- inconsistent)
+      conn <- StartingSyncS (pdsk <- inconsistent)
       disk <- Diskless (as long as it happens as administrative command)
       pdsk <- Outdated (= a 'disconnect' issued on a primary node)
 
-   ** It is more feasable to make the change on disk/pdsk cluster
-      wide atomic than working with the connection state.
-
    * When a state change might sleep ( reuqest_state() ) and it is 
      to be cluster wide atomic ( pre_state_checks() determines this!).
 	1. Aquire the cluster state change lock (bit & waitqueue) ?
@@ -781,9 +778,9 @@
     Evaluate if it is possible to use it for starting resync. (invalidate)
     Evaluate it for the other cases...
 
-  80 % Is implemented. Changing the role to primary already uses this 
+  90 % Is implemented. Changing the role to primary already uses this 
        mechanism. Starting resync with invalidate and invalidate_remote
-       now also uses this method.
+       now also uses this method. Detaching now also uses this mechanism.
 
 34 Improve the initial hand-shake, to identify the sockets (and TCP-
    links) by an initial message, and not only by the connection timming.

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-11 14:17:49 UTC (rev 2270)
+++ trunk/drbd/drbd_fs.c	2006-07-12 08:08:55 UTC (rev 2271)
@@ -1070,14 +1070,9 @@
 
 STATIC int drbd_detach_ioctl(drbd_dev *mdev)
 {
-	int interrupted,r;
-	drbd_state_t os,ns;
+	int r;
 
-	spin_lock_irq(&mdev->req_lock);
-	os = mdev->state;
-	r = _drbd_set_state(mdev,_NS(disk,Diskless),ChgStateVerbose);
-	ns = mdev->state;
-	spin_unlock_irq(&mdev->req_lock);
+	r = drbd_request_state(mdev,NS(disk,Diskless));
 
 	if( r == SS_NothingToDo ) { return 0; }
 	if( r < SS_Success ) {
@@ -1089,19 +1084,12 @@
 	/* since inc_local() only works as long as disk >= Inconsistent,
 	   and it is Diskless here, local_cnt can only go down, it can
 	   not increase... It will reach zero */
-	interrupted = wait_event_interruptible(mdev->cstate_wait,
-					       !atomic_read(&mdev->local_cnt));
-	if ( interrupted ) {
-		drbd_force_state(mdev,NS(disk,os.disk));
-		return -EINTR;
-	}
+	wait_event(mdev->cstate_wait, !atomic_read(&mdev->local_cnt));
 
 	drbd_free_bc(mdev->bc);	mdev->bc = NULL;
 	lc_free(mdev->resync);  mdev->resync = NULL;
 	lc_free(mdev->act_log); mdev->act_log = NULL;
 
-	after_state_ch(mdev, os, ns, ChgStateVerbose);
-
 	return 0;
 }
 

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-11 14:17:49 UTC (rev 2270)
+++ trunk/drbd/drbd_main.c	2006-07-12 08:08:55 UTC (rev 2271)
@@ -540,7 +540,7 @@
 		 ( ( os.role != Primary && ns.role == Primary ) ||
 		   ( os.conn != StartingSyncT && ns.conn == StartingSyncT ) ||
 		   ( os.conn != StartingSyncS && ns.conn == StartingSyncS ) ||
-		   // ( os.disk != Diskless && ns.role == Diskless ) ||
+		   ( os.disk != Diskless && ns.disk == Diskless ) ||
 		   // ( os.conn != TearDown && ns.conn == TearDown ) ||
 		   0
 		   ) );
@@ -951,7 +951,7 @@
 		dec_local(mdev);
 	}
 
-	if(mdev->bc) {
+	if( ns.disk >= Inconsistent ) {
 		mdf = mdev->bc->md.flags & ~(MDF_Consistent|MDF_PrimaryInd|
 					     MDF_ConnectedInd|MDF_WasUpToDate|
 					     MDF_PeerOutDated );
@@ -960,7 +960,8 @@
 		if (mdev->state.conn > WFReportParams) mdf |= MDF_ConnectedInd;
 		if (mdev->state.disk > Inconsistent)   mdf |= MDF_Consistent;
 		if (mdev->state.disk > Outdated)       mdf |= MDF_WasUpToDate;
-		if (mdev->state.pdsk <= Outdated)      mdf |= MDF_PeerOutDated;
+		if (mdev->state.pdsk <= Outdated && 
+		    mdev->state.pdsk >= Inconsistent)  mdf |= MDF_PeerOutDated;
 
 		if( mdf != mdev->bc->md.flags) {
 			mdev->bc->md.flags = mdf;
@@ -1016,12 +1017,6 @@
 		}
 	}
 
-	/*  Removed disk, tell peer.  */
-	if ( os.disk >= Inconsistent && ns.disk == Diskless &&
-	     ns.conn >= Connected ) {
-		drbd_send_state(mdev);
-	}
-
 	/* We want to pause resync, tell peer. */
 	if (  ( os.aftr_isp == 0 && ns.aftr_isp == 1 ) ||
 	      ( os.user_isp == 0 && ns.user_isp == 1 ) ) {
@@ -1084,7 +1079,6 @@
 		drbd_bm_unlock(mdev);		
 	}
 
-
 	/* it feels better to have the module_put last ... */
 	if ( (os.disk > Diskless || os.conn > StandAlone) &&
 	     ns.disk == Diskless && ns.conn == StandAlone ) {

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-11 14:17:49 UTC (rev 2270)
+++ trunk/drbd/drbd_receiver.c	2006-07-12 08:08:55 UTC (rev 2271)
@@ -713,7 +713,7 @@
 			case HandShakeM:
 				if(msock) sock_release(msock);
 				msock = s;
-				if(sock) set_bit(UNIQUE, &mdev->flags);
+				set_bit(UNIQUE, &mdev->flags);
 				break;
 			default:
 				WARN("Error receiving initial packet\n");

From drbd-cvs at lists.linbit.com  Wed Jul 12 11:51:27 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 12 11:51:29 2006
Subject: [DRBD-cvs] svn commit by phil - r2272 - trunk/drbd - * Moved
	releasing of backing device stuff into after_st
Message-ID: <20060712095127.91D692DEACCF@mail.linbit.com>

Author: phil
Date: 2006-07-12 11:51:26 +0200 (Wed, 12 Jul 2006)
New Revision: 2272

Modified:
   trunk/drbd/drbd_actlog.c
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
Log:
* Moved releasing of backing device stuff into after_state_ch()
* Moved stuff of the disconnect_ioctl code into after_state_ch()
* Made drbd_rs_cancel_all() more robust, it does not crash if
  there is no backing storage currently.
* Fixed the drbd_io_error() to also rely on the release-backing
  -device stuff in the after_state_ch() function.
    
Now a detach followed by disconnect no longer crashes ;)    


Modified: trunk/drbd/drbd_actlog.c
===================================================================
--- trunk/drbd/drbd_actlog.c	2006-07-12 08:08:55 UTC (rev 2271)
+++ trunk/drbd/drbd_actlog.c	2006-07-12 09:51:26 UTC (rev 2272)
@@ -939,14 +939,17 @@
 
 	spin_lock_irq(&mdev->al_lock);
 
-	for(i=0;i<mdev->resync->nr_elements;i++) {
-		bm_ext = (struct bm_extent*) lc_entry(mdev->resync,i);
-		if(bm_ext->lce.lc_number == LC_FREE) continue;
-		bm_ext->lce.refcnt = 0; // Rude but ok.
-		bm_ext->rs_left = 0;
-		clear_bit(BME_LOCKED,&bm_ext->flags);
-		clear_bit(BME_NO_WRITES,&bm_ext->flags);
-		lc_del(mdev->resync,&bm_ext->lce);
+	if(inc_md_only(mdev,Failed)) { // Makes sure mdev->resync is there.
+		for(i=0;i<mdev->resync->nr_elements;i++) {
+			bm_ext = (struct bm_extent*) lc_entry(mdev->resync,i);
+			if(bm_ext->lce.lc_number == LC_FREE) continue;
+			bm_ext->lce.refcnt = 0; // Rude but ok.
+			bm_ext->rs_left = 0;
+			clear_bit(BME_LOCKED,&bm_ext->flags);
+			clear_bit(BME_NO_WRITES,&bm_ext->flags);
+			lc_del(mdev->resync,&bm_ext->lce);
+		}
+		dec_local(mdev);
 	}
 	atomic_set(&mdev->resync_locked,0);
 	spin_unlock_irq(&mdev->al_lock);

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-12 08:08:55 UTC (rev 2271)
+++ trunk/drbd/drbd_fs.c	2006-07-12 09:51:26 UTC (rev 2272)
@@ -1079,17 +1079,6 @@
 		return -ENETRESET;
 	}
 
-	drbd_sync_me(mdev);
-
-	/* since inc_local() only works as long as disk >= Inconsistent,
-	   and it is Diskless here, local_cnt can only go down, it can
-	   not increase... It will reach zero */
-	wait_event(mdev->cstate_wait, !atomic_read(&mdev->local_cnt));
-
-	drbd_free_bc(mdev->bc);	mdev->bc = NULL;
-	lc_free(mdev->resync);  mdev->resync = NULL;
-	lc_free(mdev->act_log); mdev->act_log = NULL;
-
 	return 0;
 }
 
@@ -1152,16 +1141,9 @@
 
 STATIC int drbd_ioctl_unconfig_net(struct Drbd_Conf *mdev)
 {
-	drbd_state_t os,ns;
 	int r;
 
-	// Request state silently:
-	spin_lock_irq(&mdev->req_lock);
-	os = mdev->state;
-	r = _drbd_set_state(mdev, _NS(conn,StandAlone), 0);
-	ns = mdev->state;
-	spin_unlock_irq(&mdev->req_lock);
-	after_state_ch(mdev,os,ns,0);
+	r = _drbd_request_state(mdev,NS(conn,StandAlone),0);	// silently.
 
 	if ( r == SS_NothingToDo )  return 0;
 	if ( r == SS_PrimaryNOP ) {
@@ -1181,9 +1163,6 @@
 		mdev->cram_hmac_tfm = NULL;
 	}
 
-	drbd_sync_me(mdev); /* FIXME what if fsync returns error */
-	drbd_thread_stop(&mdev->receiver);
-
 	return 0;
 }
 

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-12 08:08:55 UTC (rev 2271)
+++ trunk/drbd/drbd_int.h	2006-07-12 09:51:26 UTC (rev 2272)
@@ -645,7 +645,6 @@
 	STOP_SYNC_TIMER,	// tell timer to cancel itself
 	UNPLUG_QUEUED,		// only relevant with kernel 2.4
 	UNPLUG_REMOTE,		// whether sending a "UnplugRemote" makes sense
-	PROCESS_EE_RUNNING,	// eek!
 	MD_DIRTY,		// current gen counts and flags not yet on disk
 	SYNC_STARTED,		// Needed to agree on the exact point in time..
 	UNIQUE,                 // Set on one node, cleared on the peer!
@@ -1237,11 +1236,12 @@
 			ERR("Ignoring local IO error!\n");
 			break;
 		case Panic:
-			_drbd_set_state(mdev,_NS(disk,Failed),1);
+			_drbd_set_state(mdev,_NS(disk,Failed),ChgStateHard);
 			drbd_panic("IO error on backing device!\n");
 			break;
 		case Detach:
-			if (_drbd_set_state(mdev,_NS(disk,Failed),1) == 1) {
+			if (_drbd_set_state(mdev,_NS(disk,Failed),ChgStateHard) 
+			    == SS_Success) {
 				ERR("Local IO failed. Detaching...\n");
 			}
 			break;

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-12 08:08:55 UTC (rev 2271)
+++ trunk/drbd/drbd_main.c	2006-07-12 09:51:26 UTC (rev 2272)
@@ -496,7 +496,8 @@
 
 	spin_lock_irqsave(&mdev->req_lock,flags);
 	if( (send = (mdev->state.disk == Failed)) ) {
-		_drbd_set_state(mdev,_NS(disk,Diskless),ChgStateHard);
+		_drbd_set_state(mdev,_NS(disk,Diskless),
+				ChgStateHard|ScheduleAfter);
 	}
 	D_ASSERT(mdev->state.disk <= Failed);
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
@@ -510,21 +511,7 @@
 	D_ASSERT(!drbd_md_test_flag(mdev->bc,MDF_Consistent));
 	drbd_md_sync(mdev);
 
-	if ( wait_event_interruptible_timeout(mdev->cstate_wait,
-		     atomic_read(&mdev->local_cnt) == 0 , HZ ) <= 0) {
-		WARN("Not releasing backing storage device.\n");
-		/* FIXME if there *are* still references,
-		 * we should be here again soon enough.
-		 * but what if not?
-		 * we still should free our ll and md devices */
-	} else {
-		/* no race. since the DISKLESS bit is set first,
-		 * further references to local_cnt are shortlived,
-		 * and no real references on the device. */
-		WARN("Releasing backing storage device.\n");
-		drbd_free_bc(mdev->bc);
-		mdev->bc=NULL;
-	}
+	/* Releasing the backing device is done in after_state_ch() */
 
 	return ok;
 }
@@ -1079,6 +1066,19 @@
 		drbd_bm_unlock(mdev);		
 	}
 
+	if ( os.disk > Diskless && ns.disk == Diskless ) {
+		drbd_sync_me(mdev);
+
+		/* since inc_local() only works as long as disk>=Inconsistent,
+		   and it is Diskless here, local_cnt can only go down, it can
+		   not increase... It will reach zero */
+		wait_event(mdev->cstate_wait, !atomic_read(&mdev->local_cnt));
+
+		drbd_free_bc(mdev->bc);	mdev->bc = NULL;
+		lc_free(mdev->resync);  mdev->resync = NULL;
+		lc_free(mdev->act_log); mdev->act_log = NULL;
+	}
+
 	/* it feels better to have the module_put last ... */
 	if ( (os.disk > Diskless || os.conn > StandAlone) &&
 	     ns.disk == Diskless && ns.conn == StandAlone ) {
@@ -1173,7 +1173,6 @@
 	     current->comm, current->pid,
 	     thi->task ? thi->task->comm : "NULL", thi->t_state, ns, wait); */
 
-
 	if (thi->t_state == None) {
 		spin_unlock(&thi->t_lock);
 		return;
@@ -1202,6 +1201,7 @@
 	spin_unlock(&thi->t_lock);
 
 	if (wait) {
+		if (thi->task == current) return;
 		D_ASSERT(thi->t_state == Exiting);
 		wait_for_completion(&thi->startstop);
 		spin_lock(&thi->t_lock);
@@ -2158,6 +2158,7 @@
 	 * oldest_barrier
 	 */
 
+	drbd_thread_stop(&mdev->receiver);
 	drbd_thread_stop(&mdev->worker);
 
 	/* no need to lock it, I'm the only thread alive */
@@ -2710,8 +2711,11 @@
 	if (!test_and_clear_bit(MD_DIRTY,&mdev->flags)) return;
 	del_timer(&mdev->md_sync_timer);
 	INFO("Writing meta data super block now.\n");
-	ERR_IF(!inc_md_only(mdev,Attaching)) return;
 
+	// We use here Failed and not Attaching because we try to write
+	// metadata even if we detach due to a disk failure!
+	ERR_IF(!inc_md_only(mdev,Failed)) return;
+
 	down(&mdev->md_io_mutex);
 	buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page);
 	memset(buffer,0,512);

From drbd-cvs at lists.linbit.com  Wed Jul 12 18:44:42 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 12 18:44:43 2006
Subject: [DRBD-cvs] svn commit by phil - r2273 - trunk/testing - First
	thoughts about testing DRBD's state mechanism. 
Message-ID: <20060712164442.3BED12DF6250@mail.linbit.com>

Author: phil
Date: 2006-07-12 18:44:41 +0200 (Wed, 12 Jul 2006)
New Revision: 2273

Added:
   trunk/testing/drbd_states.c
Modified:
   trunk/testing/Makefile
Log:
First thoughts about testing DRBD's state mechanism.


Modified: trunk/testing/Makefile
===================================================================
--- trunk/testing/Makefile	2006-07-12 09:51:26 UTC (rev 2272)
+++ trunk/testing/Makefile	2006-07-12 16:44:41 UTC (rev 2273)
@@ -7,3 +7,6 @@
 	rm -f $(PROGRAMS)
 
 distclean: clean
+
+drbd_states: drbd_states.o ../drbd/linux/drbd.h ../drbd/drbd_strings.o
+	gcc -o drbd_states drbd_states.o ../drbd/drbd_strings.o

Added: trunk/testing/drbd_states.c
===================================================================
--- trunk/testing/drbd_states.c	2006-07-12 09:51:26 UTC (rev 2272)
+++ trunk/testing/drbd_states.c	2006-07-12 16:44:41 UTC (rev 2273)
@@ -0,0 +1,117 @@
+/*
+ * A small program to enumerate all states considered by pre_state_checks() as
+ * valid, and to potentially improve that function.
+ */
+#include <stdio.h>
+#include <linux/drbd.h>
+
+#define STATIC static
+
+struct Drbd_Conf {
+	int dummy;
+};
+typedef struct Drbd_Conf drbd_dev;
+
+static void print_st(drbd_state_t ns, set_st_err_t rv)
+{
+	printf("{ cs:%s\tst:%s/%s\tds:%s/%s\t%c%c%c%c } = %s\n",
+	       conns_to_name(ns.conn),
+	       roles_to_name(ns.role),
+	       roles_to_name(ns.peer),
+	       disks_to_name(ns.disk),
+	       disks_to_name(ns.pdsk),
+	       ns.susp ? 's' : 'r',
+	       ns.aftr_isp ? 'a' : '-',
+	       ns.peer_isp ? 'p' : '-',
+	       ns.user_isp ? 'u' : '-',
+	       set_st_err_name(rv)
+	    );
+}
+
+
+STATIC int pre_state_checks(drbd_dev* mdev, drbd_state_t ns)
+{
+	/* See drbd_state_sw_errors in drbd_strings.c */
+
+	enum fencing_policy fp;
+	int rv=SS_Success;
+
+/*
+ 	fp = DontCare;
+	if(inc_local(mdev)) {
+		fp = mdev->bc->fencing;
+		dec_local(mdev);
+	}
+
+	if(inc_net(mdev)) {
+		if( !mdev->net_conf->two_primaries &&
+		    ns.role == Primary && ns.peer == Primary ) 
+			rv=SS_TowPrimaries;
+		dec_net(mdev);
+	}
+*/
+
+	if( rv <= 0 ) /* already found a reason to abort */;
+	else if( ns.role == Primary && ns.conn < Connected &&
+		 ns.disk < UpToDate ) rv=SS_NoUpToDateDisk;
+
+	else if( fp >= Resource &&
+		 ns.role == Primary && ns.conn < Connected &&
+		 ns.pdsk >= DUnknown ) rv=SS_PrimaryNOP;
+
+	else if( ns.role == Primary && ns.disk <= Inconsistent &&
+		 ns.pdsk <= Inconsistent ) rv=SS_NoUpToDateDisk;
+	
+	else if( ns.conn > Connected &&
+		 ns.disk < UpToDate && ns.pdsk < UpToDate ) 
+		rv=SS_BothInconsistent;
+
+	else if( ns.conn > Connected &&
+		 (ns.disk == Diskless || ns.pdsk == Diskless ) )
+		rv=SS_SyncingDiskless;
+
+	else if( (ns.conn == Connected ||
+		  ns.conn == SkippedSyncS ||
+		  ns.conn == WFBitMapS ||
+		  ns.conn == SyncSource ||
+		  ns.conn == PausedSyncS) &&
+		 ns.disk == Outdated ) rv=SS_ConnectedOutdates;
+
+	return rv;
+}
+
+
+int main(int argc, char **argv)
+{
+	drbd_role_t role, peer;
+	drbd_conns_t conn;
+	drbd_disks_t disk, pdsk;
+	drbd_state_t s;
+	int rv;
+	unsigned long all=0, valid=0;
+
+	for ( role = Primary ; role <= Secondary ; role++ ) {
+		for ( peer = Unknown ; peer <= Secondary ; peer++ ) {
+			for ( conn = StandAlone; conn <= PausedSyncT ; conn++ ) {
+				for ( disk = Diskless ; disk <= UpToDate ; disk++) {
+					for ( pdsk = Diskless ; pdsk <= UpToDate ; pdsk++) {
+						s = (drbd_state_t){{ role,peer,conn,disk,pdsk }};
+						rv = pre_state_checks(NULL,s);
+
+						all++;
+						if( rv == SS_Success ) {
+							print_st(s,rv);
+							valid++;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	printf("states considered: %lu\n",all);
+	printf("valid(?) states: %lu\n",valid);
+
+	return 0;
+}
+

From drbd-cvs at lists.linbit.com  Fri Jul 14 15:08:10 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Fri Jul 14 15:08:12 2006
Subject: [DRBD-cvs] svn commit by lars - r2274 - trunk/drbd - unify
	sock_create calls, use sock_create_kern so we won
Message-ID: <20060714130810.A61572D99F1C@mail.linbit.com>

Author: lars
Date: 2006-07-14 15:08:09 +0200 (Fri, 14 Jul 2006)
New Revision: 2274

Modified:
   trunk/drbd/drbd_receiver.c
Log:
unify sock_create calls, use sock_create_kern so we won't accidentally be user security context

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-12 16:44:41 UTC (rev 2273)
+++ trunk/drbd/drbd_receiver.c	2006-07-14 13:08:09 UTC (rev 2274)
@@ -428,7 +428,7 @@
 	if (err)
 		goto out;
 
-	if (sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock))
+	if (sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock))
 		goto out;
 
 	newsock->type = sock->type;
@@ -547,7 +547,7 @@
 	struct socket *sock;
 	struct sockaddr_in src_in;
 
-	err = sock_create(AF_INET, SOCK_STREAM, 0, &sock);
+	err = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
 	if (err) {
 		ERR("sock_creat(..)=%d\n", err);
 		return NULL;
@@ -596,7 +596,7 @@
 	int err;
 	struct socket *sock,*sock2;
 
-	err = sock_create(AF_INET, SOCK_STREAM, 0, &sock2);
+	err = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock2);
 	if (err) {
 		ERR("sock_creat(..)=%d\n", err);
 		return NULL;

From drbd-cvs at lists.linbit.com  Mon Jul 17 08:40:16 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 17 08:40:18 2006
Subject: [DRBD-cvs] svn commit by phil - r2275 - branches/drbd-0.7/user -
	There are cases where one wnat to set UNPLUG_WATERMARK 
Message-ID: <20060717064016.8E6902DF6279@mail.linbit.com>

Author: phil
Date: 2006-07-17 08:40:15 +0200 (Mon, 17 Jul 2006)
New Revision: 2275

Modified:
   branches/drbd-0.7/user/drbd_limits.h
Log:
There are cases where one wnat to set UNPLUG_WATERMARK to 1.


Modified: branches/drbd-0.7/user/drbd_limits.h
===================================================================
--- branches/drbd-0.7/user/drbd_limits.h	2006-07-14 13:08:09 UTC (rev 2274)
+++ branches/drbd-0.7/user/drbd_limits.h	2006-07-17 06:40:15 UTC (rev 2275)
@@ -52,8 +52,8 @@
   /* @4k PageSize -> 128kB - 512MB */
   RANGE(MAX_BUFFERS, 32, 131072);
 
-  /* @4k PageSize -> 64kB - 512MB */
-  RANGE(UNPLUG_WATERMARK, 16, 131072);
+  /* @4k PageSize -> 4kB - 512MB */
+  RANGE(UNPLUG_WATERMARK, 1, 131072);
 
   /* 0 is disabled.
    * 200 should be more than enough even for very short timeouts */

From drbd-cvs at lists.linbit.com  Mon Jul 17 10:25:52 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 17 10:25:53 2006
Subject: [DRBD-cvs] svn commit by phil - r2282 - trunk/user - Von: "Graham,
	Simon" <Simon.Graham@stratus.com> Current
Message-ID: <20060717082552.821DD2DF6279@mail.linbit.com>

Author: phil
Date: 2006-07-17 10:25:51 +0200 (Mon, 17 Jul 2006)
New Revision: 2282

Modified:
   trunk/user/drbdmeta.c
Log:
Von: "Graham, Simon" <Simon.Graham@stratus.com>

Currently, drbdmeta always prompts for confirmation before updating
meta-data - this is fine for interactive use but if you want to
initialize meta-data programmatically (as part of provisioning a box for
example) it causes problems. I would propose adding a "-force" option to
drbdmeta that overrides this and assumes a 'yes' answer to all
questions.



Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2006-07-17 07:35:49 UTC (rev 2281)
+++ trunk/user/drbdmeta.c	2006-07-17 08:25:51 UTC (rev 2282)
@@ -36,6 +36,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
+#include <getopt.h>
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -50,6 +51,13 @@
 extern FILE* yyin;
 YYSTYPE yylval;
 
+int     force = 0;
+
+struct option metaopt[] = {
+    { "force",  no_argument,    0, 'f' },
+    { NULL,     0,              0, 0 },
+};
+
 #define PAGE_SIZE  getpagesize()
 #define PAGE_MASK  (~(PAGE_SIZE-1))
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
@@ -792,11 +800,19 @@
 	size_t n = 0;
 	int ok;
 
-	printf("\n%s\n[need to type '%s' to confirm] ", text, yes);
-	ok = getline(&answer,&n,stdin) == N &&
-	     strncmp(answer,yes,N-1) == 0;
-	if (answer) free(answer);
-	printf("\n");
+        printf("\n%s\n", text);
+
+        if (force) {
+            printf("*** confirmation forced via --force option ***\n");
+            ok = 1;
+        }
+        else {
+            printf("[need to type '%s' to confirm] ", yes);
+            ok = getline(&answer,&n,stdin) == N &&
+                strncmp(answer,yes,N-1) == 0;
+            if (answer) free(answer);
+            printf("\n");
+        }
 	return ok;
 }
 
@@ -2278,7 +2294,7 @@
 	size_t i;
 
 	printf
-	    ("\nUSAGE: %s DEVICE FORMAT [FORMAT ARGS...] COMMAND [CMD ARGS...]\n",
+	    ("\nUSAGE: %s [--force] DEVICE FORMAT [FORMAT ARGS...] COMMAND [CMD ARGS...]\n",
 	     progname);
 
 	printf("\nFORMATS:\n");
@@ -2408,14 +2424,32 @@
 	if (argc < 4)
 		print_usage_and_exit();
 
+        /* Check for options (e.g. --force) */
+        while (1) {
+            int c = getopt_long(argc,argv,make_optstring(metaopt,0),metaopt,0);
+
+            if (c == -1)
+                break;
+
+            switch (c) {
+            case 'f':
+                force = 1;
+                break;
+            default:
+                print_usage_and_exit();
+                break;
+            }
+        }
+
+        // Next argument to process is specified by optind...
+        ai = optind;
+
 	/* FIXME should have a "drbd_cfg_new" and a "drbd_cfg_free"
 	 * function, maybe even a "get" and "put" ?
 	 */
 	cfg = calloc(1, sizeof(struct format));
-	cfg->drbd_dev_name = argv[1];
+	cfg->drbd_dev_name = argv[ai++];
 
-	/* argv[0] is progname, argv[1] was drbd_dev_name. */
-	ai = 2;
 	if (parse_format(cfg, argv + ai, argc - ai, &ai)) {
 		/* parse has already printed some error message */
 		exit(20);

From drbd-cvs at lists.linbit.com  Tue Jul 18 14:52:28 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul 18 14:52:30 2006
Subject: [DRBD-cvs] svn commit by phil - r2283 - in trunk: . drbd - It
	turned that some workloads are processed a lot quick
Message-ID: <20060718125229.04ED92DF6270@mail.linbit.com>

Author: phil
Date: 2006-07-18 14:52:26 +0200 (Tue, 18 Jul 2006)
New Revision: 2283

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_worker.c
Log:
It turned that some workloads are processed a lot quicker if we send
out of the worker's context. 
-> The make_requests function usually does not sleep 
-> No slowdown of the process that generates the requests.

TODOs:
* Honour the max-buffers setting for this.
* Think about read requests.	    


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-17 08:25:51 UTC (rev 2282)
+++ trunk/ROADMAP	2006-07-18 12:52:26 UTC (rev 2283)
@@ -802,6 +802,12 @@
 
    Simon works on this. 
 
+39 Send mirrored write requests out of the worker context.
+   30% DONE
+   TODO:   Honour the max-buffers setting for this.
+           Think about read requests.
+
+
 Maybe:
 
 *  Switch to protocol C in case we are running without a local 

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-17 08:25:51 UTC (rev 2282)
+++ trunk/drbd/drbd_fs.c	2006-07-18 12:52:26 UTC (rev 2283)
@@ -875,7 +875,7 @@
 int drbd_set_role(drbd_dev *mdev, int* arg)
 {
 	drbd_role_t newstate = *arg;
-	int rv,r,forced = 0, try=0;
+	int rv,r=0,forced = 0, try=0;
 	drbd_state_t mask, val;
 	drbd_disks_t nps;
 

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-17 08:25:51 UTC (rev 2282)
+++ trunk/drbd/drbd_int.h	2006-07-18 12:52:26 UTC (rev 2283)
@@ -591,6 +591,7 @@
 struct drbd_barrier;
 struct drbd_request {
 	struct drbd_work w;
+	struct list_head tl_requests; // double linked list in the TL
 	struct drbd_barrier *barrier; // The next barrier.
 	struct bio *master_bio;       // master bio pointer
 	struct bio *private_bio;
@@ -602,6 +603,7 @@
 };
 
 struct drbd_barrier {
+	struct drbd_work w;
 	struct list_head requests; // requests before
 	struct drbd_barrier *next; // pointer to the next barrier
 	int br_number;  // the barriers identifier.
@@ -849,6 +851,9 @@
 extern void tl_release(drbd_dev *mdev,unsigned int barrier_nr,
 		       unsigned int set_size);
 extern void tl_clear(drbd_dev *mdev);
+extern void tl_add(drbd_dev *mdev, drbd_request_t *req);
+extern struct drbd_barrier *tl_add_barrier(drbd_dev *mdev);
+extern struct Tl_epoch_entry * ee_have_write(drbd_dev *mdev,drbd_request_t * req);
 extern int tl_dependence(drbd_dev *mdev, drbd_request_t * item);
 extern int tl_verify(drbd_dev *mdev, drbd_request_t * item, sector_t sector);
 extern drbd_request_t * req_have_write(drbd_dev *, struct Tl_epoch_entry *);
@@ -877,7 +882,7 @@
 extern int drbd_send_block(drbd_dev *mdev, Drbd_Packet_Cmd cmd,
 			   struct Tl_epoch_entry *e);
 extern int drbd_send_dblock(drbd_dev *mdev, drbd_request_t *req);
-extern int _drbd_send_barrier(drbd_dev *mdev);
+extern int _drbd_send_barrier(drbd_dev *mdev, struct drbd_barrier *barrier);
 extern int drbd_send_drequest(drbd_dev *mdev, int cmd,
 			      sector_t sector,int size, u64 block_id);
 extern int drbd_send_bitmap(drbd_dev *mdev);
@@ -1130,6 +1135,8 @@
 extern int w_try_send_barrier    (drbd_dev *, struct drbd_work *, int);
 extern int w_send_write_hint     (drbd_dev *, struct drbd_work *, int);
 extern int w_make_resync_request (drbd_dev *, struct drbd_work *, int);
+extern int w_send_dblock         (drbd_dev *, struct drbd_work *, int);
+extern int w_send_barrier        (drbd_dev *, struct drbd_work *, int);
 extern void resync_timer_fn(unsigned long data);
 
 // drbd_receiver.c

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-17 08:25:51 UTC (rev 2282)
+++ trunk/drbd/drbd_main.c	2006-07-18 12:52:26 UTC (rev 2283)
@@ -212,7 +212,7 @@
 
 	req->barrier = b;
 	req->rq_status |= RQ_DRBD_IN_TL;
-	list_add(&req->w.list,&b->requests);
+	list_add(&req->tl_requests,&b->requests);
 
 	if( b->n_req++ > mdev->net_conf->max_epoch_size ) {
 		set_bit(ISSUE_BARRIER,&mdev->flags);
@@ -223,7 +223,7 @@
 			tl_hash_fn(mdev, drbd_req_get_sector(req) ));
 }
 
-STATIC void tl_add(drbd_dev *mdev, drbd_request_t * req)
+void tl_add(drbd_dev *mdev, drbd_request_t * req)
 {
 	spin_lock_irq(&mdev->tl_lock);
 	_tl_add(mdev,req);
@@ -239,37 +239,41 @@
 	b=req->barrier;
 	b->n_req--;
 
-	list_del(&req->w.list);
+	list_del(&req->tl_requests);
 	hlist_del(&req->colision);
 	req->rq_status &= ~RQ_DRBD_IN_TL;
 
 	spin_unlock_irq(&mdev->tl_lock);
 }
 
-STATIC unsigned int tl_add_barrier(drbd_dev *mdev)
+/**
+ * tl_add_barrier: Creates a new barrier object and links it into the
+ * transfer log. It returns the the newest (but not the just created 
+ * barrier to the caller.
+ */
+struct drbd_barrier *tl_add_barrier(drbd_dev *mdev)
 {
-	unsigned int bnr;
-	struct drbd_barrier *b;
+	struct drbd_barrier *new, *newest_before;
 
-	b=kmalloc(sizeof(struct drbd_barrier),GFP_NOIO);
-	if(!b) {
+	new=kmalloc(sizeof(struct drbd_barrier),GFP_NOIO);
+	if(!new) {
 		ERR("could not kmalloc() barrier\n");
 		return 0;
 	}
-	INIT_LIST_HEAD(&b->requests);
-	b->next=0;
-	b->n_req=0;
+	INIT_LIST_HEAD(&new->requests);
+	new->next=0;
+	new->n_req=0;
 
 	spin_lock_irq(&mdev->tl_lock);
 	/* mdev->newest_barrier == NULL "cannot happen". but anyways... */
-	bnr = mdev->newest_barrier ? mdev->newest_barrier->br_number : 1;
+	newest_before = mdev->newest_barrier;
 	/* never send a barrier number == 0 */
-	b->br_number = (bnr+1) ?: 1;
-	mdev->newest_barrier->next = b;
-	mdev->newest_barrier = b;
+	new->br_number = (newest_before->br_number+1) ?: 1;
+	mdev->newest_barrier->next = new;
+	mdev->newest_barrier = new;
 	spin_unlock_irq(&mdev->tl_lock);
 
-	return bnr;
+	return newest_before;
 }
 
 void tl_release(drbd_dev *mdev,unsigned int barrier_nr,
@@ -290,7 +294,15 @@
 	spin_unlock_irq(&mdev->tl_lock);
 
 	D_ASSERT(b->br_number == barrier_nr);
+	if(b->br_number != barrier_nr) {
+		DUMPI(b->br_number);
+		DUMPI(barrier_nr);
+	}
 	D_ASSERT(b->n_req == set_size);
+	if(b->n_req != set_size) {
+		DUMPI(b->n_req);
+		DUMPI(set_size);
+	}
 
 	kfree(b);
 }
@@ -334,7 +346,7 @@
 	spin_lock_irqsave(&mdev->tl_lock,flags);
 
 	r = ( req->barrier == mdev->newest_barrier );
-	list_del(&req->w.list);
+	list_del(&req->tl_requests);
 	hlist_del(&req->colision);
 
 	if( req->rq_status & RQ_DRBD_RECVW ) wake_up(&mdev->cstate_wait);
@@ -376,7 +388,7 @@
 
 	while ( b ) {
 		list_for_each_safe(le, tle, &b->requests) {
-			r = list_entry(le, struct drbd_request,w.list);
+			r = list_entry(le, struct drbd_request,tl_requests);
 			// bi_size and bi_sector are modified in bio_endio!
 			sector = drbd_req_get_sector(r);
 			size   = drbd_req_get_size(r);
@@ -444,7 +456,7 @@
 	return req;
 }
 
-STATIC struct Tl_epoch_entry * ee_have_write(drbd_dev *mdev,
+struct Tl_epoch_entry * ee_have_write(drbd_dev *mdev,
 					     drbd_request_t * req)
 {
 	struct hlist_head *slot;
@@ -1492,19 +1504,16 @@
 	return ok;
 }
 
-int _drbd_send_barrier(drbd_dev *mdev)
+int _drbd_send_barrier(drbd_dev *mdev, struct drbd_barrier *barrier)
 {
 	int ok;
 	Drbd_Barrier_Packet p;
 
-	/* printk(KERN_DEBUG DEVICE_NAME": issuing a barrier\n"); */
-	/* tl_add_barrier() must be called with the sock_mutex aquired */
-	p.barrier=tl_add_barrier(mdev);
+	p.barrier=barrier->br_number;
 
 	inc_ap_pending(mdev);
 	ok = _drbd_send_cmd(mdev,mdev->data.socket,Barrier,(Drbd_Header*)&p,sizeof(p),0);
 
-//	if (!ok) dec_ap_pending(mdev); // is done in tl_clear()
 	return ok;
 }
 
@@ -1721,85 +1730,36 @@
 	Drbd_Data_Packet p;
 	unsigned int dp_flags=0;
 
-	/* About tl_add():
-	1. This must be within the semaphor,
-	   to ensure right order in tl_ data structure and to
-	   ensure right order of packets on the write
-	2. This must happen before sending, otherwise we might
-	   get in the BlockAck packet before we have it on the
-	   tl_ datastructure (=> We would want to remove it before it
-	   is there!)
-	3. Q: Why can we add it to tl_ even when drbd_send() might fail ?
-	      There could be a tl_cancel() to remove it within the semaphore!
-	   A: If drbd_send fails, we will lose the connection. Then
-	      tl_cear() will simulate a RQ_DRBD_SEND and set it out of sync
-	      for everything in the data structure.
-	*/
-
-	/* Still called directly by drbd_make_request,
-	 * so all sorts of processes may end up here.
-	 * They may be interrupted by DRBD_SIG in response to
-	 * ioctl or some other "connection lost" event.
-	 * This is not propagated.
-	 */
-
 	old_blocked = drbd_block_all_signals();
 	down(&mdev->data.mutex);
 	spin_lock(&mdev->send_task_lock);
 	mdev->send_task=current;
 	spin_unlock(&mdev->send_task_lock);
 
-	if(test_and_clear_bit(ISSUE_BARRIER,&mdev->flags))
-		ok = _drbd_send_barrier(mdev);
+	p.head.magic   = BE_DRBD_MAGIC;
+	p.head.command = cpu_to_be16(Data);
+	p.head.length  = cpu_to_be16( sizeof(p)-sizeof(Drbd_Header)
+					      + drbd_req_get_size(req) );
+
+	p.sector   = cpu_to_be64(drbd_req_get_sector(req));
+	p.block_id = (unsigned long)req;
+	p.seq_num  = cpu_to_be32( req->seq_num =
+				  atomic_add_return(1,&mdev->packet_seq) );
+	if(req->master_bio->bi_rw & BIO_RW_BARRIER) {
+		dp_flags = DP_HARDBARRIER;
+	}
+	p.dp_flags = cpu_to_be32(dp_flags);
+	dump_packet(mdev,mdev->data.socket,0,(void*)&p, __FILE__, __LINE__);
+	set_bit(UNPLUG_REMOTE,&mdev->flags);
+	ok = sizeof(p) == drbd_send(mdev,mdev->data.socket,&p,sizeof(p),MSG_MORE);
 	if(ok) {
-		if (mdev->net_conf->two_primaries) {
-			if(ee_have_write(mdev,req)) {
-				ok=-1;
-				goto out;
-			}
+		if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {
+			ok = _drbd_send_bio(mdev,req->master_bio);
 		} else {
-			tl_add(mdev,req);
+			ok = _drbd_send_zc_bio(mdev,req->master_bio);
 		}
-
-		p.head.magic   = BE_DRBD_MAGIC;
-		p.head.command = cpu_to_be16(Data);
-		p.head.length  = cpu_to_be16( sizeof(p)-sizeof(Drbd_Header)
-					      + drbd_req_get_size(req) );
-
-		p.sector   = cpu_to_be64(drbd_req_get_sector(req));
-		p.block_id = (unsigned long)req;
-#if 0
-#warning "YES I KNOW. JUST SO IT COMPILES NOW."
-		atomic_inc(&mdev->packet_seq);
-		p.seq_num = atomic_read(&mdev->packet_seq);
-#else
-		p.seq_num  = cpu_to_be32( req->seq_num =
-				     atomic_add_return(1,&mdev->packet_seq) );
-#endif
-		if(req->master_bio->bi_rw & BIO_RW_BARRIER) {
-			dp_flags = DP_HARDBARRIER;
-		}
-		p.dp_flags = cpu_to_be32(dp_flags);
-		dump_packet(mdev,mdev->data.socket,0,(void*)&p, __FILE__, __LINE__);
-		set_bit(UNPLUG_REMOTE,&mdev->flags);
-		ok = sizeof(p) == drbd_send(mdev,mdev->data.socket,&p,sizeof(p),MSG_MORE);
-		if(ok) {
-			if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {
-				ok = _drbd_send_bio(mdev,drbd_req_private_bio(req));
-			} else {
-				ok = _drbd_send_zc_bio(mdev,drbd_req_private_bio(req));
-			}
-		}
-		if(!ok) tl_cancel(mdev,req);
 	}
-	if (!ok) {
-		drbd_set_out_of_sync(mdev,
-				     drbd_req_get_sector(req),
-				     drbd_req_get_size(req));
-		drbd_end_req(req,RQ_DRBD_SENT,ERF_NOTLD|1,
-			     drbd_req_get_sector(req));
-	}
- out:
+
 	spin_lock(&mdev->send_task_lock);
 	mdev->send_task=NULL;
 	spin_unlock(&mdev->send_task_lock);

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-17 08:25:51 UTC (rev 2282)
+++ trunk/drbd/drbd_req.c	2006-07-18 12:52:26 UTC (rev 2283)
@@ -326,31 +326,48 @@
 		 * or READ, and no local disk,
 		 * or READ, but not in sync.
 		 */
-		inc_ap_pending(mdev);
 		if (rw == WRITE) {
-			switch(drbd_send_dblock(mdev,req)) {
-			case 0: /* sending failed */
-				if (mdev->state.conn >= Connected)
-					drbd_force_state(mdev,NS(conn,NetworkFailure));
-				dec_ap_pending(mdev);
-				drbd_thread_restart_nowait(&mdev->receiver);
-				break;
-			case -1: /* concurrent write */
-				WARN("Concurrent write! [DISCARD L] sec=%lu\n",
-				     (unsigned long)sector);
-				dec_local(mdev);
-				dec_ap_pending(mdev);
-				local=0;
-				drbd_end_req(req, RQ_DRBD_DONE, 1, sector);
-				break;
-			default: /* block was sent */
-			  if(mdev->net_conf->wire_protocol == DRBD_PROT_A) { // PRE LOCKING
+
+	/* About tl_add():
+	1. This must be within the semaphor,
+	   to ensure right order in tl_ data structure and to
+	   ensure right order of packets on the write
+	2. This must happen before sending, otherwise we might
+	   get in the BlockAck packet before we have it on the
+	   tl_ datastructure (=> We would want to remove it before it
+	   is there!)
+	3. Q: Why can we add it to tl_ even when drbd_send() might fail ?
+	      There could be a tl_cancel() to remove it within the semaphore!
+	   A: If drbd_send fails, we will lose the connection. Then
+	      tl_cear() will simulate a RQ_DRBD_SEND and set it out of sync
+	      for everything in the data structure.
+	*/
+			down(&mdev->data.mutex);
+			if(test_and_clear_bit(ISSUE_BARRIER,&mdev->flags)) {
+				struct drbd_barrier *b = tl_add_barrier(mdev);
+				b->w.cb =  w_send_barrier;
+				drbd_queue_work(mdev,&mdev->data.work, &b->w);
+			}
+
+			if (mdev->net_conf->two_primaries) {
+				if(ee_have_write(mdev,req)) {
+					WARN("Concurrent write! [DISCARD L] sec=%lu\n",
+					     (unsigned long)sector);
+					dec_local(mdev);
 					dec_ap_pending(mdev);
-					drbd_end_req(req, RQ_DRBD_SENT, 1, sector);
+					local=0;
+					drbd_end_req(req, RQ_DRBD_DONE, 1, sector);
 				}
+			} else {
+				tl_add(mdev,req);
 			}
+			req->w.cb =  w_send_dblock;
+			drbd_queue_work(mdev,&mdev->data.work, &req->w);
+
+			up(&mdev->data.mutex);
 		} else {
 			// this node is diskless ...
+			inc_ap_pending(mdev);
 			drbd_read_remote(mdev,req);
 		}
 	}

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-17 08:25:51 UTC (rev 2282)
+++ trunk/drbd/drbd_worker.c	2006-07-18 12:52:26 UTC (rev 2283)
@@ -530,19 +530,57 @@
 
 	down(&mdev->data.mutex);
 	if(test_and_clear_bit(ISSUE_BARRIER,&mdev->flags)) {
-		ok = _drbd_send_barrier(mdev);
+		ok = _drbd_send_barrier(mdev,tl_add_barrier(mdev));
 	}
 	up(&mdev->data.mutex);
 
 	return ok;
 }
 
+int w_send_barrier(drbd_dev *mdev, struct drbd_work *w, int cancel)
+{
+	struct drbd_barrier *b = (struct drbd_barrier *)w;
+	int ok=1;
+
+	if(unlikely(cancel)) return ok;
+
+	down(&mdev->data.mutex);
+	ok = _drbd_send_barrier(mdev,b);
+	up(&mdev->data.mutex);
+
+	return ok;
+}
+
 int w_send_write_hint(drbd_dev *mdev, struct drbd_work *w, int cancel)
 {
 	if (cancel) return 1;
 	return drbd_send_short_cmd(mdev,UnplugRemote);
 }
 
+int w_send_dblock(drbd_dev *mdev, struct drbd_work *w, int cancel)
+{
+	drbd_request_t *req = (drbd_request_t *)w;
+	int ok;
+
+	if (unlikely(cancel)) { 
+		/* Nothing to do, here. tl_clear() does the work. */
+		return 1;
+	}
+
+	inc_ap_pending(mdev);
+	ok = drbd_send_dblock(mdev,req);
+	if (!ok) {
+		if (mdev->state.conn >= Connected) 
+			drbd_force_state(mdev,NS(conn,NetworkFailure));
+		drbd_thread_restart_nowait(&mdev->receiver);
+	} else if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {
+		dec_ap_pending(mdev);
+		drbd_end_req(req, RQ_DRBD_SENT, 1, drbd_req_get_sector(req));
+	}
+
+	return ok;
+}
+
 STATIC void drbd_global_lock(void)
 {
 	int i;

From drbd-cvs at lists.linbit.com  Tue Jul 18 15:34:08 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul 18 15:34:10 2006
Subject: [DRBD-cvs] svn commit by lars - r2284 - branches/drbd-0.7/drbd -
	fixed (?) the "syncer stalled" after reconnect.
Message-ID: <20060718133408.A751B2DF6270@mail.linbit.com>

the res
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: lars
Date: 2006-07-18 15:34:07 +0200 (Tue, 18 Jul 2006)
New Revision: 2284

Modified:
   branches/drbd-0.7/drbd/drbd_main.c
   branches/drbd-0.7/drbd/drbd_receiver.c
   branches/drbd-0.7/drbd/drbd_worker.c
Log:

fixed (?) the "syncer stalled" after reconnect.
the resync_timer was not scheduled because of some
paranoia checks in drbd_start_resync.
Those checks could trigger because of a race between
the various places (drbd_disconnect, resync_timer_fn
etc.) during resync cleanup on connection loss.

This patch moves the racy cleanup code from
drbd_disconnect into drbd_worker.
Also drbd_start_resync schedules the resync_timer
anyways (even when those paranoia checks should trigger
for some reason).

The other parts of this patch is "just cosmetics".



Modified: branches/drbd-0.7/drbd/drbd_main.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_main.c	2006-07-18 12:52:26 UTC (rev 2283)
+++ branches/drbd-0.7/drbd/drbd_main.c	2006-07-18 13:34:07 UTC (rev 2284)
@@ -469,10 +469,6 @@
 	smp_mb();
 	wake_up(&mdev->cstate_wait);
 
-	/* THINK.
-	 * was:
-	 * if ( ( os==SyncSource || os==SyncTarget ) && ns <= Connected ) {
-	 */
 	if ( ( os >= SyncSource ) && ns <= Connected ) {
 		clear_bit(SYNC_STARTED,&mdev->flags);
 		set_bit(STOP_SYNC_TIMER,&mdev->flags);

Modified: branches/drbd-0.7/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_receiver.c	2006-07-18 12:52:26 UTC (rev 2283)
+++ branches/drbd-0.7/drbd/drbd_receiver.c	2006-07-18 13:34:07 UTC (rev 2284)
@@ -1836,30 +1836,6 @@
 	D_ASSERT(mdev->cstate < Connected);
 	mdev->o_state = Unknown;
 
-	/* in case we have been syncing, and then we drop the connection,
-	 * we need to "w_resume_next_sg", which we try to achieve by
-	 * setting the STOP_SYNC_TIMER bit, and schedulung the timer for
-	 * immediate execution.
-	 * unfortunately we cannot be sure that the timer already triggered.
-	 *
-	 * so we del_timer_sync here, and check that bit.
-	 * if it is still set, we queue w_resume_next_sg anyways,
-	 * just to be sure.
-	 */
-
-	del_timer_sync(&mdev->resync_timer);
-	spin_lock_irq(&mdev->req_lock);
-	if (test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags)) {
-		mdev->resync_work.cb = w_resume_next_sg;
-		if (list_empty(&mdev->resync_work.list))
-			_drbd_queue_work(&mdev->data.work,&mdev->resync_work);
-		// else: already queued, we only need to release the lock.
-	} else {
-		D_ASSERT(mdev->resync_work.cb == w_resync_inactive);
-	}
-	spin_unlock_irq(&mdev->req_lock);
-
-
 	drbd_thread_stop_nowait(&mdev->worker);
 	drbd_thread_stop(&mdev->asender);
 

Modified: branches/drbd-0.7/drbd/drbd_worker.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_worker.c	2006-07-18 12:52:26 UTC (rev 2283)
+++ branches/drbd-0.7/drbd/drbd_worker.c	2006-07-18 13:34:07 UTC (rev 2284)
@@ -690,9 +690,10 @@
 	_set_cstate(mdev,ns);
 
 	if(mdev->cstate == SyncTarget) {
-		ERR_IF(test_bit(STOP_SYNC_TIMER,&mdev->flags)) {
+		int stop_syncer_timer_was_set =
+			test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags);
+		ERR_IF(stop_syncer_timer_was_set) {
 			unsigned long rs_left = drbd_bm_total_weight(mdev);
-			clear_bit(STOP_SYNC_TIMER,&mdev->flags);
 			if (rs_left == 0) {
 				INFO("rs_left==0 in _drbd_rs_resume\n");
 			} else {
@@ -778,6 +779,8 @@
 {
 	drbd_dev *odev;
 	int i,ng=10000;
+	/* FIXME need to document that 10000 somewhere!
+	 * maybe better: first iterate to find the max sync group number */
 
 	PARANOIA_BUG_ON(w != &mdev->resync_work);
 
@@ -785,6 +788,9 @@
 
 	for (i=0; i < minor_count; i++) {
 		odev = drbd_conf + i;
+		/* currently we should never reach this while being
+		 * mdev->cstate == Sync*, but just incase: skip ourselves */
+		if (odev == mdev) continue;
 		if ( odev->sync_conf.group <= mdev->sync_conf.group
 		     && ( odev->cstate == SyncSource || 
 			  odev->cstate == SyncTarget ) ) {
@@ -795,6 +801,7 @@
 
 	for (i=0; i < minor_count; i++) { // find next sync group
 		odev = drbd_conf + i;
+		if (odev == mdev) continue;
 		if ( odev->sync_conf.group > mdev->sync_conf.group
 		     && odev->sync_conf.group < ng && 
 		     (odev->cstate==PausedSyncS || odev->cstate==PausedSyncT)){
@@ -804,6 +811,7 @@
 
 	for (i=0; i < minor_count; i++) { // resume all devices in next group
 		odev = drbd_conf + i;
+		if (odev == mdev) continue;
 		if ( odev->sync_conf.group == ng &&
 		     (odev->cstate==PausedSyncS || odev->cstate==PausedSyncT)){
 			_drbd_rs_resume(odev);
@@ -811,8 +819,8 @@
 	}
 
  out:
+	w->cb = w_resync_inactive;
 	drbd_global_unlock();
-	w->cb = w_resync_inactive;
 
 	return 1;
 }
@@ -884,7 +892,6 @@
 		else
 			ERR("resync_work.cb == %p ???, should be w_resync_inactive\n",
 					mdev->resync_work.cb);
-		return;
 	}
 
 	if ( mdev->rs_total == 0 ) {
@@ -905,12 +912,16 @@
 	   */
 	drbd_global_unlock();
 
-	if (mdev->cstate == SyncTarget) {
-		D_ASSERT(!test_bit(STOP_SYNC_TIMER,&mdev->flags));
-		mod_timer(&mdev->resync_timer,jiffies);
-	} else if (mdev->cstate == PausedSyncT) { 
-		D_ASSERT(test_bit(STOP_SYNC_TIMER,&mdev->flags));
-		clear_bit(STOP_SYNC_TIMER,&mdev->flags);
+	/* THINK: for consistency, should this be before the drbd_global_unlock() ? */
+	{
+		int stop_syncer_timer_was_set =
+			test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags);
+		if (mdev->cstate == SyncTarget) {
+			D_ASSERT(!stop_syncer_timer_was_set);
+			mod_timer(&mdev->resync_timer,jiffies);
+		} else if (mdev->cstate == PausedSyncT) {
+			D_ASSERT(stop_syncer_timer_was_set);
+		}
 	}
 }
 
@@ -960,8 +971,40 @@
 
 	drbd_wait_ee(mdev,&mdev->read_ee);
 
+	/* When we terminate a resync process, either because it finished
+	 * sucessfully, or because (like in this case here) we lost
+	 * communications, we need to "w_resume_next_sg".
+	 * We cannot use del_timer_sync from within _set_cstate, and since the
+	 * resync timer may still be scheduled and would then trigger anyways,
+	 * we set the STOP_SYNC_TIMER bit, and schedule the timer for immediate
+	 * execution from within _set_cstate().
+	 * The timer should then clear that bit and queue w_resume_next_sg.
+	 *
+	 * This is fine for the normal "resync finished" case.
+	 *
+	 * In this case (worker thread beeing stopped), there is a race:
+	 * we cannot be sure that the timer already triggered.
+	 *
+	 * So we del_timer_sync here, and check that "STOP_SYNC_TIMER" bit.
+	 * if it is still set, we queue w_resume_next_sg anyways,
+	 * just to be sure.
+	 */
+
+	del_timer_sync(&mdev->resync_timer);
+	/* possible paranoia check: the STOP_SYNC_TIMER bit should be set
+	 * if and only if del_timer_sync returns true ... */
+
+	spin_lock_irq(&mdev->req_lock);
+	if (test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags)) {
+		mdev->resync_work.cb = w_resume_next_sg;
+		if (list_empty(&mdev->resync_work.list))
+			_drbd_queue_work(&mdev->data.work,&mdev->resync_work);
+		// else: already queued
+	} else {
+		mdev->resync_work.cb = w_resync_inactive;
+	}
+
 	i = 0;
-	spin_lock_irq(&mdev->req_lock);
   again:
 	list_splice_init(&mdev->data.work.q,&work_list);
 	spin_unlock_irq(&mdev->req_lock);
@@ -970,7 +1013,7 @@
 		w = list_entry(work_list.next, struct drbd_work,list);
 		list_del_init(&w->list);
 		w->cb(mdev,w,1);
-		i++;
+		i++; /* dead debugging code */
 	}
 
 	spin_lock_irq(&mdev->req_lock);

From drbd-cvs at lists.linbit.com  Tue Jul 18 16:32:21 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul 18 16:32:22 2006
Subject: [DRBD-cvs] svn commit by lars - r2285 - trunk/drbd - fix outdated
	assert
Message-ID: <20060718143221.3D2782DF6270@mail.linbit.com>

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: lars
Date: 2006-07-18 16:32:20 +0200 (Tue, 18 Jul 2006)
New Revision: 2285

Modified:
   trunk/drbd/drbd_receiver.c
Log:
fix outdated assert

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-18 13:34:07 UTC (rev 2284)
+++ trunk/drbd/drbd_receiver.c	2006-07-18 14:32:20 UTC (rev 2285)
@@ -1032,7 +1032,7 @@
 	 */
 	ERR_IF(data_size == 0) return FALSE;
 	ERR_IF(data_size &  0x1ff) return FALSE;
-	ERR_IF(data_size >  PAGE_SIZE) return FALSE;
+	ERR_IF(data_size >  DRBD_MAX_SEGMENT_SIZE) return FALSE;
 
 	if (drbd_recv(mdev, h->payload, header_size) != header_size)
 		return FALSE;

From drbd-cvs at lists.linbit.com  Wed Jul 19 10:40:04 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 19 10:40:06 2006
Subject: [DRBD-cvs] svn commit by phil - r2286 - trunk/drbd - This finally
	fixes the send_from_worker's context patch
Message-ID: <20060719084004.5FC8D2D99EC6@mail.linbit.com>

Author: phil
Date: 2006-07-19 10:40:02 +0200 (Wed, 19 Jul 2006)
New Revision: 2286

Modified:
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_worker.c
Log:
This finally fixes the send_from_worker's context patch. 
We had memory corruption ( access after free() )


Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-18 14:32:20 UTC (rev 2285)
+++ trunk/drbd/drbd_main.c	2006-07-19 08:40:02 UTC (rev 2286)
@@ -230,22 +230,6 @@
 	spin_unlock_irq(&mdev->tl_lock);
 }
 
-STATIC void tl_cancel(drbd_dev *mdev, drbd_request_t *req)
-{
-	struct drbd_barrier *b;
-
-	spin_lock_irq(&mdev->tl_lock);
-
-	b=req->barrier;
-	b->n_req--;
-
-	list_del(&req->tl_requests);
-	hlist_del(&req->colision);
-	req->rq_status &= ~RQ_DRBD_IN_TL;
-
-	spin_unlock_irq(&mdev->tl_lock);
-}
-
 /**
  * tl_add_barrier: Creates a new barrier object and links it into the
  * transfer log. It returns the the newest (but not the just created 
@@ -294,15 +278,18 @@
 	spin_unlock_irq(&mdev->tl_lock);
 
 	D_ASSERT(b->br_number == barrier_nr);
+	D_ASSERT(b->n_req == set_size);
+
+#ifdef DBG_ASSERTS
 	if(b->br_number != barrier_nr) {
 		DUMPI(b->br_number);
 		DUMPI(barrier_nr);
 	}
-	D_ASSERT(b->n_req == set_size);
 	if(b->n_req != set_size) {
 		DUMPI(b->n_req);
 		DUMPI(set_size);
 	}
+#endif
 
 	kfree(b);
 }
@@ -348,6 +335,7 @@
 	r = ( req->barrier == mdev->newest_barrier );
 	list_del(&req->tl_requests);
 	hlist_del(&req->colision);
+	// req->barrier->n_req--; // Barrier migh be free'ed already!
 
 	if( req->rq_status & RQ_DRBD_RECVW ) wake_up(&mdev->cstate_wait);
 
@@ -358,35 +346,20 @@
 void tl_clear(drbd_dev *mdev)
 {
 	struct list_head *le,*tle;
-	struct drbd_barrier *b,*f,*new_first;
+	struct drbd_barrier *b,*f;
 	struct drbd_request *r;
 	sector_t sector;
 	unsigned int size;
 
-	new_first=kmalloc(sizeof(struct drbd_barrier),GFP_NOIO);
-	if(!new_first) {
-		ERR("could not kmalloc() barrier\n");
-	}
-
-	/* FIXME if indeed we could not kmalloc, this will Oops!
-	 * can we somehow just recycle one of the existing barriers?
-	 */
-	INIT_LIST_HEAD(&new_first->requests);
-	new_first->next=0;
-	new_first->br_number=4711;
-	new_first->n_req=0;
-
 	spin_lock_irq(&mdev->tl_lock);
 
 	b=mdev->oldest_barrier;
-	mdev->oldest_barrier = new_first;
-	mdev->newest_barrier = new_first;
+	mdev->oldest_barrier = NULL;
+	mdev->newest_barrier = NULL; 
 
 	spin_unlock_irq(&mdev->tl_lock);
 
-	inc_ap_pending(mdev); // Since we count the old first as well...
-
-	while ( b ) {
+	while ( 1 ) {
 		list_for_each_safe(le, tle, &b->requests) {
 			r = list_entry(le, struct drbd_request,tl_requests);
 			// bi_size and bi_sector are modified in bio_endio!
@@ -406,9 +379,24 @@
 		f=b;
 		b=b->next;
 		list_del(&f->requests);
+		if (!b) break;
 		kfree(f);
 		dec_ap_pending(mdev); // for the barrier
 	}
+
+	// f is now the last barrier, we use it as new first barrier.
+
+	INIT_LIST_HEAD(&f->requests);
+	f->next=NULL;
+	f->br_number=4711;
+	f->n_req=0;
+
+	spin_lock_irq(&mdev->tl_lock);
+
+	mdev->oldest_barrier = f;
+	mdev->newest_barrier = f;
+
+	spin_unlock_irq(&mdev->tl_lock);
 }
 
 STATIC unsigned int ee_hash_fn(drbd_dev *mdev, sector_t sector)

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-18 14:32:20 UTC (rev 2285)
+++ trunk/drbd/drbd_req.c	2006-07-19 08:40:02 UTC (rev 2286)
@@ -77,8 +77,9 @@
 			if(tl_dependence(mdev,req))
 				set_bit(ISSUE_BARRIER,&mdev->flags);
 		} else {
-			list_del(&req->w.list); // we have the tl_lock...
+			list_del(&req->tl_requests); // we have the tl_lock...
 			hlist_del(&req->colision);
+			// req->barrier->n_req--; // Barrier migh be free'ed !
 		}
 	}
 

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-18 14:32:20 UTC (rev 2285)
+++ trunk/drbd/drbd_worker.c	2006-07-19 08:40:02 UTC (rev 2286)
@@ -562,12 +562,13 @@
 	drbd_request_t *req = (drbd_request_t *)w;
 	int ok;
 
+	inc_ap_pending(mdev); // Right here, since tl_clear() will decrease it
+
 	if (unlikely(cancel)) { 
 		/* Nothing to do, here. tl_clear() does the work. */
 		return 1;
 	}
 
-	inc_ap_pending(mdev);
 	ok = drbd_send_dblock(mdev,req);
 	if (!ok) {
 		if (mdev->state.conn >= Connected) 

From drbd-cvs at lists.linbit.com  Wed Jul 19 16:34:21 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 19 16:34:22 2006
Subject: [DRBD-cvs] svn commit by lars - r2287 - branches/drbd-0.7/drbd -
	While verifying the fix for the "syncer stalled" bug, 
Message-ID: <20060719143422.0293E2DF6271@mail.linbit.com>

w
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: lars
Date: 2006-07-19 16:34:20 +0200 (Wed, 19 Jul 2006)
New Revision: 2287

Modified:
   branches/drbd-0.7/drbd/drbd_main.c
Log:
While verifying the fix for the "syncer stalled" bug,
we hit yet an other bug.

Symptoms: Primary get stuck in WFReportParams;
if you try to drbdadm disconnect,
it hits a NULL pointer dereference
(kernel Oops) in force_sig.



Modified: branches/drbd-0.7/drbd/drbd_main.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_main.c	2006-07-19 08:40:02 UTC (rev 2286)
+++ branches/drbd-0.7/drbd/drbd_main.c	2006-07-19 14:34:20 UTC (rev 2287)
@@ -660,6 +660,13 @@
 
 	if (sock == mdev->data.socket) {
 		down(&mdev->data.mutex);
+		if (sock != mdev->data.socket) {
+			/* verify drbd_disconnect: drbd_free_sock may free this
+			 * socket while we have been waiting in down.
+			 */
+			up(&mdev->data.mutex);
+			return 0; /* not ok */
+		}
 		spin_lock(&mdev->send_task_lock);
 		mdev->send_task=current;
 		spin_unlock(&mdev->send_task_lock);

From drbd-cvs at lists.linbit.com  Thu Jul 20 12:57:58 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul 20 12:57:59 2006
Subject: [DRBD-cvs] svn commit by lars - r2288 - branches/drbd-0.7/drbd -
	don't put interpretation into error messages. just stat
Message-ID: <20060720105758.932852DF6263@mail.linbit.com>

Author: lars
Date: 2006-07-20 12:57:56 +0200 (Thu, 20 Jul 2006)
New Revision: 2288

Modified:
   branches/drbd-0.7/drbd/drbd_receiver.c
Log:
don't put interpretation into error messages. just state the facts

Modified: branches/drbd-0.7/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_receiver.c	2006-07-19 14:34:20 UTC (rev 2287)
+++ branches/drbd-0.7/drbd/drbd_receiver.c	2006-07-20 10:57:56 UTC (rev 2288)
@@ -2043,20 +2043,20 @@
 	return 1;
 
  break_c_loop:
-	WARN( "My msock connect got accepted onto peer's sock!\n");
-	/* In case a tcp connection set-up takes longer than 
+	WARN( "Network error during initial handshake. I'll try again.\n");
+	/* In case a tcp connection set-up takes longer than
 	   connect-int, we might get into the situation that this
 	   node's msock gets connected to the peer's sock!
-	   
-	   To break out of this endless loop behaviour, we need to 
-	   wait unti the peer's msock connect tries are over. (1 Second)
 
-	   Additionally we wait connect-int/2 to hit with our next 
-	   connect try exactly in the peer's window of expectation. */
+	   To break out of this endless loop behaviour, we need to
+	   wait until the peer's msock connect tries are over. (1 Second)
 
+	   Additionally we wait connect-int/2 to increase the chance for
+	   our next connect() to hit exactly the peer's accept() window. */
+
 	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout(HZ + (mdev->conf.try_connect_int*HZ)/2);
-	
+
 	return 0;
 }
 

From drbd-cvs at lists.linbit.com  Thu Jul 20 14:12:44 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul 20 14:12:46 2006
Subject: [DRBD-cvs] svn commit by lars - r2289 - branches/drbd-0.7/drbd -
	don't look at the socket without holding the appropriat
Message-ID: <20060720121244.5E7012D99EBD@mail.linbit.com>

Author: lars
Date: 2006-07-20 14:12:42 +0200 (Thu, 20 Jul 2006)
New Revision: 2289

Modified:
   branches/drbd-0.7/drbd/drbd_int.h
   branches/drbd-0.7/drbd/drbd_main.c
Log:

don't look at the socket without holding the appropriate mutex



Modified: branches/drbd-0.7/drbd/drbd_int.h
===================================================================
--- branches/drbd-0.7/drbd/drbd_int.h	2006-07-20 10:57:56 UTC (rev 2288)
+++ branches/drbd-0.7/drbd/drbd_int.h	2006-07-20 12:12:42 UTC (rev 2289)
@@ -832,7 +832,9 @@
 extern int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h,
 			  size_t size, unsigned msg_flags);
-extern int drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
+#define USE_DATA_SOCKET 1
+#define USE_META_SOCKET 0
+extern int drbd_send_cmd(drbd_dev *mdev, int use_data_socket,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h, size_t size);
 extern int drbd_send_sync_param(drbd_dev *mdev, struct syncer_config *sc);
 extern int drbd_send_b_ack(drbd_dev *mdev, u32 barrier_nr,
@@ -1271,19 +1273,19 @@
 static inline int drbd_send_short_cmd(drbd_dev *mdev, Drbd_Packet_Cmd cmd)
 {
 	Drbd_Header h;
-	return drbd_send_cmd(mdev,mdev->data.socket,cmd,&h,sizeof(h));
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,cmd,&h,sizeof(h));
 }
 
 static inline int drbd_send_ping(drbd_dev *mdev)
 {
 	Drbd_Header h;
-	return drbd_send_cmd(mdev,mdev->meta.socket,Ping,&h,sizeof(h));
+	return drbd_send_cmd(mdev,USE_META_SOCKET,Ping,&h,sizeof(h));
 }
 
 static inline int drbd_send_ping_ack(drbd_dev *mdev)
 {
 	Drbd_Header h;
-	return drbd_send_cmd(mdev,mdev->meta.socket,PingAck,&h,sizeof(h));
+	return drbd_send_cmd(mdev,USE_META_SOCKET,PingAck,&h,sizeof(h));
 }
 
 static inline void drbd_thread_stop(struct Drbd_thread *thi)

Modified: branches/drbd-0.7/drbd/drbd_main.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_main.c	2006-07-20 10:57:56 UTC (rev 2288)
+++ branches/drbd-0.7/drbd/drbd_main.c	2006-07-20 12:12:42 UTC (rev 2289)
@@ -628,6 +628,7 @@
 	UNLOCK_SIGMASK(current,flags);
 }
 
+/* the appropriate socket mutex must be held already */
 int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h,
 			  size_t size, unsigned msg_flags)
@@ -652,32 +653,36 @@
 	return ok;
 }
 
-int drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
+/* don't pass the socket. we may only look at it
+ * when we hold the appropriate socket mutex.
+ */
+int drbd_send_cmd(drbd_dev *mdev, int use_data_socket,
 		  Drbd_Packet_Cmd cmd, Drbd_Header* h, size_t size)
 {
-	int ok;
+	int ok = 0;
 	sigset_t old_blocked;
+	struct socket *sock;
 
-	if (sock == mdev->data.socket) {
+	if (use_data_socket) {
 		down(&mdev->data.mutex);
-		if (sock != mdev->data.socket) {
-			/* verify drbd_disconnect: drbd_free_sock may free this
-			 * socket while we have been waiting in down.
-			 */
-			up(&mdev->data.mutex);
-			return 0; /* not ok */
-		}
 		spin_lock(&mdev->send_task_lock);
 		mdev->send_task=current;
 		spin_unlock(&mdev->send_task_lock);
-	} else
+		sock = mdev->data.socket;
+	} else {
 		down(&mdev->meta.mutex);
+		sock = mdev->meta.socket;
+	}
 
-	old_blocked = drbd_block_all_signals();
-	ok = _drbd_send_cmd(mdev,sock,cmd,h,size,0);
-	restore_old_sigset(old_blocked);
+	/* drbd_disconnect() could have called drbd_free_sock()
+	 * while we were waiting in down()... */
+	if (likely(sock != NULL)) {
+		old_blocked = drbd_block_all_signals();
+		ok = _drbd_send_cmd(mdev, sock, cmd, h, size, 0);
+		restore_old_sigset(old_blocked);
+	}
 
-	if (sock == mdev->data.socket) {
+	if (use_data_socket) {
 		spin_lock(&mdev->send_task_lock);
 		mdev->send_task=NULL;
 		spin_unlock(&mdev->send_task_lock);
@@ -697,7 +702,7 @@
 	p.skip      = cpu_to_be32(sc->skip);
 	p.group     = cpu_to_be32(sc->group);
 
-	ok = drbd_send_cmd(mdev,mdev->data.socket,SyncParam,(Drbd_Header*)&p,sizeof(p));
+	ok = drbd_send_cmd(mdev,USE_DATA_SOCKET,SyncParam,(Drbd_Header*)&p,sizeof(p));
 	if ( ok
 	    && (mdev->cstate == SkippedSyncS || mdev->cstate == SkippedSyncT)
 	    && !sc->skip )
@@ -739,7 +744,7 @@
 	p.flags          = cpu_to_be32(flags);
 	p.magic          = BE_DRBD_MAGIC;
 
-	ok = drbd_send_cmd(mdev,mdev->data.socket,ReportParams,(Drbd_Header*)&p,sizeof(p));
+	ok = drbd_send_cmd(mdev,USE_DATA_SOCKET,ReportParams,(Drbd_Header*)&p,sizeof(p));
 	if (have_disk) dec_local(mdev);
 	return ok;
 }
@@ -827,7 +832,7 @@
 	p.barrier  = barrier_nr;
 	p.set_size = cpu_to_be32(set_size);
 
-	ok = drbd_send_cmd(mdev,mdev->meta.socket,BarrierAck,(Drbd_Header*)&p,sizeof(p));
+	ok = drbd_send_cmd(mdev,USE_META_SOCKET,BarrierAck,(Drbd_Header*)&p,sizeof(p));
 	return ok;
 }
 
@@ -842,7 +847,7 @@
 	p.blksize  = cpu_to_be32(drbd_ee_get_size(e));
 
 	if (!mdev->meta.socket || mdev->cstate < Connected) return FALSE;
-	ok = drbd_send_cmd(mdev,mdev->meta.socket,cmd,(Drbd_Header*)&p,sizeof(p));
+	ok = drbd_send_cmd(mdev,USE_META_SOCKET,cmd,(Drbd_Header*)&p,sizeof(p));
 	return ok;
 }
 
@@ -856,7 +861,7 @@
 	p.block_id = block_id;
 	p.blksize  = cpu_to_be32(size);
 
-	ok = drbd_send_cmd(mdev,mdev->data.socket,cmd,(Drbd_Header*)&p,sizeof(p));
+	ok = drbd_send_cmd(mdev,USE_DATA_SOCKET,cmd,(Drbd_Header*)&p,sizeof(p));
 	return ok;
 }
 
@@ -1151,7 +1156,7 @@
 */
 
 /*
- * you should have down()ed the appropriate [m]sock_mutex elsewhere!
+ * you must have down()ed the appropriate [m]sock_mutex elsewhere!
  */
 int drbd_send(drbd_dev *mdev, struct socket *sock,
 	      void* buf, size_t size, unsigned msg_flags)

From drbd-cvs at lists.linbit.com  Thu Jul 20 14:17:05 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul 20 14:17:06 2006
Subject: [DRBD-cvs] svn commit by lars - r2290 - branches/drbd-0.7/drbd - in
	drbd_worker, the semaphore count and list item count
Message-ID: <20060720121705.E04A42DF6263@mail.linbit.com>

Author: lars
Date: 2006-07-20 14:16:40 +0200 (Thu, 20 Jul 2006)
New Revision: 2290

Modified:
   branches/drbd-0.7/drbd/drbd_int.h
   branches/drbd-0.7/drbd/drbd_worker.c
Log:
in drbd_worker, the semaphore count and list item count could get out of sync.
fixed that.

be more robust in worker, in case somehow the semaphore count and the list
items get out of sync again.


Modified: branches/drbd-0.7/drbd/drbd_int.h
===================================================================
--- branches/drbd-0.7/drbd/drbd_int.h	2006-07-20 12:12:42 UTC (rev 2289)
+++ branches/drbd-0.7/drbd/drbd_int.h	2006-07-20 12:16:40 UTC (rev 2290)
@@ -1244,8 +1244,9 @@
 	unsigned long flags;
 	spin_lock_irqsave(&mdev->req_lock,flags);
 	list_add(&w->list,&q->q);
+	up(&q->s); /* within the spinlock,
+		      see comment near end of drbd_worker() */
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
-	up(&q->s);
 }
 
 static inline void
@@ -1255,8 +1256,9 @@
 	unsigned long flags;
 	spin_lock_irqsave(&mdev->req_lock,flags);
 	list_add_tail(&w->list,&q->q);
+	up(&q->s); /* within the spinlock,
+		      see comment near end of drbd_worker() */
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
-	up(&q->s);
 }
 
 static inline void wake_asender(drbd_dev *mdev) {

Modified: branches/drbd-0.7/drbd/drbd_worker.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_worker.c	2006-07-20 12:12:42 UTC (rev 2289)
+++ branches/drbd-0.7/drbd/drbd_worker.c	2006-07-20 12:16:40 UTC (rev 2290)
@@ -956,7 +956,21 @@
 
 		w = 0;
 		spin_lock_irq(&mdev->req_lock);
-		D_ASSERT(!list_empty(&mdev->data.work.q));
+		ERR_IF(list_empty(&mdev->data.work.q)) {
+			/* something terribly wrong in our logic.
+			 * we were able to down() the semaphore,
+			 * but the list is empty... doh.
+			 *
+			 * what is the best thing to do now?
+			 * try again from scratch, restarting the receiver,
+			 * asender, whatnot? could break even more ugly,
+			 * e.g. when we are primary, but no good local data.
+			 *
+			 * I'll try to get away just starting over this loop.
+			 */
+			spin_unlock_irq(&mdev->req_lock);
+			continue;
+		}
 		w = list_entry(mdev->data.work.q.next,struct drbd_work,list);
 		list_del_init(&w->list);
 		spin_unlock_irq(&mdev->req_lock);
@@ -1020,6 +1034,11 @@
 	ERR_IF(!list_empty(&mdev->data.work.q))
 		goto again;
 	sema_init(&mdev->data.work.s,0);
+	/* DANGEROUS race: if someone did queue his work within the spinlock,
+	 * but up() ed outside the spinlock, we could get an up() on the
+	 * semaphore without corresponding list entry.
+	 * So don't do that.
+	 */
 	spin_unlock_irq(&mdev->req_lock);
 
 	INFO("worker terminated\n");

From drbd-cvs at lists.linbit.com  Thu Jul 20 14:41:45 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul 20 14:41:47 2006
Subject: [DRBD-cvs] svn commit by lars - r2291 - branches/drbd-0.7/drbd -
	thinko; don't unconditionally assign w_resync_inactive 
Message-ID: <20060720124145.994462DF6263@mail.linbit.com>

Author: lars
Date: 2006-07-20 14:41:44 +0200 (Thu, 20 Jul 2006)
New Revision: 2291

Modified:
   branches/drbd-0.7/drbd/drbd_worker.c
Log:
thinko; don't unconditionally assign w_resync_inactive in worker cleanup...

Modified: branches/drbd-0.7/drbd/drbd_worker.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_worker.c	2006-07-20 12:16:40 UTC (rev 2290)
+++ branches/drbd-0.7/drbd/drbd_worker.c	2006-07-20 12:41:44 UTC (rev 2291)
@@ -1015,7 +1015,16 @@
 			_drbd_queue_work(&mdev->data.work,&mdev->resync_work);
 		// else: already queued
 	} else {
-		mdev->resync_work.cb = w_resync_inactive;
+		/* timer already consumed that bit, or it was never set */
+		if (list_empty(&mdev->resync_work.list)) {
+			/* not queued, should be inactive */
+			ERR_IF (mdev->resync_work.cb != w_resync_inactive)
+				mdev->resync_work.cb = w_resync_inactive;
+		} else {
+			/* still queued; should be w_resume_next_sg */
+			ERR_IF (mdev->resync_work.cb != w_resume_next_sg)
+				mdev->resync_work.cb = w_resume_next_sg;
+		}
 	}
 
 	i = 0;

From drbd-cvs at lists.linbit.com  Fri Jul 21 10:24:24 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Fri Jul 21 10:24:26 2006
Subject: [DRBD-cvs] svn commit by phil - r2292 - in trunk: documentation
	drbd user - Propagated quite a number of fixes from the 0.7-branch.
Message-ID: <20060721082424.366232DF6263@mail.linbit.com>

Author: phil
Date: 2006-07-21 10:24:20 +0200 (Fri, 21 Jul 2006)
New Revision: 2292

Modified:
   trunk/documentation/drbdsetup.sgml
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_worker.c
   trunk/user/drbd_limits.h
   trunk/user/drbdsetup.c
Log:
Propagated quite a number of fixes from the 0.7-branch.


Modified: trunk/documentation/drbdsetup.sgml
===================================================================
--- trunk/documentation/drbdsetup.sgml	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/documentation/drbdsetup.sgml	2006-07-21 08:24:20 UTC (rev 2292)
@@ -396,7 +396,7 @@
 	  </listitem>
 	</varlistentry>
 	<varlistentry>
-	  <term><option>-l</option>,
+	  <term><option>-u</option>,
 	  <option>--unplug-watermark <replaceable>val</replaceable></option></term>
 	  <listitem>
 	    <para>

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/drbd/drbd_fs.c	2006-07-21 08:24:20 UTC (rev 2292)
@@ -1170,9 +1170,10 @@
 long drbd_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
 {
 	int ret;
-	// lock_kernel(); Not needed, since we have mdev->device_mutex
 	ret = drbd_ioctl(f->f_dentry->d_inode, f, cmd, arg);
-	// unlock_kernel();
+	/* need to map "unknown" to ENOIOCTLCMD
+	 * to get the generic fallback path going */
+	if (ret == -ENOTTY) ret = -ENOIOCTLCMD;
 	return ret;
 }
 #endif
@@ -1398,7 +1399,7 @@
 		break;
 
 	default:
-		err = -EINVAL;
+		err = -ENOTTY;
 	}
  /* out: */
 	up(&mdev->device_mutex);

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/drbd/drbd_int.h	2006-07-21 08:24:20 UTC (rev 2292)
@@ -868,7 +868,9 @@
 extern int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h,
 			  size_t size, unsigned msg_flags);
-extern int drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
+#define USE_DATA_SOCKET 1
+#define USE_META_SOCKET 0
+extern int drbd_send_cmd(drbd_dev *mdev, int use_data_socket,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h, size_t size);
 extern int drbd_send_cmd2(drbd_dev *mdev, Drbd_Packet_Cmd cmd,
 			  char* data, size_t size);
@@ -1359,8 +1361,9 @@
 	unsigned long flags;
 	spin_lock_irqsave(&mdev->req_lock,flags);
 	list_add(&w->list,&q->q);
+	up(&q->s); /* within the spinlock,
+		      see comment near end of drbd_worker() */
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
-	up(&q->s);
 }
 
 static inline void
@@ -1370,8 +1373,9 @@
 	unsigned long flags;
 	spin_lock_irqsave(&mdev->req_lock,flags);
 	list_add_tail(&w->list,&q->q);
+	up(&q->s); /* within the spinlock,
+		      see comment near end of drbd_worker() */
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
-	up(&q->s);
 }
 
 static inline void wake_asender(drbd_dev *mdev) {
@@ -1388,19 +1392,19 @@
 static inline int drbd_send_short_cmd(drbd_dev *mdev, Drbd_Packet_Cmd cmd)
 {
 	Drbd_Header h;
-	return drbd_send_cmd(mdev,mdev->data.socket,cmd,&h,sizeof(h));
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,cmd,&h,sizeof(h));
 }
 
 static inline int drbd_send_ping(drbd_dev *mdev)
 {
 	Drbd_Header h;
-	return drbd_send_cmd(mdev,mdev->meta.socket,Ping,&h,sizeof(h));
+	return drbd_send_cmd(mdev,USE_META_SOCKET,Ping,&h,sizeof(h));
 }
 
 static inline int drbd_send_ping_ack(drbd_dev *mdev)
 {
 	Drbd_Header h;
-	return drbd_send_cmd(mdev,mdev->meta.socket,PingAck,&h,sizeof(h));
+	return drbd_send_cmd(mdev,USE_META_SOCKET,PingAck,&h,sizeof(h));
 }
 
 static inline void drbd_thread_stop(struct Drbd_thread *thi)

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/drbd/drbd_main.c	2006-07-21 08:24:20 UTC (rev 2292)
@@ -1235,6 +1235,7 @@
 	UNLOCK_SIGMASK(current,flags);
 }
 
+/* the appropriate socket mutex must be held already */
 int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h,
 			  size_t size, unsigned msg_flags)
@@ -1259,25 +1260,36 @@
 	return ok;
 }
 
-int drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
+/* don't pass the socket. we may only look at it
+ * when we hold the appropriate socket mutex.
+ */
+int drbd_send_cmd(drbd_dev *mdev, int use_data_socket,
 		  Drbd_Packet_Cmd cmd, Drbd_Header* h, size_t size)
 {
-	int ok;
+	int ok = 0;
 	sigset_t old_blocked;
+	struct socket *sock;
 
-	if (sock == mdev->data.socket) {
+	if (use_data_socket) {
 		down(&mdev->data.mutex);
 		spin_lock(&mdev->send_task_lock);
 		mdev->send_task=current;
 		spin_unlock(&mdev->send_task_lock);
-	} else
+		sock = mdev->data.socket;
+	} else {
 		down(&mdev->meta.mutex);
+		sock = mdev->meta.socket;
+	}
 
-	old_blocked = drbd_block_all_signals();
-	ok = _drbd_send_cmd(mdev,sock,cmd,h,size,0);
-	restore_old_sigset(old_blocked);
+	/* drbd_disconnect() could have called drbd_free_sock()
+	 * while we were waiting in down()... */
+	if (likely(sock != NULL)) {
+		old_blocked = drbd_block_all_signals();
+		ok = _drbd_send_cmd(mdev, sock, cmd, h, size, 0);
+		restore_old_sigset(old_blocked);
+	}
 
-	if (sock == mdev->data.socket) {
+	if (use_data_socket) {
 		spin_lock(&mdev->send_task_lock);
 		mdev->send_task=NULL;
 		spin_unlock(&mdev->send_task_lock);
@@ -1327,7 +1339,7 @@
 	p.skip      = cpu_to_be32(sc->skip);
 	p.after     = cpu_to_be32(sc->after);
 
-	return drbd_send_cmd(mdev,mdev->data.socket,SyncParam,(Drbd_Header*)&p,sizeof(p));
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,SyncParam,(Drbd_Header*)&p,sizeof(p));
 }
 
 int drbd_send_protocol(drbd_dev *mdev)
@@ -1336,7 +1348,7 @@
 
 	p.protocol = cpu_to_be32(mdev->net_conf->wire_protocol);
 
-	return drbd_send_cmd(mdev,mdev->data.socket,ReportProtocol,
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,ReportProtocol,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1352,7 +1364,7 @@
 	p.uuid[UUID_SIZE] = cpu_to_be64(drbd_bm_total_weight(mdev));
 	p.uuid[UUID_FLAGS] = cpu_to_be64(mdev->net_conf->want_lose);
 
-	return drbd_send_cmd(mdev,mdev->data.socket,ReportUUIDs,
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,ReportUUIDs,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1362,7 +1374,7 @@
 
 	p.uuid = cpu_to_be64(val);
 
-	return drbd_send_cmd(mdev,mdev->data.socket,ReportSyncUUID,
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,ReportSyncUUID,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1384,7 +1396,7 @@
 	p.max_segment_size = cpu_to_be32(mdev->rq_queue->max_segment_size);
 	p.queue_order_type = cpu_to_be32(drbd_queue_order_type(mdev));
 
-	ok = drbd_send_cmd(mdev,mdev->data.socket,ReportSizes,
+	ok = drbd_send_cmd(mdev,USE_DATA_SOCKET,ReportSizes,
 			   (Drbd_Header*)&p,sizeof(p));
 	return ok;
 }
@@ -1396,7 +1408,7 @@
 	p.block_id = (unsigned long)req;
 	p.seq_num  = cpu_to_be32(req->seq_num);
 
-	return drbd_send_cmd(mdev,mdev->meta.socket,DiscardNote,
+	return drbd_send_cmd(mdev,USE_META_SOCKET,DiscardNote,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1406,7 +1418,7 @@
 
 	p.state    = cpu_to_be32(mdev->state.i);
 
-	return drbd_send_cmd(mdev,mdev->data.socket,ReportState,
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,ReportState,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1417,7 +1429,7 @@
 	p.mask    = cpu_to_be32(mask.i);
 	p.val     = cpu_to_be32(val.i);
 
-	return drbd_send_cmd(mdev,mdev->data.socket,StateChgRequest,
+	return drbd_send_cmd(mdev,USE_DATA_SOCKET,StateChgRequest,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1427,7 +1439,7 @@
 
 	p.retcode    = cpu_to_be32(retcode);
 
-	return drbd_send_cmd(mdev,mdev->meta.socket,StateChgReply,
+	return drbd_send_cmd(mdev,USE_META_SOCKET,StateChgReply,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1513,7 +1525,7 @@
 	p.barrier  = barrier_nr;
 	p.set_size = cpu_to_be32(set_size);
 
-	ok = drbd_send_cmd(mdev,mdev->meta.socket,BarrierAck,(Drbd_Header*)&p,sizeof(p));
+	ok = drbd_send_cmd(mdev,USE_META_SOCKET,BarrierAck,(Drbd_Header*)&p,sizeof(p));
 	return ok;
 }
 
@@ -1538,7 +1550,7 @@
 #endif
 
 	if (!mdev->meta.socket || mdev->state.conn < Connected) return FALSE;
-	ok=drbd_send_cmd(mdev,mdev->meta.socket,cmd,(Drbd_Header*)&p,sizeof(p));
+	ok=drbd_send_cmd(mdev,USE_META_SOCKET,cmd,(Drbd_Header*)&p,sizeof(p));
 	return ok;
 }
 
@@ -1552,7 +1564,7 @@
 	p.block_id = block_id;
 	p.blksize  = cpu_to_be32(size);
 
-	ok = drbd_send_cmd(mdev,mdev->data.socket,cmd,(Drbd_Header*)&p,sizeof(p));
+	ok = drbd_send_cmd(mdev,USE_DATA_SOCKET,cmd,(Drbd_Header*)&p,sizeof(p));
 	return ok;
 }
 
@@ -1813,7 +1825,7 @@
 */
 
 /*
- * you should have down()ed the appropriate [m]sock_mutex elsewhere!
+ * you must have down()ed the appropriate [m]sock_mutex elsewhere!
  */
 int drbd_send(drbd_dev *mdev, struct socket *sock,
 	      void* buf, size_t size, unsigned msg_flags)

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/drbd/drbd_receiver.c	2006-07-21 08:24:20 UTC (rev 2292)
@@ -2431,30 +2431,6 @@
 		dec_local(mdev);
 	}
 
-	/* in case we have been syncing, and then we drop the connection,
-	 * we need to "w_resume_next_sg", which we try to achieve by
-	 * setting the STOP_SYNC_TIMER bit, and schedulung the timer for
-	 * immediate execution.
-	 * unfortunately we cannot be sure that the timer already triggered.
-	 *
-	 * so we del_timer_sync here, and check that bit.
-	 * if it is still set, we queue w_resume_next_sg anyways,
-	 * just to be sure.
-	 */
-
-	del_timer_sync(&mdev->resync_timer);
-	spin_lock_irq(&mdev->req_lock);
-	if (test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags)) {
-		mdev->resync_work.cb = w_resume_next_sg;
-		if (list_empty(&mdev->resync_work.list))
-			_drbd_queue_work(&mdev->data.work,&mdev->resync_work);
-		// else: already queued, we only need to release the lock.
-	} else {
-		D_ASSERT(mdev->resync_work.cb == w_resync_inactive);
-	}
-	spin_unlock_irq(&mdev->req_lock);
-
-
 	drbd_thread_stop_nowait(&mdev->worker);
 	drbd_thread_stop(&mdev->asender);
 

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/drbd/drbd_worker.c	2006-07-21 08:24:20 UTC (rev 2292)
@@ -752,10 +752,9 @@
 
 	drbd_global_lock();
 	_drbd_resume_next(mdev);
+	w->cb = w_resync_inactive;
 	drbd_global_unlock();
 
-	w->cb = w_resync_inactive;
-
 	return 1;
 }
 
@@ -900,7 +899,21 @@
 
 		w = 0;
 		spin_lock_irq(&mdev->req_lock);
-		D_ASSERT(!list_empty(&mdev->data.work.q));
+		ERR_IF(list_empty(&mdev->data.work.q)) {
+			/* something terribly wrong in our logic.
+			 * we were able to down() the semaphore,
+			 * but the list is empty... doh.
+			 *
+			 * what is the best thing to do now?
+			 * try again from scratch, restarting the receiver,
+			 * asender, whatnot? could break even more ugly,
+			 * e.g. when we are primary, but no good local data.
+			 *
+			 * I'll try to get away just starting over this loop.
+			 */
+			spin_unlock_irq(&mdev->req_lock);
+			continue;
+		}
 		w = list_entry(mdev->data.work.q.next,struct drbd_work,list);
 		list_del_init(&w->list);
 		spin_unlock_irq(&mdev->req_lock);
@@ -915,8 +928,49 @@
 
 	drbd_wait_ee_list_empty(mdev,&mdev->read_ee);
 
+	/* When we terminate a resync process, either because it finished
+	 * sucessfully, or because (like in this case here) we lost
+	 * communications, we need to "w_resume_next_sg".
+	 * We cannot use del_timer_sync from within _set_cstate, and since the
+	 * resync timer may still be scheduled and would then trigger anyways,
+	 * we set the STOP_SYNC_TIMER bit, and schedule the timer for immediate
+	 * execution from within _set_cstate().
+	 * The timer should then clear that bit and queue w_resume_next_sg.
+	 *
+	 * This is fine for the normal "resync finished" case.
+	 *
+	 * In this case (worker thread beeing stopped), there is a race:
+	 * we cannot be sure that the timer already triggered.
+	 *
+	 * So we del_timer_sync here, and check that "STOP_SYNC_TIMER" bit.
+	 * if it is still set, we queue w_resume_next_sg anyways,
+	 * just to be sure.
+	 */
+
+	del_timer_sync(&mdev->resync_timer);
+	/* possible paranoia check: the STOP_SYNC_TIMER bit should be set
+	 * if and only if del_timer_sync returns true ... */
+
+	spin_lock_irq(&mdev->req_lock);
+	if (test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags)) {
+		mdev->resync_work.cb = w_resume_next_sg;
+		if (list_empty(&mdev->resync_work.list))
+			_drbd_queue_work(&mdev->data.work,&mdev->resync_work);
+		// else: already queued
+	} else {
+		/* timer already consumed that bit, or it was never set */
+		if (list_empty(&mdev->resync_work.list)) {
+			/* not queued, should be inactive */
+			ERR_IF (mdev->resync_work.cb != w_resync_inactive)
+				mdev->resync_work.cb = w_resync_inactive;
+		} else {
+			/* still queued; should be w_resume_next_sg */
+			ERR_IF (mdev->resync_work.cb != w_resume_next_sg)
+				mdev->resync_work.cb = w_resume_next_sg;
+		}
+	}
+
 	i = 0;
-	spin_lock_irq(&mdev->req_lock);
   again:
 	list_splice_init(&mdev->data.work.q,&work_list);
 	spin_unlock_irq(&mdev->req_lock);
@@ -925,13 +979,18 @@
 		w = list_entry(work_list.next, struct drbd_work,list);
 		list_del_init(&w->list);
 		w->cb(mdev,w,1);
-		i++;
+		i++; /* dead debugging code */
 	}
 
 	spin_lock_irq(&mdev->req_lock);
 	ERR_IF(!list_empty(&mdev->data.work.q))
 		goto again;
 	sema_init(&mdev->data.work.s,0);
+	/* DANGEROUS race: if someone did queue his work within the spinlock,
+	 * but up() ed outside the spinlock, we could get an up() on the
+	 * semaphore without corresponding list entry.
+	 * So don't do that.
+	 */
 	spin_unlock_irq(&mdev->req_lock);
 
 	INFO("worker terminated\n");

Modified: trunk/user/drbd_limits.h
===================================================================
--- trunk/user/drbd_limits.h	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/user/drbd_limits.h	2006-07-21 08:24:20 UTC (rev 2292)
@@ -52,8 +52,8 @@
   /* @4k PageSize -> 128kB - 512MB */
   RANGE(MAX_BUFFERS, 32, 131072);
 
-  /* @4k PageSize -> 64kB - 512MB */
-  RANGE(UNPLUG_WATERMARK, 16, 131072);
+  /* @4k PageSize -> 4kB - 512MB */
+  RANGE(UNPLUG_WATERMARK, 1, 131072);
 
   /* 0 is disabled.
    * 200 should be more than enough even for very short timeouts */

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2006-07-20 12:41:44 UTC (rev 2291)
+++ trunk/user/drbdsetup.c	2006-07-21 08:24:20 UTC (rev 2292)
@@ -165,7 +165,7 @@
      { "timeout",    required_argument, 0, 't' },
      { "max-epoch-size", required_argument, 0, 'e' },
      { "max-buffers",required_argument, 0, 'b' },
-     { "unplug-watermark",required_argument, 0, 'l' },
+     { "unplug-watermark",required_argument, 0, 'u' },
      { "connect-int",required_argument, 0, 'c' },
      { "ping-int",   required_argument, 0, 'i' },
      { "sndbuf-size",required_argument, 0, 'S' },
@@ -557,7 +557,7 @@
 	  cn->config.max_buffers = m_strtoll_range(optarg,1, "max-buffers",
 			  DRBD_MAX_BUFFERS_MIN, DRBD_MAX_BUFFERS_MAX);
 	  break;
-	case 'l':
+	case 'u':
 	  cn->config.unplug_watermark = m_strtoll_range(optarg,1, "unplug-watermark",
 			  DRBD_UNPLUG_WATERMARK_MIN, DRBD_UNPLUG_WATERMARK_MAX);
 	  break;

From drbd-cvs at lists.linbit.com  Mon Jul 24 14:11:42 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 24 14:11:44 2006
Subject: [DRBD-cvs] svn commit by phil - r2293 - in trunk: . drbd - * Send
	remote read requests from the worker context.
Message-ID: <20060724121142.F04102D99AAE@mail.linbit.com>

* 
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: phil
Date: 2006-07-24 14:11:40 +0200 (Mon, 24 Jul 2006)
New Revision: 2293

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_worker.c
Log:
* Send remote read requests from the worker context.
* Impose the max_buffers setting also on a primary node.


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-21 08:24:20 UTC (rev 2292)
+++ trunk/ROADMAP	2006-07-24 12:11:40 UTC (rev 2293)
@@ -803,9 +803,8 @@
    Simon works on this. 
 
 39 Send mirrored write requests out of the worker context.
-   30% DONE
-   TODO:   Honour the max-buffers setting for this.
-           Think about read requests.
+   90% DONE
+       TODO: Get rid of the "send_task" thing.
 
 
 Maybe:

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-21 08:24:20 UTC (rev 2292)
+++ trunk/drbd/drbd_int.h	2006-07-24 12:11:40 UTC (rev 2293)
@@ -756,6 +756,7 @@
 
 	drbd_state_t state;
 	wait_queue_head_t cstate_wait; // TODO Rename into "misc_wait".
+	wait_queue_head_t rq_wait;
 	unsigned int send_cnt;
 	unsigned int recv_cnt;
 	unsigned int read_cnt;
@@ -1126,7 +1127,6 @@
 extern int drbd_md_sync_page_io(drbd_dev *mdev, struct drbd_backing_dev *bdev,
 				sector_t sector, int rw);
 // worker callbacks
-extern int w_is_app_read         (drbd_dev *, struct drbd_work *, int);
 extern int w_is_resync_read      (drbd_dev *, struct drbd_work *, int);
 extern int w_read_retry_remote   (drbd_dev *, struct drbd_work *, int);
 extern int w_e_end_data_req      (drbd_dev *, struct drbd_work *, int);
@@ -1139,6 +1139,8 @@
 extern int w_make_resync_request (drbd_dev *, struct drbd_work *, int);
 extern int w_send_dblock         (drbd_dev *, struct drbd_work *, int);
 extern int w_send_barrier        (drbd_dev *, struct drbd_work *, int);
+extern int w_send_read_req       (drbd_dev *, struct drbd_work *, int);
+
 extern void resync_timer_fn(unsigned long data);
 
 // drbd_receiver.c
@@ -1564,16 +1566,25 @@
 	D_ASSERT(atomic_read(&mdev->local_cnt)>=0);
 }
 
+/* 
 static inline void inc_ap_bio(drbd_dev* mdev)
 {
 	atomic_inc(&mdev->ap_bio_cnt);
 }
+*/
 
 static inline void dec_ap_bio(drbd_dev* mdev)
 {
-	if(atomic_dec_and_test(&mdev->ap_bio_cnt))
-		wake_up(&mdev->cstate_wait);
+	int ap_bio = atomic_dec_return(&mdev->ap_bio_cnt);
 
+	if(ap_bio == 0) wake_up(&mdev->cstate_wait);
+
+	if(inc_net(mdev)) {
+		if(ap_bio < mdev->net_conf->max_buffers) 
+			wake_up(&mdev->rq_wait);
+		dec_net(mdev);
+	}
+
 	D_ASSERT(atomic_read(&mdev->ap_bio_cnt)>=0);
 }
 

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-21 08:24:20 UTC (rev 2292)
+++ trunk/drbd/drbd_main.c	2006-07-24 12:11:40 UTC (rev 2293)
@@ -1978,12 +1978,12 @@
 	if (mdev->state.pdsk >= Inconsistent) /* implies cs >= Connected */ {
 		D_ASSERT(mdev->state.role == Primary);
 		if (test_and_clear_bit(UNPLUG_REMOTE,&mdev->flags)) {
-			/* add to the front of the data.work queue,
+			/* add to the data.work queue,
 			 * unless already queued.
 			 * XXX this might be a good addition to drbd_queue_work
 			 * anyways, to detect "double queuing" ... */
 			if (list_empty(&mdev->unplug_work.list))
-				_drbd_queue_work_front(&mdev->data.work,&mdev->unplug_work);
+				_drbd_queue_work(&mdev->data.work,&mdev->unplug_work);
 		}
 	}
 	spin_unlock_irq(&mdev->req_lock);
@@ -2064,6 +2064,7 @@
 	mdev->md_sync_timer.data = (unsigned long) mdev;
 
 	init_waitqueue_head(&mdev->cstate_wait);
+	init_waitqueue_head(&mdev->rq_wait);
 	init_waitqueue_head(&mdev->ee_wait);
 	init_waitqueue_head(&mdev->al_wait);
 

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-21 08:24:20 UTC (rev 2292)
+++ trunk/drbd/drbd_receiver.c	2006-07-24 12:11:40 UTC (rev 2293)
@@ -1045,8 +1045,6 @@
 		return FALSE;
 	}
 
-	D_ASSERT(req->w.cb == w_is_app_read);
-
 	spin_lock(&mdev->pr_lock);
 	hlist_del(&req->colision);
 	spin_unlock(&mdev->pr_lock);
@@ -2940,7 +2938,6 @@
 		ERR("Got a corrupt block_id/sector pair(3).\n");
 		return FALSE;
 	}
-	D_ASSERT(req->w.cb == w_is_app_read);
 
 	spin_lock(&mdev->pr_lock);
 	list_del(&req->w.list);

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-21 08:24:20 UTC (rev 2292)
+++ trunk/drbd/drbd_req.c	2006-07-24 12:11:40 UTC (rev 2293)
@@ -124,19 +124,17 @@
 
 int drbd_read_remote(drbd_dev *mdev, drbd_request_t *req)
 {
-	int rv;
-	struct bio *bio = req->master_bio;
-
-	req->w.cb = w_is_app_read;
+	req->w.cb = w_send_read_req;
 	spin_lock(&mdev->pr_lock);
 	INIT_HLIST_NODE(&req->colision);
 	hlist_add_head( &req->colision, mdev->app_reads_hash +
 			ar_hash_fn(mdev, drbd_req_get_sector(req) ));
 	spin_unlock(&mdev->pr_lock);
 	set_bit(UNPLUG_REMOTE,&mdev->flags);
-	rv=drbd_send_drequest(mdev, DataRequest, bio->bi_sector, bio->bi_size,
-			      (unsigned long)req);
-	return rv;
+
+	drbd_queue_work(mdev, &mdev->data.work, &req->w);
+
+	return 1;
 }
 
 int drbd_pr_verify(drbd_dev *mdev, drbd_request_t * req, sector_t sector)
@@ -224,7 +222,14 @@
 {
 	drbd_request_t *req;
 	int local, remote;
+	int mxb;
 
+	mxb = 1000000; /* Artificial limit on open requests */
+	if(inc_net(mdev)) {
+		mxb = mdev->net_conf->max_buffers;
+		dec_net(mdev);
+	}
+
 	/* allocate outside of all locks
 	 */
 	req = drbd_req_new(mdev,bio);
@@ -237,10 +242,6 @@
 		return 0;
 	}
 
-	/* XXX req->w.cb = something; drbd_queue_work() ....
-	 * Not yet.
-	 */
-
 	// down_read(mdev->device_lock);
 
 	wait_event( mdev->cstate_wait,
@@ -321,7 +322,9 @@
 	/* we need to plug ALWAYS since we possibly need to kick lo_dev */
 	drbd_plug_device(mdev);
 
-	inc_ap_bio(mdev); // XXX maybe make this the first thing to do in drbd_make_request
+	// inc_ap_bio(mdev); do not allow more open requests than max_buffers!
+	wait_event( mdev->rq_wait,atomic_add_unless(&mdev->ap_bio_cnt,1,mxb) );
+
 	if (remote) {
 		/* either WRITE and Connected,
 		 * or READ, and no local disk,
@@ -368,7 +371,6 @@
 			up(&mdev->data.mutex);
 		} else {
 			// this node is diskless ...
-			inc_ap_pending(mdev);
 			drbd_read_remote(mdev,req);
 		}
 	}

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-21 08:24:20 UTC (rev 2292)
+++ trunk/drbd/drbd_worker.c	2006-07-24 12:11:40 UTC (rev 2293)
@@ -242,7 +242,6 @@
 	ok = drbd_io_error(mdev);
 	if(unlikely(!ok)) ERR("Sending in w_read_retry_remote() failed\n");
 	
-	inc_ap_pending(mdev);
 	ok = drbd_read_remote(mdev,req);
 	if(unlikely(!ok)) {
 		ERR("drbd_read_remote() failed\n");
@@ -270,15 +269,6 @@
 	return 0;
 }
 
-/* in case we need it. currently unused,
- * since should be assigned to "w_read_retry_remote"
- */
-int w_is_app_read(drbd_dev *mdev, struct drbd_work *w, int unused)
-{
-	ERR("%s: Typecheck only, should never be called!\n", __FUNCTION__ );
-	return 0;
-}
-
 void resync_timer_fn(unsigned long data)
 {
 	unsigned long flags;
@@ -443,6 +433,9 @@
 	return 1;
 }
 
+/**
+ * w_e_end_data_req: Send the answer (DataReply) to a DataRequest.
+ */
 int w_e_end_data_req(drbd_dev *mdev, struct drbd_work *w, int cancel)
 {
 	struct Tl_epoch_entry *e = (struct Tl_epoch_entry*)w;
@@ -478,6 +471,9 @@
 	return ok;
 }
 
+/**
+ * w_e_end_data_req: Send the answer (RSDataReply) to a RSDataRequest.
+ */
 int w_e_end_rsdata_req(drbd_dev *mdev, struct drbd_work *w, int cancel)
 {
 	struct Tl_epoch_entry *e = (struct Tl_epoch_entry*)w;
@@ -557,6 +553,9 @@
 	return drbd_send_short_cmd(mdev,UnplugRemote);
 }
 
+/**
+ * w_send_dblock: Send a mirrored write request.
+ */
 int w_send_dblock(drbd_dev *mdev, struct drbd_work *w, int cancel)
 {
 	drbd_request_t *req = (drbd_request_t *)w;
@@ -582,6 +581,31 @@
 	return ok;
 }
 
+/**
+ * w_send_read_req: Send a read requests.
+ */
+int w_send_read_req(drbd_dev *mdev, struct drbd_work *w, int cancel)
+{
+	drbd_request_t *req = (drbd_request_t *)w;
+	struct bio *bio = req->master_bio;
+	int ok;
+
+	inc_ap_pending(mdev);
+
+	if (unlikely(cancel)) return 1;
+
+	ok = drbd_send_drequest(mdev, DataRequest, bio->bi_sector, bio->bi_size,
+				(unsigned long)req);
+
+	if (!ok) {
+		if (mdev->state.conn >= Connected) 
+			drbd_force_state(mdev,NS(conn,NetworkFailure));
+		drbd_thread_restart_nowait(&mdev->receiver);
+	}
+
+	return ok;
+}
+
 STATIC void drbd_global_lock(void)
 {
 	int i;

From drbd-cvs at lists.linbit.com  Tue Jul 25 12:32:40 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul 25 12:32:42 2006
Subject: [DRBD-cvs] svn commit by phil - r2294 - in trunk: . drbd - *
	Removed the "send_task" code and the conecpt, since w
Message-ID: <20060725103240.A2B6F2DF6270@mail.linbit.com>

Author: phil
Date: 2006-07-25 12:32:38 +0200 (Tue, 25 Jul 2006)
New Revision: 2294

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_req.c
Log:
* Removed the "send_task" code and the conecpt, since we no longer
  send out of the context of a caller of drbd_make_request.
* Fixed the way we determin the "remote" in drbd_req.c
* Added a missing drbd_sync_md()


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-24 12:11:40 UTC (rev 2293)
+++ trunk/ROADMAP	2006-07-25 10:32:38 UTC (rev 2294)
@@ -803,8 +803,7 @@
    Simon works on this. 
 
 39 Send mirrored write requests out of the worker context.
-   90% DONE
-       TODO: Get rid of the "send_task" thing.
+   99% DONE
 
 
 Maybe:

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-24 12:11:40 UTC (rev 2293)
+++ trunk/drbd/drbd_int.h	2006-07-25 10:32:38 UTC (rev 2294)
@@ -775,8 +775,6 @@
 	struct drbd_barrier* oldest_barrier;
 	struct hlist_head * tl_hash;
 	unsigned int tl_hash_s;
-	struct task_struct *send_task; /* about pid calling drbd_send */
-	spinlock_t send_task_lock;
 	// sector_t rs_left;	   // blocks not up-to-date [unit BM_BLOCK_SIZE]
 	// moved into bitmap->bm_set
 	unsigned long rs_total;    // blocks to sync in this run [unit BM_BLOCK_SIZE]

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-24 12:11:40 UTC (rev 2293)
+++ trunk/drbd/drbd_main.c	2006-07-25 10:32:38 UTC (rev 2294)
@@ -1212,29 +1212,6 @@
 	}
 }
 
-inline sigset_t drbd_block_all_signals(void)
-{
-	unsigned long flags;
-	sigset_t oldset;
-	LOCK_SIGMASK(current,flags);
-	oldset = current->blocked;
-	sigfillset(&current->blocked);
-	RECALC_SIGPENDING();
-	UNLOCK_SIGMASK(current,flags);
-	return oldset;
-}
-
-inline void restore_old_sigset(sigset_t oldset)
-{
-	unsigned long flags;
-	LOCK_SIGMASK(current,flags);
-	// _never_ propagate this to anywhere...
-	sigdelset(&current->pending.signal, DRBD_SIG);
-	current->blocked = oldset;
-	RECALC_SIGPENDING();
-	UNLOCK_SIGMASK(current,flags);
-}
-
 /* the appropriate socket mutex must be held already */
 int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
 			  Drbd_Packet_Cmd cmd, Drbd_Header *h,
@@ -1267,14 +1244,10 @@
 		  Drbd_Packet_Cmd cmd, Drbd_Header* h, size_t size)
 {
 	int ok = 0;
-	sigset_t old_blocked;
 	struct socket *sock;
 
 	if (use_data_socket) {
 		down(&mdev->data.mutex);
-		spin_lock(&mdev->send_task_lock);
-		mdev->send_task=current;
-		spin_unlock(&mdev->send_task_lock);
 		sock = mdev->data.socket;
 	} else {
 		down(&mdev->meta.mutex);
@@ -1284,15 +1257,10 @@
 	/* drbd_disconnect() could have called drbd_free_sock()
 	 * while we were waiting in down()... */
 	if (likely(sock != NULL)) {
-		old_blocked = drbd_block_all_signals();
 		ok = _drbd_send_cmd(mdev, sock, cmd, h, size, 0);
-		restore_old_sigset(old_blocked);
 	}
 
 	if (use_data_socket) {
-		spin_lock(&mdev->send_task_lock);
-		mdev->send_task=NULL;
-		spin_unlock(&mdev->send_task_lock);
 		up(&mdev->data.mutex);
 	} else
 		up(&mdev->meta.mutex);
@@ -1302,7 +1270,6 @@
 int drbd_send_cmd2(drbd_dev *mdev, Drbd_Packet_Cmd cmd, char* data,
 		   size_t size)
 {
-	sigset_t old_blocked;
 	Drbd_Header h;
 	int ok;
 
@@ -1311,20 +1278,10 @@
 	h.length  = cpu_to_be16(size);
 
 	down(&mdev->data.mutex);
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=current;
-	spin_unlock(&mdev->send_task_lock);
 
-	old_blocked = drbd_block_all_signals();
-
 	ok = ( sizeof(h) == drbd_send(mdev,mdev->data.socket,&h,sizeof(h),0) );
 	ok = ok && ( size == drbd_send(mdev,mdev->data.socket,data,size,0) );
 
-	restore_old_sigset(old_blocked);
-
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=NULL;
-	spin_unlock(&mdev->send_task_lock);
 	up(&mdev->data.mutex);
 
 	return ok;
@@ -1649,11 +1606,6 @@
 	}
 #endif
 
-
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=current;
-	spin_unlock(&mdev->send_task_lock);
-
 	/* PARANOIA. if this ever triggers,
 	 * something in the layers above us is really kaputt.
 	 *one roundtrip later:
@@ -1696,10 +1648,6 @@
 	set_fs(oldfs);
 
   out:
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=NULL;
-	spin_unlock(&mdev->send_task_lock);
-
 	ok = (len == 0);
 	if (likely(ok))
 		mdev->send_cnt += size>>9;
@@ -1726,15 +1674,10 @@
 int drbd_send_dblock(drbd_dev *mdev, drbd_request_t *req)
 {
 	int ok=1;
-	sigset_t old_blocked;
 	Drbd_Data_Packet p;
 	unsigned int dp_flags=0;
 
-	old_blocked = drbd_block_all_signals();
 	down(&mdev->data.mutex);
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=current;
-	spin_unlock(&mdev->send_task_lock);
 
 	p.head.magic   = BE_DRBD_MAGIC;
 	p.head.command = cpu_to_be16(Data);
@@ -1760,12 +1703,7 @@
 		}
 	}
 
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=NULL;
-	spin_unlock(&mdev->send_task_lock);
-
 	up(&mdev->data.mutex);
-	restore_old_sigset(old_blocked);
 	return ok;
 }
 
@@ -1777,7 +1715,6 @@
 		    struct Tl_epoch_entry *e)
 {
 	int ok;
-	sigset_t old_blocked;
 	Drbd_Data_Packet p;
 
 	p.head.magic   = BE_DRBD_MAGIC;
@@ -1793,21 +1730,13 @@
 	 * This one may be interupted by DRBD_SIG and/or DRBD_SIGKILL
 	 * in response to ioctl or module unload.
 	 */
-	old_blocked = drbd_block_all_signals();
 	down(&mdev->data.mutex);
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=current;
-	spin_unlock(&mdev->send_task_lock);
 
 	dump_packet(mdev,mdev->data.socket,0,(void*)&p, __FILE__, __LINE__);
 	ok = sizeof(p) == drbd_send(mdev,mdev->data.socket,&p,sizeof(p),MSG_MORE);
 	if (ok) ok = _drbd_send_zc_bio(mdev,e->private_bio);
 
-	spin_lock(&mdev->send_task_lock);
-	mdev->send_task=NULL;
-	spin_unlock(&mdev->send_task_lock);
 	up(&mdev->data.mutex);
-	restore_old_sigset(old_blocked);
 	return ok;
 }
 
@@ -2036,7 +1965,6 @@
 	spin_lock_init(&mdev->ee_lock);
 	spin_lock_init(&mdev->req_lock);
 	spin_lock_init(&mdev->pr_lock);
-	spin_lock_init(&mdev->send_task_lock);
 	spin_lock_init(&mdev->peer_seq_lock);
 
 	INIT_LIST_HEAD(&mdev->active_ee);
@@ -2142,7 +2070,6 @@
 	mdev->rs_mark_left =
 	mdev->rs_mark_time = 0;
 	mdev->net_conf     = NULL;
-	mdev->send_task    = NULL;
 	drbd_set_my_capacity(mdev,0);
 	drbd_bm_resize(mdev,0);
 

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-24 12:11:40 UTC (rev 2293)
+++ trunk/drbd/drbd_receiver.c	2006-07-25 10:32:38 UTC (rev 2294)
@@ -2066,6 +2066,7 @@
 	if (test_bit(UNIQUE,&mdev->flags)) drbd_state_unlock(mdev);
 
 	drbd_send_sr_reply(mdev,rv);
+	drbd_md_sync(mdev);
 
 	return TRUE;
 }
@@ -2432,20 +2433,7 @@
 	drbd_thread_stop_nowait(&mdev->worker);
 	drbd_thread_stop(&mdev->asender);
 
-	while(down_trylock(&mdev->data.mutex)) {
-		struct task_struct *task;
-		spin_lock(&mdev->send_task_lock);
-		if((task=mdev->send_task)) {
-			force_sig(DRBD_SIG, task);
-			spin_unlock(&mdev->send_task_lock);
-			down(&mdev->data.mutex);
-			break;
-		} else {
-			spin_unlock(&mdev->send_task_lock);
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 10);
-		}
-	}
+	down(&mdev->data.mutex);
 	/* By grabbing the sock_mutex we make sure that no one
 	   uses the socket right now. */
 	drbd_free_sock(mdev);

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-24 12:11:40 UTC (rev 2293)
+++ trunk/drbd/drbd_req.c	2006-07-25 10:32:38 UTC (rev 2294)
@@ -301,8 +301,9 @@
 	if (rw == WRITE && local)
 		drbd_al_begin_io(mdev, sector);
 
-	remote = remote && (mdev->state.pdsk == Inconsistent ||
-			    mdev->state.pdsk == UpToDate);
+	remote = remote && (mdev->state.pdsk == UpToDate || 
+			    ( mdev->state.pdsk == Inconsistent && 
+			      mdev->state.conn >= Connected ) );
 
 	D_ASSERT( (rw != WRITE) || (remote == (mdev->state.conn >= Connected)) );
 

From drbd-cvs at lists.linbit.com  Tue Jul 25 15:55:02 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul 25 15:55:03 2006
Subject: [DRBD-cvs] svn commit by phil - r2295 - in trunk: . drbd - Work of
	today afternoon... 
Message-ID: <20060725135503.1E92A2D99B0E@mail.linbit.com>

Author: phil
Date: 2006-07-25 15:55:01 +0200 (Tue, 25 Jul 2006)
New Revision: 2295

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_actlog.c
   trunk/drbd/drbd_req.c
Log:
Work of today afternoon...


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-25 10:32:38 UTC (rev 2294)
+++ trunk/ROADMAP	2006-07-25 13:55:01 UTC (rev 2295)
@@ -844,3 +844,34 @@
 
 
 
+
+Currently known bug(s):
+-----------------------
+The client (kjournald) hangs in drbd_al_begin_io(). It waits for
+the completion of w_al_write_transaction(). That will not happen
+since the worker exited alrady.
+
+The receiver hangs in drbd_disconnect(), actuall at this line:
+wait_event( mdev->cstate_wait, atomic_read(&mdev->ap_pending_cnt)==0 );
+
+BTW, mdev->ap_pending_cnt is -1. 
+
+The counter could got below zero, since the requests gets onto the
+TL first, and then it gets queued on the worker's queue.
+
+The the disconnect code comes in, and decreases mdev->ap_pending_cnt
+for each entry in the TL.
+
+The entry on the worker's queue is still there and would increase 
+the counter again, but the worker is dead by now.
+
+Solution:
+
+ * Mark requests as they are moved from the queue to the socket.
+   The tl_clear() function should only decrease mdev->ap_pending_cnt
+   for requests that where already on the socket...
+ * The worker should not exit upon loss of connection.
+
+
+
+

Modified: trunk/drbd/drbd_actlog.c
===================================================================
--- trunk/drbd/drbd_actlog.c	2006-07-25 10:32:38 UTC (rev 2294)
+++ trunk/drbd/drbd_actlog.c	2006-07-25 13:55:01 UTC (rev 2295)
@@ -949,6 +949,7 @@
 			clear_bit(BME_NO_WRITES,&bm_ext->flags);
 			lc_del(mdev->resync,&bm_ext->lce);
 		}
+		mdev->resync->used=0;
 		dec_local(mdev);
 	}
 	atomic_set(&mdev->resync_locked,0);

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-25 10:32:38 UTC (rev 2294)
+++ trunk/drbd/drbd_req.c	2006-07-25 13:55:01 UTC (rev 2295)
@@ -355,7 +355,7 @@
 			}
 
 			if (mdev->net_conf->two_primaries) {
-				if(ee_have_write(mdev,req)) {
+				if(ee_have_write(mdev,req)) { // tl_add() here
 					WARN("Concurrent write! [DISCARD L] sec=%lu\n",
 					     (unsigned long)sector);
 					dec_local(mdev);

From drbd-cvs at lists.linbit.com  Tue Jul 25 15:55:39 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jul 25 15:55:41 2006
Subject: [DRBD-cvs] svn commit by phil - r2296 - branches/drbd-0.7/drbd -
	Actually a bug fix, but I guess nothing/nobody is affec
Message-ID: <20060725135539.E164F2D99B0E@mail.linbit.com>

Author: phil
Date: 2006-07-25 15:55:36 +0200 (Tue, 25 Jul 2006)
New Revision: 2296

Modified:
   branches/drbd-0.7/drbd/drbd_actlog.c
Log:
Actually a bug fix, but I guess nothing/nobody is affected by this bug.


Modified: branches/drbd-0.7/drbd/drbd_actlog.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_actlog.c	2006-07-25 13:55:01 UTC (rev 2295)
+++ branches/drbd-0.7/drbd/drbd_actlog.c	2006-07-25 13:55:36 UTC (rev 2296)
@@ -985,6 +985,7 @@
 		clear_bit(BME_NO_WRITES,&bm_ext->flags);
 		lc_del(mdev->resync,&bm_ext->lce);
 	}
+	mdev->resync->used=0;
 	atomic_set(&mdev->resync_locked,0);   
 	spin_unlock_irq(&mdev->al_lock);
 	wake_up(&mdev->al_wait);

From drbd-cvs at lists.linbit.com  Wed Jul 26 11:25:49 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 26 11:25:51 2006
Subject: [DRBD-cvs] svn commit by phil - r2297 - trunk/drbd - Changed the
	way we start/stop the worker thread. * It n
Message-ID: <20060726092550.0DABA2CDC49E@mail.linbit.com>

Author: phil
Date: 2006-07-26 11:25:48 +0200 (Wed, 26 Jul 2006)
New Revision: 2297

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
Log:
Changed the way we start/stop the worker thread. 
* It no longer gets restarted when we loose the connection.
* Starting / Stopping is handled with state transitions.


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-25 13:55:36 UTC (rev 2296)
+++ trunk/drbd/drbd_fs.c	2006-07-26 09:25:48 UTC (rev 2297)
@@ -538,7 +538,6 @@
 		drbd_send_sizes(mdev);  // to start sync...
 		drbd_send_uuids(mdev);
 		drbd_send_state(mdev);
-		drbd_thread_start(&mdev->worker);
 	} else {
 		spin_lock_irq(&mdev->req_lock);
 		os = mdev->state;
@@ -577,9 +576,7 @@
 		spin_unlock_irq(&mdev->req_lock);
 		after_state_ch(mdev,os,ns,ChgStateVerbose);
 
-		if(rv >= SS_Success ) {
-			drbd_thread_start(&mdev->worker);
-		} else {
+		if(rv < SS_Success ) {
 			drbd_bm_unlock(mdev);
 			goto  release_bdev3_fail_ioctl;
 		}
@@ -789,7 +786,6 @@
 	}
 	mdev->cram_hmac_tfm = tfm;
 
-	drbd_thread_start(&mdev->worker);
 	if( drbd_request_state(mdev,NS(conn,Unconnected)) >= SS_Success ) {
 		drbd_thread_start(&mdev->receiver);
 	}

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-25 13:55:36 UTC (rev 2296)
+++ trunk/drbd/drbd_main.c	2006-07-26 09:25:48 UTC (rev 2297)
@@ -1079,9 +1079,15 @@
 		lc_free(mdev->act_log); mdev->act_log = NULL;
 	}
 
+	if ( os.disk == Diskless && os.conn == StandAlone &&
+	     (ns.disk > Diskless || ns.conn > StandAlone) ) {
+		drbd_thread_start(&mdev->worker);
+	}
+
 	/* it feels better to have the module_put last ... */
 	if ( (os.disk > Diskless || os.conn > StandAlone) &&
 	     ns.disk == Diskless && ns.conn == StandAlone ) {
+		drbd_thread_stop(&mdev->worker);
 		drbd_mdev_cleanup(mdev);
 		module_put(THIS_MODULE);
 	}
@@ -2218,7 +2224,6 @@
 				up(&mdev->device_mutex);
 				drbd_sync_me(mdev);
 				drbd_thread_stop(&mdev->receiver);
-				drbd_thread_stop(&mdev->worker);
 			}
 		}
 

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-25 13:55:36 UTC (rev 2296)
+++ trunk/drbd/drbd_receiver.c	2006-07-26 09:25:48 UTC (rev 2297)
@@ -2430,7 +2430,6 @@
 		dec_local(mdev);
 	}
 
-	drbd_thread_stop_nowait(&mdev->worker);
 	drbd_thread_stop(&mdev->asender);
 
 	down(&mdev->data.mutex);
@@ -2440,7 +2439,6 @@
 	up(&mdev->data.mutex);
 
 	drbd_fail_pending_reads(mdev);
-	drbd_thread_stop(&mdev->worker);
 	// now worker is dead and read_ee is empty
 	drbd_rs_cancel_all(mdev);
 
@@ -2498,10 +2496,8 @@
 
 	if (get_t_state(&mdev->receiver) == Exiting) {
 		drbd_force_state(mdev,NS(conn,StandAlone));
-		drbd_thread_start(&mdev->worker);
 	} else {
 		drbd_force_state(mdev,NS(conn,Unconnected));
-		drbd_thread_start(&mdev->worker);
 	}
 
 	if ( mdev->state.role == Primary ) {		

From drbd-cvs at lists.linbit.com  Wed Jul 26 12:23:36 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 26 12:23:37 2006
Subject: [DRBD-cvs] svn commit by phil - r2298 - in trunk: . drbd - * Mark
	requests as they are moved from the queue to the
Message-ID: <20060726102336.F03192D9989D@mail.linbit.com>

Author: phil
Date: 2006-07-26 12:23:35 +0200 (Wed, 26 Jul 2006)
New Revision: 2298

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_worker.c
Log:
 * Mark requests as they are moved from the queue to the socket.
   The tl_clear() function should only decrease mdev->ap_pending_cnt
   for requests that where already on the socket...

 ( The worker should not exit upon loss of connection.
   Done by previous patch )

The bug I want to fix:
-----------------------
The client (kjournald) hangs in drbd_al_begin_io(). It waits for
the completion of w_al_write_transaction(). That will not happen
since the worker exited alrady.

The receiver hangs in drbd_disconnect(), actuall at this line:
wait_event( mdev->cstate_wait, atomic_read(&mdev->ap_pending_cnt)==0 );

BTW, mdev->ap_pending_cnt is -1. 

The counter could got below zero, since the requests gets onto the
TL first, and then it gets queued on the worker's queue.

The the disconnect code comes in, and decreases mdev->ap_pending_cnt
for each entry in the TL.

The entry on the worker's queue is still there and would increase 
the counter again, but the worker is dead by now.



Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-07-26 09:25:48 UTC (rev 2297)
+++ trunk/ROADMAP	2006-07-26 10:23:35 UTC (rev 2298)
@@ -842,36 +842,3 @@
 6 Have protocol version 74 available in drbd-0.8, to allow rolling 
   upgrades
 
-
-
-
-Currently known bug(s):
------------------------
-The client (kjournald) hangs in drbd_al_begin_io(). It waits for
-the completion of w_al_write_transaction(). That will not happen
-since the worker exited alrady.
-
-The receiver hangs in drbd_disconnect(), actuall at this line:
-wait_event( mdev->cstate_wait, atomic_read(&mdev->ap_pending_cnt)==0 );
-
-BTW, mdev->ap_pending_cnt is -1. 
-
-The counter could got below zero, since the requests gets onto the
-TL first, and then it gets queued on the worker's queue.
-
-The the disconnect code comes in, and decreases mdev->ap_pending_cnt
-for each entry in the TL.
-
-The entry on the worker's queue is still there and would increase 
-the counter again, but the worker is dead by now.
-
-Solution:
-
- * Mark requests as they are moved from the queue to the socket.
-   The tl_clear() function should only decrease mdev->ap_pending_cnt
-   for requests that where already on the socket...
- * The worker should not exit upon loss of connection.
-
-
-
-

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-26 09:25:48 UTC (rev 2297)
+++ trunk/drbd/drbd_int.h	2006-07-26 10:23:35 UTC (rev 2298)
@@ -231,11 +231,11 @@
 /* these defines should go into blkdev.h
    (if it will be ever includet into linus' linux) */
 #define RQ_DRBD_NOTHING	  0x0001
-#define RQ_DRBD_SENT      0x0010
-#define RQ_DRBD_LOCAL     0x0020
-#define RQ_DRBD_DONE      0x0030
-#define RQ_DRBD_IN_TL     0x0040
-#define RQ_DRBD_RECVW     0x0080
+#define RQ_DRBD_SENT      0x0010   // We got an ack
+#define RQ_DRBD_LOCAL     0x0020   // We wrote it to the local disk
+#define RQ_DRBD_DONE      0x0030   // We are done ;)
+#define RQ_DRBD_IN_TL     0x0040   // Set when it is in the TL
+#define RQ_DRBD_ON_WIRE   0x0080   // Set as soon as it is on the socket...
 
 /* drbd_meta-data.c (still in drbd_main.c) */
 #define DRBD_MD_MAGIC (DRBD_MAGIC+4) // 4th incarnation of the disk layout.

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-26 09:25:48 UTC (rev 2297)
+++ trunk/drbd/drbd_main.c	2006-07-26 10:23:35 UTC (rev 2298)
@@ -337,8 +337,6 @@
 	hlist_del(&req->colision);
 	// req->barrier->n_req--; // Barrier migh be free'ed already!
 
-	if( req->rq_status & RQ_DRBD_RECVW ) wake_up(&mdev->cstate_wait);
-
 	spin_unlock_irqrestore(&mdev->tl_lock,flags);
 	return r;
 }
@@ -365,9 +363,13 @@
 			// bi_size and bi_sector are modified in bio_endio!
 			sector = drbd_req_get_sector(r);
 			size   = drbd_req_get_size(r);
+			
+			if( r->rq_status & RQ_DRBD_ON_WIRE &&
+			    mdev->net_conf->wire_protocol != DRBD_PROT_A ) {
+				dec_ap_pending(mdev);
+			}
+
 			if( !(r->rq_status & RQ_DRBD_SENT) ) {
-				if(mdev->net_conf->wire_protocol != DRBD_PROT_A )
-					dec_ap_pending(mdev);
 				drbd_end_req(r,RQ_DRBD_SENT,ERF_NOTLD|1, sector);
 				goto mark;
 			}
@@ -1702,6 +1704,10 @@
 	set_bit(UNPLUG_REMOTE,&mdev->flags);
 	ok = sizeof(p) == drbd_send(mdev,mdev->data.socket,&p,sizeof(p),MSG_MORE);
 	if(ok) {
+		spin_lock_irq(&mdev->req_lock);
+		req->rq_status |= RQ_DRBD_ON_WIRE;
+		spin_unlock_irq(&mdev->req_lock);
+
 		if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {
 			ok = _drbd_send_bio(mdev,req->master_bio);
 		} else {

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-26 09:25:48 UTC (rev 2297)
+++ trunk/drbd/drbd_worker.c	2006-07-26 10:23:35 UTC (rev 2298)
@@ -561,21 +561,24 @@
 	drbd_request_t *req = (drbd_request_t *)w;
 	int ok;
 
-	inc_ap_pending(mdev); // Right here, since tl_clear() will decrease it
-
 	if (unlikely(cancel)) { 
 		/* Nothing to do, here. tl_clear() does the work. */
 		return 1;
 	}
 
 	ok = drbd_send_dblock(mdev,req);
-	if (!ok) {
+	if (ok) {
+		inc_ap_pending(mdev);
+
+		if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {
+			dec_ap_pending(mdev);
+			drbd_end_req(req, RQ_DRBD_SENT, 1, 
+				     drbd_req_get_sector(req));
+		}
+	} else {
 		if (mdev->state.conn >= Connected) 
 			drbd_force_state(mdev,NS(conn,NetworkFailure));
 		drbd_thread_restart_nowait(&mdev->receiver);
-	} else if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {
-		dec_ap_pending(mdev);
-		drbd_end_req(req, RQ_DRBD_SENT, 1, drbd_req_get_sector(req));
 	}
 
 	return ok;

From drbd-cvs at lists.linbit.com  Wed Jul 26 16:51:56 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jul 26 16:51:56 2006
Subject: [DRBD-cvs] svn commit by phil - r2299 - trunk/drbd - I should "code
	what I mean" ; ) 
Message-ID: <20060726145156.3AF002CDC495@mail.linbit.com>

Author: phil
Date: 2006-07-26 16:51:53 +0200 (Wed, 26 Jul 2006)
New Revision: 2299

Modified:
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_worker.c
Log:
I should "code what I mean" ;)


Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-26 10:23:35 UTC (rev 2298)
+++ trunk/drbd/drbd_main.c	2006-07-26 14:51:53 UTC (rev 2299)
@@ -1704,10 +1704,6 @@
 	set_bit(UNPLUG_REMOTE,&mdev->flags);
 	ok = sizeof(p) == drbd_send(mdev,mdev->data.socket,&p,sizeof(p),MSG_MORE);
 	if(ok) {
-		spin_lock_irq(&mdev->req_lock);
-		req->rq_status |= RQ_DRBD_ON_WIRE;
-		spin_unlock_irq(&mdev->req_lock);
-
 		if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {
 			ok = _drbd_send_bio(mdev,req->master_bio);
 		} else {

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-26 10:23:35 UTC (rev 2298)
+++ trunk/drbd/drbd_worker.c	2006-07-26 14:51:53 UTC (rev 2299)
@@ -568,6 +568,10 @@
 
 	ok = drbd_send_dblock(mdev,req);
 	if (ok) {
+		spin_lock_irq(&mdev->req_lock);
+		req->rq_status |= RQ_DRBD_ON_WIRE;
+		spin_unlock_irq(&mdev->req_lock);
+
 		inc_ap_pending(mdev);
 
 		if(mdev->net_conf->wire_protocol == DRBD_PROT_A) {

From drbd-cvs at lists.linbit.com  Thu Jul 27 11:37:42 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul 27 11:37:49 2006
Subject: [DRBD-cvs] svn commit by phil - r2301 - trunk/drbd - Changed the
	way the receiver is started, stopped and th
Message-ID: <20060727093742.56BA02CDC35F@mail.linbit.com>

Author: phil
Date: 2006-07-27 11:37:40 +0200 (Thu, 27 Jul 2006)
New Revision: 2301

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_worker.c
Log:
Changed the way the receiver is started, stopped and the mess
after a loss of connection is cleared up.


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-27 06:14:28 UTC (rev 2300)
+++ trunk/drbd/drbd_fs.c	2006-07-27 09:37:40 UTC (rev 2301)
@@ -786,9 +786,7 @@
 	}
 	mdev->cram_hmac_tfm = tfm;
 
-	if( drbd_request_state(mdev,NS(conn,Unconnected)) >= SS_Success ) {
-		drbd_thread_start(&mdev->receiver);
-	}
+	drbd_request_state(mdev,NS(conn,Unconnected));
 
 	return 0;
 

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-27 06:14:28 UTC (rev 2300)
+++ trunk/drbd/drbd_int.h	2006-07-27 09:37:40 UTC (rev 2301)
@@ -1138,6 +1138,7 @@
 extern int w_send_dblock         (drbd_dev *, struct drbd_work *, int);
 extern int w_send_barrier        (drbd_dev *, struct drbd_work *, int);
 extern int w_send_read_req       (drbd_dev *, struct drbd_work *, int);
+extern int w_disconnect          (drbd_dev *, struct drbd_work *, int);
 
 extern void resync_timer_fn(unsigned long data);
 
@@ -1151,6 +1152,7 @@
 extern void drbd_wait_ee_list_empty(drbd_dev *mdev, struct list_head *head);
 extern void _drbd_wait_ee_list_empty(drbd_dev *mdev, struct list_head *head);
 extern void drbd_set_recv_tcq(drbd_dev *mdev, int tcq_enabled);
+extern void _drbd_clear_done_ee(drbd_dev *mdev);
 
 // drbd_proc.c
 extern struct proc_dir_entry *drbd_proc;

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-27 06:14:28 UTC (rev 2300)
+++ trunk/drbd/drbd_main.c	2006-07-27 09:37:40 UTC (rev 2301)
@@ -903,7 +903,7 @@
 			ascw->ns = ns;
 			ascw->flags = flags;
 			ascw->w.cb = w_after_state_ch;
-			_drbd_queue_work_front(&mdev->data.work,&ascw->w);
+			_drbd_queue_work(&mdev->data.work,&ascw->w);
 		} else {
 			WARN("Could not kmalloc an ascw\n");
 		}
@@ -1022,12 +1022,6 @@
 	if ( ( os.conn != StartingSyncT && ns.conn == StartingSyncT ) ||
 	     ( os.conn != StartingSyncS && ns.conn == StartingSyncS ) ) {
 
-		/* avoid races with set_in_sync
-		 * for successfull mirrored writes
-		 */
-		wait_event(mdev->cstate_wait,
-			   atomic_read(&mdev->ap_bio_cnt)==0);
-
 		drbd_bm_lock(mdev); // racy...
 
 		drbd_md_set_flag(mdev,MDF_FullSync);
@@ -1081,6 +1075,11 @@
 		lc_free(mdev->act_log); mdev->act_log = NULL;
 	}
 
+	if ( os.conn != Unconnected && ns.conn == Unconnected ) {
+		drbd_thread_stop(&mdev->receiver);
+		drbd_thread_start(&mdev->receiver);
+	}
+
 	if ( os.disk == Diskless && os.conn == StandAlone &&
 	     (ns.disk > Diskless || ns.conn > StandAlone) ) {
 		drbd_thread_start(&mdev->worker);
@@ -1187,7 +1186,7 @@
 	}
 
 	if (thi->t_state != ns) {
-		ERR_IF (thi->task == NULL) {
+		if (thi->task == NULL) {
 			spin_unlock(&thi->t_lock);
 			return;
 		}

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-27 06:14:28 UTC (rev 2300)
+++ trunk/drbd/drbd_receiver.c	2006-07-27 09:37:40 UTC (rev 2301)
@@ -372,7 +372,7 @@
 }
 
 /* clean-up helper for drbd_disconnect */
-STATIC void _drbd_clear_done_ee(drbd_dev *mdev)
+void _drbd_clear_done_ee(drbd_dev *mdev)
 {
 	struct list_head *le;
 	struct Tl_epoch_entry *e;
@@ -616,7 +616,7 @@
 	if (err) {
 		ERR("Unable to bind sock2 (%d)\n", err);
 		sock_release(sock2);
-		drbd_force_state(mdev,NS(conn,Unconnected));
+		drbd_force_state(mdev,NS(conn,StandAlone));
 		return NULL;
 	}
 
@@ -721,7 +721,7 @@
 			}
 		}
 
-		if(mdev->state.conn == Unconnected) return -1;
+		if(mdev->state.conn == StandAlone) return -1;
 		if(signal_pending(current)) {
 			flush_signals(current);
 			smp_rmb();
@@ -2218,44 +2218,6 @@
 	return ok;
 }
 
-STATIC void drbd_fail_pending_reads(drbd_dev *mdev)
-{
-	struct hlist_head *slot;
-	struct hlist_node *n;
-	drbd_request_t * req;
-	struct list_head *le;
-	struct bio *bio;
-	LIST_HEAD(workset);
-	int i;
-
-	/*
-	 * Application READ requests
-	 */
-	spin_lock(&mdev->pr_lock);
-	for(i=0;i<APP_R_HSIZE;i++) {
-		slot = mdev->app_reads_hash+i;
-		hlist_for_each_entry(req, n, slot, colision) {
-			list_add(&req->w.list, &workset);
-		}
-	}
-	memset(mdev->app_reads_hash,0,APP_R_HSIZE*sizeof(void*));
-	spin_unlock(&mdev->pr_lock);
-
-	while(!list_empty(&workset)) {
-		le = workset.next;
-		req = list_entry(le, drbd_request_t, w.list);
-		list_del(le);
-
-		bio = req->master_bio;
-
-		drbd_bio_IO_error(bio);
-		dec_ap_bio(mdev);
-		dec_ap_pending(mdev);
-
-		drbd_req_free(req);
-	}
-}
-
 STATIC int receive_skip(drbd_dev *mdev,Drbd_Header *h)
 {
 	// TODO zero copy sink :)
@@ -2422,84 +2384,30 @@
 {
 	enum fencing_policy fp;
 
+	struct drbd_work *disconnect_work;
+
 	D_ASSERT(mdev->state.conn < Connected);
 
+	drbd_thread_stop(&mdev->asender);
+
 	fp = DontCare;
 	if(inc_local(mdev)) {
 		fp = mdev->bc->fencing;
 		dec_local(mdev);
 	}
 
-	drbd_thread_stop(&mdev->asender);
 
-	down(&mdev->data.mutex);
-	/* By grabbing the sock_mutex we make sure that no one
-	   uses the socket right now. */
-	drbd_free_sock(mdev);
-	up(&mdev->data.mutex);
-
-	drbd_fail_pending_reads(mdev);
-	// now worker is dead and read_ee is empty
-	drbd_rs_cancel_all(mdev);
-
-	// Receiving side (may be primary, in case we had two primaries)
-	spin_lock_irq(&mdev->ee_lock);
-	_drbd_wait_ee_list_empty(mdev,&mdev->read_ee);
-	_drbd_wait_ee_list_empty(mdev,&mdev->active_ee);
-	_drbd_wait_ee_list_empty(mdev,&mdev->sync_ee);
-	_drbd_clear_done_ee(mdev);
-	mdev->epoch_size = 0;
-	spin_unlock_irq(&mdev->ee_lock);
-
-	// primary
-	clear_bit(ISSUE_BARRIER,&mdev->flags);
-
-	if(fp != Stonith ) {
-		tl_clear(mdev);
-		wait_event( mdev->cstate_wait, 
-			    atomic_read(&mdev->ap_pending_cnt)==0 );
-		D_ASSERT(mdev->oldest_barrier->n_req == 0);
-
-		if(atomic_read(&mdev->ap_pending_cnt)) {
-			ERR("ap_pending_cnt = %d\n",
-			    atomic_read(&mdev->ap_pending_cnt));
-			atomic_set(&mdev->ap_pending_cnt,0);
-		}
-	}
-
-	D_ASSERT(atomic_read(&mdev->pp_in_use) == 0);
-	D_ASSERT(list_empty(&mdev->read_ee)); // done by termination of worker
-	D_ASSERT(list_empty(&mdev->active_ee)); // done here
-	D_ASSERT(list_empty(&mdev->sync_ee)); // done here
-	D_ASSERT(list_empty(&mdev->done_ee)); // done here
-
-	mdev->rs_total=0;
-
-	if(atomic_read(&mdev->unacked_cnt)) {
-		ERR("unacked_cnt = %d\n",atomic_read(&mdev->unacked_cnt));
-		atomic_set(&mdev->unacked_cnt,0);
-	}
-
-	/* We do not have data structures that would allow us to
-	   get the rs_pending_cnt down to 0 again.
-	   * On SyncTarget we do not have any data structures describing
-	     the pending RSDataRequest's we have sent.
-	   * On SyncSource there is no data structure that tracks
-	     the RSDataReply blocks that we sent to the SyncTarget.
-	   And no, it is not the sum of the reference counts in the
-	   resync_LRU. The resync_LRU tracks the whole operation including
-           the disk-IO, while the rs_pending_cnt only tracks the blocks
-	   on the fly. */
-	atomic_set(&mdev->rs_pending_cnt,0);
-
-	wake_up(&mdev->cstate_wait);
-
-	if (get_t_state(&mdev->receiver) == Exiting) {
-		drbd_force_state(mdev,NS(conn,StandAlone));
+	disconnect_work = kmalloc(sizeof(struct drbd_work),GFP_KERNEL);
+	if(disconnect_work) {
+		disconnect_work->cb = w_disconnect;
+		drbd_queue_work(mdev,&mdev->data.work,disconnect_work);
 	} else {
-		drbd_force_state(mdev,NS(conn,Unconnected));
+		WARN("kmalloc failed, taking messy shortcut.\n");
+		w_disconnect(mdev,NULL,1);
 	}
 
+	drbd_md_sync(mdev);
+
 	if ( mdev->state.role == Primary ) {		
 		if( fp >= Resource &&
 		    mdev->state.pdsk >= DUnknown ) {
@@ -2508,13 +2416,14 @@
 		}
 	}
 
-	if ( mdev->p_uuid ) {
-		kfree(mdev->p_uuid);
-		mdev->p_uuid = NULL;
+	spin_lock_irq(&mdev->req_lock);
+	if ( mdev->state.conn > Unconnected ) {
+		// Do not restart in case we are StandAlone
+		_drbd_set_state(mdev, _NS(conn,Unconnected), ScheduleAfter);
 	}
+	spin_unlock_irq(&mdev->req_lock);
 
 	drbd_md_sync(mdev);
-	INFO("Connection lost.\n");
 }
 
 /*
@@ -2757,7 +2666,6 @@
 
 int drbdd_init(struct Drbd_thread *thi)
 {
-	enum disconnect_handler on_disconnect = Reconnect;
 	drbd_dev *mdev = thi->mdev;
 	int minor = (int)(mdev-drbd_conf);
 	int h;
@@ -2766,48 +2674,28 @@
 
 	/* printk(KERN_INFO DEVICE_NAME ": receiver living/m=%d\n", minor); */
 
-	while (TRUE) {
+	do {
 		h = drbd_connect(mdev);
-		if (h <= 0) {
-			/* FIXME DISKLESS StandAlone
-			 * does not make much sense...
-			 * drbd_disconnect should set cstate properly...
-			 */
+		if (h == 0) {
 			drbd_disconnect(mdev);
-			if (h == 0) {
-				schedule_timeout(HZ);
-				continue;
-			}
-
+			schedule_timeout(HZ);
+		}
+		if( h < 0 ) {
 			WARN("Discarding network configuration.\n");
 			drbd_force_state(mdev,NS(conn,StandAlone));
-			break;
 		}
-		if (get_t_state(thi) == Exiting) break;
+	} while ( h == 0 );
+
+	if( h > 0 ) {
 		if(inc_net(mdev)) {
 			drbdd(mdev);
-			on_disconnect = mdev->net_conf->on_disconnect;
 			dec_net(mdev);
 		}
-		drbd_disconnect(mdev);
-		if (get_t_state(thi) == Exiting) break;
-		if(on_disconnect == DropNetConf) {
-			drbd_force_state(mdev,NS(conn,StandAlone));
-			break;
-		}
-		else {
-			if (signal_pending(current)) {
-				flush_signals(current);
-			}
-			spin_lock(&thi->t_lock);
-			D_ASSERT(thi->t_state == Restarting);
-			thi->t_state = Running;
-			spin_unlock(&thi->t_lock);
-		}
 	}
 
-	INFO("receiver terminated\n");
+	drbd_disconnect(mdev);
 
+	INFO("receiver terminated\n");
 	return 0;
 }
 

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-27 06:14:28 UTC (rev 2300)
+++ trunk/drbd/drbd_worker.c	2006-07-27 09:37:40 UTC (rev 2301)
@@ -613,6 +613,129 @@
 	return ok;
 }
 
+STATIC void drbd_fail_pending_reads(drbd_dev *mdev)
+{
+	struct hlist_head *slot;
+	struct hlist_node *n;
+	drbd_request_t * req;
+	struct list_head *le;
+	struct bio *bio;
+	LIST_HEAD(workset);
+	int i;
+
+	/*
+	 * Application READ requests
+	 */
+	spin_lock(&mdev->pr_lock);
+	for(i=0;i<APP_R_HSIZE;i++) {
+		slot = mdev->app_reads_hash+i;
+		hlist_for_each_entry(req, n, slot, colision) {
+			list_add(&req->w.list, &workset);
+		}
+	}
+	memset(mdev->app_reads_hash,0,APP_R_HSIZE*sizeof(void*));
+	spin_unlock(&mdev->pr_lock);
+
+	while(!list_empty(&workset)) {
+		le = workset.next;
+		req = list_entry(le, drbd_request_t, w.list);
+		list_del(le);
+
+		bio = req->master_bio;
+
+		drbd_bio_IO_error(bio);
+		dec_ap_bio(mdev);
+		dec_ap_pending(mdev);
+
+		drbd_req_free(req);
+	}
+}
+
+/**
+ * w_disconnect clean up everything, and restart the receiver.
+ */
+int w_disconnect(drbd_dev *mdev, struct drbd_work *w, int cancel)
+{
+	enum fencing_policy fp;
+
+	D_ASSERT(cancel);
+
+	fp = DontCare;
+	if(inc_local(mdev)) {
+		fp = mdev->bc->fencing;
+		dec_local(mdev);
+	}
+
+	down(&mdev->data.mutex);
+	/* By grabbing the sock_mutex we make sure that no one
+	   uses the socket right now. */
+	drbd_free_sock(mdev);
+	up(&mdev->data.mutex);
+
+	drbd_fail_pending_reads(mdev);
+	drbd_rs_cancel_all(mdev);
+
+	// Receiving side (may be primary, in case we had two primaries)
+	spin_lock_irq(&mdev->ee_lock);
+	_drbd_wait_ee_list_empty(mdev,&mdev->read_ee);
+	_drbd_wait_ee_list_empty(mdev,&mdev->active_ee);
+	_drbd_wait_ee_list_empty(mdev,&mdev->sync_ee);
+	_drbd_clear_done_ee(mdev);
+	mdev->epoch_size = 0;
+	spin_unlock_irq(&mdev->ee_lock);
+
+	// primary
+	clear_bit(ISSUE_BARRIER,&mdev->flags);
+
+	if(fp != Stonith ) {
+		tl_clear(mdev);
+		D_ASSERT(mdev->oldest_barrier->n_req == 0);
+
+		if(atomic_read(&mdev->ap_pending_cnt)) {
+			ERR("ap_pending_cnt = %d\n",
+			    atomic_read(&mdev->ap_pending_cnt));
+			atomic_set(&mdev->ap_pending_cnt,0);
+		}
+	}
+
+	D_ASSERT(atomic_read(&mdev->pp_in_use) == 0);
+	D_ASSERT(list_empty(&mdev->read_ee));
+	D_ASSERT(list_empty(&mdev->active_ee)); // done here
+	D_ASSERT(list_empty(&mdev->sync_ee)); // done here
+	D_ASSERT(list_empty(&mdev->done_ee)); // done here
+
+	mdev->rs_total=0;
+
+	if(atomic_read(&mdev->unacked_cnt)) {
+		ERR("unacked_cnt = %d\n",atomic_read(&mdev->unacked_cnt));
+		atomic_set(&mdev->unacked_cnt,0);
+	}
+
+	/* We do not have data structures that would allow us to
+	   get the rs_pending_cnt down to 0 again.
+	   * On SyncTarget we do not have any data structures describing
+	     the pending RSDataRequest's we have sent.
+	   * On SyncSource there is no data structure that tracks
+	     the RSDataReply blocks that we sent to the SyncTarget.
+	   And no, it is not the sum of the reference counts in the
+	   resync_LRU. The resync_LRU tracks the whole operation including
+           the disk-IO, while the rs_pending_cnt only tracks the blocks
+	   on the fly. */
+	atomic_set(&mdev->rs_pending_cnt,0);
+	wake_up(&mdev->cstate_wait);
+
+	if ( mdev->p_uuid ) {
+		kfree(mdev->p_uuid);
+		mdev->p_uuid = NULL;
+	}
+
+	INFO("Connection closed\n");
+
+	if(w) kfree(w);
+
+	return 1;
+}
+
 STATIC void drbd_global_lock(void)
 {
 	int i;

From drbd-cvs at lists.linbit.com  Thu Jul 27 14:59:51 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul 27 14:59:56 2006
Subject: [DRBD-cvs] svn commit by phil - r2302 - trunk/drbd - We missed to
	call tl_clear() in case fencing-policy was
Message-ID: <20060727125954.CFE3B2DF6263@mail.linbit.com>

Author: phil
Date: 2006-07-27 14:59:48 +0200 (Thu, 27 Jul 2006)
New Revision: 2302

Modified:
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_worker.c
Log:
We missed to call tl_clear() in case fencing-policy was set to 
resource-and-stonith. Fixed.



Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-27 09:37:40 UTC (rev 2301)
+++ trunk/drbd/drbd_main.c	2006-07-27 12:59:48 UTC (rev 2302)
@@ -349,6 +349,8 @@
 	sector_t sector;
 	unsigned int size;
 
+	WARN("tl_clear()\n");
+
 	spin_lock_irq(&mdev->tl_lock);
 
 	b=mdev->oldest_barrier;

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-27 09:37:40 UTC (rev 2301)
+++ trunk/drbd/drbd_worker.c	2006-07-27 12:59:48 UTC (rev 2302)
@@ -656,16 +656,8 @@
  */
 int w_disconnect(drbd_dev *mdev, struct drbd_work *w, int cancel)
 {
-	enum fencing_policy fp;
-
 	D_ASSERT(cancel);
 
-	fp = DontCare;
-	if(inc_local(mdev)) {
-		fp = mdev->bc->fencing;
-		dec_local(mdev);
-	}
-
 	down(&mdev->data.mutex);
 	/* By grabbing the sock_mutex we make sure that no one
 	   uses the socket right now. */
@@ -687,7 +679,7 @@
 	// primary
 	clear_bit(ISSUE_BARRIER,&mdev->flags);
 
-	if(fp != Stonith ) {
+	if(!mdev->state.susp) {
 		tl_clear(mdev);
 		D_ASSERT(mdev->oldest_barrier->n_req == 0);
 

From drbd-cvs at lists.linbit.com  Thu Jul 27 16:06:51 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jul 27 16:06:52 2006
Subject: [DRBD-cvs] svn commit by phil - r2303 - trunk/drbd - Shaking the
	bugs out of the last big change... 
Message-ID: <20060727140651.607042CDC614@mail.linbit.com>

Author: phil
Date: 2006-07-27 16:06:49 +0200 (Thu, 27 Jul 2006)
New Revision: 2303

Modified:
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_worker.c
Log:
Shaking the bugs out of the last big change...


Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-27 12:59:48 UTC (rev 2302)
+++ trunk/drbd/drbd_receiver.c	2006-07-27 14:06:49 UTC (rev 2303)
@@ -2396,6 +2396,16 @@
 		dec_local(mdev);
 	}
 
+	// Receiving side (may be primary, in case we had two primaries)
+	spin_lock_irq(&mdev->ee_lock);
+	_drbd_wait_ee_list_empty(mdev,&mdev->read_ee);
+	_drbd_wait_ee_list_empty(mdev,&mdev->active_ee);
+	_drbd_wait_ee_list_empty(mdev,&mdev->sync_ee);
+	_drbd_clear_done_ee(mdev);
+	mdev->epoch_size = 0;
+	spin_unlock_irq(&mdev->ee_lock);
+	// Needs to happen before we schedule the disconnect work callback,
+	// Since they might have something for the worker's queue as well.
 
 	disconnect_work = kmalloc(sizeof(struct drbd_work),GFP_KERNEL);
 	if(disconnect_work) {

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-27 12:59:48 UTC (rev 2302)
+++ trunk/drbd/drbd_worker.c	2006-07-27 14:06:49 UTC (rev 2303)
@@ -667,15 +667,6 @@
 	drbd_fail_pending_reads(mdev);
 	drbd_rs_cancel_all(mdev);
 
-	// Receiving side (may be primary, in case we had two primaries)
-	spin_lock_irq(&mdev->ee_lock);
-	_drbd_wait_ee_list_empty(mdev,&mdev->read_ee);
-	_drbd_wait_ee_list_empty(mdev,&mdev->active_ee);
-	_drbd_wait_ee_list_empty(mdev,&mdev->sync_ee);
-	_drbd_clear_done_ee(mdev);
-	mdev->epoch_size = 0;
-	spin_unlock_irq(&mdev->ee_lock);
-
 	// primary
 	clear_bit(ISSUE_BARRIER,&mdev->flags);
 

From drbd-cvs at lists.linbit.com  Fri Jul 28 09:38:45 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Fri Jul 28 09:38:46 2006
Subject: [DRBD-cvs] svn commit by phil - r2304 - trunk/drbd - Fixed some
	bugs, related to "drbdad down [res]" 
Message-ID: <20060728073845.57EF12D99AB1@mail.linbit.com>

Author: phil
Date: 2006-07-28 09:38:43 +0200 (Fri, 28 Jul 2006)
New Revision: 2304

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_main.c
Log:
Fixed some bugs, related to "drbdad down [res]"


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-07-27 14:06:49 UTC (rev 2303)
+++ trunk/drbd/drbd_fs.c	2006-07-28 07:38:43 UTC (rev 2304)
@@ -1157,6 +1157,8 @@
 		mdev->cram_hmac_tfm = NULL;
 	}
 
+	drbd_md_sync(mdev);
+
 	return 0;
 }
 

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-27 14:06:49 UTC (rev 2303)
+++ trunk/drbd/drbd_main.c	2006-07-28 07:38:43 UTC (rev 2304)
@@ -550,7 +550,7 @@
 	rv = _drbd_set_state(mdev, ns, f);
 	ns = mdev->state;
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
-	if (rv == SS_Success) after_state_ch(mdev,os,ns,f);
+	if (rv==SS_Success && !(f&ScheduleAfter)) after_state_ch(mdev,os,ns,f);
 
 	return rv;
 }
@@ -639,7 +639,7 @@
 	ns = mdev->state;
 	spin_unlock_irqrestore(&mdev->req_lock,flags);
 
-	if (rv == SS_Success) after_state_ch(mdev,os,ns,f);
+	if (rv==SS_Success && !(f&ScheduleAfter)) after_state_ch(mdev,os,ns,f);
 
 	return rv;
 }
@@ -750,6 +750,12 @@
 		ns.pdsk = os.pdsk;
 	}
 
+	/* Dissalow Network errors to configure a device's network part */
+	if( (ns.conn >= BrokenPipe && ns.conn <= NetworkFailure ) && 
+	    os.conn == StandAlone ) {
+		ns.conn = os.conn;
+	}
+
 	if( ns.i == os.i ) return SS_NothingToDo;
 
 	fp = DontCare;
@@ -1077,6 +1083,10 @@
 		lc_free(mdev->act_log); mdev->act_log = NULL;
 	}
 
+	if ( os.conn != StandAlone && ns.conn == StandAlone ) {
+		drbd_thread_stop(&mdev->receiver);
+	}
+
 	if ( os.conn != Unconnected && ns.conn == Unconnected ) {
 		drbd_thread_stop(&mdev->receiver);
 		drbd_thread_start(&mdev->receiver);
@@ -2606,12 +2616,13 @@
 
 	if (!test_and_clear_bit(MD_DIRTY,&mdev->flags)) return;
 	del_timer(&mdev->md_sync_timer);
-	INFO("Writing meta data super block now.\n");
 
 	// We use here Failed and not Attaching because we try to write
 	// metadata even if we detach due to a disk failure!
-	ERR_IF(!inc_md_only(mdev,Failed)) return;
+	if(!inc_md_only(mdev,Failed)) return;
 
+	INFO("Writing meta data super block now.\n");
+
 	down(&mdev->md_io_mutex);
 	buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page);
 	memset(buffer,0,512);

From drbd-cvs at lists.linbit.com  Fri Jul 28 12:41:11 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Fri Jul 28 12:41:12 2006
Subject: [DRBD-cvs] svn commit by phil - r2305 - trunk/drbd - Finally found
	and fixed that terribly bug that tortured
Message-ID: <20060728104111.357AB2D99842@mail.linbit.com>

Author: phil
Date: 2006-07-28 12:41:09 +0200 (Fri, 28 Jul 2006)
New Revision: 2305

Modified:
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_worker.c
Log:
Finally found and fixed that terribly bug that tortured me te last
days. 

The w_send_dblock() could run even after tl_clear() ...


Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-28 07:38:43 UTC (rev 2304)
+++ trunk/drbd/drbd_main.c	2006-07-28 10:41:09 UTC (rev 2305)
@@ -211,7 +211,7 @@
 	b=mdev->newest_barrier;
 
 	req->barrier = b;
-	req->rq_status |= RQ_DRBD_IN_TL;
+	req->rq_status |= RQ_DRBD_IN_TL; /* BUG, not holding req_lock */
 	list_add(&req->tl_requests,&b->requests);
 
 	if( b->n_req++ > mdev->net_conf->max_epoch_size ) {

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-28 07:38:43 UTC (rev 2304)
+++ trunk/drbd/drbd_req.c	2006-07-28 10:41:09 UTC (rev 2305)
@@ -32,6 +32,22 @@
 #include <linux/drbd.h>
 #include "drbd_int.h"
 
+/*
+void drbd_show_req(struct Drbd_Conf* mdev, char *txt, drbd_request_t *req)
+{
+	INFO("req %s %p %c%c%c%c%c %p\n",
+	     txt,
+	     req,
+	     req->rq_status & RQ_DRBD_ON_WIRE ? 'w' :'_',
+	     req->rq_status & RQ_DRBD_IN_TL   ? 't' :'_',
+	     req->rq_status & RQ_DRBD_SENT    ? 's' :'_',
+	     req->rq_status & RQ_DRBD_LOCAL   ? 'l' :'_',
+	     req->rq_status & RQ_DRBD_NOTHING ? 'u' :'_',
+	     req->barrier
+	     );
+}
+*/
+
 void drbd_end_req(drbd_request_t *req, int nextstate, int er_flags,
 		  sector_t rsector)
 {
@@ -205,6 +221,7 @@
 		req->mdev        = mdev;
 		req->master_bio  = bio_src;
 		req->private_bio = bio;
+		req->barrier     = NULL;
 
 		bio->bi_private  = req;
 		bio->bi_end_io   =
@@ -326,6 +343,8 @@
 	// inc_ap_bio(mdev); do not allow more open requests than max_buffers!
 	wait_event( mdev->rq_wait,atomic_add_unless(&mdev->ap_bio_cnt,1,mxb) );
 
+	/* remote might be already wrong here, since we might slept after
+	   looking at the connection state, but this is ok. */
 	if (remote) {
 		/* either WRITE and Connected,
 		 * or READ, and no local disk,

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-28 07:38:43 UTC (rev 2304)
+++ trunk/drbd/drbd_worker.c	2006-07-28 10:41:09 UTC (rev 2305)
@@ -559,10 +559,21 @@
 int w_send_dblock(drbd_dev *mdev, struct drbd_work *w, int cancel)
 {
 	drbd_request_t *req = (drbd_request_t *)w;
+	sector_t sector;
+	unsigned int size;
 	int ok;
 
-	if (unlikely(cancel)) { 
-		/* Nothing to do, here. tl_clear() does the work. */
+	D_ASSERT( !(req->rq_status & RQ_DRBD_SENT) );
+
+	if (unlikely(cancel)) {
+		/* We clear it up here explicit, since we might be _after_ the
+		   run of tl_clear() */
+		sector = drbd_req_get_sector(req);
+		size   = drbd_req_get_size(req);
+
+		drbd_end_req(req,RQ_DRBD_SENT,1, sector);
+		drbd_set_out_of_sync(mdev, sector, size);
+
 		return 1;
 	}
 
@@ -583,6 +594,7 @@
 		if (mdev->state.conn >= Connected) 
 			drbd_force_state(mdev,NS(conn,NetworkFailure));
 		drbd_thread_restart_nowait(&mdev->receiver);
+		/* The request gets cleared up by tl_clear() */
 	}
 
 	return ok;

From drbd-cvs at lists.linbit.com  Fri Jul 28 13:45:53 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Fri Jul 28 13:45:54 2006
Subject: [DRBD-cvs] svn commit by lars - r2306 - trunk/user - * drbdadm *
	added sh-ip command prints the local ip ass
Message-ID: <20060728114554.15B132D99842@mail.linbit.com>

Author: lars
Date: 2006-07-28 13:45:47 +0200 (Fri, 28 Jul 2006)
New Revision: 2306

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/drbdmeta.c
   trunk/user/drbdsetup.c
Log:
* drbdadm
  * added sh-ip command
    prints the local ip associated with the given resource
  * just call get_ifi_info once, if needed.
  * strip ip-checking from attach, detach and primary,
    it may be valid to use those commands even if the local ip is
    not currently configured/up
  * make configuration file parsing / verify errors print the
    correct line numbers and text tokens, added a few
    check_uniq()s that got lost, ...
  * make all compile warnings go away (but one about signedness
    from the flex generated drbdadm_scanner.c)


Modified: trunk/user/drbdadm.h
===================================================================
--- trunk/user/drbdadm.h	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdadm.h	2006-07-28 11:45:47 UTC (rev 2306)
@@ -33,7 +33,7 @@
 #define EXIT_ON_CONFLICT 1
 
 /* for verify_ips(): are not verifyable ips fatal? */
-#define INVALID_IP_IS_INVALID_CONF 0
+#define INVALID_IP_IS_INVALID_CONF 1
 
 enum usage_count_type {
   UC_YES,

Modified: trunk/user/drbdadm_adjust.c
===================================================================
--- trunk/user/drbdadm_adjust.c	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdadm_adjust.c	2006-07-28 11:45:47 UTC (rev 2306)
@@ -139,7 +139,7 @@
 	return !strcmp(conf->protocol, running->protocol);
 }
 
-static int dev_eq(char* device_name, int g_major, int g_minor)
+static int dev_eq(char* device_name, unsigned int g_major, unsigned int g_minor)
 {
 	struct stat sb;
 	

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdadm_main.c	2006-07-28 11:45:47 UTC (rev 2306)
@@ -97,6 +97,7 @@
 static int sh_resources(struct d_resource* ,const char* );
 static int sh_mod_parms(struct d_resource* ,const char* );
 static int sh_dev(struct d_resource* ,const char* );
+static int sh_ip(struct d_resource* ,const char* );
 static int sh_ll_dev(struct d_resource* ,const char* );
 static int sh_md_dev(struct d_resource* ,const char* );
 static int sh_md_idx(struct d_resource* ,const char* );
@@ -115,6 +116,7 @@
 char *config_file = NULL;
 struct d_resource* config = NULL;
 struct d_resource* common = NULL;
+struct ifi_info *my_ifis = NULL;
 int nr_resources;
 int highest_minor;
 int config_valid=1;
@@ -183,13 +185,13 @@
 
 struct adm_cmd cmds[] = {
 /*   name, function,                  show, needs res, verify_ips */
-  { "attach",            adm_attach,    1,1,1 },
-  { "detach",            adm_generic_s, 1,1,1 },
+  { "attach",            adm_attach,    1,1,0 },
+  { "detach",            adm_generic_s, 1,1,0 },
   { "connect",           adm_connect,   1,1,1 },
   { "disconnect",        adm_generic_s, 1,1,0 },
   { "up",                adm_up,        1,1,1 },
   { "down",              adm_generic_s, 1,1,0 },
-  { "primary",           adm_generic_s, 1,1,1 },
+  { "primary",           adm_generic_s, 1,1,0 },
   { "secondary",         adm_generic_s, 1,1,1 },
   { "invalidate",        adm_generic_l, 1,1,1 },
   { "invalidate_remote", adm_generic_l, 1,1,1 },
@@ -217,6 +219,7 @@
   { "sh-ll-dev",         sh_ll_dev,     2,1,0 },
   { "sh-md-dev",         sh_md_dev,     2,1,0 },
   { "sh-md-idx",         sh_md_idx,     2,1,0 },
+  { "sh-ip",             sh_ip,         0,1,0 },
   { "pri-on-incon-degr", adm_khelper,   3,1,0 },
   { "pri-lost-after-sb", adm_khelper,   3,1,0 },
   { "outdate-peer",      adm_khelper,   3,1,0 },
@@ -356,6 +359,13 @@
   return 0;
 }
 
+static int sh_ip(struct d_resource* res,const char* unused __attribute((unused)))
+{
+  printf("%s\n",res->me->address);
+
+  return 0;
+}
+
 static int sh_ll_dev(struct d_resource* res,const char* unused __attribute((unused)))
 {
   printf("%s\n",res->me->disk);
@@ -417,6 +427,7 @@
   }
 }
 
+static void free_ifi_info(struct ifi_info *ifihead);
 static void free_config(struct d_resource* res)
 {
   struct d_resource *f,*t;
@@ -440,6 +451,7 @@
     free_options(common->handlers);
     free(common);
   }
+  if (my_ifis) free_ifi_info(my_ifis);
 }
 
 static void expand_opts(struct d_option* co, struct d_option** opts)
@@ -1278,28 +1290,28 @@
   return ifihead;
 }
 
-void verify_ips(struct d_resource* res)
+int have_ip(const char *ip)
 {
   struct ifi_info *ifi, *ifihead;
-  int family, valid = 0;
+  int family;
   uint32_t addr = 0;
   struct in_addr sin_addr;
-  const char *my_ip;
 
-  my_ip = res->me->address;
-  sin_addr.s_addr = inet_addr(my_ip);
+  sin_addr.s_addr = inet_addr(ip);
 
-  /* does DRBD support inet6? */
+  /* FIXME make DRBD support inet6 */
   family = AF_INET;
+  if (!my_ifis) my_ifis = get_ifi_info(family);
     
-  for (ifihead = ifi = get_ifi_info(family); ifi != NULL; ifi = ifi->ifi_next) {        
+  for (ifihead = ifi = my_ifis; ifi != NULL; ifi = ifi->ifi_next) {
     switch (family) {
     case AF_INET: {
       struct sockaddr_in * sin = (struct sockaddr_in *)ifi->ifi_addr;
       addr = sin->sin_addr.s_addr;
 
-      if (addr == sin_addr.s_addr) /* loop a few times needlessly */
-	valid = 1;
+      if (addr == sin_addr.s_addr) {
+	return 1;
+      }
       break;
     }
     default:
@@ -1307,15 +1319,26 @@
     }
   }
 
-  free_ifi_info(ifihead);
+  return 0;
+}
 
-  if (valid == 0) {
-    fprintf(stderr, "OOPS, the IP address %s isn't configure/up on your system!\n", my_ip);
-#if INVALID_IP_IS_INVALID_CONF
+void verify_ips(struct d_resource *res)
+{
+	if (global_options.disable_ip_verification) return;
+	if (dry_run == 1 || do_verify_ips == 0) return;
+
+	if (! have_ip(res->me->address)) {
+		ENTRY e, *ep;
+		e.key = e.data = ep = NULL;
+		asprintf(&e.key, "%s:%s", res->me->address, res->me->port);
+		ep = hsearch(e, FIND);
+		fprintf(stderr, "%s:%d: in resource %s, on %s:\n\t"
+			"IP %s not found on this host.\n",
+			config_file, (int)(long)ep->data, res->name,
+			res->me->name, res->me->address);
+		if (INVALID_IP_IS_INVALID_CONF)
     config_valid = 0;
-#endif
   }
-  return;
 }
 
 static char* conf_file[] = {

Modified: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdadm_parser.c	2006-07-28 11:45:47 UTC (rev 2306)
@@ -3,8 +3,9 @@
 
    This file is part of drbd by Philipp Reisner.
 
-   Copyright (C) 2006, Philipp Reisner <philipp.reisner@linbit.com>.
-        Initial author.
+   Copyright (C) 2006, Philipp Reisner <philipp.reisner@linbit.com>
+   Copyright (C) 2006, Lars Ellenberg  <lars.ellenberg@linbit.com>
+   Copyright (C) 2006, LINBIT Information Technologies GmbH
 
    drbd is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,6 +22,7 @@
    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
  */
+
 #define _GNU_SOURCE
 
 #include <stdlib.h>
@@ -205,7 +207,7 @@
 	int token; 						\
 	token = yylex(); 					\
 	if(token != TOKEN1)					\
-		pe_expected_got( #TOKEN1, token, yylval.txt); 	\
+		pe_expected_got( #TOKEN1, token);		\
 	token;							\
 })
 
@@ -214,26 +216,37 @@
 	int token; 							\
 	token = yylex(); 						\
 	if(token != TOKEN1 && token != TOKEN2) 				\
-		pe_expected_got( #TOKEN1 "|" # TOKEN2, token, yylval.txt ); \
+		pe_expected_got( #TOKEN1 "|" # TOKEN2, token);		\
 	token;								\
 })
 
-static void pe_expected(const char *exp, char* got_txt)
+static void pe_expected(const char *exp)
 {
-	fprintf(stderr,"Parse error '%s' expected,\n"
-		"but got '%s' at line %d\n",exp,got_txt,line);
-	exit(10);
+	fprintf(stderr,"%s:%u: Parse error: '%s' expected,\n\t"
+		"but got '%s'\n",config_file,line,exp,yytext);
+	exit(E_config_invalid);
 }
 
-static void pe_expected_got(const char *exp, int got, char* got_txt)
+static void pe_expected_got(const char *exp, int got)
 {
-	fprintf(stderr,"Parse error '%s' expected,\n"
-		"but got '%s' (TK %d) at line %d\n",
-		exp,got_txt,got,line);
-	exit(10);
+	static char tmp[2] = "\0";
+	if (exp[0] == '\'' && exp[1] && exp[2] == '\'' && exp[3] == 0) {
+		tmp[0] = exp[1];
+	}
+	fprintf(stderr,"%s:%u: Parse error: '%s' expected,\n\t"
+		"but got '%s' (TK %d)\n",config_file,line,exp,yytext,got);
+	exit(E_config_invalid);
 }
 
 static void parse_global(void) {
+	fline = line;
+	check_uniq("global section","global");
+	if (config) {
+		fprintf(stderr,
+			"%s:%u: You should put the global {} section\n\t"
+			"in front of any resource {} section\n",
+			config_file,line);
+	}
 	EXP('{');
 	while(1) {
 		switch(yylex()) {
@@ -255,14 +268,14 @@
 			case TK_YES: global_options.usage_count=UC_YES; break; 
 			case TK_NO:  global_options.usage_count=UC_NO;  break; 
 			case TK_ASK: global_options.usage_count=UC_ASK; break; 
-			default:     pe_expected("yes | no | ask",yylval.txt);
+			default:     pe_expected("yes | no | ask");
 			}
 			break;
 		case '}':
 			return;
 		default:
 			pe_expected("dialog-refresh | minor-count | "
-				    "disable-ip-verification",yylval.txt);
+				    "disable-ip-verification");
 		}
 		EXP(';');
 	}
@@ -275,6 +288,7 @@
 	enum range_checks rc;
 
 	struct d_option* options = NULL, *ro = NULL;
+	fline = line;
 
 	EXP('{');
 	while(1) {
@@ -291,7 +305,7 @@
 		} else if ( token == '}' ) {
 			return options;
 		} else {
-			pe_expected("an option keyword",yylval.txt);
+			pe_expected("an option keyword");
 		}
 		switch(yylex()) {
 		case TK__IS_DEFAULT:
@@ -301,7 +315,7 @@
 		case ';':
 			break;
 		default:
-			pe_expected("_is_default | ;",yylval.txt);
+			pe_expected("_is_default | ;");
 		}
 	}
 }
@@ -314,6 +328,7 @@
 	while(1) {
 		switch(yylex()) {
 		case TK_DISK:
+			check_uniq("disk statement","%s:%s:disk",res->name,host->name);
 			EXP(TK_STRING);
 			host->disk = yylval.txt;
 			check_uniq("disk", "%s:%s:%s","disk",
@@ -329,10 +344,11 @@
 			case ';':
 				break;
 			default:
-				pe_expected("_major | ;",yylval.txt);
+				pe_expected("_major | ;");
 			}
 			break;
 		case TK_DEVICE:
+			check_uniq("device statement","%s:%s:device",res->name,host->name);
 			EXP(TK_STRING);
 			host->device = yylval.txt;
 			check_uniq("device", "%s:%s:%s","device",
@@ -340,15 +356,18 @@
 			EXP(';');
 			break;
 		case TK_ADDRESS:
+			check_uniq("address statement","%s:%s:address",res->name,host->name);
 			EXP(TK_IPADDR);
 			host->address = yylval.txt;
 			EXP(':');
 			EXP(TK_INTEGER);
 			host->port = yylval.txt;
 			range_check(R_PORT, "port", yylval.txt);
+			check_uniq("IP","%s:%s", host->address,host->port);
 			EXP(';');
 			break;
 		case TK_META_DISK:
+			check_uniq("meta-disk statement","%s:%s:meta-disk",res->name,host->name);
 			EXP(TK_STRING);
 			host->meta_disk = yylval.txt;
 			if(strcmp("internal",yylval.txt)) {
@@ -367,7 +386,7 @@
 				case ';':
 					break;
 				default:
-					pe_expected("_major | ;",yylval.txt);
+					pe_expected("_major | ;");
 				}
 			} else {
 				EXP(';');
@@ -375,6 +394,7 @@
 			check_meta_disk(host);
 			break;
 		case TK_FLEX_META_DISK:
+			check_uniq("meta-disk statement","%s:%s:meta-disk",res->name,host->name);
 			EXP(TK_STRING);
 			host->meta_disk = yylval.txt;
 			host->meta_index = strdup("flexible");
@@ -385,7 +405,7 @@
 			goto break_loop;
 		default:
 			pe_expected("disk | device | address | meta-disk "
-				    "| flex-meta-disk",yylval.txt);
+				    "| flex-meta-disk");
 		}
 	}
  break_loop:
@@ -396,16 +416,55 @@
 	if (!host->meta_disk)	derror(host,res,"meta-disk");
 }
 
+void parse_skip()
+{
+	int level;
+	fline = line;
+
+	switch (yylex()) {
+		case TK_STRING:
+			EXP('{');
+			break;
+		case '{':
+			break;
+		default:
+			pe_expected("[ some_text ] {");
+	}
+
+	level = 1;
+	while(level) {
+		switch(yylex()) {
+		case '{':
+			level++; /* if you really want to,
+				    you can wrap this with a GB size config file :) */
+			break;
+		case '}':
+			level--;
+			break;
+		case 0:
+			fprintf(stderr,"%s:%u: reached eof "
+				"while parsing this skip block.\n",
+				config_file, fline);
+			exit(E_config_invalid);
+		}
+	} while(level);
+}
+
+
 static void parse_host_section(struct d_resource* res)
 {
 	struct d_host_info *host;
 
 	c_section_start = line;
+	fline = line;
 
 	host=calloc(1,sizeof(struct d_host_info));
 	EXP(TK_STRING);
 	host->name = yylval.txt;
+
+	check_uniq("host section", "%s: on %s", res->name, host->name);
 	if(strcmp(host->name, nodeinfo.nodename) == 0) {
+		// if (res->me) die duplicate entry ... done by check_uniq above
 		res->me = host;
 	} else {
 		if (res->peer) {
@@ -444,6 +503,8 @@
 	struct d_resource* res;
 	int token;
 
+	fline = line;
+
 	res=calloc(1,sizeof(struct d_resource));
 	res->name = res_name;
 	res->next = NULL;
@@ -451,6 +512,7 @@
 	while(1) {
 		switch((token=yylex())) {
 		case TK_PROTOCOL:
+			check_uniq("protocol statement","%s: protocol",res->name);
 			EXP(TK_STRING);
 			res->protocol=yylval.txt;
 			EXP(';');
@@ -465,50 +527,39 @@
 			parse_drbdsetup_host_dump(res, 0);
 			break;
 		case TK_DISK:
+			check_uniq("disk section", "%s:disk", res->name);
 			res->disk_options = parse_options(TK_DISK_SWITCH,
 							  TK_DISK_OPTION);
 			break;
 		case TK_NET: 
+			check_uniq("net section", "%s:net", res->name);
 			res->net_options = parse_options(TK_NET_SWITCH,
 							 TK_NET_OPTION);
 			break;
 		case TK_SYNCER:
+			check_uniq("syncer section", "%s:syncer", res->name);
 			res->sync_options = parse_options(TK_SYNCER_SWITCH,
 							  TK_SYNCER_OPTION);
 			break;
 		case TK_STARTUP:
+			check_uniq("startup section", "%s:startup", res->name);
 			res->startup_options=parse_options(TK_STARTUP_SWITCH,
 							   TK_STARTUP_OPTION);
 			break;
 		case TK_HANDLER:
-			res->handlers =  parse_options(0,
-						       TK_HANDLER_OPTION);
+			check_uniq("handlers section", "%s:handlers", res->name);
+			res->handlers =  parse_options(0, TK_HANDLER_OPTION);
 			break;
 		case '}': 
 		case 0:	
 			return res;
 		default:
 			pe_expected_got("protocol | on | disk | net | syncer |"
-					" startup | handler",token,yylval.txt);
+					" startup | handler",token);
 		}
 	}
 }
 
-void parse_skip()
-{
-	int level=0;
-	do {
-		switch(yylex()) {
-		case '{': 
-			level++;
-			break;
-		case '}': 
-			level--;
-			break;
-		}
-	} while(level);
-}
-
 void yyparse(void)
 {
 	common = NULL;
@@ -516,7 +567,9 @@
 
 	while(1) {
 		switch(yylex()) {
-		case TK_GLOBAL: parse_global(); break;
+		case TK_GLOBAL:
+			parse_global();
+			break;
 		case TK_COMMON: 
 			EXP('{');
 			common = parse_resource("common"); 
@@ -529,8 +582,7 @@
 		case TK_SKIP: parse_skip(); break;
 		case 0: return;
 		default:
-			pe_expected("global | common | resource | skip",
-				    yylval.txt);
+			pe_expected("global | common | resource | skip");
 		}
 	}
 }

Modified: trunk/user/drbdadm_parser.h
===================================================================
--- trunk/user/drbdadm_parser.h	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdadm_parser.h	2006-07-28 11:45:47 UTC (rev 2306)
@@ -101,6 +101,7 @@
 #define YYSTYPE_IS_TRIVIAL 1
 
 extern yystype yylval;
+extern char* yytext;
 
 /* avoid compiler warnings about implicit declaration */
 int yylex(void);

Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdadm_scanner.fl	2006-07-28 11:45:47 UTC (rev 2306)
@@ -20,8 +20,6 @@
 #define YY_NO_UNPUT 1
 static void yyunput (int c, register char * yy_bp ) __attribute((unused));
 
-int skip_level=0;
-
 %}
 
 %option noyywrap
@@ -35,12 +33,10 @@
 STRING		[a-zA-Z0-9/._-]{1,80}
 LONG_STRING	[a-zA-Z0-9/._-]{81}
 
-%x in_string id skip
-
 %%
 
 \n			{ line++; 				}
-#[^\n]*			/* ignore comments */
+\#.*			/* ignore comments */
 {WS}			/* ignore whitespaces */
 {OPCHAR}		{ DP; return yytext[0];			}
 on			{ DP; return TK_ON;			}
@@ -101,7 +97,7 @@
 {DQSTRING}		{ unescape(); DP; CP; return TK_STRING;	}
 {STRING}		{ DP; CP; return TK_STRING;		}
 {LONG_STRING}		{ long_string( yylval.txt ); 		}
-[^\n]			{ DP; return TK_ELSE;			}
+.			{ DP; return TK_ELSE;			}
 
 %%
 

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdmeta.c	2006-07-28 11:45:47 UTC (rev 2306)
@@ -1067,9 +1067,9 @@
 	return 0;
 }
 
-int m_strsep_bit(char **s, int *val, int mask)
+int m_strsep_bit(char **s, u32 *val, int mask)
 {
-	int d;
+	u32 d;
 	int rv;
 
 	d = *val & mask ? 1 : 0;

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2006-07-28 10:41:09 UTC (rev 2305)
+++ trunk/user/drbdsetup.c	2006-07-28 11:45:47 UTC (rev 2306)
@@ -1247,7 +1247,7 @@
   return 0;
 }
 
-const char* guess_dev_name(const char* dir,int g_major,int g_minor)
+const char* guess_dev_name(const char* dir,unsigned int g_major,unsigned int g_minor)
 {
   DIR* device_dir;
   struct dirent* dde;

From drbd-cvs at lists.linbit.com  Fri Jul 28 15:33:14 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Fri Jul 28 15:33:18 2006
Subject: [DRBD-cvs] svn commit by lars - r2307 - trunk/user - * renamed
	yyparse to my_parse * piped drbdadm_parser.c 
Message-ID: <20060728133314.64C142D99842@mail.linbit.com>

Author: lars
Date: 2006-07-28 15:33:13 +0200 (Fri, 28 Jul 2006)
New Revision: 2307

Modified:
   trunk/user/drbdadm_main.c
   trunk/user/drbdadm_parser.c
Log:
* renamed yyparse to my_parse 
* piped drbdadm_parser.c through Lindent
  (only whitespace changes)



Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-07-28 11:45:47 UTC (rev 2306)
+++ trunk/user/drbdadm_main.c	2006-07-28 13:33:13 UTC (rev 2307)
@@ -78,7 +78,7 @@
   struct deferred_cmd* next;
 };
 
-extern int yyparse();
+extern int my_parse();
 extern int yydebug;
 extern FILE* yyin;
 
@@ -1641,7 +1641,7 @@
   };
 
   //yydebug = 1;
-  yyparse();
+  my_parse();
 
   if(!config_valid) exit(E_config_invalid);
 

Modified: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c	2006-07-28 11:45:47 UTC (rev 2306)
+++ trunk/user/drbdadm_parser.c	2006-07-28 13:33:13 UTC (rev 2307)
@@ -51,161 +51,155 @@
   _l;					      \
 })
 
-static int   c_section_start;
+static int c_section_start;
 
-void
-m_strtoll_range(const char *s, char def_unit,
-		const char *name,
-		unsigned long long min, unsigned long long max)
+void m_strtoll_range(const char *s, char def_unit,
+		     const char *name,
+		     unsigned long long min, unsigned long long max)
 {
-  unsigned long long r = m_strtoll(s, def_unit);
-  char unit[] = { def_unit > '1' ? def_unit : 0, 0 };
-  if (min > r || r > max)
-    {
-      fprintf(stderr,
-	      "%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n",
-	      config_file, fline, name, s, r, unit, min, max, unit);
-      exit(E_config_invalid);
-    }
-  if (DEBUG_RANGE_CHECK)
-    {
-      fprintf(stderr,
-	      "%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n",
-	      config_file, fline, name, s, r, unit, min, max, unit);
-    }
+	unsigned long long r = m_strtoll(s, def_unit);
+	char unit[] = { def_unit > '1' ? def_unit : 0, 0 };
+	if (min > r || r > max) {
+		fprintf(stderr,
+			"%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n",
+			config_file, fline, name, s, r, unit, min, max, unit);
+		exit(E_config_invalid);
+	}
+	if (DEBUG_RANGE_CHECK) {
+		fprintf(stderr,
+			"%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n",
+			config_file, fline, name, s, r, unit, min, max, unit);
+	}
 }
 
-
-void
-range_check(const enum range_checks what, const char *name, const char *value)
+void range_check(const enum range_checks what, const char *name,
+		 const char *value)
 {
-  switch (what)
-    {
-    case R_NO_CHECK: 
-      break;
-    default:
-      fprintf(stderr, "%s:%d: unknown range for %s => %s\n",
-	      config_file, fline, name, value);
-      break;
-    case R_MINOR_COUNT:
-      m_strtoll_range(value, 1, name,
-		      DRBD_MINOR_COUNT_MIN, DRBD_MINOR_COUNT_MAX);
-      break;
-    case R_DIALOG_REFRESH:
-      m_strtoll_range(value, 1, name,
-		      DRBD_DIALOG_REFRESH_MIN, DRBD_DIALOG_REFRESH_MAX);
-      break;
-    case R_DISK_SIZE:
-      m_strtoll_range(value, 'K', name,
-		      DRBD_DISK_SIZE_SECT_MIN >> 1,
-		      DRBD_DISK_SIZE_SECT_MAX >> 1);
-      break;
-    case R_TIMEOUT:
-      m_strtoll_range(value, 1, name, DRBD_TIMEOUT_MIN, DRBD_TIMEOUT_MAX);
-      break;
-    case R_CONNECT_INT:
-      m_strtoll_range(value, 1, name, DRBD_CONNECT_INT_MIN,
-		      DRBD_CONNECT_INT_MAX);
-      break;
-    case R_PING_INT:
-      m_strtoll_range(value, 1, name, DRBD_PING_INT_MIN, DRBD_PING_INT_MAX);
-      break;
-    case R_MAX_BUFFERS:
-      m_strtoll_range(value, 1, name, DRBD_MAX_BUFFERS_MIN,
-		      DRBD_MAX_BUFFERS_MAX);
-      break;
-    case R_MAX_EPOCH_SIZE:
-      m_strtoll_range(value, 1, name, DRBD_MAX_EPOCH_SIZE_MIN,
-		      DRBD_MAX_EPOCH_SIZE_MAX);
-      break;
-    case R_SNDBUF_SIZE:
-      m_strtoll_range(value, 1, name, DRBD_SNDBUF_SIZE_MIN,
-		      DRBD_SNDBUF_SIZE_MAX);
-      break;
-    case R_KO_COUNT:
-      m_strtoll_range(value, 1, name, DRBD_KO_COUNT_MIN, DRBD_KO_COUNT_MAX);
-      break;
-    case R_RATE:
-      m_strtoll_range(value, 'K', name, DRBD_RATE_MIN, DRBD_RATE_MAX);
-      break;
-    case R_AL_EXTENTS:
-      m_strtoll_range(value, 1, name, DRBD_AL_EXTENTS_MIN,
-		      DRBD_AL_EXTENTS_MAX);
-      break;
-    case R_PORT:
-      m_strtoll_range(value, 1, name, DRBD_PORT_MIN, DRBD_PORT_MAX);
-      break;
-      /* FIXME not yet implemented!
-         case R_META_IDX:
-         m_strtoll_range(value, 1, name, DRBD_META_IDX_MIN, DRBD_META_IDX_MAX);
-         break;
-       */
-    case R_WFC_TIMEOUT:
-      m_strtoll_range(value, 1, name, DRBD_WFC_TIMEOUT_MIN,
-		      DRBD_WFC_TIMEOUT_MAX);
-      break;
-    case R_DEGR_WFC_TIMEOUT:
-      m_strtoll_range(value, 1, name, DRBD_DEGR_WFC_TIMEOUT_MIN,
-		      DRBD_DEGR_WFC_TIMEOUT_MAX);
-      break;
-    }
+	switch (what) {
+	case R_NO_CHECK:
+		break;
+	default:
+		fprintf(stderr, "%s:%d: unknown range for %s => %s\n",
+			config_file, fline, name, value);
+		break;
+	case R_MINOR_COUNT:
+		m_strtoll_range(value, 1, name,
+				DRBD_MINOR_COUNT_MIN, DRBD_MINOR_COUNT_MAX);
+		break;
+	case R_DIALOG_REFRESH:
+		m_strtoll_range(value, 1, name,
+				DRBD_DIALOG_REFRESH_MIN,
+				DRBD_DIALOG_REFRESH_MAX);
+		break;
+	case R_DISK_SIZE:
+		m_strtoll_range(value, 'K', name,
+				DRBD_DISK_SIZE_SECT_MIN >> 1,
+				DRBD_DISK_SIZE_SECT_MAX >> 1);
+		break;
+	case R_TIMEOUT:
+		m_strtoll_range(value, 1, name, DRBD_TIMEOUT_MIN,
+				DRBD_TIMEOUT_MAX);
+		break;
+	case R_CONNECT_INT:
+		m_strtoll_range(value, 1, name, DRBD_CONNECT_INT_MIN,
+				DRBD_CONNECT_INT_MAX);
+		break;
+	case R_PING_INT:
+		m_strtoll_range(value, 1, name, DRBD_PING_INT_MIN,
+				DRBD_PING_INT_MAX);
+		break;
+	case R_MAX_BUFFERS:
+		m_strtoll_range(value, 1, name, DRBD_MAX_BUFFERS_MIN,
+				DRBD_MAX_BUFFERS_MAX);
+		break;
+	case R_MAX_EPOCH_SIZE:
+		m_strtoll_range(value, 1, name, DRBD_MAX_EPOCH_SIZE_MIN,
+				DRBD_MAX_EPOCH_SIZE_MAX);
+		break;
+	case R_SNDBUF_SIZE:
+		m_strtoll_range(value, 1, name, DRBD_SNDBUF_SIZE_MIN,
+				DRBD_SNDBUF_SIZE_MAX);
+		break;
+	case R_KO_COUNT:
+		m_strtoll_range(value, 1, name, DRBD_KO_COUNT_MIN,
+				DRBD_KO_COUNT_MAX);
+		break;
+	case R_RATE:
+		m_strtoll_range(value, 'K', name, DRBD_RATE_MIN, DRBD_RATE_MAX);
+		break;
+	case R_AL_EXTENTS:
+		m_strtoll_range(value, 1, name, DRBD_AL_EXTENTS_MIN,
+				DRBD_AL_EXTENTS_MAX);
+		break;
+	case R_PORT:
+		m_strtoll_range(value, 1, name, DRBD_PORT_MIN, DRBD_PORT_MAX);
+		break;
+		/* FIXME not yet implemented!
+		   case R_META_IDX:
+		   m_strtoll_range(value, 1, name, DRBD_META_IDX_MIN, DRBD_META_IDX_MAX);
+		   break;
+		 */
+	case R_WFC_TIMEOUT:
+		m_strtoll_range(value, 1, name, DRBD_WFC_TIMEOUT_MIN,
+				DRBD_WFC_TIMEOUT_MAX);
+		break;
+	case R_DEGR_WFC_TIMEOUT:
+		m_strtoll_range(value, 1, name, DRBD_DEGR_WFC_TIMEOUT_MIN,
+				DRBD_DEGR_WFC_TIMEOUT_MAX);
+		break;
+	}
 }
 
-static struct d_option* new_opt(char* name,char* value)
+static struct d_option *new_opt(char *name, char *value)
 {
-	struct d_option* cn = malloc(sizeof(struct d_option));
+	struct d_option *cn = malloc(sizeof(struct d_option));
 
 	/* fprintf(stderr,"%s:%d: %s = %s\n",config_file,line,name,value); */
-	cn->name=name;
-	cn->value=value;
-	cn->mentioned=0;
-	cn->is_default=0;
+	cn->name = name;
+	cn->value = value;
+	cn->mentioned = 0;
+	cn->is_default = 0;
 
 	return cn;
 }
-
-static void derror(struct d_host_info *host,
-		   struct d_resource* res,
-		   char* text)
+static void derror(struct d_host_info *host, struct d_resource *res, char *text)
 {
-	config_valid=0;
+	config_valid = 0;
 	fprintf(stderr, "%s:%d: in resource %s, on %s { ... }:"
 		" '%s' keyword missing.\n",
-		config_file,c_section_start,res->name,host->name,text);
+		config_file, c_section_start, res->name, host->name, text);
 }
 
 void check_meta_disk(struct d_host_info *host)
 {
-  if (strcmp(host->meta_disk, "internal") != 0) {
-    /* external */
-    if (host->meta_index == NULL) {
-      fprintf(stderr, "%s:%d: expected 'meta-disk = %s [index]'.\n",
-	      config_file, fline, host->meta_disk);
-    }
-    /* index either some number, or "flexible" */
-    check_uniq("meta-disk", "%s:%s[%s]", host->name,
-	       host->meta_disk, host->meta_index);
-  } else if (host->meta_index) {
-    /* internal */
-    if (strcmp(host->meta_index,"flexible") != 0) {
-      /* internal, not flexible, but index given: no sir! */
-      fprintf(stderr,
-	      "%s:%d: no index allowed with 'meta-disk = internal'.\n",
-	      config_file, fline);
-    } /* else internal, flexible: fine */
-  } else {
-    /* internal, not flexible */
-    host->meta_index = strdup("internal");
-  }
+	if (strcmp(host->meta_disk, "internal") != 0) {
+		/* external */
+		if (host->meta_index == NULL) {
+			fprintf(stderr,
+				"%s:%d: expected 'meta-disk = %s [index]'.\n",
+				config_file, fline, host->meta_disk);
+		}
+		/* index either some number, or "flexible" */
+		check_uniq("meta-disk", "%s:%s[%s]", host->name,
+			   host->meta_disk, host->meta_index);
+	} else if (host->meta_index) {
+		/* internal */
+		if (strcmp(host->meta_index, "flexible") != 0) {
+			/* internal, not flexible, but index given: no sir! */
+			fprintf(stderr,
+				"%s:%d: no index allowed with 'meta-disk = internal'.\n",
+				config_file, fline);
+		}		/* else internal, flexible: fine */
+	} else {
+		/* internal, not flexible */
+		host->meta_index = strdup("internal");
+	}
 }
 
-///////////////////////////
-
-
 #define EXP(TOKEN1)						\
 ({ 								\
-	int token; 						\
-	token = yylex(); 					\
+	int token;						\
+	token = yylex();					\
 	if(token != TOKEN1)					\
 		pe_expected_got( #TOKEN1, token);		\
 	token;							\
@@ -213,17 +207,17 @@
 
 #define EXP2(TOKEN1,TOKEN2)						\
 ({ 									\
-	int token; 							\
-	token = yylex(); 						\
-	if(token != TOKEN1 && token != TOKEN2) 				\
+	int token;							\
+	token = yylex();						\
+	if(token != TOKEN1 && token != TOKEN2)				\
 		pe_expected_got( #TOKEN1 "|" # TOKEN2, token);		\
 	token;								\
 })
 
 static void pe_expected(const char *exp)
 {
-	fprintf(stderr,"%s:%u: Parse error: '%s' expected,\n\t"
-		"but got '%s'\n",config_file,line,exp,yytext);
+	fprintf(stderr, "%s:%u: Parse error: '%s' expected,\n\t"
+		"but got '%s'\n", config_file, line, exp, yytext);
 	exit(E_config_invalid);
 }
 
@@ -233,42 +227,51 @@
 	if (exp[0] == '\'' && exp[1] && exp[2] == '\'' && exp[3] == 0) {
 		tmp[0] = exp[1];
 	}
-	fprintf(stderr,"%s:%u: Parse error: '%s' expected,\n\t"
-		"but got '%s' (TK %d)\n",config_file,line,exp,yytext,got);
+	fprintf(stderr, "%s:%u: Parse error: '%s' expected,\n\t"
+		"but got '%s' (TK %d)\n", config_file, line, exp, yytext, got);
 	exit(E_config_invalid);
 }
 
-static void parse_global(void) {
+static void parse_global(void)
+{
 	fline = line;
-	check_uniq("global section","global");
+	check_uniq("global section", "global");
 	if (config) {
 		fprintf(stderr,
 			"%s:%u: You should put the global {} section\n\t"
 			"in front of any resource {} section\n",
-			config_file,line);
+			config_file, line);
 	}
 	EXP('{');
-	while(1) {
-		switch(yylex()) {
+	while (1) {
+		switch (yylex()) {
 		case TK_DISABLE_IP_VERIFICATION:
-			global_options.disable_ip_verification=1;
+			global_options.disable_ip_verification = 1;
 			break;
 		case TK_MINOR_COUNT:
 			EXP(TK_INTEGER);
-			range_check(R_MINOR_COUNT,"minor-count",yylval.txt);
-			global_options.minor_count=atoi(yylval.txt);
+			range_check(R_MINOR_COUNT, "minor-count", yylval.txt);
+			global_options.minor_count = atoi(yylval.txt);
 			break;
 		case TK_DIALOG_REFRESH:
 			EXP(TK_INTEGER);
-			range_check(R_DIALOG_REFRESH,"dialog-refresh",yylval.txt);
-			global_options.dialog_refresh=atoi(yylval.txt);
+			range_check(R_DIALOG_REFRESH, "dialog-refresh",
+				    yylval.txt);
+			global_options.dialog_refresh = atoi(yylval.txt);
 			break;
 		case TK_USAGE_COUNT:
-			switch(yylex()) {
-			case TK_YES: global_options.usage_count=UC_YES; break; 
-			case TK_NO:  global_options.usage_count=UC_NO;  break; 
-			case TK_ASK: global_options.usage_count=UC_ASK; break; 
-			default:     pe_expected("yes | no | ask");
+			switch (yylex()) {
+			case TK_YES:
+				global_options.usage_count = UC_YES;
+				break;
+			case TK_NO:
+				global_options.usage_count = UC_NO;
+				break;
+			case TK_ASK:
+				global_options.usage_count = UC_ASK;
+				break;
+			default:
+				pe_expected("yes | no | ask");
 			}
 			break;
 		case '}':
@@ -281,35 +284,35 @@
 	}
 }
 
-static struct d_option* parse_options(int token_switch,int token_option)
+static struct d_option *parse_options(int token_switch, int token_option)
 {
 	char *opt_name;
 	int token;
 	enum range_checks rc;
 
-	struct d_option* options = NULL, *ro = NULL;
+	struct d_option *options = NULL, *ro = NULL;
 	fline = line;
 
 	EXP('{');
-	while(1) {
+	while (1) {
 		token = yylex();
-		if( token == token_switch) {
-			options = APPEND(options,new_opt(yylval.txt,NULL));
-		} else if ( token == token_option) {
+		if (token == token_switch) {
+			options = APPEND(options, new_opt(yylval.txt, NULL));
+		} else if (token == token_option) {
 			opt_name = yylval.txt;
 			rc = yylval.rc;
-			EXP2(TK_STRING,TK_INTEGER);
-			range_check(rc,opt_name,yylval.txt);
-			ro = new_opt(opt_name,yylval.txt);
-			options = APPEND(options,ro);
-		} else if ( token == '}' ) {
+			EXP2(TK_STRING, TK_INTEGER);
+			range_check(rc, 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");
 		}
-		switch(yylex()) {
+		switch (yylex()) {
 		case TK__IS_DEFAULT:
-			ro->is_default=1;
+			ro->is_default = 1;
 			EXP(';');
 			break;
 		case ';':
@@ -320,20 +323,20 @@
 	}
 }
 
-static void parse_host_body(struct d_host_info *host, 
-			    struct d_resource* res,
-			    int require_all) 
+static void parse_host_body(struct d_host_info *host,
+			    struct d_resource *res, int require_all)
 {
 	EXP('{');
-	while(1) {
-		switch(yylex()) {
+	while (1) {
+		switch (yylex()) {
 		case TK_DISK:
-			check_uniq("disk statement","%s:%s:disk",res->name,host->name);
+			check_uniq("disk statement", "%s:%s:disk", res->name,
+				   host->name);
 			EXP(TK_STRING);
 			host->disk = yylval.txt;
-			check_uniq("disk", "%s:%s:%s","disk",
-				   host->name,yylval.txt);
-			switch(yylex()) {
+			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);
@@ -348,34 +351,37 @@
 			}
 			break;
 		case TK_DEVICE:
-			check_uniq("device statement","%s:%s:device",res->name,host->name);
+			check_uniq("device statement", "%s:%s:device",
+				   res->name, host->name);
 			EXP(TK_STRING);
 			host->device = yylval.txt;
-			check_uniq("device", "%s:%s:%s","device",
-				   host->name,yylval.txt);
+			check_uniq("device", "%s:%s:%s", "device",
+				   host->name, yylval.txt);
 			EXP(';');
 			break;
 		case TK_ADDRESS:
-			check_uniq("address statement","%s:%s:address",res->name,host->name);
+			check_uniq("address statement", "%s:%s:address",
+				   res->name, host->name);
 			EXP(TK_IPADDR);
 			host->address = yylval.txt;
 			EXP(':');
 			EXP(TK_INTEGER);
 			host->port = yylval.txt;
 			range_check(R_PORT, "port", yylval.txt);
-			check_uniq("IP","%s:%s", host->address,host->port);
+			check_uniq("IP", "%s:%s", host->address, host->port);
 			EXP(';');
 			break;
 		case TK_META_DISK:
-			check_uniq("meta-disk statement","%s:%s:meta-disk",res->name,host->name);
+			check_uniq("meta-disk statement", "%s:%s:meta-disk",
+				   res->name, host->name);
 			EXP(TK_STRING);
 			host->meta_disk = yylval.txt;
-			if(strcmp("internal",yylval.txt)) {
+			if (strcmp("internal", yylval.txt)) {
 				EXP('[');
 				EXP(TK_INTEGER);
 				host->meta_index = yylval.txt;
 				EXP(']');
-				switch(yylex()) {
+				switch (yylex()) {
 				case TK__MAJOR:
 					EXP(TK_INTEGER);
 					host->meta_major = atoi(yylval.txt);
@@ -394,7 +400,8 @@
 			check_meta_disk(host);
 			break;
 		case TK_FLEX_META_DISK:
-			check_uniq("meta-disk statement","%s:%s:meta-disk",res->name,host->name);
+			check_uniq("meta-disk statement", "%s:%s:meta-disk",
+				   res->name, host->name);
 			EXP(TK_STRING);
 			host->meta_disk = yylval.txt;
 			host->meta_index = strdup("flexible");
@@ -408,12 +415,17 @@
 				    "| flex-meta-disk");
 		}
 	}
- 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");
+      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");
 }
 
 void parse_skip()
@@ -422,32 +434,34 @@
 	fline = line;
 
 	switch (yylex()) {
-		case TK_STRING:
-			EXP('{');
-			break;
-		case '{':
-			break;
-		default:
-			pe_expected("[ some_text ] {");
+	case TK_STRING:
+		EXP('{');
+		break;
+	case '{':
+		break;
+	default:
+		pe_expected("[ some_text ] {");
 	}
 
 	level = 1;
-	while(level) {
-		switch(yylex()) {
+	while (level) {
+		switch (yylex()) {
 		case '{':
-			level++; /* if you really want to,
-				    you can wrap this with a GB size config file :) */
+			/* if you really want to,
+			   you can wrap this with a GB size config file :) */
+			level++;
 			break;
 		case '}':
 			level--;
 			break;
 		case 0:
-			fprintf(stderr,"%s:%u: reached eof "
+			fprintf(stderr, "%s:%u: reached eof "
 				"while parsing this skip block.\n",
 				config_file, fline);
 			exit(E_config_invalid);
 		}
-	} while(level);
+	}
+	while (level) ;
 }
 
 
@@ -560,27 +574,30 @@
 	}
 }
 
-void yyparse(void)
+void my_parse(void)
 {
 	common = NULL;
 	config = NULL;
 
-	while(1) {
-		switch(yylex()) {
+	while (1) {
+		switch (yylex()) {
 		case TK_GLOBAL:
 			parse_global();
 			break;
-		case TK_COMMON: 
+		case TK_COMMON:
 			EXP('{');
-			common = parse_resource("common"); 
+			common = parse_resource("common");
 			break;
-		case TK_RESOURCE: 
+		case TK_RESOURCE:
 			EXP(TK_STRING);
 			EXP('{');
-			config = APPEND( config , parse_resource(yylval.txt) );
+			config = APPEND(config, parse_resource(yylval.txt));
 			break;
-		case TK_SKIP: parse_skip(); break;
-		case 0: return;
+		case TK_SKIP:
+			parse_skip();
+			break;
+		case 0:
+			return;
 		default:
 			pe_expected("global | common | resource | skip");
 		}

From drbd-cvs at lists.linbit.com  Mon Jul 31 11:33:30 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 31 11:33:31 2006
Subject: [DRBD-cvs] svn commit by phil - r2308 - trunk/drbd - Now tl_clear()
	never exposes mdev->oldest_barrier == 0 
Message-ID: <20060731093330.2B0B42CE6AAB@mail.linbit.com>

Author: phil
Date: 2006-07-31 11:33:28 +0200 (Mon, 31 Jul 2006)
New Revision: 2308

Modified:
   trunk/drbd/drbd_main.c
Log:
Now tl_clear() never exposes 
mdev->oldest_barrier == 0 or
mdev->newerst_barrier == 0
.


Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-28 13:33:13 UTC (rev 2307)
+++ trunk/drbd/drbd_main.c	2006-07-31 09:33:28 UTC (rev 2308)
@@ -341,66 +341,70 @@
 	return r;
 }
 
-void tl_clear(drbd_dev *mdev)
+STATIC void tl_clear_barrier(drbd_dev *mdev, struct list_head *requests)
 {
-	struct list_head *le,*tle;
-	struct drbd_barrier *b,*f;
+	struct list_head *le, *tle;
 	struct drbd_request *r;
 	sector_t sector;
 	unsigned int size;
 
+	list_for_each_safe(le, tle, requests) {
+		r = list_entry(le, struct drbd_request,tl_requests);
+		// bi_size and bi_sector are modified in bio_endio!
+		sector = drbd_req_get_sector(r);
+		size   = drbd_req_get_size(r);
+		
+		if( r->rq_status & RQ_DRBD_ON_WIRE &&
+		    mdev->net_conf->wire_protocol != DRBD_PROT_A ) {
+			dec_ap_pending(mdev);
+		}
+		
+		if( !(r->rq_status & RQ_DRBD_SENT) ) {
+			drbd_end_req(r,RQ_DRBD_SENT,ERF_NOTLD|1, sector);
+			goto mark;
+		}
+		if(mdev->net_conf->wire_protocol != DRBD_PROT_C ) {
+		mark:
+			drbd_set_out_of_sync(mdev, sector, size);
+		}
+	}
+}
+
+void tl_clear(drbd_dev *mdev)
+{
+	struct list_head tmp;
+	struct drbd_barrier *b,*f;
+
 	WARN("tl_clear()\n");
+	INIT_LIST_HEAD(&tmp);
 
 	spin_lock_irq(&mdev->tl_lock);
 
-	b=mdev->oldest_barrier;
-	mdev->oldest_barrier = NULL;
-	mdev->newest_barrier = NULL; 
+	f = mdev->oldest_barrier;
+	b = f->next;
 
+	// mdev->oldest_barrier = f;
+	mdev->newest_barrier = f;
+
+	list_add(&tmp,&f->requests);
+	list_del_init(&f->requests);
+
+	f->next=NULL;
+	f->br_number=4711;
+	f->n_req=0;
+
 	spin_unlock_irq(&mdev->tl_lock);
 
-	while ( 1 ) {
-		list_for_each_safe(le, tle, &b->requests) {
-			r = list_entry(le, struct drbd_request,tl_requests);
-			// bi_size and bi_sector are modified in bio_endio!
-			sector = drbd_req_get_sector(r);
-			size   = drbd_req_get_size(r);
-			
-			if( r->rq_status & RQ_DRBD_ON_WIRE &&
-			    mdev->net_conf->wire_protocol != DRBD_PROT_A ) {
-				dec_ap_pending(mdev);
-			}
+	tl_clear_barrier(mdev,&tmp);
 
-			if( !(r->rq_status & RQ_DRBD_SENT) ) {
-				drbd_end_req(r,RQ_DRBD_SENT,ERF_NOTLD|1, sector);
-				goto mark;
-			}
-			if(mdev->net_conf->wire_protocol != DRBD_PROT_C ) {
-			mark:
-				drbd_set_out_of_sync(mdev, sector, size);
-			}
-		}
+	while ( b ) {
+		tl_clear_barrier(mdev,&b->requests);
 		f=b;
 		b=b->next;
 		list_del(&f->requests);
-		if (!b) break;
 		kfree(f);
 		dec_ap_pending(mdev); // for the barrier
 	}
-
-	// f is now the last barrier, we use it as new first barrier.
-
-	INIT_LIST_HEAD(&f->requests);
-	f->next=NULL;
-	f->br_number=4711;
-	f->n_req=0;
-
-	spin_lock_irq(&mdev->tl_lock);
-
-	mdev->oldest_barrier = f;
-	mdev->newest_barrier = f;
-
-	spin_unlock_irq(&mdev->tl_lock);
 }
 
 STATIC unsigned int ee_hash_fn(drbd_dev *mdev, sector_t sector)

From drbd-cvs at lists.linbit.com  Mon Jul 31 11:51:33 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 31 11:51:35 2006
Subject: [DRBD-cvs] svn commit by lars - r2309 - trunk/user - * fixed the
	potentially double validation of resources.
Message-ID: <20060731095133.8393B2CE6AAC@mail.linbit.com>

Author: lars
Date: 2006-07-31 11:51:32 +0200 (Mon, 31 Jul 2006)
New Revision: 2309

Modified:
   trunk/user/drbdadm_main.c
Log:
 * fixed the potentially double validation of resources.
 * reimplemented that verify ip stuff again, half of that code was unnecessary
   and partially wrong. BTW, I still don't like it.


Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-07-31 09:33:28 UTC (rev 2308)
+++ trunk/user/drbdadm_main.c	2006-07-31 09:51:32 UTC (rev 2309)
@@ -106,7 +106,7 @@
 static int adm_generic_b(struct d_resource* ,const char* );
 static int hidden_cmds(struct d_resource* ,const char* );
 
-static struct ifi_info* get_ifi_info(int family);
+static struct ifreq* get_ifreq();
 
 char ss_buffer[255];
 struct utsname nodeinfo;
@@ -116,7 +116,7 @@
 char *config_file = NULL;
 struct d_resource* config = NULL;
 struct d_resource* common = NULL;
-struct ifi_info *my_ifis = NULL;
+struct ifreq *ifreq_list = NULL;
 int nr_resources;
 int highest_minor;
 int config_valid=1;
@@ -427,7 +427,6 @@
   }
 }
 
-static void free_ifi_info(struct ifi_info *ifihead);
 static void free_config(struct d_resource* res)
 {
   struct d_resource *f,*t;
@@ -451,7 +450,7 @@
     free_options(common->handlers);
     free(common);
   }
-  if (my_ifis) free_ifi_info(my_ifis);
+  if (ifreq_list) free(ifreq_list);
 }
 
 static void expand_opts(struct d_option* co, struct d_option** opts)
@@ -483,7 +482,6 @@
     expand_opts(common->sync_options,    &res->sync_options);
     expand_opts(common->startup_options, &res->startup_options);
     expand_opts(common->handlers,        &res->handlers);
-    validate_resource(res);
   }
 }
 
@@ -1170,174 +1168,105 @@
   exit(E_usage);
 }
 
-static void free_ifi_info(struct ifi_info *ifihead)
-{
-  struct ifi_info *ifi, *ifinext;
-  for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
-    if (ifi->ifi_addr != NULL)
-      free(ifi->ifi_addr);
-    ifinext = ifi->ifi_next;
-    free(ifi);
-  }
-}
+/*
+ * I'd really rather parse the output of
+ *   ip -o a s
+ * once, and be done.
+ * But anyways....
+ */
 
-static struct ifi_info* get_ifi_info(int family)
+static struct ifreq * get_ifreq(void)
 {
-  struct ifi_info *ifi, *ifihead, **ifipnext;
-  int sockfd, len, lastlen, flags, myflags;
-  char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
-  struct ifconf ifc;
-  struct ifreq *ifr, ifrcopy;
-  struct sockaddr_in *sinptr;
-    
-  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-  if (sockfd < 0) {
-    fprintf(stderr, "sockfd < 0\n");
-    return NULL;
-  }
+  int                sockfd, num_ifaces;
+  struct ifreq       *ifr;
+  struct ifconf      ifc;
+  size_t buf_size;
 
-  lastlen = 0;
-  len = 100 * sizeof(struct ifreq); /* initial guess */
-    
-  for (;;) {
-    buf = malloc(len);
-    if (!buf)
-      return NULL;
-    ifc.ifc_len = len;
-    ifc.ifc_buf = buf;
-        
-    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
-      if (errno != EINVAL || lastlen != 0)
-	return NULL;
-    } else {
-      if (ifc.ifc_len == lastlen)
-	break; /* success, len has not changed */
-      lastlen = ifc.ifc_len;
-    }
-    len += 10 * sizeof(struct ifreq); /* increment */
-    free(buf);
+  if (0 > (sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP ))) {
+    perror("Cannot open socket");
+    exit(EXIT_FAILURE);
   }
 
-  ifihead = NULL;
-  ifipnext = &ifihead;
-  lastname[0] = 0;
+  num_ifaces = 0;
+  ifc.ifc_req = NULL;
 
-  for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
-    ifr = (struct ifreq*) ptr;
-
-    switch (ifr->ifr_addr.sa_family) {
-      /*         case AF_INET6: len = sizeof(struct sockaddr_in6); break; */
-    case AF_INET:
-    default:
-      len = sizeof(struct sockaddr);
-      break;
+  /* realloc buffer size until no overflow occurs  */
+  do {
+    num_ifaces += 16; /* initial guess and increment */
+    buf_size = ++num_ifaces * sizeof(struct ifreq);
+    ifc.ifc_len = buf_size;
+    if (NULL == (ifc.ifc_req = realloc(ifc.ifc_req, ifc.ifc_len))) {
+      fprintf(stderr, "Out of memory.\n");
+      return NULL;
     }
-        
-    ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */
-        
-    if (ifr->ifr_addr.sa_family != family)
-      continue; /* ignore if not desired address family */
-        
-    myflags = 0;
-    if ((cptr = strchr(ifr->ifr_name, ':')) != NULL)
-      *cptr = 0; /* replace colon with null */
-
-    if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0)
-      myflags = IFI_ALIAS;
-
-    memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
-
-    ifrcopy = *ifr;
-    if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0)
+    if (ioctl(sockfd, SIOCGIFCONF, &ifc)) {
+      perror("ioctl SIOCFIFCONF");
+      free(ifc.ifc_req);
       return NULL;
+    }
+  } while  (buf_size <= (size_t)ifc.ifc_len);
 
-    flags = ifrcopy.ifr_flags;
-    if ((flags & IFF_UP) == 0)
-      continue; /* ignore if the interface is not up */
-
-    ifi = calloc(1, sizeof(struct ifi_info));
-    if (!ifi)
-      return NULL;
-        
-    *ifipnext = ifi; /* prev points to this new one */
-    ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
-
-    ifi->ifi_flags = flags; /* IFI_xxx values */
-    ifi->ifi_myflags = myflags; /* IFI_xxx values */
-    memcpy(ifi->ifi_name, ifr->ifr_name, IFNAMSIZ);
-    ifi->ifi_name[IFNAMSIZ - 1] = '\0';
-
-    switch(ifr->ifr_addr.sa_family) {
-      /*         case AF_INET6: return NULL; */
-    case AF_INET:
-      sinptr = (struct sockaddr_in *)&ifr->ifr_addr;
-      if (ifi->ifi_addr == NULL) {
-	ifi->ifi_addr = calloc(1, sizeof(struct sockaddr));
-	if (!ifi->ifi_addr)
-	  return NULL;
-
-	memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr));
-      }
-      /* IFF_BROADCAST and IFF_POINTTOPOINT are ignored */
-    default:
-      break;
+  num_ifaces = ifc.ifc_len / sizeof(struct ifreq);
+  /* Since we allocated at least one more than neccessary,
+   * this serves as a stop marker for the iteration in
+   * have_ip() */
+  ifc.ifc_req[num_ifaces].ifr_name[0] = 0;
+  for (ifr = ifc.ifc_req; ifr->ifr_name[0] != 0; ifr++) {
+    /* we only want to look up the presence or absence of a certain address
+     * here. but we want to skip "down" interfaces.  if an interface is down,
+     * we store an invalid sa_family, so the lookup will skip it.
+     */
+    struct ifreq ifr_for_flags = *ifr; /* get a copy to work with */
+    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr_for_flags) < 0) {
+      perror("ioctl SIOCGIFFLAGS");
+      ifr->ifr_addr.sa_family = -1; /* what's wrong here? anyways: skip */
+      continue;
     }
+    if (!(ifr_for_flags.ifr_flags & IFF_UP)) {
+      ifr->ifr_addr.sa_family = -1; /* is not up: skip */
+      continue;
+    }
   }
-
-  free(buf);
   close(sockfd);
-
-  return ifihead;
+  return ifc.ifc_req;
 }
 
 int have_ip(const char *ip)
 {
-  struct ifi_info *ifi, *ifihead;
-  int family;
-  uint32_t addr = 0;
-  struct in_addr sin_addr;
+  struct ifreq *ifr;
+  struct in_addr query_addr;
 
-  sin_addr.s_addr = inet_addr(ip);
+  query_addr.s_addr = inet_addr(ip);
 
-  /* FIXME make DRBD support inet6 */
-  family = AF_INET;
-  if (!my_ifis) my_ifis = get_ifi_info(family);
-    
-  for (ifihead = ifi = my_ifis; ifi != NULL; ifi = ifi->ifi_next) {
-    switch (family) {
-    case AF_INET: {
-      struct sockaddr_in * sin = (struct sockaddr_in *)ifi->ifi_addr;
-      addr = sin->sin_addr.s_addr;
+  if (!ifreq_list) ifreq_list = get_ifreq();
 
-      if (addr == sin_addr.s_addr) {
-	return 1;
-      }
-      break;
-    }
-    default:
-      break;
-    }
+  for (ifr = ifreq_list; ifr && ifr->ifr_name[0] != 0; ifr++) {
+    /* currently we only support AF_INET */
+    struct sockaddr_in * list_addr = (struct sockaddr_in *)&ifr->ifr_addr;
+    if (ifr->ifr_addr.sa_family != AF_INET)
+      continue;
+    if (query_addr.s_addr == list_addr->sin_addr.s_addr)
+      return 1;
   }
-
   return 0;
 }
 
 void verify_ips(struct d_resource *res)
 {
-	if (global_options.disable_ip_verification) return;
-	if (dry_run == 1 || do_verify_ips == 0) return;
+  if (global_options.disable_ip_verification) return;
+  if (dry_run == 1 || do_verify_ips == 0) return;
 
-	if (! have_ip(res->me->address)) {
-		ENTRY e, *ep;
-		e.key = e.data = ep = NULL;
-		asprintf(&e.key, "%s:%s", res->me->address, res->me->port);
-		ep = hsearch(e, FIND);
-		fprintf(stderr, "%s:%d: in resource %s, on %s:\n\t"
-			"IP %s not found on this host.\n",
-			config_file, (int)(long)ep->data, res->name,
-			res->me->name, res->me->address);
-		if (INVALID_IP_IS_INVALID_CONF)
-    config_valid = 0;
+  if (! have_ip(res->me->address)) {
+    ENTRY e, *ep;
+    e.key = e.data = ep = NULL;
+    asprintf(&e.key, "%s:%s", res->me->address, res->me->port);
+    ep = hsearch(e, FIND);
+    fprintf(stderr, "%s:%d: in resource %s, on %s:\n\t"
+      "IP %s not found on this host.\n",
+      config_file, (int)(long)ep->data, res->name,
+      res->me->name, res->me->address);
+    if (INVALID_IP_IS_INVALID_CONF)
+      config_valid = 0;
   }
 }
 
@@ -1427,6 +1356,23 @@
       config_valid=0;
     }
   }
+  // need to verify that in the discard-node-nodename options only known
+  // nodenames are mentioned.
+  if ( (opt = find_opt(res->net_options, "after-sb-0pri")) ) {
+    if(!strncmp(opt->value,"discard-node-",13)) {
+      if(strcmp(res->peer->name,opt->value+13) &&
+	 strcmp(res->me->name,opt->value+13)) {
+	fprintf(stderr,
+		" in resource %s:\n\t"
+		"the nodename in the '%s' option is "
+		"not known.\n\t"
+		"valid nodenames are: '%s' and '%s'.\n",
+		res->name, opt->value,
+		res->me->name, res->peer->name );
+	config_valid = 0;
+      }
+    }
+  }
   if (res->me && res->peer) {
     verify_ips(res);
   }
@@ -1435,40 +1381,8 @@
 static void global_validate(void)
 {
   struct d_resource *res,*tmp;
-  struct d_option* opt;
-
   for_each_resource(res,tmp,config) {
-
-    // need to verify that in the "after" key words only valid resources
-    // are named.
-    if ( (opt = find_opt(res->sync_options, "after")) ) {
-      if( res_by_name(opt->value) == NULL ) {
-	fprintf(stderr,
-		" in resource %s:\n\t"
-		"the resource named '%s' in the after option is "
-		"not known.\n\t",
-		res->name, opt->value);
-	config_valid = 0;
-      }
-    }
-
-    // need to verify that in the discard-node-nodename options only known
-    // nodenames are mentioned.
-    if ( (opt = find_opt(res->net_options, "after-sb-0pri")) ) {
-      if(!strncmp(opt->value,"discard-node-",13)) {
-	if(strcmp(res->peer->name,opt->value+13) &&
-	   strcmp(res->me->name,opt->value+13)) {
-	  fprintf(stderr,
-		  " in resource %s:\n\t"
-		  "the nodename in the '%s' option is "
-		  "not known.\n\t"
-		  "valid nodenames are: '%s' and '%s'.\n",
-		  res->name, opt->value,
-		  res->me->name, res->peer->name );
-	  config_valid = 0;
-	}
-      }
-    }
+    validate_resource(res);
   }
 }
 
@@ -1688,8 +1602,7 @@
 
       if(!is_dump) {
 	expand_common();
-
-	global_validate(); 
+	global_validate();
 	if(!config_valid) exit(E_config_invalid);
 
         for_each_resource(res,tmp,config) {

From drbd-cvs at lists.linbit.com  Mon Jul 31 12:39:06 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 31 12:39:08 2006
Subject: [DRBD-cvs] svn commit by phil - r2310 - in trunk: . debian drbd
	drbd/linux testing - Preparing drbd-8.0pre4 
Message-ID: <20060731103906.CD84C2DF6278@mail.linbit.com>

Author: phil
Date: 2006-07-31 12:39:04 +0200 (Mon, 31 Jul 2006)
New Revision: 2310

Modified:
   trunk/
   trunk/ChangeLog
   trunk/debian/changelog
   trunk/drbd.spec.in
   trunk/drbd/drbd_main.c
   trunk/drbd/linux/drbd_config.h
   trunk/testing/Makefile
Log:
Preparing drbd-8.0pre4



Property changes on: trunk
___________________________________________________________________
Name: propagate:at
   - 2249
   + 2291

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-07-31 09:51:32 UTC (rev 2309)
+++ trunk/ChangeLog	2006-07-31 10:39:04 UTC (rev 2310)
@@ -4,6 +4,16 @@
  Cumulative changes since last tarball.
  For even more detail, use "svn log" and "svn diff".
 
+8.0pre4 (api:83/proto:82)
+--------
+ * Added the "drbd-peer-outdater" heartbeat plugin.
+ * New ("cluster wide") state changes. (Cluster wide serialisation of
+   major state changes, like becomming primary, invalidateing a disk etc...)
+ * Write requests are now sent by the worker instead out of the process's
+   context that calls make_request().
+ * The worker thread no longer gets restarted upon loss of connection.
+ * A testsuite developed by students of 'FH Hagenberg' was added.
+	
 8.0pre3 (api:82/proto:80)
 --------
  * Now it works on device mapper (LVM) as well as on "real" block devices.

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog	2006-07-31 09:51:32 UTC (rev 2309)
+++ trunk/debian/changelog	2006-07-31 10:39:04 UTC (rev 2310)
@@ -1,3 +1,9 @@
+drbd8 (8.0pre4-0) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Philipp Reisner <phil@linbit.com>  Mon, 31 Jul 2006 12:04:41 +0200
+
 drbd8 (8.0pre3-0) unstable; urgency=low
 
   * New upstream release.

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-31 09:51:32 UTC (rev 2309)
+++ trunk/drbd/drbd_main.c	2006-07-31 10:39:04 UTC (rev 2310)
@@ -280,7 +280,7 @@
 	D_ASSERT(b->br_number == barrier_nr);
 	D_ASSERT(b->n_req == set_size);
 
-#ifdef DBG_ASSERTS
+#if 1
 	if(b->br_number != barrier_nr) {
 		DUMPI(b->br_number);
 		DUMPI(barrier_nr);

Modified: trunk/drbd/linux/drbd_config.h
===================================================================
--- trunk/drbd/linux/drbd_config.h	2006-07-31 09:51:32 UTC (rev 2309)
+++ trunk/drbd/linux/drbd_config.h	2006-07-31 10:39:04 UTC (rev 2310)
@@ -22,9 +22,9 @@
 
 extern const char * drbd_buildtag(void);
 
-#define REL_VERSION "8.0pre3"
-#define API_VERSION 82
-#define PRO_VERSION 81
+#define REL_VERSION "8.0pre4"
+#define API_VERSION 83
+#define PRO_VERSION 82
 
 // undef if you need the workaround in drbd_receiver
 #define HAVE_UML_TO_VIRT 1

Modified: trunk/drbd.spec.in
===================================================================
--- trunk/drbd.spec.in	2006-07-31 09:51:32 UTC (rev 2309)
+++ trunk/drbd.spec.in	2006-07-31 10:39:04 UTC (rev 2310)
@@ -194,6 +194,16 @@
 
 %changelog
 
+* Mon Jul 31 2006 12:04:41 +0200 Philipp Reisner <phil@linbit.com>
+- drbd (8.0pre4-1)
+ * Added the "drbd-peer-outdater" heartbeat plugin.
+ * New ("cluster wide") state changes. (Cluster wide serialisation of
+   major state changes, like becomming primary, invalidateing a disk etc...)
+ * Write requests are now sent by the worker instead out of the process's
+   context that calls make_request().
+ * The worker thread no longer gets restarted upon loss of connection.
+ * A testsuite developed by students of 'FH Hagenberg' was added.
+
 * Tue Apr 20 2006 13:46:18 +0200 Philipp Reisner <phil@linbit.com>
 - drbd (8.0pre3-1)
  * Now it works on device mapper (LVM) as well as on "real" block devices.

Modified: trunk/testing/Makefile
===================================================================
--- trunk/testing/Makefile	2006-07-31 09:51:32 UTC (rev 2309)
+++ trunk/testing/Makefile	2006-07-31 10:39:04 UTC (rev 2310)
@@ -1,4 +1,4 @@
-PROGRAMS=show_size  access_and_verify ioctl_structs_sizes
+PROGRAMS=show_size  access_and_verify ioctl_structs_sizes drbd_states
 CFLAGS=-Wall -I../drbd
 
 all: $(PROGRAMS)

From drbd-cvs at lists.linbit.com  Mon Jul 31 15:45:44 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 31 15:45:45 2006
Subject: [DRBD-cvs] svn commit by phil - r2315 - trunk/drbd - Removed that
	sensless down()/up() from the drbd_make_re
Message-ID: <20060731134544.259772DF6278@mail.linbit.com>

Author: phil
Date: 2006-07-31 15:45:42 +0200 (Mon, 31 Jul 2006)
New Revision: 2315

Modified:
   trunk/drbd/drbd_actlog.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_worker.c
Log:
Removed that sensless down()/up() from the drbd_make_request() function.
This should make DRBD fly... 


Modified: trunk/drbd/drbd_actlog.c
===================================================================
--- trunk/drbd/drbd_actlog.c	2006-07-31 13:05:01 UTC (rev 2314)
+++ trunk/drbd/drbd_actlog.c	2006-07-31 13:45:42 UTC (rev 2315)
@@ -231,7 +231,7 @@
 		al_work.al_ext = al_ext;
 		al_work.enr = enr;
 		al_work.w.cb = w_al_write_transaction;
-		drbd_queue_work_front(mdev,&mdev->data.work,&al_work.w);
+		drbd_queue_work_front(&mdev->data.work,&al_work.w);
 		wait_for_completion(&al_work.event);
 		
 		mdev->al_writ_cnt++;
@@ -673,7 +673,7 @@
 			}
 			udw->enr = ext1->lce.lc_number;
 			udw->w.cb = w_update_odbm;
-			drbd_queue_work_front(mdev,&mdev->data.work,&udw->w);
+			drbd_queue_work_front(&mdev->data.work,&udw->w);
 			if (ext1->flags != 0) {
 				WARN("deleting resync lce: %d[%u;%02lx]\n",
 				     ext1->lce.lc_number, ext1->rs_left,

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-07-31 13:05:01 UTC (rev 2314)
+++ trunk/drbd/drbd_int.h	2006-07-31 13:45:42 UTC (rev 2315)
@@ -672,6 +672,7 @@
 struct drbd_work_queue {
 	struct list_head q;
 	struct semaphore s; // producers up it, worker down()s it
+	spinlock_t q_lock;  // to protect the list.
 };
 
 /* If Philipp agrees, we remove the "mutex", and make_request will only
@@ -851,8 +852,10 @@
 		       unsigned int set_size);
 extern void tl_clear(drbd_dev *mdev);
 extern void tl_add(drbd_dev *mdev, drbd_request_t *req);
+extern void _tl_add(drbd_dev *mdev, drbd_request_t *req);
 extern struct drbd_barrier *tl_add_barrier(drbd_dev *mdev);
-extern struct Tl_epoch_entry * ee_have_write(drbd_dev *mdev,drbd_request_t * req);
+extern struct drbd_barrier *_tl_add_barrier(drbd_dev *,struct drbd_barrier *);
+extern struct Tl_epoch_entry * _ee_have_write(drbd_dev *mdev,drbd_request_t * req);
 extern int tl_dependence(drbd_dev *mdev, drbd_request_t * item);
 extern int tl_verify(drbd_dev *mdev, drbd_request_t * item, sector_t sector);
 extern drbd_request_t * req_have_write(drbd_dev *, struct Tl_epoch_entry *);
@@ -1341,7 +1344,6 @@
 	}
 }
 
-
 static inline void
 _drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
 {
@@ -1350,34 +1352,25 @@
 }
 
 static inline void
-_drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
+drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
 {
-	list_add(&w->list,&q->q);
-	up(&q->s);
-}
-
-static inline void
-drbd_queue_work_front(drbd_dev *mdev, struct drbd_work_queue *q,
-			struct drbd_work *w)
-{
 	unsigned long flags;
-	spin_lock_irqsave(&mdev->req_lock,flags);
+	spin_lock_irqsave(&q->q_lock,flags);
 	list_add(&w->list,&q->q);
 	up(&q->s); /* within the spinlock,
 		      see comment near end of drbd_worker() */
-	spin_unlock_irqrestore(&mdev->req_lock,flags);
+	spin_unlock_irqrestore(&q->q_lock,flags);
 }
 
 static inline void
-drbd_queue_work(drbd_dev *mdev, struct drbd_work_queue *q,
-		  struct drbd_work *w)
+drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&mdev->req_lock,flags);
+	spin_lock_irqsave(&q->q_lock,flags);
 	list_add_tail(&w->list,&q->q);
 	up(&q->s); /* within the spinlock,
 		      see comment near end of drbd_worker() */
-	spin_unlock_irqrestore(&mdev->req_lock,flags);
+	spin_unlock_irqrestore(&q->q_lock,flags);
 }
 
 static inline void wake_asender(drbd_dev *mdev) {

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-07-31 13:05:01 UTC (rev 2314)
+++ trunk/drbd/drbd_main.c	2006-07-31 13:45:42 UTC (rev 2315)
@@ -204,7 +204,7 @@
 }
 
 
-STATIC void _tl_add(drbd_dev *mdev, drbd_request_t *req)
+void _tl_add(drbd_dev *mdev, drbd_request_t *req)
 {
 	struct drbd_barrier *b;
 
@@ -260,6 +260,24 @@
 	return newest_before;
 }
 
+struct drbd_barrier *_tl_add_barrier(drbd_dev *mdev,struct drbd_barrier *new)
+{
+	struct drbd_barrier *newest_before;
+
+	INIT_LIST_HEAD(&new->requests);
+	new->next=0;
+	new->n_req=0;
+
+	/* mdev->newest_barrier == NULL "cannot happen". but anyways... */
+	newest_before = mdev->newest_barrier;
+	/* never send a barrier number == 0 */
+	new->br_number = (newest_before->br_number+1) ?: 1;
+	mdev->newest_barrier->next = new;
+	mdev->newest_barrier = new;
+
+	return newest_before;
+}
+
 void tl_release(drbd_dev *mdev,unsigned int barrier_nr,
 		       unsigned int set_size)
 {
@@ -452,8 +470,7 @@
 	return req;
 }
 
-struct Tl_epoch_entry * ee_have_write(drbd_dev *mdev,
-					     drbd_request_t * req)
+struct Tl_epoch_entry * _ee_have_write(drbd_dev *mdev, drbd_request_t * req)
 {
 	struct hlist_head *slot;
 	struct hlist_node *n;
@@ -464,8 +481,6 @@
 
 	D_ASSERT(size <= 1<<(HT_SHIFT+9) );
 
-	spin_lock_irq(&mdev->tl_lock);
-
 	for(i=-1;i<=1;i++ ) {
 		slot = mdev->ee_hash + ee_hash_fn(mdev,
 						  sector + i*(1<<(HT_SHIFT)));
@@ -480,7 +495,6 @@
 	// Good, no conflict found
 	_tl_add(mdev,req);
  out:
-	spin_unlock_irq(&mdev->tl_lock);
 
 	return ee;
 }
@@ -915,7 +929,7 @@
 			ascw->ns = ns;
 			ascw->flags = flags;
 			ascw->w.cb = w_after_state_ch;
-			_drbd_queue_work(&mdev->data.work,&ascw->w);
+			drbd_queue_work(&mdev->data.work,&ascw->w);
 		} else {
 			WARN("Could not kmalloc an ascw\n");
 		}
@@ -1935,7 +1949,7 @@
 			 * XXX this might be a good addition to drbd_queue_work
 			 * anyways, to detect "double queuing" ... */
 			if (list_empty(&mdev->unplug_work.list))
-				_drbd_queue_work(&mdev->data.work,&mdev->unplug_work);
+				drbd_queue_work(&mdev->data.work,&mdev->unplug_work);
 		}
 	}
 	spin_unlock_irq(&mdev->req_lock);
@@ -1983,6 +1997,9 @@
 	sema_init(&mdev->data.work.s,0);
 	sema_init(&mdev->meta.work.s,0);
 
+	spin_lock_init(&mdev->data.work.q_lock);
+	spin_lock_init(&mdev->meta.work.q_lock);
+
 	spin_lock_init(&mdev->al_lock);
 	spin_lock_init(&mdev->tl_lock);
 	spin_lock_init(&mdev->ee_lock);
@@ -2850,7 +2867,7 @@
 {
 	drbd_dev* mdev = (drbd_dev*) data;
 
-	drbd_queue_work_front(mdev,&mdev->data.work,&mdev->md_sync_work);
+	drbd_queue_work_front(&mdev->data.work,&mdev->md_sync_work);
 }
 
 STATIC int w_md_sync(drbd_dev *mdev, struct drbd_work *w, int unused)

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-07-31 13:05:01 UTC (rev 2314)
+++ trunk/drbd/drbd_receiver.c	2006-07-31 13:45:42 UTC (rev 2315)
@@ -2410,7 +2410,7 @@
 	disconnect_work = kmalloc(sizeof(struct drbd_work),GFP_KERNEL);
 	if(disconnect_work) {
 		disconnect_work->cb = w_disconnect;
-		drbd_queue_work(mdev,&mdev->data.work,disconnect_work);
+		drbd_queue_work(&mdev->data.work,disconnect_work);
 	} else {
 		WARN("kmalloc failed, taking messy shortcut.\n");
 		w_disconnect(mdev,NULL,1);

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-07-31 13:05:01 UTC (rev 2314)
+++ trunk/drbd/drbd_req.c	2006-07-31 13:45:42 UTC (rev 2315)
@@ -112,7 +112,7 @@
 // FIXME proto A and diskless :)
 
 		req->w.cb = w_io_error;
-		drbd_queue_work(mdev,&mdev->data.work,&req->w);
+		drbd_queue_work(&mdev->data.work,&req->w);
 
 		goto out;
 
@@ -125,11 +125,11 @@
 
  out:
 	if (test_bit(ISSUE_BARRIER,&mdev->flags)) {
-		spin_lock_irqsave(&mdev->req_lock,flags);
+		spin_lock_irqsave(&mdev->data.work.q_lock,flags);
 		if(list_empty(&mdev->barrier_work.list)) {
 			_drbd_queue_work(&mdev->data.work,&mdev->barrier_work);
 		}
-		spin_unlock_irqrestore(&mdev->req_lock,flags);
+		spin_unlock_irqrestore(&mdev->data.work.q_lock,flags);
 	}
 }
 
@@ -148,7 +148,7 @@
 	spin_unlock(&mdev->pr_lock);
 	set_bit(UNPLUG_REMOTE,&mdev->flags);
 
-	drbd_queue_work(mdev, &mdev->data.work, &req->w);
+	drbd_queue_work(&mdev->data.work, &req->w);
 
 	return 1;
 }
@@ -237,6 +237,7 @@
 drbd_make_request_common(drbd_dev *mdev, int rw, int size,
 			 sector_t sector, struct bio *bio)
 {
+	struct drbd_barrier *b;
 	drbd_request_t *req;
 	int local, remote;
 	int mxb;
@@ -352,43 +353,43 @@
 		 */
 		if (rw == WRITE) {
 
-	/* About tl_add():
-	1. This must be within the semaphor,
-	   to ensure right order in tl_ data structure and to
-	   ensure right order of packets on the write
-	2. This must happen before sending, otherwise we might
-	   get in the BlockAck packet before we have it on the
-	   tl_ datastructure (=> We would want to remove it before it
-	   is there!)
-	3. Q: Why can we add it to tl_ even when drbd_send() might fail ?
-	      There could be a tl_cancel() to remove it within the semaphore!
-	   A: If drbd_send fails, we will lose the connection. Then
-	      tl_cear() will simulate a RQ_DRBD_SEND and set it out of sync
-	      for everything in the data structure.
-	*/
-			down(&mdev->data.mutex);
+			b = kmalloc(sizeof(struct drbd_barrier),GFP_NOIO);
+			if(!b) {
+				ERR("Failed to alloc barrier.");
+				goto fail_and_free_req;
+			}
+
+			spin_lock_irq(&mdev->tl_lock);
+
 			if(test_and_clear_bit(ISSUE_BARRIER,&mdev->flags)) {
-				struct drbd_barrier *b = tl_add_barrier(mdev);
+				b = _tl_add_barrier(mdev,b);
 				b->w.cb =  w_send_barrier;
-				drbd_queue_work(mdev,&mdev->data.work, &b->w);
+				drbd_queue_work(&mdev->data.work, &b->w);
+				b = NULL;
 			}
 
 			if (mdev->net_conf->two_primaries) {
-				if(ee_have_write(mdev,req)) { // tl_add() here
+				if(_ee_have_write(mdev,req)) { // tl_add() here
+					spin_unlock_irq(&mdev->tl_lock);
+
 					WARN("Concurrent write! [DISCARD L] sec=%lu\n",
 					     (unsigned long)sector);
 					dec_local(mdev);
 					dec_ap_pending(mdev);
 					local=0;
+
 					drbd_end_req(req, RQ_DRBD_DONE, 1, sector);
+					return 0;
 				}
 			} else {
-				tl_add(mdev,req);
+				_tl_add(mdev,req);
 			}
 			req->w.cb =  w_send_dblock;
-			drbd_queue_work(mdev,&mdev->data.work, &req->w);
+			drbd_queue_work(&mdev->data.work, &req->w);
 
-			up(&mdev->data.mutex);
+			spin_unlock_irq(&mdev->tl_lock);
+
+			if(b) kfree(b);
 		} else {
 			// this node is diskless ...
 			drbd_read_remote(mdev,req);

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-07-31 13:05:01 UTC (rev 2314)
+++ trunk/drbd/drbd_worker.c	2006-07-31 13:45:42 UTC (rev 2315)
@@ -88,7 +88,7 @@
 	spin_unlock_irqrestore(&mdev->ee_lock,flags);
 
 	drbd_chk_io_error(mdev,error);
-	drbd_queue_work(mdev,&mdev->data.work,&e->w);
+	drbd_queue_work(&mdev->data.work,&e->w);
 	dec_local(mdev);
 	return 0;
 }
@@ -181,7 +181,7 @@
 		if (DRBD_ratelimit(5*HZ,5))
 			ERR("local read failed, retrying remotely\n");
 		req->w.cb = w_read_retry_remote;
-		drbd_queue_work(mdev,&mdev->data.work,&req->w);
+		drbd_queue_work(&mdev->data.work,&req->w);
 	} else {
 	pass_on:
 		bio_endio(req->master_bio,req->master_bio->bi_size,error);
@@ -282,11 +282,11 @@
 		mdev->resync_work.cb = w_resume_next_sg;
 	}
 
+	spin_unlock_irqrestore(&mdev->req_lock,flags);
+
 	if(list_empty(&mdev->resync_work.list)) {
-		_drbd_queue_work(&mdev->data.work,&mdev->resync_work);
+		drbd_queue_work(&mdev->data.work,&mdev->resync_work);
 	} else INFO("Avoided requeue of resync_work\n");
-
-	spin_unlock_irqrestore(&mdev->req_lock,flags);
 }
 
 #define SLEEP_TIME (HZ/10)
@@ -1047,7 +1047,7 @@
 		   this...   */
 
 		w = 0;
-		spin_lock_irq(&mdev->req_lock);
+		spin_lock_irq(&mdev->data.work.q_lock);
 		ERR_IF(list_empty(&mdev->data.work.q)) {
 			/* something terribly wrong in our logic.
 			 * we were able to down() the semaphore,
@@ -1060,12 +1060,12 @@
 			 *
 			 * I'll try to get away just starting over this loop.
 			 */
-			spin_unlock_irq(&mdev->req_lock);
+			spin_unlock_irq(&mdev->data.work.q_lock);
 			continue;
 		}
 		w = list_entry(mdev->data.work.q.next,struct drbd_work,list);
 		list_del_init(&w->list);
-		spin_unlock_irq(&mdev->req_lock);
+		spin_unlock_irq(&mdev->data.work.q_lock);
 
 		if(!w->cb(mdev,w, mdev->state.conn < Connected )) {
 			//WARN("worker: a callback failed! \n");
@@ -1100,11 +1100,11 @@
 	/* possible paranoia check: the STOP_SYNC_TIMER bit should be set
 	 * if and only if del_timer_sync returns true ... */
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->data.work.q_lock);
 	if (test_and_clear_bit(STOP_SYNC_TIMER,&mdev->flags)) {
 		mdev->resync_work.cb = w_resume_next_sg;
 		if (list_empty(&mdev->resync_work.list))
-			_drbd_queue_work(&mdev->data.work,&mdev->resync_work);
+			drbd_queue_work(&mdev->data.work,&mdev->resync_work);
 		// else: already queued
 	} else {
 		/* timer already consumed that bit, or it was never set */
@@ -1122,7 +1122,7 @@
 	i = 0;
   again:
 	list_splice_init(&mdev->data.work.q,&work_list);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->data.work.q_lock);
 
 	while(!list_empty(&work_list)) {
 		w = list_entry(work_list.next, struct drbd_work,list);
@@ -1131,7 +1131,7 @@
 		i++; /* dead debugging code */
 	}
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irq(&mdev->data.work.q_lock);
 	ERR_IF(!list_empty(&mdev->data.work.q))
 		goto again;
 	sema_init(&mdev->data.work.s,0);
@@ -1140,7 +1140,7 @@
 	 * semaphore without corresponding list entry.
 	 * So don't do that.
 	 */
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irq(&mdev->data.work.q_lock);
 
 	INFO("worker terminated\n");
 

From drbd-cvs at lists.linbit.com  Mon Jul 31 16:26:47 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 31 16:26:49 2006
Subject: [DRBD-cvs] svn commit by phil - r2316 - trunk - Lars' last second
	fix. 
Message-ID: <20060731142647.AA2B22DF6278@mail.linbit.com>

Author: phil
Date: 2006-07-31 16:26:46 +0200 (Mon, 31 Jul 2006)
New Revision: 2316

Modified:
   trunk/Makefile
Log:
Lars' last second fix.


Modified: trunk/Makefile
===================================================================
--- trunk/Makefile	2006-07-31 13:45:42 UTC (rev 2315)
+++ trunk/Makefile	2006-07-31 14:26:46 UTC (rev 2316)
@@ -111,8 +111,8 @@
 .PHONY: .filelist
 .filelist:
 	@ svn info >/dev/null || { echo "you need a svn checkout to do this." ; false ; }
-	@find $$(svn st -v | sed '/^?/d;s/^.\{8\} \+[0-9]\+ \+[0-9]\+ [a-z]\+ *//;$(if $(PRESERVE_DEBIAN),,/^debian/d)' ) \
-	\! -type d -maxdepth 0 |\
+	@find  $$(svn st -v | sed '/^?/d;s/^.\{8\} \+[0-9]\+ \+[0-9]\+ [a-z-]\+ *//;$(if $(PRESERVE_DEBIAN),,/^debian/d)' ) \
+	-maxdepth 0 \! -type d |\
 	sed 's#^#drbd-$(DIST_VERSION)/#' > .filelist
 	@[ -s .filelist ] # assert there is something in .filelist now
 	@find documentation -name "[^.]*.[58]" -o -name "*.html" | \

From drbd-cvs at lists.linbit.com  Mon Jul 31 16:29:02 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jul 31 16:29:05 2006
Subject: [DRBD-cvs] svn commit by phil - r2317 - tags - Tagging 8.0pre4 
Message-ID: <20060731142903.134412CE6AC2@mail.linbit.com>

Author: phil
Date: 2006-07-31 16:29:02 +0200 (Mon, 31 Jul 2006)
New Revision: 2317

Added:
   tags/drbd-8.0pre4/
Log:
Tagging 8.0pre4



Copied: tags/drbd-8.0pre4 (from rev 2316, trunk)

