File sfex_uuid.patch of Package resource-agents

Index: resource-agents/tools/sfex.h
===================================================================
--- resource-agents.orig/tools/sfex.h	2011-10-31 17:40:17.000000000 +0800
+++ resource-agents/tools/sfex.h	2011-10-31 17:40:55.000000000 +0800
@@ -88,8 +88,8 @@
  * (In the Linux kernel 2.6, if this value is not 512 multibles, direct I/O 
  * does not work)
  
- * number of locks  --- 4 bytes. This is printable integer number and range 
- * is from 1 to 999. This must be left-justify, null(0x00) padding, and make 
+ * number of locks  --- 8 bytes. This is printable integer number and range
+ * is from 1 to 9999. This must be left-justify, null(0x00) padding, and make
  * a last byte null. This is the number of locks following this control data.
  *
  * padding --- The size of this member depend on blocksize. It is adjusted so 
@@ -101,7 +101,7 @@
   int version;			/*  version number */
   int revision;			/*  revision number */
   size_t blocksize;		/*  block size */
-  int numlocks;			/*  number of locks */
+  unsigned long numlocks;			/*  number of locks */
 } sfex_controldata;
 
 typedef struct sfex_controldata_ondisk {
@@ -109,7 +109,7 @@
   uint8_t version[4];
   uint8_t revision[4];
   uint8_t blocksize[8];
-  uint8_t numlocks[4];
+  uint8_t numlocks[8];
 } sfex_controldata_ondisk;
 
 /*
@@ -145,12 +145,14 @@
   char status;				/* status of lock */
   int count;				/* increment counter */
   char nodename[256];		/* node name */
+  char uuid[36];
 } sfex_lockdata;
 
 typedef struct sfex_lockdata_ondisk {
 	uint8_t status;
 	uint8_t count[4];
 	uint8_t nodename[256];
+	uint8_t uuid[37];
 } sfex_lockdata_ondisk;
 
 /* character for lock status. This is used in sfex_lockdata.status */
@@ -160,7 +162,7 @@
 /* features of each member of control data and lock data */
 #define SFEX_MAGIC "SFEX"
 #define SFEX_MIN_NUMLOCKS 1
-#define SFEX_MAX_NUMLOCKS 999
+#define SFEX_MAX_NUMLOCKS 9999
 #define SFEX_MIN_COUNT 0
 #define SFEX_MAX_COUNT 999
 #define SFEX_MAX_NODENAME (sizeof(((sfex_lockdata *)0)->nodename) - 1)
Index: resource-agents/tools/sfex_daemon.c
===================================================================
--- resource-agents.orig/tools/sfex_daemon.c	2011-10-31 17:40:14.000000000 +0800
+++ resource-agents/tools/sfex_daemon.c	2011-11-08 11:58:43.000000000 +0800
@@ -10,6 +10,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <linux/types.h>
 #include <fcntl.h>
 #include <syslog.h>
 #include "sfex.h"
@@ -39,28 +40,128 @@
 	  fprintf(dist, "usage: %s [-i <index>] [-c <collision_timeout>] [-t <lock_timeout>] <device>\n", progname);
 }
 
-static void acquire_lock(void)
+static void check_lock(void)
 {
 	if (read_lockdata(&cdata, &ldata, lock_index) == -1) {
 		cl_log(LOG_ERR, "read_lockdata failed in acquire_lock\n");
 		exit(EXIT_FAILURE);
 	}
+	if (ldata.status == SFEX_STATUS_LOCK) {
+		printf("host=%s, uuid=%s\n",
+				(const char*)(ldata.nodename),
+				(const char*)(ldata.uuid));
+	} else {
+		printf("\n");
+	}
+}
+
+/* 0 -> false, 1 -> true */
+static inline int is_used_by_uuid(const char* uuid)
+{
+	if (read_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "read_lockdata failed in acquire_lock\n");
+		exit(EXIT_FAILURE);
+	}
+	return !(strncmp(uuid, ldata.uuid, sizeof(ldata.uuid)));
+}
 
-	if ((ldata.status == SFEX_STATUS_LOCK) && (strncmp(nodename, (const char*)(ldata.nodename), sizeof(ldata.nodename)))) {
+/* 0 -> unlocked, 1 -> locked */
+static inline int is_locked(void)
+{
+	if (read_lockdata(&cdata, &ldata, lock_index) == -1) {
+		cl_log(LOG_ERR, "read_lockdata failed in acquire_lock\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (ldata.status == SFEX_STATUS_LOCK) {
 		unsigned int t = lock_timeout;
-		while (t > 0)
-			t = sleep(t);
+		while (t > 0) t = sleep(t);
 		read_lockdata(&cdata, &ldata_new, lock_index);
 		if (ldata.count != ldata_new.count) {
-			cl_log(LOG_ERR, "can\'t acquire lock: the lock's already hold by some other node.\n");
+			return 1;
+		} else {
+			return 0;
+		}
+	}
+	return 0;
+}
+
+#define SFEX_BULK_SIZE 10
+
+/* SBDMhash */
+static inline unsigned int uuid2int(const char *str)
+{
+	unsigned int hash = 0;
+
+	while (*str)
+	{
+		if (*str == '-') { str++; continue;}
+		/* equivalent to: hash = 65599*hash + (*str++); */
+		hash = (*str++) + (hash << 6) + (hash << 16) - hash;
+	}
+
+	return (((hash & 0x7FFFFFFF) % SFEX_MAX_NUMLOCKS)/SFEX_BULK_SIZE)*SFEX_BULK_SIZE;
+}
+
+static inline void search_for_uuid(const char* uuid, unsigned int lock_index_limit)
+{
+	unsigned int old_lock_index;
+	old_lock_index = lock_index;
+	while (lock_index < lock_index_limit) {
+		if (is_used_by_uuid(uuid)) return;
+		else lock_index++;
+	}
+	lock_index = old_lock_index;
+}
+
+static void acquire_lock(const char* uuid)
+{
+
+	unsigned int lock_index_limit = 0;
+/*	unsigned int old_lock_index = lock_index; */
+	if (uuid) {
+		if (cdata.numlocks < 9999) {
+			cl_log(LOG_ERR, "must have at least 9999 lock slots to use uuid based lock.\n");
 			exit(2);
 		}
+		lock_index = uuid2int(uuid);
+		lock_index_limit = lock_index + SFEX_BULK_SIZE;
+		search_for_uuid(uuid, lock_index_limit);
+	} else {
+		lock_index_limit = lock_index + 1;
+	}
+
+	while (lock_index < lock_index_limit) {
+		cl_log(LOG_INFO, "Try lock_index = %d\n", lock_index);
+		if (is_locked()) {
+			if (strncmp(uuid, (const char*)(ldata.uuid), sizeof(ldata.uuid))) {
+				cl_log(LOG_INFO, "can\'t acquire lock: the lock is used for other uuid.\n");
+				lock_index = lock_index + 1;
+				continue;
+			}
+			if (strncmp(nodename, (const char*)(ldata.nodename), sizeof(ldata.nodename))) {
+				cl_log(LOG_ERR, "can\'t acquire lock: the lock is already held by other node.\n");
+				exit(2);
+			} else {
+				cl_log(LOG_ERR, "this lock is already held by me\n");
+				exit(2);
+			}
+		} else {
+			break;
+		}
 	}
 
+	if (lock_index == lock_index_limit) { /* we have run out of bulk */
+		cl_log(LOG_ERR, "can\'t find free lock slot to hold this uuid.\n");
+		exit(2);
+	}
+
+	/* from now on, we have a unlocked lock slot */
 	/* The lock acquisition is possible because it was not updated. */
 	ldata.status = SFEX_STATUS_LOCK;
 	ldata.count = SFEX_NEXT_COUNT(ldata.count);
 	strncpy((char*)(ldata.nodename), nodename, sizeof(ldata.nodename));
+	strncpy((char*)(ldata.uuid), uuid, sizeof(ldata.uuid));
 	if (write_lockdata(&cdata, &ldata, lock_index) == -1) {
 		cl_log(LOG_ERR, "write_lockdata failed\n");
 		exit(EXIT_FAILURE);
@@ -81,7 +182,11 @@
 			cl_log(LOG_ERR, "read_lockdata failed in collision detection\n");
 		}
 		if (strncmp((char*)(ldata.nodename), (const char*)(ldata_new.nodename), sizeof(ldata.nodename))) {
-			cl_log(LOG_ERR, "can\'t acquire lock: collision detected in the air.\n");
+			cl_log(LOG_ERR, "can\'t acquire lock: nodename collision detected in the air.\n");
+			exit(2);
+		}
+		if (strncmp((char*)(ldata.uuid), (const char*)(ldata_new.uuid), sizeof(ldata.uuid))) {
+			cl_log(LOG_ERR, "can\'t acquire lock: uuid collision detected in the air.\n");
 			exit(2);
 		}
 	}
@@ -190,6 +295,8 @@
 {	
 
 	int ret;
+	int check_status = 0;
+	char *uuid = NULL;
 
 	progname = get_progname(argv[0]);
 	nodename = get_nodename();
@@ -201,13 +308,16 @@
 	/* read command line option */
 	opterr = 0;
 	while (1) {
-		int c = getopt(argc, argv, "hi:c:t:m:n:r:");
+		int c = getopt(argc, argv, "shi:u:c:t:m:n:r:");
 		if (c == -1)
 			break;
 		switch (c) {
 			case 'h':           /* help*/
 				usage(stdout);
 				exit(EXIT_SUCCESS);
+			case 's':           /* status */
+				check_status = 1;
+				break;
 			case 'i':           /* -i <index> */
 				{
 					unsigned long l = strtoul(optarg, NULL, 10);
@@ -281,6 +391,17 @@
 					rsc_id = strdup(optarg);
 				}
 				break;
+			case 'u':
+				{
+					uuid = strdup(optarg);
+					if (strlen(uuid) > 36) {
+						cl_log(LOG_ERR, "uuid %s is too long. must be less than 36 byte.\n",
+								uuid);
+						exit(EXIT_FAILURE);
+					}
+
+				}
+				break;
 			case '?':           /* error */
 				usage(stderr);
 				exit(4);
@@ -326,8 +447,13 @@
 
 	cl_log(LOG_INFO, "Starting SFeX Daemon...\n");
 	
+	if (check_status) {
+		check_lock();
+		exit(EXIT_SUCCESS);
+	}
+
 	/* acquire lock first.*/
-	acquire_lock();
+	acquire_lock(uuid);
 
 	if (daemon(0, 1) != 0) {
 		cl_perror("%s::%d: daemon() failed.", __FUNCTION__, __LINE__);
Index: resource-agents/tools/sfex_lib.c
===================================================================
--- resource-agents.orig/tools/sfex_lib.c	2011-10-31 17:40:14.000000000 +0800
+++ resource-agents/tools/sfex_lib.c	2011-11-08 13:05:46.000000000 +0800
@@ -192,7 +192,7 @@
 	    cdata->revision);
   snprintf ((char *) (block->blocksize), sizeof (block->blocksize), "%u",
 	    (unsigned)cdata->blocksize);
-  snprintf ((char *) (block->numlocks), sizeof (block->numlocks), "%d",
+  snprintf ((char *) (block->numlocks), sizeof (block->numlocks), "%lu",
 	    cdata->numlocks);
 
   fd = dev_fd;
@@ -252,6 +252,8 @@
 	    ldata->count);
   snprintf ((char *) (block->nodename), sizeof (block->nodename), "%s",
 	    ldata->nodename);
+  snprintf ((char *) (block->uuid), sizeof (block->uuid), "%s",
+	    ldata->uuid);
 
   fd = dev_fd;
 
@@ -419,11 +421,12 @@
   ldata->status = block->status;
   if (ldata->status != SFEX_STATUS_UNLOCK
       && ldata->status != SFEX_STATUS_LOCK) {
-    cl_log(LOG_ERR, "lock data format error.\n");
+    cl_log(LOG_ERR, "lock data format error:%d.\n",index);
     return -1;
   }
   ldata->count = atoi ((char *) (block->count));
   strncpy ((char *) (ldata->nodename), (const char *) (block->nodename), sizeof(block->nodename));
+  strncpy ((char *) (ldata->uuid), (const char *) (block->uuid), sizeof(block->uuid));
 
 #ifdef SFEX_DEBUG
   cl_log(LOG_INFO, "status: %c\n", ldata->status);
@@ -458,7 +461,7 @@
 #endif
 
         if (index > cdata->numlocks) {
-                cl_log(LOG_ERR, "index %d is too large. %d locks are stored.\n",
+                cl_log(LOG_ERR, "index %d is too large. %ld locks are stored.\n",
                                 index, cdata->numlocks);
                 return -1;
         }
Index: resource-agents/tools/sfex_stat.c
===================================================================
--- resource-agents.orig/tools/sfex_stat.c	2011-10-19 23:35:57.000000000 +0800
+++ resource-agents/tools/sfex_stat.c	2011-11-08 13:09:21.000000000 +0800
@@ -78,7 +78,7 @@
   printf("  version: %d\n", cdata->version);
   printf("  revision: %d\n", cdata->revision);
   printf("  blocksize: %d\n", (int)cdata->blocksize);
-  printf("  numlocks: %d\n", cdata->numlocks);
+  printf("  numlocks: %ld\n", cdata->numlocks);
 }
 
 /*
openSUSE Build Service is sponsored by