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

[Cluster-devel] Cluster Project branch, RHEL5, updated. cmirror_1_1_15-114-g6f5127d



This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Cluster Project".

http://sources.redhat.com/git/gitweb.cgi?p=cluster.git;a=commitdiff;h=6f5127de838baf655212e2122b44823fc75da452

The branch, RHEL5 has been updated
       via  6f5127de838baf655212e2122b44823fc75da452 (commit)
      from  28ad2cde0e76c92ece9a28b453b931a43c584340 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6f5127de838baf655212e2122b44823fc75da452
Author: Lon Hohberger <lhh redhat com>
Date:   Thu Jun 12 15:01:21 2008 -0400

    [qdisk] Merge scandisk in to RHEL5 branch
    
    - Scandisk written by Fabio M. Di Nitto
    - Bump mkqdisk's version string to 0.6.0
    - Fixes type casting errors on some architectures
    - Resolves Red Hat bugzilla #362031

-----------------------------------------------------------------------

Summary of changes:
 cman/qdisk/Makefile    |    4 +-
 cman/qdisk/disk.c      |   20 +-
 cman/qdisk/disk.h      |    9 +-
 cman/qdisk/disk_util.c |    2 +-
 cman/qdisk/main.c      |   42 ++--
 cman/qdisk/mkqdisk.c   |    8 +-
 cman/qdisk/proc.c      |  176 +++++++-----
 cman/qdisk/scandisk.c  |  751 ++++++++++++++++++++++++++++++++++++++++++++++++
 cman/qdisk/scandisk.h  |  105 +++++++
 9 files changed, 1010 insertions(+), 107 deletions(-)
 create mode 100644 cman/qdisk/scandisk.c
 create mode 100644 cman/qdisk/scandisk.h

diff --git a/cman/qdisk/Makefile b/cman/qdisk/Makefile
index f68fa5c..23d0890 100644
--- a/cman/qdisk/Makefile
+++ b/cman/qdisk/Makefile
@@ -28,11 +28,11 @@ install: all
 	install ${TARGET} ${sbindir}
 
 qdiskd: disk.o crc32.o disk_util.o main.o score.o bitmap.o clulog.o \
-	gettid.o proc.o daemon_init.o  ../lib/libcman.a
+	gettid.o proc.o daemon_init.o scandisk.o ../lib/libcman.a
 	gcc -o $@ $^ -lpthread -L../lib -L${ccslibdir} -lccs
 
 mkqdisk: disk.o crc32.o disk_util.o \
-	 proc.o mkqdisk.o
+	 proc.o mkqdisk.o scandisk.o
 	gcc -o $@ $^ 
 
 %.o: %.c
diff --git a/cman/qdisk/disk.c b/cman/qdisk/disk.c
index cd9a462..f3222ed 100644
--- a/cman/qdisk/disk.c
+++ b/cman/qdisk/disk.c
@@ -385,7 +385,7 @@ diskRawReadShadow(target_info_t *disk, off_t readOffset, char *buf, int len)
 static int
 diskRawRead(target_info_t *disk, char *buf, int len)
 {
-	char *alignedBuf;
+	void *alignedBuf;
 	int readret;
 	int extraLength;
 	int readlen;
@@ -458,7 +458,7 @@ diskRawRead(target_info_t *disk, char *buf, int len)
 static int
 diskRawWrite(target_info_t *disk, char *buf, int len)
 {
-	char *alignedBuf;
+	void *alignedBuf;
 	int ret;
 	int extraLength;
 	int writelen;
@@ -567,6 +567,7 @@ int
 qdisk_read(target_info_t *disk, __off64_t offset, void *buf, int count)
 {
 	shared_header_t *hdrp;
+	void *ptr;
 	char *data;
 	size_t total;
 	int rv;
@@ -583,14 +584,15 @@ qdisk_read(target_info_t *disk, __off64_t offset, void *buf, int count)
 	if (total % disk->d_blksz) 
 		total = total + (disk->d_blksz * !!(total % disk->d_blksz)) - (total % disk->d_blksz);
 
-	hdrp = NULL;
-	rv = posix_memalign((void **)&hdrp, disk->d_pagesz, disk->d_blksz);
+	ptr = NULL;
+	rv = posix_memalign((void **)&ptr, disk->d_pagesz, disk->d_blksz);
 	if (rv < 0)
 		return -1;
 
-	if (hdrp == NULL) 
+	if (ptr == NULL) 
 		return -1;
 
+	hdrp = (shared_header_t *)ptr;
 	data = (char *)hdrp + sizeof(shared_header_t);
 
 	rv = diskRawReadShadow(disk, offset, (char *)hdrp, disk->d_blksz);
@@ -618,6 +620,7 @@ qdisk_write(target_info_t *disk, __off64_t offset, const void *buf, int count)
 {
 	size_t maxsize;
 	shared_header_t *hdrp;
+	void *ptr;
 	char *data;
 	size_t total = 0, rv = -1, psz = disk->d_blksz; //sysconf(_SC_PAGESIZE);
 
@@ -640,8 +643,8 @@ qdisk_write(target_info_t *disk, __off64_t offset, const void *buf, int count)
 	if (total % psz) 
 		total = total + (psz * !!(total % psz)) - (total % psz);
 
-	hdrp = NULL;
-	rv = posix_memalign((void **)&hdrp, disk->d_pagesz, total);
+	ptr = NULL;
+	rv = posix_memalign((void **)&ptr, disk->d_pagesz, total);
 	if (rv < 0) {
 		perror("posix_memalign");
 		return -1;
@@ -650,6 +653,7 @@ qdisk_write(target_info_t *disk, __off64_t offset, const void *buf, int count)
 	/* 
 	 * Copy the data into our new buffer
 	 */
+	hdrp = (shared_header_t *)ptr;
 	data = (char *)hdrp + sizeof(shared_header_t);
 	memcpy(data, buf, count);
 
@@ -708,7 +712,7 @@ header_init(target_info_t *disk, char *label)
 
 	qh.qh_magic = HEADER_MAGIC_NUMBER;
 	qh.qh_blksz = disk->d_blksz;
-	qh.qh_pad = 0;
+	qh.qh_kernsz = 0;
 
 	swab_quorum_header_t(&qh);
 	if (qdisk_write(disk, OFFSET_HEADER, &qh, sizeof(qh)) != sizeof(qh)) {
diff --git a/cman/qdisk/disk.h b/cman/qdisk/disk.h
index 0856f2e..8c9a424 100644
--- a/cman/qdisk/disk.h
+++ b/cman/qdisk/disk.h
@@ -162,7 +162,7 @@ typedef struct __attribute__ ((packed)) {
 	char		qh_cluster[120];   // Cluster name; CMAN only 
 					   // supports 16 chars.
 	uint32_t	qh_blksz;          // Known block size @ creation
-	uint32_t	qh_pad;
+	uint32_t	qh_kernsz;	   // Ingored
 } quorum_header_t;
 
 #define swab_quorum_header_t(ptr) \
@@ -170,7 +170,7 @@ typedef struct __attribute__ ((packed)) {
 	swab32((ptr)->qh_magic); \
 	swab32((ptr)->qh_version); \
 	swab32((ptr)->qh_blksz); \
-	swab32((ptr)->qh_pad); \
+	swab32((ptr)->qh_kernsz); \
 	swab64((ptr)->qh_timestamp); \
 }
 
@@ -293,10 +293,9 @@ 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,
+int find_partitions(const char *label,
 		    char *devname, size_t devlen, int print);
-int check_device(char *device, char *label, int *ssz, quorum_header_t *qh,
-		 int flags);
+int check_device(char *device, char *label, quorum_header_t *qh, int flags);
 
 
 #endif
diff --git a/cman/qdisk/disk_util.c b/cman/qdisk/disk_util.c
index a3d73d8..f5539c0 100644
--- a/cman/qdisk/disk_util.c
+++ b/cman/qdisk/disk_util.c
@@ -71,7 +71,7 @@ getuptime(struct timeval *tv)
 	if (!fp)
 		return -1;
 
-#if defined(__sparc__) || defined(__hppa__) || defined(__sparc64__) || defined (__hppa64__)
+#if defined(__sparc__) || defined(__sparc64__)
 	rv = fscanf(fp,"%ld.%d %ld.%d\n", &tv->tv_sec, &tv->tv_usec,
 		    &junk.tv_sec, &junk.tv_usec);
 #else
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index 6bec85a..b953367 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -254,23 +254,6 @@ check_transitions(qd_ctx *ctx, node_info_t *ni, int max, memb_mask_t mask)
 		     state_run(ni[x].ni_status.ps_state)) {
 
 			/*
-			   Mark our internal views as dead if nodes miss too
-			   many heartbeats...  This will cause a master
-			   transition if no live master exists.
-			 */
-			if (ni[x].ni_status.ps_state >= S_RUN &&
-			    ni[x].ni_seen) {
-				clulog(LOG_DEBUG, "Node %d DOWN\n",
-				       ni[x].ni_status.ps_nodeid);
-				ni[x].ni_seen = 0;	
-			}
-
-			ni[x].ni_state = S_EVICT;
-			ni[x].ni_status.ps_state = S_EVICT;
-			ni[x].ni_evil_incarnation = 
-				ni[x].ni_status.ps_incarnation;
-			
-			/*
 			   Write eviction notice if we're the master.
 			 */
 			if (ctx->qc_status == S_MASTER) {
@@ -287,6 +270,23 @@ check_transitions(qd_ctx *ctx, node_info_t *ni, int max, memb_mask_t mask)
 				}
 			}
 
+			/*
+			   Mark our internal views as dead if nodes miss too
+			   many heartbeats...  This will cause a master
+			   transition if no live master exists.
+			 */
+			if (ni[x].ni_status.ps_state >= S_RUN &&
+			    ni[x].ni_seen) {
+				clulog(LOG_DEBUG, "Node %d DOWN\n",
+				       ni[x].ni_status.ps_nodeid);
+				ni[x].ni_seen = 0;	
+			}
+
+			ni[x].ni_state = S_EVICT;
+			ni[x].ni_status.ps_state = S_EVICT;
+			ni[x].ni_evil_incarnation = 
+				ni[x].ni_status.ps_incarnation;
+			
 			/* Clear our master mask for the node after eviction */
 			if (mask)
 				clear_bit(mask, (ni[x].ni_status.ps_nodeid-1),
@@ -1481,15 +1481,15 @@ main(int argc, char **argv)
 	}
 	
 	if (ctx.qc_label) {
-		if (find_partitions("/proc/partitions",
-				    ctx.qc_label, device,
-				    sizeof(device), 0) != 0) {
+		ret = find_partitions(ctx.qc_label, device, sizeof(device), 0);
+		if (ret < 0) {
 			clulog_and_print(LOG_CRIT, "Unable to match label"
 					 " '%s' to any device\n",
 					 ctx.qc_label);
 			check_stop_cman(&ctx);
 			goto out;
 		}
+		/* XXX Multiple matches: do we care? */
 
 		if (ctx.qc_device)
 			free(ctx.qc_device);
@@ -1499,7 +1499,7 @@ main(int argc, char **argv)
 		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, &rv, &qh, 0) != 0) {
+		if (check_device(ctx.qc_device, NULL, &qh, 0) != 0) {
 			clulog(LOG_CRIT,
 			       "Specified partition %s does not have a "
 			       "qdisk label\n", ctx.qc_device);
diff --git a/cman/qdisk/mkqdisk.c b/cman/qdisk/mkqdisk.c
index 0c87d72..b76b808 100644
--- a/cman/qdisk/mkqdisk.c
+++ b/cman/qdisk/mkqdisk.c
@@ -39,7 +39,7 @@ main(int argc, char **argv)
 	char *newdev = NULL, *newlabel = NULL;
 	int rv, verbose_level = 1;
 
-	printf("mkqdisk v0.5.2\n");
+	printf("mkqdisk v0.6.0\n");
 
 	while ((rv = getopt(argc, argv, "Ldf:c:l:h")) != EOF) {
 		switch (rv) {
@@ -49,13 +49,11 @@ main(int argc, char **argv)
 		case 'L':
 			/* List */
 			close(2);
-			return find_partitions("/proc/partitions",
-					       NULL, NULL, 0, verbose_level);
+			return find_partitions(NULL, NULL, 0, verbose_level);
 			break;
 		case 'f':
 			close(2);
-			return find_partitions("/proc/partitions",
-					       optarg, device,
+			return find_partitions( optarg, device,
 					       sizeof(device), verbose_level);
 		case 'c':
 			newdev = optarg;
diff --git a/cman/qdisk/proc.c b/cman/qdisk/proc.c
index e777dc1..5623e7e 100644
--- a/cman/qdisk/proc.c
+++ b/cman/qdisk/proc.c
@@ -29,10 +29,20 @@
 #include <platform.h>
 #include <stdlib.h>
 #include <string.h>
+#include "scandisk.h"
+
+struct device_args {
+	char *label;
+	struct devnode *devnode;
+	int sector_size;
+	int flags;
+	int count;
+	int pad;
+};
 
 
 int
-check_device(char *device, char *label, int *ssz, quorum_header_t *qh,
+check_device(char *device, char *label, quorum_header_t *qh,
 	     int flags)
 {
 	int ret = -1;
@@ -54,9 +64,6 @@ check_device(char *device, char *label, int *ssz, quorum_header_t *qh,
 		return -1;
 	}
 
-	if (ssz) 
-		*ssz = disk.d_blksz;
-
 	ret = -1;
 	if (qdisk_read(&disk, OFFSET_HEADER, qh, sizeof(*qh)) == sizeof(*qh)) {
 		swab_quorum_header_t(qh);
@@ -67,6 +74,8 @@ check_device(char *device, char *label, int *ssz, quorum_header_t *qh,
                 }
         }
 
+	qh->qh_kernsz = disk.d_blksz;
+
 	/* only flag now is 'strict device check'; i.e.,
 	  "block size recorded must match kernel's reported size" */
 	if (flags && qh->qh_version == VERSION_MAGIC_V2 &&
@@ -80,6 +89,40 @@ check_device(char *device, char *label, int *ssz, quorum_header_t *qh,
 }
 
 
+void
+filter_devs(struct devnode *node, void *v_args)
+{
+	struct device_args *args = (struct device_args *)v_args;
+	quorum_header_t qh;
+	quorum_header_t *ret_qh = NULL;
+	int ret;
+
+	if (!node->sysfsattrs.sysfs)
+		return;
+	if (!node->devpath)
+		return;
+	if (node->sysfsattrs.holders)
+		return;
+	/* Qdiskd doesn't work on soft-raid */
+	if (node->md > 0)
+		return;
+
+	ret = check_device(node->devpath->path, args->label, &qh, args->flags);
+	if (ret == 0) {
+		ret_qh = malloc(sizeof(qh));
+		if (!ret_qh)
+			return;
+		memcpy(ret_qh, &qh, sizeof(qh));
+
+		node->filter = (void *)ret_qh;
+		if (!args->count) {
+			args->devnode = node;
+		}
+		++args->count;
+	}
+}
+
+
 char *
 state_str(disk_node_state_t s)
 {
@@ -103,11 +146,13 @@ state_str(disk_node_state_t s)
 void
 print_status_block(status_block_t *sb)
 {
+	time_t timestamp = (time_t)sb->ps_timestamp;
+
 	if (sb->ps_state == S_NONE)
 		return;
 	printf("Status block for node %d\n", sb->ps_nodeid);
 	printf("\tLast updated by node %d\n", sb->ps_updatenode);
-	printf("\tLast updated on %s", ctime((time_t *)&sb->ps_timestamp));
+	printf("\tLast updated on %s", ctime((time_t *)&timestamp));
 	printf("\tState: %s\n", state_str(sb->ps_state));
 	printf("\tFlags: %04x\n", sb->ps_flags);
 	printf("\tScore: %d/%d\n", sb->ps_score, sb->ps_scoremax);
@@ -152,82 +197,83 @@ read_info(char *dev)
 }
 
 
-int
-find_partitions(const char *partfile, const char *label,
-	        char *devname, size_t devlen, int print)
+void
+print_qdisk_info(struct devnode *dn)
 {
-	char line[4096];
-	FILE *fp;
-	int minor, major;
-	unsigned long long blkcnt;
-	char device[128];
-	char realdev[256];
-	quorum_header_t qh;
-	int ssz;
-
-	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);
+	quorum_header_t *qh = (quorum_header_t *)dn->filter;
+	struct devpath *dp;
+	time_t timestamp = (time_t)qh->qh_timestamp;
+
+	for (dp = dn->devpath; dp; dp = dp->next)
+		printf("%s:\n", dp->path);
+	printf("\tMagic:                %08x\n", qh->qh_magic);
+	printf("\tLabel:                %s\n", qh->qh_cluster);
+	printf("\tCreated:              %s", ctime(&timestamp));
+	printf("\tHost:                 %s\n", qh->qh_updatehost);
+	printf("\tKernel Sector Size:   %d\n", qh->qh_kernsz);
+	if (qh->qh_version == VERSION_MAGIC_V2) {
+		printf("\tRecorded Sector Size: %d\n\n", (int)qh->qh_blksz);
+	}
+}
 
-			/* If we're not "just printing", then 
-			   then reject devices which don't match
-			   the recorded sector size */
-			if (check_device(realdev, (char *)label, &ssz,
-					 &qh, !print) != 0)
+int
+find_partitions(const char *label, char *devname, size_t devlen, int print)
+{
+	struct devlisthead *dh = NULL;
+	struct devnode *dn = NULL;
+	struct device_args dargs;
+
+	memset(&dargs, 0, sizeof(dargs));
+	dargs.label = (char *)label;
+	dargs.flags = 1;	/* strict device check */
+	dargs.devnode = NULL;	/* First matching device */
+
+	dh = scan_for_dev(NULL, 5, filter_devs, (void *)(&dargs));
+	if (!dh)
+		goto not_found;
+	if (!dargs.devnode)
+		goto not_found;
+
+	if (dargs.count > 0 && print) {
+		for (dn = dh->devnode; dn; dn = dn->next) {
+			if (dn->filter == NULL) {
 				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", qh.qh_updatehost);
-				printf("\tKernel Sector Size:   %d\n", ssz);
-				if (qh.qh_version == VERSION_MAGIC_V2) {
-					printf("\tRecorded Sector Size: %d\n\n", (int)qh.qh_blksz);
-					if (qh.qh_blksz != ssz) {
-						printf("WARNING: Sector size mismatch: Header: %d  Kernel: %d\n",
-							(int)qh.qh_blksz, ssz);
-					}
-				} else
-					printf("\n");
 			}
 
+			print_qdisk_info(dn);
 			if (print >= 2) {
 				/* Print node stuff */
-				read_info(realdev);
-			}
-
-			if (devname && devlen) {
-				/* Got it */
-				strncpy(devname, realdev, devlen);
-				fclose(fp);
-				return 0;
+				read_info(dn->devpath->path);
 			}
 		}
 	}
 
-	fclose(fp);
+	if (dargs.count == 1 && label) {
+		snprintf(devname, devlen, "%s", dargs.devnode->devpath->path);
+	}
+
+	for (dn = dh->devnode; dn; dn = dn->next)
+		if (dn->filter)
+			free(dn->filter);
+        free_dev_list(dh);
 
 	if (print)
 		/* No errors if we're just printing stuff */
 		return 0;
 
+	if (dargs.count == 1 || !label)
+		return 0;
+
+	/* more than one match */
+	return 1;
+
+   not_found:
+        if (dh) {
+		for (dn = dh->devnode; dn; dn = dn->next)
+			if (dn->filter)
+				free(dn->filter);
+		free_dev_list(dh);
+	}
 	errno = ENOENT;
 	return -1;
 }
diff --git a/cman/qdisk/scandisk.c b/cman/qdisk/scandisk.c
new file mode 100644
index 0000000..77484f6
--- /dev/null
+++ b/cman/qdisk/scandisk.c
@@ -0,0 +1,751 @@
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
+**  All rights reserved.
+**
+**  Author: Fabio M. Di Nitto <fdinitto redhat com>
+**
+**  Original design by:
+**  Joel Becker <Joel Becker oracle com>
+**  Fabio M. Di Nitto <fdinitto redhat com>
+**
+**  This copyrighted material is made available to anyone wishing to use,
+**  modify, copy, or redistribute it subject to the terms and conditions
+**  of the GNU General Public License v.2.
+**
+*******************************************************************************
+******************************************************************************/
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <sys/sysmacros.h>
+#include <sys/stat.h>
+
+#include "scandisk.h"
+
+/** search in cache helpers **/
+
+/*
+ * match is 0 for exact match
+ *          1 to see if the string is contained and return the first match
+ */
+
+static struct devnode *find_dev_by_path(struct devnode *startnode, char *path,
+					int match)
+{
+	struct devnode *nextnode;
+	struct devpath *nextpath;
+
+	while (startnode) {
+		nextnode = startnode->next;
+		nextpath = startnode->devpath;
+		while (nextpath) {
+			if (match) {
+				if (strstr(nextpath->path, path))
+					return startnode;
+			} else {
+				if (!strcmp(nextpath->path, path))
+					return startnode;
+			}
+			nextpath = nextpath->next;
+		}
+		startnode = nextnode;
+	}
+
+	return 0;
+}
+
+static struct devnode *find_dev_by_majmin(struct devnode *startnode, int maj,
+					  int min)
+{
+	struct devnode *nextnode;
+
+	while (startnode) {
+		nextnode = startnode->next;
+		if ((startnode->maj == maj) && (startnode->min == min))
+			return startnode;
+		startnode = nextnode;
+	}
+
+	return 0;
+}
+
+/** free the cache.. this one is easy ;) **/
+
+/* free all the path associated to one node */
+static void flush_dev_list(struct devpath *startpath)
+{
+	struct devpath *nextpath;
+
+	while (startpath) {
+		nextpath = startpath->next;
+		free(startpath);
+		startpath = nextpath;
+	}
+
+	return;
+}
+
+/* free all nodes associated with one devlist */
+static void flush_dev_cache(struct devlisthead *devlisthead)
+{
+	struct devnode *nextnode, *startnode = devlisthead->devnode;
+
+	while (startnode) {
+		nextnode = startnode->next;
+		flush_dev_list(startnode->devpath);
+		free(startnode);
+		startnode = nextnode;
+	}
+
+	return;
+}
+
+/** list object allocation helpers **/
+
+/* our only certain keys in the list are maj and min
+ * this function append a devnode obj to devlisthead
+ * and set maj and min
+ */
+
+static struct devnode *alloc_list_obj(struct devlisthead *devlisthead, int maj,
+				      int min)
+{
+	struct devnode *nextnode, *startnode;
+
+	nextnode = malloc(sizeof(struct devnode));
+	if (!nextnode)
+		return 0;
+
+	memset(nextnode, 0, sizeof(struct devnode));
+
+	if (!devlisthead->devnode) {
+		devlisthead->devnode = startnode = nextnode;
+	} else {
+		startnode = devlisthead->devnode;
+		while (startnode->next)
+			startnode = startnode->next;
+
+		/* always append what we find */
+		startnode->next = nextnode;
+		startnode = nextnode;
+	}
+
+	startnode->maj = maj;
+	startnode->min = min;
+
+	return startnode;
+}
+
+/* really annoying but we have no way to know upfront how
+ * many paths are linked to a certain maj/min combo.
+ * Once we find a device, we know maj/min and this new path.
+ * add_path_obj will add the given path to the devnode
+ */
+static int add_path_obj(struct devnode *startnode, char *path)
+{
+	struct devpath *nextpath, *startpath;
+
+	nextpath = malloc(sizeof(struct devpath));
+	if (!nextpath)
+		return 0;
+
+	memset(nextpath, 0, sizeof(struct devpath));
+
+	if (!startnode->devpath) {
+		startnode->devpath = startpath = nextpath;
+	} else {
+		startpath = startnode->devpath;
+		while (startpath->next)
+			startpath = startpath->next;
+
+		/* always append what we find */
+		startpath->next = nextpath;
+		startpath = nextpath;
+	}
+
+	strncpy(startpath->path, path, MAXPATHLEN - 1);
+
+	return 1;
+}
+
+/* lsdev needs to add blocks in 2 conditions: if we have a real block device
+ * or if have a symlink to a block device.
+ * this function simply avoid duplicate code around.
+ */
+static int add_lsdev_block(struct devlisthead *devlisthead, struct stat *sb,
+			   char *path)
+{
+	int maj, min;
+	struct devnode *startnode;
+
+	maj = major(sb->st_rdev);
+	min = minor(sb->st_rdev);
+
+	startnode = find_dev_by_majmin(devlisthead->devnode, maj, min);
+	if (!startnode) {
+		startnode = alloc_list_obj(devlisthead, maj, min);
+		if (!startnode)
+			return 0;
+	}
+
+	if (!add_path_obj(startnode, path))
+		return 0;
+
+	return 1;
+}
+
+/* check if it is a device or a symlink to a device */
+static int dev_is_block(struct stat *sb, char *path)
+{
+	if (S_ISBLK(sb->st_mode))
+		return 1;
+
+	if (S_ISLNK(sb->st_mode))
+		if (!stat(path, sb))
+			if (S_ISBLK(sb->st_mode))
+				return 1;
+
+	return 0;
+}
+
+/* lsdev does nothing more than ls -lR /dev
+ * dives into dirs (skips hidden directories)
+ * add block devices
+ * parse symlinks
+ *
+ * ret:
+ * 1 on success
+ * -1 for generic errors
+ * -2 -ENOMEM
+ */
+static int lsdev(struct devlisthead *devlisthead, char *path)
+{
+	int i, n, err = 0;
+	struct dirent **namelist;
+	struct stat sb;
+	char newpath[MAXPATHLEN];
+
+	i = scandir(path, &namelist, 0, alphasort);
+	if (i < 0)
+		return -1;
+
+	for (n = 0; n < i; n++) {
+		if (namelist[n]->d_name[0] != '.') {
+			snprintf(newpath, sizeof(newpath), "%s/%s", path,
+				 namelist[n]->d_name);
+
+			if (!lstat(newpath, &sb)) {
+				if (S_ISDIR(sb.st_mode))
+					err = lsdev(devlisthead, newpath);
+				if (err < 0)
+					return err;
+
+				if (dev_is_block(&sb, newpath))
+					if (!add_lsdev_block
+					    (devlisthead, &sb, newpath) < 0)
+						return -2;
+			}
+		}
+		free(namelist[n]);
+	}
+	free(namelist);
+	return 1;
+}
+
+/*
+ * scan /proc/partitions and adds info into the list.
+ * It's able to add nodes if those are not found in sysfs.
+ *
+ * ret:
+ *  0 if we can't scan
+ *  -2 -ENOMEM
+ *  1 if everything is ok
+ */
+
+static int scanprocpart(struct devlisthead *devlisthead)
+{
+	char line[4096];
+	FILE *fp;
+	int minor, major;
+	unsigned long long blkcnt;
+	char device[128];
+	struct devnode *startnode;
+	fp = fopen("/proc/partitions", "r");
+	if (!fp)
+		return 0;
+	while (fgets(line, sizeof(line), fp)
+	       != NULL) {
+
+		if (strlen(line) > 128 + (22))
+			continue;
+		sscanf(line, "%4d %4d %10llu %s",
+		       &major, &minor, &blkcnt, device);
+
+		/* careful here.. if there is no device, we are scanning the
+		 * first two lines that are not useful to us
+		 */
+		if (!strlen(device))
+			continue;
+		startnode =
+		    find_dev_by_majmin(devlisthead->devnode, major, minor);
+		if (!startnode) {
+			startnode = alloc_list_obj(devlisthead, major, minor);
+			if (!startnode)
+				return -2;
+		}
+
+		startnode->procpart = 1;
+		strcpy(startnode->procname, device);
+	}
+
+	fclose(fp);
+	return 1;
+}
+
+/* scan /proc/mdstat and adds info to the list. At this point
+ * all the devices _must_ be already in the list. We don't add anymore
+ * since raids can only be assembled out of existing devices
+ *
+ * ret:
+ * 1 if we could scan
+ * 0 otherwise
+ */
+static int scanmdstat(struct devlisthead *devlisthead)
+{
+	char line[4096];
+	FILE *fp;
+	char device[16];
+	char separator[4];
+	char status[16];
+	char personality[16];
+	char firstdevice[16];
+	char devices[4096];
+	char *tmp, *next;
+	struct devnode *startnode = NULL;
+
+	fp = fopen("/proc/mdstat", "r");
+	if (!fp)
+		return 0;
+
+	while (fgets(line, sizeof(line), fp) != NULL) {
+
+		/* i like things to be absolutely clean */
+		memset(device, 0, 16);
+		memset(separator, 0, 4);
+		memset(status, 0, 16);
+		memset(personality, 0, 16);
+		memset(firstdevice, 0, 16);
+		memset(devices, 0, 4096);
+
+		if (strlen(line) > 4096)
+			continue;
+
+		/* we only parse stuff that starts with ^md
+		 * that's supposed to point to raid */
+		if (!(line[0] == 'm' && line[1] == 'd'))
+			continue;
+
+		sscanf(line, "%s %s %s %s %s",
+		       device, separator, status, personality, firstdevice);
+
+		/* scan only raids that are active */
+		if (strcmp(status, "active"))
+			continue;
+
+		/* try to find *mdX and set the device as real raid.
+		 * if we don't find the device we don't try to set the slaves */
+		startnode = find_dev_by_path(devlisthead->devnode, device, 1);
+		if (!startnode)
+			continue;
+
+		startnode->md = 1;
+
+		/* trunkate the string from sdaX[Y] to sdaX and
+		 * copy the whole device string over */
+		memset(strstr(firstdevice, "["), 0, 1);
+		strcpy(devices, strstr(line, firstdevice));
+
+		/* if we don't find any slave (for whatever reason)
+		 * keep going */
+		if (!strlen(devices))
+			continue;
+
+		tmp = devices;
+		while ((tmp) && ((next = strstr(tmp, " ")) || strlen(tmp))) {
+
+			memset(strstr(tmp, "["), 0, 1);
+
+			startnode =
+			    find_dev_by_path(devlisthead->devnode, tmp, 1);
+			if (startnode)
+				startnode->md = 2;
+
+			tmp = next;
+
+			if (tmp)
+				tmp++;
+
+		}
+	}
+
+	fclose(fp);
+	return 1;
+}
+
+/* scanmapper parses /proc/devices to identify what maj are associated
+ * with device-mapper
+ *
+ * ret:
+ * can't fail for now
+ */
+static int scanmapper(struct devlisthead *devlisthead)
+{
+	struct devnode *startnode;
+	FILE *fp;
+	char line[4096];
+	char major[4];
+	char device[64];
+	int maj, start = 0;
+
+	fp = fopen("/proc/devices", "r");
+	if (!fp)
+		return 0;
+
+	while (fgets(line, sizeof(line), fp) != NULL) {
+		memset(major, 0, 4);
+		memset(device, 0, 64);
+
+		if (strlen(line) > 4096)
+			continue;
+
+		if (!strncmp(line, "Block devices:", 13)) {
+			start = 1;
+			continue;
+		}
+
+		if (!start)
+			continue;
+
+		sscanf(line, "%s %s", major, device);
+
+		if (!strncmp(device, "device-mapper", 13)) {
+			maj = atoi(major);
+			startnode = devlisthead->devnode;
+
+			while (startnode) {
+				if (startnode->maj == maj)
+					startnode->mapper = 1;
+
+				startnode = startnode->next;
+			}
+
+		}
+
+	}
+
+	fclose(fp);
+	return 1;
+}
+
+/* scan through the list and execute the custom filter for each entry */
+static void run_filter(struct devlisthead *devlisthead,
+		       devfilter filter, void *filter_args)
+{
+	struct devnode *startnode = devlisthead->devnode;
+
+	while (startnode) {
+		filter(startnode, filter_args);
+		startnode = startnode->next;
+	}
+	return;
+}
+
+/** sysfs helper functions **/
+
+/* /sys/block/sda/dev or /sys/block/sda1/dev exists
+ * the device is real and dev contains maj/min info.
+ *
+ * ret:
+ * 1 on success and set maj/min
+ * 0 if no file is found
+ * -1 if we could not open the file
+ */
+static int sysfs_is_dev(char *path, int *maj, int *min)
+{
+	char newpath[MAXPATHLEN];
+	struct stat sb;
+	FILE *f;
+	snprintf(newpath, sizeof(newpath), "%s/dev", path);
+	if (!lstat(newpath, &sb)) {
+		f = fopen(newpath, "r");
+		if (f) {
+			fscanf(f, "%d:%d", maj, min);
+			fclose(f);
+			return 1;
+		} else
+			return -1;
+	}
+	return 0;
+}
+
+/* /sys/block/sda/removable tells us if a device can be ejected
+ * from the system or not. This is useful for USB pendrive that are
+ * both removable and disks.
+ *
+ * ret:
+ * 1 if is removable
+ * 0 if not
+ * -1 if we couldn't find the file.
+ */
+static int sysfs_is_removable(char *path)
+{
+	char newpath[MAXPATHLEN];
+	struct stat sb;
+	int i = -1;
+	FILE *f;
+	snprintf(newpath, sizeof(newpath), "%s/removable", path);
+	if (!lstat(newpath, &sb)) {
+		f = fopen(newpath, "r");
+		if (f) {
+			fscanf(f, "%d\n", &i);
+			fclose(f);
+		}
+	}
+	return i;
+}
+
+/* we use this function to scan /sys/block/sda{,1}/{holders,slaves}
+ * to know in what position of the foodchain this device is.
+ * NOTE: a device can have both holders and slaves at the same time!
+ * (for example an lvm volume on top of a raid device made of N real disks
+ *
+ * ret:
+ * always return the amount of entries in the dir if successful
+ * or any return value from scandir.
+ */
+static int sysfs_has_subdirs_entries(char *path, char *subdir)
+{
+	char newpath[MAXPATHLEN];
+	struct dirent **namelist;
+	struct stat sb;
+	int n, i, count = 0;
+
+	snprintf(newpath, sizeof(newpath), "%s/%s", path, subdir);
+	if (!lstat(newpath, &sb)) {
+		if (S_ISDIR(sb.st_mode)) {
+			i = scandir(newpath, &namelist, 0, alphasort);
+			if (i < 0)
+				return i;
+			for (n = 0; n < i; n++) {
+				if (namelist[n]->d_name[0] != '.')
+					count++;
+				free(namelist[n]);
+			}
+			free(namelist);
+		}
+	}
+	return count;
+}
+
+/* this is the best approach so far to make sure a block device
+ * is a disk and distinguish it from a cdrom or tape or etc.
+ * What we know for sure is that a type 0 is a disk.
+ * From an old piece code 0xe is an IDE disk and comes from media.
+ * NOTE: we scan also for ../ that while it seems stupid, it will
+ * allow to easily mark partitions as real disks.
+ * (see for example /sys/block/sda/device/type and
+ * /sys/block/sda1/../device/type)
+ * TODO: there might be more cases to evaluate.
+ *
+ * ret:
+ * -2 we were not able to open the file
+ * -1 no path found
+ *  0 we found the path but we have 0 clue on what it is
+ *  1 is a disk
+ */
+static int sysfs_is_disk(char *path)
+{
+	char newpath[MAXPATHLEN];
+	struct stat sb;
+	int i = -1;
+	FILE *f;
+
+	snprintf(newpath, sizeof(newpath), "%s/device/type", path);
+	if (!lstat(newpath, &sb))
+		goto found;
+
+	snprintf(newpath, sizeof(newpath), "%s/../device/type", path);
+	if (!lstat(newpath, &sb))
+		goto found;
+
+	snprintf(newpath, sizeof(newpath), "%s/device/media", path);
+	if (!lstat(newpath, &sb))
+		goto found;
+
+	snprintf(newpath, sizeof(newpath), "%s/../device/media", path);
+	if (lstat(newpath, &sb))
+		return -1;
+
+      found:
+	f = fopen(newpath, "r");
+	if (f) {
+		fscanf(f, "%d\n", &i);
+		fclose(f);
+
+		switch (i) {
+		case 0x0:	/* scsi type_disk */
+		case 0xe:	/* found on ide disks from old kernels.. */
+			i = 1;
+			break;
+		default:
+			i = 0;	/* by default we have no clue */
+			break;
+		}
+	} else
+		i = -2;
+
+	return i;
+}
+
+/* recursive function that will scan and dive into /sys/block
+ * looking for devices and scanning for attributes.
+ *
+ * ret:
+ * 1 on success
+ * -1 on generic error
+ * -2 -ENOMEM
+ */
+static int scansysfs(struct devlisthead *devlisthead, char *path)
+{
+	struct devnode *startnode;
+	int i, n, maj, min;
+	struct dirent **namelist;
+	struct stat sb;
+	char newpath[MAXPATHLEN];
+
+	i = scandir(path, &namelist, 0, alphasort);
+	if (i < 0)
+		return -1;
+
+	for (n = 0; n < i; n++) {
+		if (namelist[n]->d_name[0] != '.') {
+			snprintf(newpath, sizeof(newpath),
+				 "%s/%s", path, namelist[n]->d_name);
+			if (!lstat(newpath, &sb)) {
+
+				if (S_ISDIR(sb.st_mode))
+					if (scansysfs(devlisthead, newpath) < 0)
+						return -1;
+
+				if (S_ISLNK(sb.st_mode))
+					continue;
+
+				if (sysfs_is_dev(newpath, &maj, &min) > 0) {
+					startnode =
+					    alloc_list_obj(devlisthead, maj,
+							   min);
+					if (!startnode)
+						return -2;
+
+					startnode->sysfsattrs.sysfs = 1;
+					startnode->sysfsattrs.removable =
+					    sysfs_is_removable(newpath);
+					startnode->sysfsattrs.holders =
+					    sysfs_has_subdirs_entries(newpath,
+								      "holders");
+					startnode->sysfsattrs.slaves =
+					    sysfs_has_subdirs_entries(newpath,
+								      "slaves");
+					startnode->sysfsattrs.disk =
+					    sysfs_is_disk(newpath);
+				}
+			}
+		}
+		free(namelist[n]);
+	}
+
+	free(namelist);
+	return 1;
+}
+
+/*
+ * devlisthead can be null if you are at init time. pass the old one if you are
+ * updating or scanning..
+ *
+ * timeout is used only at init time to set the cache timeout value if default
+ * value is not good enough. We might extend its meaning at somepoint.
+ * Anything <= 0 means that the cache does not expire.
+ */
+
+struct devlisthead *scan_for_dev(struct devlisthead *devlisthead,
+				 time_t timeout,
+				 devfilter filter, void *filter_args)
+{
+	int res;
+	time_t current;
+
+	time(&current);
+
+	if (devlisthead) {
+		if ((current - devlisthead->cache_timestamp) <
+		    devlisthead->cache_timeout) {
+			return devlisthead;
+		}
+	} else {
+		devlisthead = malloc(sizeof(struct devlisthead));
+		if (!devlisthead)
+			return NULL;
+		memset(devlisthead, 0, sizeof(struct devlisthead));
+		if (timeout)
+			devlisthead->cache_timeout = timeout;
+		else
+			devlisthead->cache_timeout = DEVCACHETIMEOUT;
+	}
+
+	flush_dev_cache(devlisthead);
+	devlisthead->cache_timestamp = current;
+
+	/* it's important we check those 3 errors and abort in case
+	 * as it means that we are running out of mem,
+	 */
+	devlisthead->sysfs = res = scansysfs(devlisthead, SYSBLOCKPATH);
+	if (res < -1)
+		goto emergencyout;
+
+	devlisthead->procpart = res = scanprocpart(devlisthead);
+	if (res < -1)
+		goto emergencyout;
+
+	devlisthead->lsdev = res = lsdev(devlisthead, DEVPATH);
+	if (res < -1)
+		goto emergencyout;
+
+	/* from now on we don't alloc mem ourselves but only add info */
+	devlisthead->mdstat = scanmdstat(devlisthead);
+	devlisthead->mapper = scanmapper(devlisthead);
+	if (filter)
+		run_filter(devlisthead, filter, filter_args);
+
+	return devlisthead;
+
+      emergencyout:
+	free_dev_list(devlisthead);
+	return 0;
+}
+
+/* free everything we used so far */
+
+void free_dev_list(struct devlisthead *devlisthead)
+{
+	if (devlisthead) {
+		flush_dev_cache(devlisthead);
+		free(devlisthead);
+	}
+	return;
+}
diff --git a/cman/qdisk/scandisk.h b/cman/qdisk/scandisk.h
new file mode 100644
index 0000000..6c82148
--- /dev/null
+++ b/cman/qdisk/scandisk.h
@@ -0,0 +1,105 @@
+/******************************************************************************
+*******************************************************************************
+**
+**  Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
+**
+**  Author: Fabio M. Di Nitto <fdinitto redhat com>
+**
+**  Original design by: 
+**  Joel Becker <Joel Becker oracle com> 
+**  Fabio M. Di Nitto <fdinitto redhat com>
+**
+**  This copyrighted material is made available to anyone wishing to use,
+**  modify, copy, or redistribute it subject to the terms and conditions
+**  of the GNU General Public License v.2.
+**
+*******************************************************************************
+******************************************************************************/
+
+#ifndef __SCANDISK_H__
+#define __SCANDISK_H__
+
+#ifndef DEVPATH
+#define	DEVPATH		"/dev"
+#endif
+
+#ifndef SYSFSPATH
+#define SYSFSPATH	"/sys"
+#endif
+
+#ifndef SYSBLOCKPATH
+#define SYSBLOCKPATH	SYSFSPATH "/block"
+#endif
+
+#ifdef DEBUG
+#define	DEVCACHETIMEOUT	5	/* expressed in seconds */
+#else
+#define	DEVCACHETIMEOUT	30
+#endif
+
+/* each entry can be (generally):
+ * > 0 on success or good hit
+ * 0 on success with no hit
+ * < 0 on error
+ */
+
+struct sysfsattrs {		/* usual 0 | 1 game */
+	int sysfs;		/* did we find an entry in sysfs at all? */
+	int slaves;		/* device has slaves */
+	int holders;		/* device has holders */
+	int removable;		/* device is removable */
+	int disk;		/* device is a disk */
+};
+
+/* this structure is required because we don't know upfront how many
+ * entries for a certain maj/min will be found in /dev, and so we need
+ * to alloc them dynamically.
+ */
+struct devpath {
+	struct devpath *next;
+	char path[MAXPATHLEN];
+};
+
+/* this structure holds all the data for each maj/min found in the system
+ * that is a block device
+ */
+struct devnode {
+	struct devnode *next;
+	struct devpath *devpath;	/* point to the first path entry */
+	int maj;		/* device major */
+	int min;		/* device minor */
+	struct sysfsattrs sysfsattrs;	/* like the others.. scanning /sys */
+	int procpart;		/* 0 if the device is not in proc/part or 1 on success. <0 on error */
+	char procname[MAXPATHLEN];	/* non-NULL if we find a maj/min match */
+	int md;			/* 0 nothing to do with raid, 1 is raid,
+				 * 2 is raid slave - data from /proc/mdstat */
+	int mapper;		/* 0 nothing, 1 we believe it's a devmap dev */
+	void *filter;		/* your filter output.. whatever it is */
+};
+
+/* this is what you get after a scan... if you are lucky */
+/* each entry can be 0 if we can't scan or < 0 if there are errors */
+
+struct devlisthead {
+	time_t cache_timestamp;	/* this cache timestamp */
+	int cache_timeout;	/* for how long this cache is valid */
+	int sysfs;		/* set to 1 if we were able to scan
+				 * /sys */
+	int procpart;		/* set to 1 if we were able to scan
+				 * /proc/partitions */
+	int lsdev;		/* set to 1 if we were able to ls /dev */
+	int mdstat;		/* set to 1 if we were able to scan
+				 * /proc/mdstat */
+	int mapper;		/* set to 1 if we were able to run
+				 * something against mapper */
+	struct devnode *devnode;	/* points to the first entry */
+};
+
+typedef void (*devfilter) (struct devnode * cur, void *arg);
+
+struct devlisthead *scan_for_dev(struct devlisthead *devlisthead,
+				 time_t timeout,
+				 devfilter filter, void *filter_args);
+void free_dev_list(struct devlisthead *devlisthead);
+
+#endif /* __SCANDISK_H__ */


hooks/post-receive
--
Cluster Project


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