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

[Cluster-devel] cluster/cman/qdisk Makefile README disk.c disk ...



CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	lhh sourceware org	2006-06-23 16:05:34

Modified files:
	cman/qdisk     : Makefile README disk.c disk.h main.c 
Added files:
	cman/qdisk     : mkqdisk.c proc.c 

Log message:
	Implements 'label' support for qdisk.  Uses /proc/partitions for device
	info & scans devices for signatures.  Useful in environments where a
	device is present but maybe numbered differently on different nodes
	depending on the host/SAN configuration.
	
	Also adds initialization utility which must be run before qdiskd will
	use a given partition.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/qdisk/mkqdisk.c.diff?cvsroot=cluster&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/qdisk/proc.c.diff?cvsroot=cluster&r1=1.1&r2=1.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/qdisk/Makefile.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/qdisk/README.diff?cvsroot=cluster&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/qdisk/disk.c.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/qdisk/disk.h.diff?cvsroot=cluster&r1=1.2&r2=1.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/cman/qdisk/main.c.diff?cvsroot=cluster&r1=1.2&r2=1.3

--- cluster/cman/qdisk/mkqdisk.c	2006/06/23 16:01:02	1.1
+++ cluster/cman/qdisk/mkqdisk.c	2006/06/23 16:05:33	1.2
@@ -0,0 +1,92 @@
+/**
+  Copyright Red Hat, Inc. 2006
+
+  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: Lon Hohberger <lhh at redhat.com>
+ */
+/**
+  @file Quorum disk utility
+ */
+#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>
+
+
+int
+main(int argc, char **argv)
+{
+	char device[128];
+	char *newdev = NULL, *newlabel = NULL;
+	int rv;
+
+	printf("mkqdisk v0.5\n");
+
+	while ((rv = getopt(argc, argv, "Lfc:l:h")) != EOF) {
+		switch (rv) {
+		case 'L':
+			/* List */
+			close(2);
+			return find_partitions("/proc/partitions",
+					       NULL, NULL, 0, 1);
+			break;
+		case 'f':
+			close(2);
+			return find_partitions("/proc/partitions",
+					       optarg, device,
+					       sizeof(device), 0);
+		case 'c':
+			newdev = optarg;
+			break;
+		case 'l':
+			newlabel = optarg;
+			break;
+		case 'h':
+			printf("usage: mkqdisk -L | -f <label> | -c "
+			       "<device> -l <label>\n");
+			return 0;
+		default:
+			break;
+		}
+	}
+
+	if (!newdev && !newlabel) {
+		printf("usage: mkqdisk -L | -f <label> | -c "
+		       "<device> -l <label>\n");
+		return 1;
+	}
+
+	if (!newdev || !newlabel) {
+		printf("Both a device and a label are required\n");
+		return 1;
+	}
+
+	printf("Writing new quorum disk label '%s' to %s.\n",
+	       newlabel, newdev);
+	printf("WARNING: About to destroy all data on %s; proceed [N/y] ? ",
+	       newdev);
+	if (getc(stdin) != 'y') {
+		printf("Good thinking.\n");
+		return 0;
+	}
+
+	return qdisk_init(newdev, newlabel);
+}
--- cluster/cman/qdisk/proc.c	2006/06/23 16:01:02	1.1
+++ cluster/cman/qdisk/proc.c	2006/06/23 16:05:33	1.2
@@ -0,0 +1,128 @@
+/**
+  Copyright Red Hat, Inc. 2006
+
+  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: Lon Hohberger <lhh at redhat.com>
+ */
+/**
+  @file Quorum disk /proc/partition scanning functions
+ */
+#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>
+
+
+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,
+	        char *devname, size_t devlen, int print)
+{
+	char line[4096];
+	FILE *fp;
+	int minor, major;
+	unsigned long long blkcnt;
+	char device[128];
+	char realdev[256];
+	quorum_header_t qh;
+
+	fp = fopen(partfile, "r");
+	if (!fp)
+		return -1;
+
+	while (fgets(line, sizeof(line), fp) != NULL) {
+		if (strlen(line) > 128 + (22) /* 5 + 5 + 11 + 1 */) {
+			/*printf("Line too long!\n");*/
+			continue;
+		}
+
+		/* This line is taken from 2.6.15.4's proc line */
+		sscanf(line, "%4d %4d %10llu %s", &major, &minor,
+		       &blkcnt, device);
+
+		if (strlen(device)) {
+			snprintf(realdev, sizeof(realdev),
+				 "/dev/%s", device);
+			if (check_device(realdev, (char *)label, &qh) != 0)
+				continue;
+
+			if (print) {
+				printf("%s:\n", realdev);
+				printf("\tMagic:   %08x\n", qh.qh_magic);
+				printf("\tLabel:   %s\n", qh.qh_cluster);
+				printf("\tCreated: %s",
+				       ctime((time_t *)&qh.qh_timestamp));
+				printf("\tHost:    %s\n\n", qh.qh_updatehost);
+			}
+
+			if (devname && devlen) {
+				/* Got it */
+				strncpy(devname, realdev, devlen);
+				fclose(fp);
+				return 0;
+			}
+		}
+	}
+
+	fclose(fp);
+
+	if (print)
+		/* No errors if we're just printing stuff */
+		return 0;
+
+	errno = ENOENT;
+	return -1;
+}
--- cluster/cman/qdisk/Makefile	2006/05/31 21:07:06	1.3
+++ cluster/cman/qdisk/Makefile	2006/06/23 16:05:33	1.4
@@ -19,26 +19,30 @@
 CFLAGS +=-I${ccsincdir} -I${incdir} -I${top_srcdir}/config \
          -Wall -Werror -Wstrict-prototypes -Wshadow -D_GNU_SOURCE -g
 
-TARGET=qdiskd
+TARGET=qdiskd mkqdisk
 
 all: ${TARGET}
 
 copytobin: all
 	cp ${TARGET} ${top_srcdir}/bin
 
-install: qdiskd
+install: ${TARGET}
 	install -d ${sbindir}
-	install qdiskd ${sbindir}
+	install ${TARGET} ${sbindir}
 
 qdiskd: disk.o crc32.o disk_util.o main.o score.o bitmap.o clulog.o \
-	gettid.o ../lib/libcman.a
+	gettid.o proc.o ../lib/libcman.a
 	gcc -o $@ $^ -lpthread -L../lib -L${ccslibdir} -lccs
 
+mkqdisk: disk.o crc32.o disk_util.o \
+	 proc.o mkqdisk.o
+ 	gcc -o $@ $^ 
+
 %.o: %.c
 	$(CC) -c -o $@ $^ $(INCLUDES) $(CFLAGS)
 
 clean:
-	rm -f *.o qdiskd
+	rm -f *.o ${TARGET}
 
 uninstall:
-	${UNINSTALL} qdiskd ${sbindir}
+	${UNINSTALL} ${TARGET} ${sbindir}
--- cluster/cman/qdisk/README	2006/05/19 14:41:35	1.2
+++ cluster/cman/qdisk/README	2006/06/23 16:05:33	1.3
@@ -213,8 +213,16 @@
     min_score="3"	  Absolute minimum score to be consider one's
 			  self "alive".  If omitted, or set to 0, the
 			  default function "floor((n+1)/2)" is used.
-    device="/dev/sda1"/>  This is the device the quorum daemon will use.
+    device="/dev/sda1"    This is the device the quorum daemon will use.
 			  This device must be the same on all nodes.
+    label="mylabel"/>     This overrides the device field if present.
+			  If specified, the quorum daemon will read
+			  /proc/partitions and check for qdisk signatures
+			  on every block device found, comparing the label
+			  against the specified label.  This is useful in
+			  configurations where the block device name
+			  differs on a per-node basis.
+
 
 3.2.  The <heuristic> tag
 
@@ -249,3 +257,18 @@
 * The worst-case for improperly configured quorum heuristics is a race
 to fence where two partitions simultaneously try to kill each other.
 
+3.5. Creating a quorum disk partition
+
+3.5.1. The mkqdisk utility.
+
+The mkqdisk utility can create and list currently configured quorum disks
+visible to the local node.
+
+  mkqdisk -L		List available quorum disks.
+
+  mkqdisk -f <label>	Find a quorum device by the given label.
+
+  mkqdisk -c <device> -l <label>
+			Initialize <device> and name it <label>.  This
+			will destroy all data on the device, so be careful
+			when running this command.
--- cluster/cman/qdisk/disk.c	2006/05/22 17:33:22	1.3
+++ cluster/cman/qdisk/disk.c	2006/06/23 16:05:33	1.4
@@ -336,7 +336,8 @@
 		       "diskRawReadShadow: can't seek to offset %d.\n",
 		       (int) readOffset);
 #endif
-		return ENODATA;
+		errno = ENODATA;
+		return -1;
 	}
 
 	ret = diskRawRead(fd, buf, len);
@@ -345,7 +346,8 @@
 		fprintf(stderr, "diskRawReadShadow: aligned read "
 		       "returned %d, not %d.\n", ret, len);
 #endif
-		return ENODATA;
+		errno = ENODATA;
+		return -1;
 	}
 
 	/* Decode the header portion so we can run a checksum on it. */
@@ -360,7 +362,8 @@
 		       "fd = %d offset = %d len = %d\n", fd,
 		       (int) readOffset, len);
 #endif
-		return EPROTO;
+		errno = EPROTO;
+		return -1;
 	}
 
 	return 0;
@@ -655,7 +658,7 @@
 
 
 static int
-header_init(int fd, char *clustername)
+header_init(int fd, char *label)
 {
 	quorum_header_t qh;
 
@@ -675,6 +678,9 @@
 		return -1;
 	}
 
+	/* Copy in the cluster/label name */
+	snprintf(qh.qh_cluster, sizeof(qh.qh_cluster)-1, label);
+
 	if ((qh.qh_timestamp = (uint64_t)time(NULL)) <= 0) {
 		perror("time");
 		return -1;
@@ -691,7 +697,7 @@
 
 
 int
-qdisk_init(char *partname, char *clustername)
+qdisk_init(char *partname, char *label)
 {
 	int fd;
 	status_block_t ps, wps;
@@ -710,7 +716,7 @@
 		return -1;
 	}
 
-	if (header_init(fd, clustername) < 0) {
+	if (header_init(fd, label) < 0) {
 		return -1;
 	}
 
--- cluster/cman/qdisk/disk.h	2006/05/19 14:41:35	1.2
+++ cluster/cman/qdisk/disk.h	2006/06/23 16:05:33	1.3
@@ -238,6 +238,7 @@
 	int qc_unused;
 	cman_handle_t qc_ch;
 	char *qc_device;
+	char *qc_label;
 	char *qc_status_file;
 } qd_ctx;
 
@@ -259,4 +260,10 @@
 int qd_init(qd_ctx *ctx, cman_handle_t ch, int me);
 void qd_destroy(qd_ctx *ctx);
 
+/* proc.c */
+int find_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);
+
+
 #endif
--- cluster/cman/qdisk/main.c	2006/05/19 14:41:35	1.2
+++ cluster/cman/qdisk/main.c	2006/06/23 16:05:33	1.3
@@ -880,6 +880,12 @@
 		ctx->qc_device = val;
 	}
 
+	/* Get label (overrides device) */
+	snprintf(query, sizeof(query), "/cluster/quorumd/@label");
+	if (ccs_get(ccsfd, query, &val) == 0) {
+		ctx->qc_label = val;
+	}
+
 	/* Get status file */
 	snprintf(query, sizeof(query), "/cluster/quorumd/@status_file");
 	if (ccs_get(ccsfd, query, &val) == 0) {
@@ -917,6 +923,7 @@
 	node_info_t ni[MAX_NODES_DISK];
 	struct h_data h[10];
 	char debug = 0, foreground = 0;
+	char device[128];
 
 	while ((rv = getopt(argc, argv, "fd")) != EOF) {
 		switch (rv) {
@@ -958,6 +965,32 @@
 		return -1;
 	}
 
+	if (ctx.qc_label) {
+		if (find_partitions("/proc/partitions",
+				    ctx.qc_label, device,
+				    sizeof(device), 0) != 0) {
+			clulog_and_print(LOG_CRIT, "Unable to match label"
+					 " '%s' to any device\n",
+					 ctx.qc_label);
+			return -1;
+		}
+
+		if (ctx.qc_device)
+			free(ctx.qc_device);
+
+		ctx.qc_device = strdup(device);
+
+		clulog(LOG_INFO, "Quorum Partition: %s Label: %s\n",
+		       ctx.qc_device, ctx.qc_label);
+	} else if (ctx.qc_device) {
+		if (check_device(ctx.qc_device, NULL, NULL) != 0) {
+			clulog(LOG_CRIT,
+			       "Specified partition %s does not have a "
+			       "qdisk label\n", ctx.qc_device);
+			return -1;
+		}
+	}
+
 	if (!foreground)
                 daemon(0,0);
 


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