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);
}
/*