[Cluster-devel] cluster/gnbd bin/Makefile tools/gnbd_export/Ma ...

bmarzins at sourceware.org bmarzins at sourceware.org
Fri Jun 23 20:32:44 UTC 2006


CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL4
Changes by:	bmarzins at sourceware.org	2006-06-23 20:32:43

Modified files:
	gnbd/bin       : Makefile 
	gnbd/tools/gnbd_export: Makefile gnbd_export.c 
	gnbd/tools/gnbd_import: gnbd_import.c 
Added files:
	gnbd/tools/gnbd_export: gnbd_get_uid 

Log message:
	gnbd can now multipath exported partitions, instead of just whole devices.
	Also, multipathd will now automagically monitor the gnbd devices correctly,
	and multipath will now automagically create multipath devices on top of the
	appropriate gnbds when they are imported, just like it does with other
	block devices when they are loaded.
	Fixes bug 196084, and a bunch of other ones which never got bugzillas.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gnbd/bin/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.2&r2=1.2.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gnbd/tools/gnbd_export/gnbd_get_uid.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gnbd/tools/gnbd_export/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.1.2.4&r2=1.1.2.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gnbd/tools/gnbd_export/gnbd_export.c.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.5.2.3&r2=1.5.2.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gnbd/tools/gnbd_import/gnbd_import.c.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.11.2.4&r2=1.11.2.5

--- cluster/gnbd/bin/Makefile	2004/06/25 17:12:19	1.2
+++ cluster/gnbd/bin/Makefile	2006/06/23 20:32:43	1.2.2.1
@@ -22,7 +22,8 @@
 	gnbd_recvd \
 	gnbd_serv \
 	gnbd_monitor \
-	gnbd_clusterd
+	gnbd_clusterd \
+	gnbd_get_uid
 
 include ${top_srcdir}/make/defines.mk
 
--- cluster/gnbd/tools/gnbd_export/Makefile	2006/05/12 01:53:04	1.1.2.4
+++ cluster/gnbd/tools/gnbd_export/Makefile	2006/06/23 20:32:43	1.1.2.5
@@ -33,8 +33,9 @@
 gnbd_export: ${SOURCE}
 	${CC} ${CFLAGS} ${LDFLAGS} ${SOURCE} ${LOADLIBES} ${LDLIBS} -o $@
 
-copytobin: all
+copytobin: all gnbd_get_uid
 	cp ${TARGET} ${top_srcdir}/bin
+	cp gnbd_get_uid ${top_srcdir}/bin
 
 clean:
 	rm -f *.o ${TARGET}
--- cluster/gnbd/tools/gnbd_export/gnbd_export.c	2006/05/12 01:53:04	1.5.2.3
+++ cluster/gnbd/tools/gnbd_export/gnbd_export.c	2006/06/23 20:32:43	1.5.2.4
@@ -40,7 +40,7 @@
 #define TIMEOUT_DEFAULT 60
 
 #define MAN_MSG "Please see man page for details.\n"
-#define DEFAULT_GETUID "/sbin/scsi_id -g -u -s /block/%n"
+#define DEFAULT_GETUID "/sbin/gnbd_get_uid %n"
 
 int start_gnbd_clusterd(void)
 {
@@ -313,7 +313,8 @@
       printf("   timeout : %u\n", info->timeout);
     else
       printf("   timeout : no\n");
-    printf("       uid : %s\n", info->uid);
+    if (info->uid[0] != '\0')
+      printf("       uid : %s\n", info->uid);
     printf("\n");
     info++;
   }
@@ -341,54 +342,102 @@
   *minor = minor(stat_buf.st_rdev);
 }
 
+char *get_sysfs_info(char *path) {
+  int fd;
+  int bytes;
+  int count = 0;
+
+  if ((fd = open(path, O_RDONLY)) < 0) {
+    printe("cannot open %s : %s\n", path, strerror(errno));
+    exit(1);
+  }
+  while (count < 4096) {
+    bytes = read(fd, &sysfs_buf[count], 4096 - count);
+    if (bytes < 0 && errno != EINTR) {
+      printe("cannot read from %s : %s\n", path, strerror(errno));
+      exit(1);
+    }
+    if (bytes == 0)
+      break;
+    count += bytes;
+  }
+  if (sysfs_buf[count - 1] == '\n' || count == 4096)
+    sysfs_buf[count - 1] = '\0';
+  else
+    sysfs_buf[count] = '\0';
+  close(fd);
+  return sysfs_buf;
+}
+    
 #define SYSFS_PATH_MAX 64
 #define SYSFS_PATH_BASE "/sys/block"
 #define SYSFS_PATH_BASE_SIZE 10
-char *get_sysfs_name(char *dev_t){
+int get_sysfs_majmin(char *dev, int *major, int *minor)
+{
   char path[SYSFS_PATH_MAX];
+  char *buf;
+
+  if (snprintf(path, SYSFS_PATH_MAX, "%s/%s/dev", SYSFS_PATH_BASE, dev) >=
+      SYSFS_PATH_MAX) {
+    printe("sysfs path name '%s/%s/dev' too long\n", SYSFS_PATH_BASE, dev);
+    exit(1);
+  }
+  buf = get_sysfs_info(path);
+  if (sscanf(buf, "%u:%u", major, minor) != 2){
+    printe("cannot parse %s entry '%s'\n", path, buf);
+    exit(1);
+  }
+  return 0;
+}
+
+int get_sysfs_range(char *dev, int *range)
+{
+  char path[SYSFS_PATH_MAX];
+  char *buf;
+
+  if (snprintf(path, SYSFS_PATH_MAX, "%s/%s/range", SYSFS_PATH_BASE, dev) >=
+      SYSFS_PATH_MAX) {
+    printe("sysfs path name '%s/%s/range' too long\n", SYSFS_PATH_BASE, dev);
+    exit(1);
+  }
+  buf = get_sysfs_info(path);
+  if (sscanf(buf, "%u", range) != 1){
+    printe("cannot parse %s etnry '%s'\n", path, buf);
+    exit(1);
+  }
+  return 0;
+}
+
+char *get_sysfs_name(int major, int minor){
   char *name = NULL;
   DIR *dir;
   struct dirent *dp;
 
-  memset(path, 0, sizeof(path));
-  strcpy(path, SYSFS_PATH_BASE);
-  dir = opendir(path);
+  dir = opendir(SYSFS_PATH_BASE);
   if (!dir) {
-    printe("cannot open /sys/block to find the device name for %s : %s\n",
-           dev_t, strerror(errno));
+    printe("cannot open %s to find the device name for %d:%d : %s\n",
+           SYSFS_PATH_BASE, major, minor, strerror(errno));
     exit(1);
   }
   while ((dp = readdir(dir))) {
-    int fd;
-    int bytes;
-    int count = 0;
-
+    int dev_major, dev_minor, dev_range;
     if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
       continue;
-    snprintf(path + SYSFS_PATH_BASE_SIZE,
-	     SYSFS_PATH_MAX - SYSFS_PATH_BASE_SIZE - 1, "/%s/dev", dp->d_name);
-    fd = open(path, O_RDONLY);
-    if (fd < 0) {
-      printe("cannot open %s to find device name for %s : %s\n", path, dev_t,
-             strerror(errno));
-      exit(1);
-    }
-    while (count < 4096){
-      bytes = read(fd, &sysfs_buf[count], 4096 - count);
-      if (bytes < 0 && errno != EINTR) {
-        printe("cannot read from %s: %s\n", path, strerror(errno));
-        exit(1);
+    get_sysfs_majmin(dp->d_name, &dev_major, &dev_minor);
+    get_sysfs_range(dp->d_name, &dev_range);
+    if (major == dev_major && minor >= dev_minor &&
+        minor < dev_minor + dev_range){
+      if (minor == dev_minor)
+        name = strdup(dp->d_name);
+      else {
+        name = malloc(SYSFS_PATH_MAX);
+        if (!name){
+          printe("cannot allocate memory for sysfs name : %s\n",
+                 strerror(errno));
+          exit(1);
+        }
+        sprintf(name, "%s/%s%d", dp->d_name, dp->d_name, minor - dev_minor);
       }
-      if (bytes == 0)
-         break;
-      count += bytes;
-    }
-    if (count == 4096)
-      sysfs_buf[4095] = 0;
-    else
-      sysfs_buf[count] = 0;
-    if (strcmp(dev_t, sysfs_buf) == 0){
-      name = strdup(dp->d_name);
       break;
     }
   }
@@ -397,7 +446,7 @@
     exit(1);
   }
   if (!name) {
-    printe("cannot find sysfs block device %s\n", dev_t);
+    printe("cannot find sysfs block device %d:%d\n", major, minor);
     exit(1);
   }
   return name;
@@ -569,8 +618,7 @@
         if (!name){
           if (major == -1)
             get_dev(path, &major, &minor);
-          sprintf(temp, "%d:%d\n", major, minor);
-          name = get_sysfs_name(temp);
+          name = get_sysfs_name(major, minor);
         }
         len = strlen(name);
         if (len > SPACE_LEFT){
@@ -627,7 +675,7 @@
 "  -u <uid>         manually set the Unique ID of a device (used with -e)\n"
 "  -U[command]      command to get the Unique ID of a device (used with -e)\n"
 "                   If no command is specificed, the default is\n"
-"                   \"/sbin/scsi_id -g -u -s /block/%%n\"\n"
+"                   \"/sbin/gnbd_get_uid %%n\"\n"
 "  -v               verbose output (useful with -l)\n"
 "  -V               version information\n");
   return 0;
--- cluster/gnbd/tools/gnbd_import/gnbd_import.c	2006/03/22 21:45:51	1.11.2.4
+++ cluster/gnbd/tools/gnbd_import/gnbd_import.c	2006/06/23 20:32:43	1.11.2.5
@@ -101,9 +101,10 @@
                      ssize_t request_data_size)
 {
   int sock_fd;
-  int n, total;
+  int n, total = 0;
   uint32_t msg;
 
+  *buf = NULL;
   sock_fd = connect_to_server(host, (uint16_t)server_port);
   if (sock_fd < 0){
     printe("cannot connect to server %s (%d) : %s\n", host, sock_fd,
@@ -136,13 +137,14 @@
     exit(1);
   }
   msg = be32_to_cpu(msg);
+  if (!msg)
+    goto exit;
   *buf = malloc(msg);
   if (*buf == NULL){
     printe("couldn't allocate memory for server reply : %s\n", strerror(errno));
     exit(1);
   }
   memset(*buf, 0, msg);
-  total = 0;
   while(total < msg){
     n = read(sock_fd, *buf + total, msg - total);
     if (n <= 0){
@@ -152,6 +154,7 @@
     }
     total += n;
   }
+exit:
   close(sock_fd);
   return total;
 }
@@ -170,6 +173,10 @@
     return 0;
 
   read_from_server(host, EXTERN_NODENAME_REQ, &serv_node);
+  if (!serv_node) {
+    printe("got empty server name\n");
+    return -1;
+  }
 
   snprintf(cmd, 256, "gnbd_monitor %d %d %s", minor_nr, timeout, serv_node);
   ret = system(cmd);
@@ -569,6 +576,46 @@
   }
 }
 
+
+#define MULTIPATH_SCRIPT "/etc/dev.d/block/multipath.dev"
+void run_multipath_code(int minor_nr, int add)
+{
+  int i_am_parent, fd;
+  char *envp[6];
+  char devpath[32];
+  char devname[32];
+
+  i_am_parent = daemonize();
+  if (i_am_parent < 0){
+    printm("cannot daemonize to exec multipath code : %s\n", strerror(errno));	
+    return;
+  }
+  if (i_am_parent)
+    return;
+  if ((fd = open("/dev/null", O_RDWR)) < 0) {
+    printm("cannot open /dev/null in daemon : %s\n", strerror(errno));
+    exit(1);
+  }
+  dup2(fd, 0);
+  dup2(fd, 1);
+  dup2(fd, 2);
+  if (fd > 2)
+    close(fd);
+  envp[0] = "HOME=/";
+  envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+  envp[2] = (add)? "ACTION=add" : "ACTION=remove";
+  snprintf(devpath, 31, "DEVPATH=/block/gnbd%d", minor_nr);
+  devpath[31] = '\0';
+  envp[3] = devpath;
+  snprintf(devname, 31, "DEVNAME=/dev/gnbd%d", minor_nr);
+  devname[31] = '\0';
+  envp[4] = devname;
+  envp[5] = NULL;
+  execle(MULTIPATH_SCRIPT, MULTIPATH_SCRIPT, NULL, envp);
+  log_verbose("cannot exec %s : %s", MULTIPATH_SCRIPT, strerror(errno));
+  exit(1);
+}
+
 void remove_gnbd(char *name, int minor, int pid)
 {
   int fd;
@@ -595,6 +642,7 @@
   if (pid > 0)
   	kill(pid, SIGKILL);
   cleanup_device(name, minor, fd);
+  run_multipath_code(minor, 0);
   close(fd);
 }
 
@@ -980,6 +1028,8 @@
   int size;
   int minor_nr;
   size = read_from_server(host, EXTERN_NAMES_REQ, &buf);
+  if (!size)
+    return;
   ptr = (import_info_t *)buf;
   while ((char *)ptr < buf + size){
     if (ptr->timeout != 0 && is_clustered == 0){
@@ -992,6 +1042,7 @@
         exit(1);
       if (start_receiver(minor_nr))
         exit(1);
+      run_multipath_code(minor_nr, 1);
     }
     ptr++;
   }
@@ -1003,10 +1054,12 @@
   import_info_t *ptr;
   int size;
   size = read_from_server(host, EXTERN_NAMES_REQ, &buf);
-  ptr = (import_info_t *)buf;
-  while ((char *)ptr < buf + size){
-    printf("%s\n", ptr->name);
-    ptr++;
+  if (size) {
+    ptr = (import_info_t *)buf;
+    while ((char *)ptr < buf + size){
+      printf("%s\n", ptr->name);
+      ptr++;
+    }
   }
   printf("\n");
   free(buf);
@@ -1018,10 +1071,12 @@
   node_req_t *ptr;
   int size;
   size = read_from_server(host, EXTERN_LIST_BANNED_REQ, &buf);
-  ptr = (node_req_t *)buf;
-  while ((char *)ptr < buf + size){
-    printf("%s\n", ptr->node_name);
-    ptr++;
+  if (size) {
+    ptr = (node_req_t *)buf;
+    while ((char *)ptr < buf + size){
+      printf("%s\n", ptr->node_name);
+      ptr++;
+    }
   }
   printf("\n");
   free(buf);
@@ -1067,7 +1122,7 @@
   sscanf(name, "/block/gnbd%d", &minor_nr);
   list_foreach(item, &gnbd_list){
     gnbd = list_entry(item, gnbd_info_t, list);
-    if (minor_nr >= 0 && minor_nr == gnbd->minor_nr);
+    if (minor_nr >= 0 && minor_nr == gnbd->minor_nr)
       break;
     if (strncmp(gnbd->name, name, 32) == 0)
       break;
@@ -1080,7 +1135,8 @@
   strncpy(req.name, gnbd->name, 32);
   req.name[31] = 0;
   talk_to_server(gnbd->server_name, EXTERN_UID_REQ, &uid, &req, sizeof(req));
-  printf("%s\n", uid);
+  if (uid)
+  	printf("%s\n", uid);
   free(uid);
 }
   




More information about the Cluster-devel mailing list