[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [PATCH] cman/qdiskd: fix bugzilla 362031



Hi guys,

the patch in attachment does:

- create a find_partition wrapper for find_sysfs_partitions and
find_proc_partitions (for backward compatibility)

- move check_device from proc.c to disk.c as it is now used by sysfs too.

- create a common print_qh from proc.c in disk.c as it is shared.

- cleanup proc.c and make find_proc_partitions use print_qh.

- add a whole bunch of stuff in sysfs.c:
  - sysfs_nodes_init is used to create and clean /dev/.qdiskd namespace where we
    can work without interfering with other /dev management tools.
  - create_node takes care to properly mknod given a sysfs path to a block
    device.
  - find_sysfs_partitions that does the real scanning. This is the most tricky
    one as it needs to be recursive due to the very nature of sysfs layout.
  - NOTE: I left the original RH copyright for this file on purpose to avoid any
    kind of possible legal issues in case of relicensing or whatever. If this
    might be a problem, somebody can just commit the patch for me. I give out
    all permissions to use/reuse it and etc. I don't even care about having my
    name in the author to be honest :)

- main.c:
  - invoke sysfs_nodes_init. NOTE: in case we decide to backport, this should
    probably be non-fatal and the find_partition wrapper updated to use proc
    before sysfs.
  - memset device to make sure it's a 0 len string when passed around. It is
    useful in find_sysfs_partition to break the recursion loop once we find the
    device.

- mkqdisk.c
  - remove static version for release and use RELEASE_VERSION.
  - invoke sysfs_nodes_init. Same note as above applies here.

- update copyright dates here and there.

- update Makefile.

I tested the patch by using a shared block device like NBD that does not appear
in /proc/partitions and asking qdiskd to find it by label and everything seems
to work fine. mkqdisk -L and -f work. You might want to note that Device
names are now owned by our node manager and might not reflect user expectations.
If the patch goes in, we should properly update the documentation explaining
why device names don't match but everything will work as expected.

Please review :)

Thanks
Fabio
diff -Naurd cluster.orig/cman/qdisk/disk.c cluster/cman/qdisk/disk.c
--- cluster.orig/cman/qdisk/disk.c	2007-10-29 01:21:40.000000000 -0400
+++ cluster/cman/qdisk/disk.c	2007-11-07 15:29:15.000000000 -0500
@@ -1,5 +1,5 @@
 /*
-  Copyright Red Hat, Inc. 2002-2003, 2006
+  Copyright Red Hat, Inc. 2002-2003, 2006-2007
   Copyright Mission Critical Linux, 2000
 
   This program is free software; you can redistribute it and/or modify it
@@ -760,3 +760,63 @@
 	return 0;
 }
 
+int
+check_device(char *device, char *label, quorum_header_t *qh)
+{
+	int fd = -1, ret = -1;
+	quorum_header_t qh_local;
+
+	if (!qh)
+		qh = &qh_local;
+
+	fd = qdisk_validate(device);
+	if (fd < 0) {
+		perror("qdisk_verify");
+		return -1;
+	}
+
+	fd = qdisk_open(device);
+	if (fd < 0) {
+		perror("qdisk_open");
+		return -1;
+	}
+
+	if (qdisk_read(fd, OFFSET_HEADER, qh, sizeof(*qh)) == sizeof(*qh)) {
+		swab_quorum_header_t(qh);
+                if (qh->qh_magic == HEADER_MAGIC_NUMBER) {
+			if (!label || !strcmp(qh->qh_cluster, label)) {
+				ret = 0;
+			}
+                }
+        }
+
+	qdisk_close(&fd);
+
+	return ret;
+}
+
+void print_qh(char *realdev, quorum_header_t *qh)
+{
+	time_t timestamp = qh->qh_timestamp;
+	printf("%s:\n", realdev);
+	printf("\tMagic:   %08x\n", qh->qh_magic);
+	printf("\tLabel:   %s\n", qh->qh_cluster);
+	printf("\tCreated: %s",
+		ctime((time_t *)&timestamp));
+	printf("\tHost:    %s\n\n", qh->qh_updatehost);
+
+	return;
+}
+
+int find_partitions(const char *partfile, const char *label, char *devname, size_t devlen, int print)
+{
+	int ret;
+
+	ret=find_sysfs_partitions("/sys/block", label, devname, devlen, print);
+
+	if ((!ret) || (ret && print))
+		return 0;
+
+	return find_proc_partitions(partfile, label, devname, devlen, print);
+}
+
diff -Naurd cluster.orig/cman/qdisk/disk.h cluster/cman/qdisk/disk.h
--- cluster.orig/cman/qdisk/disk.h	2007-02-21 15:24:30.000000000 -0500
+++ cluster/cman/qdisk/disk.h	2007-11-07 15:23:12.000000000 -0500
@@ -218,6 +218,8 @@
 int qdisk_validate(char *name);
 int qdisk_read(int fd, __off64_t ofs, void *buf, int len);
 int qdisk_write(int fd, __off64_t ofs, const void *buf, int len);
+int check_device(char *device, char *label, quorum_header_t *qh);
+void print_qh(char *realdev, quorum_header_t *qh);
 
 #define qdisk_nodeid_offset(nodeid) \
 	(OFFSET_FIRST_STATUS_BLOCK + (SPACE_PER_STATUS_BLOCK * (nodeid - 1)))
@@ -277,9 +279,15 @@
 void qd_destroy(qd_ctx *ctx);
 
 /* proc.c */
-int find_partitions(const char *partfile, const char *label,
+int find_proc_partitions(const char *partfile, const char *label,
 		    char *devname, size_t devlen, int print);
-int check_device(char *device, char *label, quorum_header_t *qh);
+/* sysfs.c */
+int find_sysfs_partitions(const char *partfile, const char *label,
+		    char *devname, size_t devlen, int print);
+int sysfs_nodes_init(void);
 
+/* disk.c */
+int find_partitions(const char *partfile, const char *label,
+		    char *devname, size_t devlen, int print);
 
 #endif
diff -Naurd cluster.orig/cman/qdisk/main.c cluster/cman/qdisk/main.c
--- cluster.orig/cman/qdisk/main.c	2007-10-30 00:32:07.000000000 -0400
+++ cluster/cman/qdisk/main.c	2007-11-08 06:47:09.000000000 -0500
@@ -1412,7 +1412,12 @@
 		printf("QDisk services already running\n");
 		return 0;
 	}
-	
+
+	if (sysfs_nodes_init()) {
+		printf("QDisk was unable to init sysfs nodes\n");
+		return 0;
+	}
+
 	while ((rv = getopt(argc, argv, "fdQ")) != EOF) {
 		switch (rv) {
 		case 'd':
@@ -1491,6 +1496,7 @@
 	}
 	
 	if (ctx.qc_label) {
+		memset(device, 0, sizeof(device));
 		if (find_partitions("/proc/partitions",
 				    ctx.qc_label, device,
 				    sizeof(device), 0) != 0) {
diff -Naurd cluster.orig/cman/qdisk/Makefile cluster/cman/qdisk/Makefile
--- cluster.orig/cman/qdisk/Makefile	2007-08-29 23:16:33.000000000 -0400
+++ cluster/cman/qdisk/Makefile	2007-11-07 15:45:54.000000000 -0500
@@ -36,7 +36,8 @@
 SHAREDOBJS= disk.o \
 	    crc32.o \
 	    disk_util.o \
-	    proc.o
+	    proc.o \
+	    sysfs.o
 
 all: depends ${TARGET1} ${TARGET2}
 
diff -Naurd cluster.orig/cman/qdisk/mkqdisk.c cluster/cman/qdisk/mkqdisk.c
--- cluster.orig/cman/qdisk/mkqdisk.c	2006-11-21 09:50:49.000000000 -0500
+++ cluster/cman/qdisk/mkqdisk.c	2007-11-07 15:36:49.000000000 -0500
@@ -39,7 +39,12 @@
 	char *newdev = NULL, *newlabel = NULL;
 	int rv;
 
-	printf("mkqdisk v0.5.1\n");
+	printf("mkqdisk v" RELEASE_VERSION "\n");
+
+	if (sysfs_nodes_init()) {
+		printf("QDisk was unable to init sysfs nodes\n");
+		return 0;
+	}
 
 	while ((rv = getopt(argc, argv, "Lf:c:l:h")) != EOF) {
 		switch (rv) {
diff -Naurd cluster.orig/cman/qdisk/proc.c cluster/cman/qdisk/proc.c
--- cluster.orig/cman/qdisk/proc.c	2007-09-11 08:40:16.000000000 -0400
+++ cluster/cman/qdisk/proc.c	2007-11-07 15:10:11.000000000 -0500
@@ -1,5 +1,5 @@
 /**
-  Copyright Red Hat, Inc. 2006
+  Copyright Red Hat, Inc. 2006-2007
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
@@ -19,56 +19,16 @@
   Author: Lon Hohberger <lhh at redhat.com>
  */
 /**
-  @file Quorum disk /proc/partition scanning functions
+  @file Quorum disk /proc/partition scanning function
  */
 #include <stdio.h>
-#include <stdlib.h>
-#include <disk.h>
 #include <errno.h>
-#include <sys/types.h>
-#include <platform.h>
-#include <stdlib.h>
 #include <string.h>
 
+#include "disk.h"
 
 int
-check_device(char *device, char *label, quorum_header_t *qh)
-{
-	int fd = -1, ret = -1;
-	quorum_header_t qh_local;
-
-	if (!qh)
-		qh = &qh_local;
-
-	fd = qdisk_validate(device);
-	if (fd < 0) {
-		perror("qdisk_verify");
-		return -1;
-	}
-
-	fd = qdisk_open(device);
-	if (fd < 0) {
-		perror("qdisk_open");
-		return -1;
-	}
-
-	if (qdisk_read(fd, OFFSET_HEADER, qh, sizeof(*qh)) == sizeof(*qh)) {
-		swab_quorum_header_t(qh);
-                if (qh->qh_magic == HEADER_MAGIC_NUMBER) {
-			if (!label || !strcmp(qh->qh_cluster, label)) {
-				ret = 0;
-			}
-                }
-        }
-
-	qdisk_close(&fd);
-
-	return ret;
-}
-
-
-int
-find_partitions(const char *partfile, const char *label,
+find_proc_partitions(const char *partfile, const char *label,
 	        char *devname, size_t devlen, int print)
 {
 	char line[4096];
@@ -99,15 +59,8 @@
 			if (check_device(realdev, (char *)label, &qh) != 0)
 				continue;
 
-			if (print) {
-				time_t timestamp = qh.qh_timestamp;
-				printf("%s:\n", realdev);
-				printf("\tMagic:   %08x\n", qh.qh_magic);
-				printf("\tLabel:   %s\n", qh.qh_cluster);
-				printf("\tCreated: %s",
-				       ctime((time_t *)&timestamp));
-				printf("\tHost:    %s\n\n", qh.qh_updatehost);
-			}
+			if (print)
+				print_qh(realdev, &qh);
 
 			if (devname && devlen) {
 				/* Got it */
diff -Naurd cluster.orig/cman/qdisk/sysfs.c cluster/cman/qdisk/sysfs.c
--- cluster.orig/cman/qdisk/sysfs.c	1969-12-31 19:00:00.000000000 -0500
+++ cluster/cman/qdisk/sysfs.c	2007-11-08 06:52:24.000000000 -0500
@@ -0,0 +1,192 @@
+/**
+  Copyright Red Hat, Inc. 2007
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge,
+  MA 02139, USA.
+
+  Author: Fabio M. Di Nitto <fabbione at ubuntu.com>
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <libgen.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/sysmacros.h>
+
+#include "disk.h"
+
+#define DEVPATH "/dev/.qdiskd"
+
+int sysfs_nodes_init(void)
+{
+	DIR *dir;
+	struct dirent *de;
+	struct stat sb;
+	int flushme;
+	mode_t oldumask;
+	char *fn;
+	char path[256];
+
+	if (stat(DEVPATH, &sb)) {
+		if (errno != ENOENT) {
+			printf("ERROR: Unable to access " DEVPATH ". Please clean up manually\n");
+			return -1;
+		}
+		flushme=0;
+		oldumask=umask(0);
+		if (mkdir(DEVPATH, S_IRWXU)) {
+			printf("ERROR: Unable to create " DEVPATH ". Please make sure to have permissions to create the directory\n");
+			return -1;
+		}
+		umask(oldumask);
+	} else {
+		if (!S_ISDIR(sb.st_mode)) {
+			printf("ERROR: " DEVPATH " is not a directory. Please check and remove manually before running qdiskd\n");
+			return -1;
+		}
+		flushme=1;
+	}
+
+	/* at this point DEVPATH is either there or created and it is a directory */
+	dir = opendir(DEVPATH);
+
+	/* remove possible stale nodes */
+	if (flushme) {
+		while ((de = readdir(dir))) {
+			fn = basename(de->d_name);
+			if (!fn)
+				continue;
+
+			/* if the filename has our *cough*magic*cough* label
+			 * we kill it.
+			 */
+			if (strstr(fn, "qdisk")) {
+
+				snprintf(path, sizeof(path), DEVPATH "/%s", de->d_name);
+
+				if (stat(path, &sb))
+					continue;
+
+				if (!S_ISBLK(sb.st_mode))
+					continue;
+
+				if (unlink(path)) {
+					printf("WARNING: Unable to unlink %s\n", path);
+				}
+			}
+		}
+	}
+
+	closedir(dir);
+
+	return 0;
+}
+
+/* given a syspath, create a block device node.
+ * return a path to the created device or null on error. Remember to free the result.
+ */
+static char *create_node(char *sysfspath)
+{
+	char *node;
+	FILE *fd;
+	mode_t oldumask;
+	int major, minor, err;
+	dev_t device;
+
+	node=malloc(256);
+	if (!node)
+		return node;
+
+	fd = fopen(sysfspath, "r");
+	if (!fd) {
+		printf("ERROR: Unable to open %s\n", sysfspath);
+		return NULL;
+	} else {
+		/* get the maj/min from sysfs */
+		fscanf(fd, "%4d:%4d", &major, &minor);
+		fclose(fd);
+		device=makedev(major, minor);
+		snprintf(node, 256, DEVPATH "/qdisk-%d-%d", major, minor);
+		oldumask=umask(0);
+		err=mknod(node, S_IFBLK | S_IRUSR | S_IWUSR, device);
+		umask(oldumask);
+		if (!err)
+			return node;
+	}
+
+	return NULL;
+}
+
+int
+find_sysfs_partitions(const char *partfile, const char *label,
+		char *devname, size_t devlen, int print)
+{
+	struct dirent **namelist;
+	struct stat sb;
+	char newpath[256];
+	char *node;
+	int n;
+	quorum_header_t qh;
+
+	n = scandir(partfile, &namelist, 0, alphasort);
+	if (n <= 0)
+		return -1;
+
+	while (n--) {
+		/* filter out .. and . */
+		if (strcmp(namelist[n]->d_name, ".") && strcmp(namelist[n]->d_name, "..")) {
+			snprintf(newpath, sizeof(newpath), "%s/%s", partfile, namelist[n]->d_name);
+			if (!lstat(newpath, &sb)) {
+				/* dive into directories */
+				if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
+					if (!find_sysfs_partitions(newpath, label, devname, devlen, print)) {
+						if (devname && (strlen(devname) > 0))
+							return 0;
+						}
+				}
+				/* check regular files (dev) */
+				if (S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
+					if (!strcmp(namelist[n]->d_name, "dev")) {
+						node=create_node(newpath);
+						if (node) {
+							if (!check_device(node, (char *)label, &qh)) {
+								if (print)
+									print_qh(node, &qh);
+
+								if (devname && devlen) {
+									strncpy(devname, node, devlen);
+									free(node);
+									return 0;
+								}
+							}
+							unlink(node);
+							free(node);
+						}
+					}
+				}
+			}
+		}
+		free(namelist[n]);
+	}
+
+	errno = ENOENT;
+	return -1;
+}

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]