[DRBD-cvs] svn commit by phil - r3021 - in branches/drbd-8.1: . debian documentation drbd scripts user - svnp run. Propagating the 8.0.5 fixes to the 8.1 branch

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Mon Aug 13 15:50:05 CEST 2007


Author: phil
Date: 2007-08-13 15:50:02 +0200 (Mon, 13 Aug 2007)
New Revision: 3021

Modified:
   branches/drbd-8.1/
   branches/drbd-8.1/ChangeLog
   branches/drbd-8.1/debian/changelog
   branches/drbd-8.1/documentation/drbd.conf.sgml
   branches/drbd-8.1/documentation/drbdsetup.sgml
   branches/drbd-8.1/drbd.spec.in
   branches/drbd-8.1/drbd/drbd_main.c
   branches/drbd-8.1/drbd/drbd_worker.c
   branches/drbd-8.1/scripts/drbd.conf
   branches/drbd-8.1/user/drbdadm_adjust.c
   branches/drbd-8.1/user/drbdadm_scanner.fl
   branches/drbd-8.1/user/drbdsetup.c
   branches/drbd-8.1/user/drbdtool_common.c
   branches/drbd-8.1/user/drbdtool_common.h
Log:
svnp run. Propagating the 8.0.5 fixes to the 8.1 branch.

Fixed a bug that was introduced with 8.0.1 (r2737). In case you slowed
down the resync speed during a running resync process considerabely, you
could trigger a bug in w_make_resync_request(), that causes the
local_cnt
to go below zero.

When the number of requests that should be on the fly for the new
(lower) resync speed is higher than the number of requests that are
currently on the fly, we had that "goto requeue:". In the exit path of
the function we decreased the local_cnt by one...
--
Ernest pointed out that we erroneously created a new current_id
each time a diskless peer become secondary. We should do that
only the first time...

By the way, I enlosed this in a inc_local() - dec_local() pair,
since mdev->bc gets dereferenced in this code block.
--
When we attach a disk to a connected device pair, we are in
disk state Nogotiating on the node that gets the disk attache

When in the mean time some event on the peer node triggers
the transmittion of a state packet, we might end up using an
old p_uuid set and find a wrong resync decission.

Fixed that.
--
Implemented the wait-after-sb option for the startup section.
AND CHANGED THE DEFAULT BEHAVIOUR OF THE INIT SCRIPT.
--
Preparing the 8.0.5 release.
--
Using the test isdigit(val1[0]) to find out if a string
represents a number is of course right out stupid and wrong.

When you used a shared secret that started with a digit,
this broke the "drbdadm adjust" function.

Fixed now.
--




Property changes on: branches/drbd-8.1
___________________________________________________________________
Name: propagate:at:2
   - 2977
   + 3019

Modified: branches/drbd-8.1/ChangeLog
===================================================================
--- branches/drbd-8.1/ChangeLog	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/ChangeLog	2007-08-13 13:50:02 UTC (rev 3021)
@@ -4,6 +4,40 @@
  Cumulative changes since last tarball.
  For even more detail, use "svn log" and "svn diff".
 
+8.0.5 (api:86/proto:86)
+--------
+ * Changed the default behaviour of the init script. Now the init
+   script terminates in case the devices refuse to because they 
+   had a split brain. Introduced an option to preserve the old
+   behaviour.
+ * Fixed a bug where the local_cnt could get imbalanced upon a 
+   state change.
+ * Fixed an bug in the UUID algorithm, that could lead to both
+   sides in cs:WFBitMapT state. It was triggered when the disk
+   on the SyncTarget gets detached and attached.
+ * Implemented proper size checking on strings that get communicated
+   with DRBD's netlink protocol.
+ * Changed the maximal length of device names from 32 characters to
+   128 characters. (udev based disk names might be very long nowadays)
+ * Fixed the after-sb-0pri policies discard-younger/discard-older
+ * When the resync speed was changed to a considerably lower 
+   value while resync was running, it could happen that we erronously
+   decremented the local_cnt too often.
+ * Fixed a bug in the UUID code, that caused drbd to erronously report 
+   a split brain after changing the role of a diskless node multiple 
+   times.
+ * Both nodes ended up in SyncSource when a state change occured on 
+   one node while the disk state on the other node is in the temporal 
+   'Negotiating' state. Fixed got fixed.
+ * drbdmeta's parse/scan code for meta-data dumps got fixed for 
+   huge devices, and an improved error reporting.
+ * drbdadm had difficulties with option values of type string that
+   start with an digit. Fixed.
+ * Fixed a code path that should it make possible to unload the
+   module even in case some of our receive buffers leaked.
+ * The usermode helper program is now user definable. It is no
+   longer hardcoded set to 'drbdadm'.
+
 8.0.4 (api:86/proto:86)
 --------
  * Fixed an OOPS in case you do an invalidate on an diskless device. And

Modified: branches/drbd-8.1/debian/changelog
===================================================================
--- branches/drbd-8.1/debian/changelog	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/debian/changelog	2007-08-13 13:50:02 UTC (rev 3021)
@@ -1,3 +1,9 @@
+drbd8 (8.0.5-0) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Philipp Reisner <phil at linbit.com>  Fri, 3 Aug 2007 09:34:49 +0200
+
 drbd8 (8.0.4-0) unstable; urgency=low
 
   * New upstream release.
@@ -2,3 +8,3 @@
 
- -- Philipp Reisner <phil at linbit.com>  Wed, 27 Jun 2007 10:0:00 +0200
+ -- Philipp Reisner <phil at linbit.com>  Wed, 27 Jun 2007 10:00:00 +0200
 

Modified: branches/drbd-8.1/documentation/drbd.conf.sgml
===================================================================
--- branches/drbd-8.1/documentation/drbd.conf.sgml	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/documentation/drbd.conf.sgml	2007-08-13 13:50:02 UTC (rev 3021)
@@ -217,7 +217,8 @@
     <manvolnum>8</manvolnum></citerefentry> for a detailed description
     of this section's parameters.
     Optional parameters:
-    <option>wfc-timeout</option>, <option>degr-wfc-timeout</option>.
+    <option>wfc-timeout</option>, <option>degr-wfc-timeout</option> and
+    <option>wait-after-sb</option>.
   </para>
   </listitem>
 </varlistentry>
@@ -835,6 +836,16 @@
 </varlistentry>
 
 <varlistentry>
+  <term><option>wait-after-sb</option></term>
+  <listitem><para>
+  By setting this option you can make the init script to continue 
+  to wait even if the device pair had a split brain situation
+  and therefore refuses to connect.
+  </para>
+  </listitem>
+</varlistentry>
+
+<varlistentry>
   <term><option>rate <replaceable>rate</replaceable></option></term>
   <listitem><para>
   <indexterm><primary>drbd.conf</primary><secondary>rate </secondary></indexterm>

Modified: branches/drbd-8.1/documentation/drbdsetup.sgml
===================================================================
--- branches/drbd-8.1/documentation/drbdsetup.sgml	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/documentation/drbdsetup.sgml	2007-08-13 13:50:02 UTC (rev 3021)
@@ -103,16 +103,18 @@
     <cmdsynopsis>
       <command>drbdsetup</command>
       <arg choice="req"><replaceable>device</replaceable></arg>
-      <arg choice="req">wait_connect</arg>
+      <arg choice="req">wait-connect</arg>
       <arg>-t<arg choice="req"><replaceable>wfc_timeout</replaceable></arg></arg>
       <arg>-d<arg choice="req"><replaceable>degr_wfc_timeout</replaceable></arg></arg>
+      <arg>-w</arg>
     </cmdsynopsis>
     <cmdsynopsis>
       <command>drbdsetup</command>
       <arg choice="req"><replaceable>device</replaceable></arg>
-      <arg choice="req">wait_sync</arg>
+      <arg choice="req">wait-sync</arg>
       <arg>-t<arg choice="req"><replaceable>wfc_timeout</replaceable></arg></arg>
       <arg>-d<arg choice="req"><replaceable>degr_wfc_timeout</replaceable></arg></arg>
+      <arg>-w</arg>
     </cmdsynopsis>
     <cmdsynopsis>
       <command>drbdsetup</command>
@@ -817,8 +819,8 @@
       </para>
     </refsect2>
     <refsect2>
-      <title>wait_connect</title>
-      <indexterm><primary>drbdsetup</primary><secondary>wait_connect</secondary></indexterm>
+      <title>wait-connect</title>
+      <indexterm><primary>drbdsetup</primary><secondary>wait-connect</secondary></indexterm>
       <para>
 	Returns as soon as the <replaceable>device</replaceable> can
 	communicate with its partner device.
@@ -829,6 +831,7 @@
 	  <option>--wfc-timeout <replaceable>wfc_timeout</replaceable></option></term>
 	  <term><option>-d</option>,
 	  <option>--degr-wfc-timeout <replaceable>degr_wfc_timeout</replaceable></option></term>
+	  <term><option>-w</option>, <option>--wait-after-sb</option></term>
 	  <listitem>
 	    <para>
 	      This command will fail if the
@@ -841,18 +844,22 @@
 	      The default value for <replaceable>wfc_timeout</replaceable>
 	      is 0 which means to wait forever. The default for
 	      <replaceable>degr_wfc_timeout</replaceable> is 120 seconds.
+	      In case the connection status goes down to StandAlone because
+              the peer appeared but the devices had a split brain situation,
+              the default for the command is to terminate. You can change this
+              behaviour with the <option>--wait-after-sb</option> option.
 	    </para>
 	  </listitem>
 	</varlistentry>
       </variablelist>
     </refsect2>
     <refsect2>
-      <title>wait_sync</title>
-      <indexterm><primary>drbdsetup</primary><secondary>wait_sync</secondary></indexterm>
+      <title>wait-sync</title>
+      <indexterm><primary>drbdsetup</primary><secondary>wait-sync</secondary></indexterm>
       <para>
 	Returns as soon as the <replaceable>device</replaceable> leaves any
 	synchronisation into connected state. The options
-	are the same as with the <replaceable>wait_connect</replaceable>
+	are the same as with the <replaceable>wait-connect</replaceable>
 	command.
       </para>
     </refsect2>

Modified: branches/drbd-8.1/drbd/drbd_main.c
===================================================================
--- branches/drbd-8.1/drbd/drbd_main.c	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/drbd/drbd_main.c	2007-08-13 13:50:02 UTC (rev 3021)
@@ -954,18 +954,21 @@
 		}
 	}
 
-	if (ns.pdsk < Inconsistent) {
+	if (ns.pdsk < Inconsistent && inc_local(mdev)) {
 		/* Diskless Peer becomes primary */
-		if (os.peer == Secondary && ns.peer == Primary)
+		if (os.peer == Secondary && ns.peer == Primary && mdev->bc->md.uuid[Bitmap] == 0)
 			drbd_uuid_new_current(mdev);
 		/* Diskless Peer becomes secondary */
 		if (os.peer == Primary && ns.peer == Secondary)
 			drbd_al_to_on_disk_bm(mdev);
+		dec_local(mdev);
 	}
 
 	/* Last part of the attaching process ... */
 	if ( ns.conn >= Connected &&
 	     os.disk == Attaching && ns.disk == Negotiating ) {
+		kfree(mdev->p_uuid); /* We expect to receive up-to-date UUIDs soon. */
+		mdev->p_uuid = NULL; /* ...to not use the old ones in the mean time */
 		drbd_send_sizes(mdev);  /* to start sync... */
 		drbd_send_uuids(mdev);
 		drbd_send_state(mdev);

Modified: branches/drbd-8.1/drbd/drbd_worker.c
===================================================================
--- branches/drbd-8.1/drbd/drbd_worker.c	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/drbd/drbd_worker.c	2007-08-13 13:50:02 UTC (rev 3021)
@@ -335,12 +335,6 @@
 		ERR("%s in w_make_resync_request\n",
 			conns_to_name(mdev->state.conn));
 
-	number = SLEEP_TIME*mdev->sync_conf.rate / ((BM_BLOCK_SIZE/1024)*HZ);
-
-	if (atomic_read(&mdev->rs_pending_cnt) > number)
-		goto requeue;
-	number -= atomic_read(&mdev->rs_pending_cnt);
-
 	if (!inc_local(mdev)) {
 		/* Since we only need to access mdev->rsync a
 		   inc_local_if_state(mdev,Failed) would be sufficient, but
@@ -350,7 +344,14 @@
 		mdev->resync_work.cb = w_resync_inactive;
 		return 1;
 	}
+	/* All goto requeses have to happend after this block: inc_local() */
 
+	number = SLEEP_TIME*mdev->sync_conf.rate / ((BM_BLOCK_SIZE/1024)*HZ);
+
+	if (atomic_read(&mdev->rs_pending_cnt) > number)
+		goto requeue;
+	number -= atomic_read(&mdev->rs_pending_cnt);
+
 	for (i = 0; i < number; i++) {
 next_sector:
 		size = BM_BLOCK_SIZE;

Modified: branches/drbd-8.1/drbd.spec.in
===================================================================
--- branches/drbd-8.1/drbd.spec.in	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/drbd.spec.in	2007-08-13 13:50:02 UTC (rev 3021)
@@ -191,6 +191,40 @@
 /sbin/depmod -a -F /boot/System.map-%{kernelversion} %{kernelversion} >/dev/null 2>&1 || true
 
 %changelog
+* Fri Aug  3 2007 09:34:49 +0200 Philipp Reisner <phil at linbit.com>
+- drbd (8.0.5-1)
+ * Changed the default behaviour of the init script. Now the init
+   script terminates in case the devices refuse to because they 
+   had a split brain. Introduced an option to preserve the old
+   behaviour.
+ * Fixed a bug where the local_cnt could get imbalanced upon a 
+   state change.
+ * Fixed an bug in the UUID algorithm, that could lead to both
+   sides in cs:WFBitMapT state. It was triggered when the disk
+   on the SyncTarget gets detached and attached.
+ * Implemented proper size checking on strings that get communicated
+   with DRBD's netlink protocol.
+ * Changed the maximal length of device names from 32 characters to
+   128 characters. (udev based disk names might be very long nowadays)
+ * Fixed the after-sb-0pri policies discard-younger/discard-older
+ * When the resync speed was changed to a considerably lower 
+   value while resync was running, it could happen that we erronously
+   decremented the local_cnt too often.
+ * Fixed a bug in the UUID code, that caused drbd to erronously report 
+   a split brain after changing the role of a diskless node multiple 
+   times.
+ * Both nodes ended up in SyncSource when a state change occured on 
+   one node while the disk state on the other node is in the temporal 
+   'Negotiating' state. Fixed got fixed.
+ * drbdmeta's parse/scan code for meta-data dumps got fixed for 
+   huge devices, and an improved error reporting.
+ * drbdadm had difficulties with option values of type string that
+   start with an digit. Fixed.
+ * Fixed a code path that should it make possible to unload the
+   module even in case some of our receive buffers leaked.
+ * The usermode helper program is now user definable. It is no
+   longer hardcoded set to 'drbdadm'.
+
 * Wed Jun 27 2007 10:00:00 +0200 Philipp Reisner <phil at linbit.com>
 - drbd (8.0.4-1)
  * Fixed an OOPS in case you do an invalidate on an diskless device. And

Modified: branches/drbd-8.1/scripts/drbd.conf
===================================================================
--- branches/drbd-8.1/scripts/drbd.conf	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/scripts/drbd.conf	2007-08-13 13:50:02 UTC (rev 3021)
@@ -161,6 +161,15 @@
     # is rebooted, this timeout value is used.
     #
     degr-wfc-timeout 120;    # 2 minutes.
+
+    # In case there was a split brain situation the devices will
+    # drop their network configuration instead of connecting. Since
+    # this means that the network is working, the cluster manager
+    # should be able to communicate as well. Therefore the default
+    # of DRBD's init script is to terminate in this case. To make
+    # it to continue waiting in this case set this option.
+    # 
+    # wait-after-sb;
   }
 
   disk {

Modified: branches/drbd-8.1/user/drbdadm_adjust.c
===================================================================
--- branches/drbd-8.1/user/drbdadm_adjust.c	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/user/drbdadm_adjust.c	2007-08-13 13:50:02 UTC (rev 3021)
@@ -29,7 +29,6 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -77,13 +76,9 @@
 	if(val1 == NULL && val2 == NULL) return 1;
 	if(val1 == NULL || val2 == NULL) return 0;
 
-	if(isdigit(val1[0])) {
-		v1 = m_strtoll(val1,0);
-		v2 = m_strtoll(val2,0);
+	if(new_strtoll(val1,0,&v1) == MSE_OK &&
+	   new_strtoll(val2,0,&v2) == MSE_OK) return v1 == v2;
 
-		return v1 == v2;
-	}
-
 	return !strcmp(val1,val2);
 }
 

Modified: branches/drbd-8.1/user/drbdadm_scanner.fl
===================================================================
--- branches/drbd-8.1/user/drbdadm_scanner.fl	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/user/drbdadm_scanner.fl	2007-08-13 13:50:02 UTC (rev 3021)
@@ -88,6 +88,7 @@
 al-extents		{ DP; CP; RC(AL_EXTENTS); return TK_SYNCER_OPTION;}
 wfc-timeout		{ DP; CP; RC(WFC_TIMEOUT); return TK_STARTUP_OPTION;}
 degr-wfc-timeout	{ DP; CP; RC(DEGR_WFC_TIMEOUT); return TK_STARTUP_OPTION;}
+wait-after-sb		{ DP; CP; return TK_STARTUP_SWITCH;     }
 pri-on-incon-degr	{ DP; CP; return TK_HANDLER_OPTION;	}
 pri-lost-after-sb	{ DP; CP; return TK_HANDLER_OPTION;	}
 pri-lost	        { DP; CP; return TK_HANDLER_OPTION;     }

Modified: branches/drbd-8.1/user/drbdsetup.c
===================================================================
--- branches/drbd-8.1/user/drbdsetup.c	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/user/drbdsetup.c	2007-08-13 13:50:02 UTC (rev 3021)
@@ -124,7 +124,8 @@
 		} gp; // for generic_get_cmd, get_usage
 		struct {
 			struct option *options;
-			int (*proc_event)();
+			int (*proc_event)(unsigned int, int, 
+					  struct drbd_nl_cfg_reply *);
 		} ep; // for events_cmd, events_usage
 	};
 };
@@ -191,9 +192,9 @@
 void show_string(struct drbd_option *od, unsigned short* tp);
 
 // sub functions for events_cmd
-int print_state(unsigned int seq, struct drbd_nl_cfg_reply *reply);
-int w_connected_state(unsigned int seq, struct drbd_nl_cfg_reply *reply);
-int w_synced_state(unsigned int seq, struct drbd_nl_cfg_reply *reply);
+int print_state(unsigned int seq, int, struct drbd_nl_cfg_reply *reply);
+int w_connected_state(unsigned int seq, int, struct drbd_nl_cfg_reply *reply);
+int w_synced_state(unsigned int seq, int, struct drbd_nl_cfg_reply *reply);
 
 const char *on_error[] = {
 	[PassOn]         = "pass_on",
@@ -240,6 +241,7 @@
 struct option wait_cmds_options[] = {
 	{ "wfc-timeout",required_argument, 0, 't' },
 	{ "degr-wfc-timeout",required_argument,0,'d'},
+	{ "wait-after-sb",no_argument,0,'w'},
 	{ 0,            0,           0,  0  }
 };
 
@@ -1187,7 +1189,8 @@
 	return rv;
 }
 
-int print_state(unsigned int seq, struct drbd_nl_cfg_reply *reply)
+int print_state(unsigned int seq, int u __attribute((unused)),
+		struct drbd_nl_cfg_reply *reply)
 {
 	drbd_state_t state;
 	char* str;
@@ -1239,6 +1242,7 @@
 }
 
 int w_connected_state(unsigned int seq __attribute((unused)),
+		      int wait_after_sb,
 		      struct drbd_nl_cfg_reply *reply)
 {
 	drbd_state_t state;
@@ -1246,6 +1250,7 @@
 	if(reply->packet_type == P_get_state) {
 		if(consume_tag_int(T_state_i,reply->tag_list,(int*)&state.i)) {
 			if(state.conn >= Connected) return 0;
+			if(!wait_after_sb && state.conn < Unconnected) return 0;
 		} else fprintf(stderr,"Missing tag !?\n");
 	}
 
@@ -1253,14 +1258,15 @@
 }
 
 int w_synced_state(unsigned int seq __attribute((unused)),
+		   int wait_after_sb,
 		   struct drbd_nl_cfg_reply *reply)
 {
 	drbd_state_t state;
 
 	if(reply->packet_type == P_get_state) {
 		if(consume_tag_int(T_state_i,reply->tag_list,(int*)&state.i)) {
-			if(state.conn == Connected || state.conn < Unconnected )
-				return 0;
+			if(state.conn == Connected) return 0;
+			if(!wait_after_sb && state.conn < Unconnected) return 0;
 		} else fprintf(stderr,"Missing tag !?\n");
 	}
 	return 1;
@@ -1278,6 +1284,7 @@
 	int unfiltered=0, all_devices=0;
 	int wfc_timeout=0, degr_wfc_timeout=0,timeout_ms;
 	struct timeval before,after;
+	int wasb=0;
 
 	lo = cm->ep.options;
 
@@ -1307,6 +1314,9 @@
 				return 20;
 			}
 			break;
+		case 'w':
+			wasb=1;
+			break;
 		}
 	}
 
@@ -1372,7 +1382,7 @@
 		seq = cn_reply->seq;
 
 		if( all_devices || minor == reply->minor ) {
-			cont=cm->ep.proc_event(cn_reply->seq, reply);
+			cont=cm->ep.proc_event(cn_reply->seq, wasb, reply);
 		}
 	} while(cont);
 

Modified: branches/drbd-8.1/user/drbdtool_common.c
===================================================================
--- branches/drbd-8.1/user/drbdtool_common.c	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/user/drbdtool_common.c	2007-08-13 13:50:02 UTC (rev 3021)
@@ -53,88 +53,96 @@
   return buffer;
 }
 
-unsigned long long
-m_strtoll(const char *s, const char def_unit)
+int
+new_strtoll(const char *s, const char def_unit, unsigned long long *rv)
 {
-  unsigned long long r;
-  char unit = 0;
-  char dummy = 0;
-  int shift, c;
+	char unit = 0;
+	char dummy = 0;
+	int shift, c;
 
-  /*
-   * paranoia
-   */
-  switch (def_unit)
-    {
-    default:
-      fprintf(stderr, "%s:%d: unexpected default unit\n", __FILE__, __LINE__);
-      exit(100);
-    case 0:
-    case 1:
-    case '1':
-      shift = 0;
-      break;
+	switch (def_unit) {
+	default:
+		return MSE_DEFAULT_UNIT;
+	case 0:
+	case 1:
+	case '1':
+		shift = 0;
+		break;
+	case 'K':
+	case 'k':
+		shift = -10;
+		break;
+	case 's':
+		shift = -9;   // sectors
+		break;
+		/*
+		  case 'M':
+		  case 'm':
+		  case 'G':
+		  case 'g':
+		*/
+	}
+	
+	if (!s || !*s) return MSE_MISSING_NUMBER;
 
-    case 'K':
-    case 'k':
-      shift = -10;
-      break;
+	c = sscanf(s, "%llu%c%c", rv, &unit, &dummy);
 
-    case 's':
-      shift = -9;   // sectors
-      break;
+	if (c != 1 && c != 2) return MSE_INVALID_NUMBER;
 
-      /*
-         case 'M':
-         case 'm':
-         case 'G':
-         case 'g':
-       */
-    }
+	switch (unit) {
+	case 0:
+		return MSE_OK;
+	case 'K':
+	case 'k':
+		shift += 10;
+		break;
+	case 'M':
+	case 'm':
+		shift += 20;
+		break;
+	case 'G':
+	case 'g':
+		shift += 30;
+		break;
+	case 's':
+		shift += 9;
+		break;		
+	default:
+		return MSE_INVALID_UNIT;
+	}
+	if (*rv > (~0ULL >> shift)) return MSE_OUT_OF_RANGE;
 
-  if (!s || !*s)
-    {
-      fprintf(stderr, "missing number argument\n");
-      exit(100);
-    }
+	*rv = *rv << shift;
+	return MSE_OK;
+}
 
-  c = sscanf(s, "%llu%c%c", &r, &unit, &dummy);
+unsigned long long
+m_strtoll(const char *s, const char def_unit)
+{
+	unsigned long long r;
 
-  if (c != 1 && c != 2)
-    {
-      fprintf(stderr, "%s is not a valid number\n", s);
-      exit(20);
-    }
-
-  switch (unit)
-    {
-    case 0:
-      return r;
-    case 'K':
-    case 'k':
-      shift += 10;
-      break;
-    case 'M':
-    case 'm':
-      shift += 20;
-      break;
-    case 'G':
-    case 'g':
-      shift += 30;
-      break;
-    case 's':
-      shift += 9;
-      break;
-    default:
-      fprintf(stderr, "%s is not a valid number\n", s);
-      exit(20);
-    }
-  if (r > (~0ULL >> shift))
-    {
-      fprintf(stderr, "%s: out of range\n", s);
-      exit(20);
-    }
-  return r << shift;
+	switch(new_strtoll(s, def_unit, &r)) {
+	case MSE_OK:
+		return r;
+	case MSE_DEFAULT_UNIT:
+		fprintf(stderr, "unexpected default unit: %d\n",def_unit);
+		exit(100);
+	case MSE_MISSING_NUMBER:
+		fprintf(stderr, "missing number argument\n");
+		exit(100);
+	case MSE_INVALID_NUMBER:
+		fprintf(stderr, "%s is not a valid number\n", s);
+		exit(20);
+	case MSE_INVALID_UNIT:
+		fprintf(stderr, "%s is not a valid number\n", s);
+		exit(20);
+	case MSE_OUT_OF_RANGE:
+		fprintf(stderr, "%s: out of range\n", s);
+		exit(20);
+	default:
+		fprintf(stderr, "m_stroll() is confused\n");
+		exit(20);
+	}
 }
 
 void alarm_handler(int __attribute((unused)) signo)

Modified: branches/drbd-8.1/user/drbdtool_common.h
===================================================================
--- branches/drbd-8.1/user/drbdtool_common.h	2007-08-13 13:20:18 UTC (rev 3020)
+++ branches/drbd-8.1/user/drbdtool_common.h	2007-08-13 13:50:02 UTC (rev 3021)
@@ -23,12 +23,22 @@
 */
 #define PERROR(fmt, args...) fprintf(stderr, fmt ": %m\n" , ##args);
 
+enum new_strtoll_errs {
+	MSE_OK,
+	MSE_DEFAULT_UNIT,
+	MSE_MISSING_NUMBER,
+	MSE_INVALID_NUMBER,
+	MSE_INVALID_UNIT,
+	MSE_OUT_OF_RANGE,
+};
+
 struct option;
 
 extern int dt_lock_drbd(const char* device);
 extern void dt_unlock_drbd(int lock_fd);
 extern void dt_release_lockfile(int drbd_fd);
 extern int dt_minor_of_dev(const char *device);
+extern int new_strtoll(const char *s, const char def_unit, unsigned long long *rv);
 extern unsigned long long m_strtoll(const char* s,const char def_unit);
 extern const char* make_optstring(struct option *options, char startc);
 extern char* ppsize(char* buf, size_t size);



More information about the drbd-cvs mailing list