Cluster Project branch, STABLE2, updated. cluster-2.03.01-12-g23d5682

fabbione@sourceware.org fabbione@sourceware.org
Tue Apr 22 18:47:00 GMT 2008


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=23d5682698c2de24f29037c3a8081740a0419668

The branch, STABLE2 has been updated
       via  23d5682698c2de24f29037c3a8081740a0419668 (commit)
       via  41a9904b9a2bcebc862cb55f3306df698431b8d1 (commit)
       via  83d29d3c08e13d5ae2649509cca388b2a2ca168a (commit)
       via  4e7f6c121a1cc1c40011aff6d885d6c396717072 (commit)
       via  ad7f3c12a864eacbb9c5f552a8d4870c8ccc59bd (commit)
       via  bd5b07b062cea5f29f92752df9afba5821b61b4f (commit)
       via  b8d8c52f46c8c81885b6a0db08e4f95dafbbc672 (commit)
       via  9baa0907064ec24cbc295f1180558bafd94ba56d (commit)
      from  f3b6ea990e81e9234903a7fb65565f7dd3d3d43f (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 23d5682698c2de24f29037c3a8081740a0419668
Author: Fabio M. Di Nitto <fdinitto@redhat.com>
Date:   Tue Apr 22 20:34:16 2008 +0200

    [MISC] Update Red Hat main copyright file
    
    Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>

commit 41a9904b9a2bcebc862cb55f3306df698431b8d1
Author: Fabio M. Di Nitto <fdinitto@redhat.com>
Date:   Tue Apr 22 20:33:31 2008 +0200

    [MISC] Update copyright headers
    
    Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>

commit 83d29d3c08e13d5ae2649509cca388b2a2ca168a
Author: Fabio M. Di Nitto <fabbione@fabbione.net>
Date:   Fri Mar 28 06:39:45 2008 +0100

    [CMAN] qdisk: add credits to Joel
    
    Signed-off-by: Fabio M. Di Nitto <fabbione@fabbione.net>

commit 4e7f6c121a1cc1c40011aff6d885d6c396717072
Author: Lon Hohberger <lhh@redhat.com>
Date:   Mon Mar 24 11:41:00 2008 -0400

    [cman/qdisk] Fix type pun errors in proc.c

commit ad7f3c12a864eacbb9c5f552a8d4870c8ccc59bd
Author: Fabio M. Di Nitto <fabbione@fabbione.net>
Date:   Fri Mar 21 05:05:43 2008 +0100

    [CMAN] Drop dependency on libdevmapper
    
    Signed-off-by: Fabio M. Di Nitto <fabbione@fabbione.net>

commit bd5b07b062cea5f29f92752df9afba5821b61b4f
Author: Lon Hohberger <lhh@redhat.com>
Date:   Thu Mar 20 16:42:09 2008 -0400

    [cman] Make mkqdisk print all device paths

commit b8d8c52f46c8c81885b6a0db08e4f95dafbbc672
Author: Lon Hohberger <lhh@redhat.com>
Date:   Thu Mar 20 16:34:20 2008 -0400

    [cman] Fix qdisk Makefile / disk_util merge bugs

commit 9baa0907064ec24cbc295f1180558bafd94ba56d
Author: Lon Hohberger <lhh@redhat.com>
Date:   Thu Mar 20 12:49:36 2008 -0400

    [cman] Merge scandisk & fixes from RHEL5 branch
    
    Scandisk replaces the old scanning of /proc/partitions with
    a flexible library created by Fabio M. Di Nitto
    
    Fixes from the RHEL5 branch include:
     * ability to use block devices with >512 byte sector size
     * bug causing infinite "Node X is undead" messages

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

Summary of changes:
 cman/qdisk/Makefile    |    3 +-
 cman/qdisk/disk.c      |  207 ++++++++------
 cman/qdisk/disk.h      |   62 +++--
 cman/qdisk/disk_util.c |   21 +-
 cman/qdisk/main.c      |  157 ++++++-----
 cman/qdisk/mkqdisk.c   |   15 +-
 cman/qdisk/proc.c      |  267 +++++++++++++----
 cman/qdisk/scandisk.c  |  751 ++++++++++++++++++++++++++++++++++++++++++++++++
 cman/qdisk/scandisk.h  |  105 +++++++
 config/copyright.cf    |    4 +-
 10 files changed, 1323 insertions(+), 269 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 a6ab43f..4d3634d 100644
--- a/cman/qdisk/Makefile
+++ b/cman/qdisk/Makefile
@@ -44,7 +44,8 @@ OBJS2=	mkqdisk.o
 SHAREDOBJS= disk.o \
 	    crc32.o \
 	    disk_util.o \
-	    proc.o
+	    proc.o \
+	    scandisk.o
 
 
 ${TARGET1}: ${SHAREDOBJS} ${OBJS1}
diff --git a/cman/qdisk/disk.c b/cman/qdisk/disk.c
index eb1cf67..f3222ed 100644
--- a/cman/qdisk/disk.c
+++ b/cman/qdisk/disk.c
@@ -43,8 +43,9 @@
 #include <platform.h>
 #include <unistd.h>
 #include <time.h>
+#include <linux/fs.h>
 
-static int diskRawRead(int fd, char *buf, int len);
+static int diskRawRead(target_info_t *disk, char *buf, int len);
 uint32_t clu_crc32(const char *data, size_t count);
 
 
@@ -211,49 +212,57 @@ header_verify(shared_header_t *hdr, const char *data, size_t count)
  * Returns - (the file descriptor), a value >= 0 on success.
  */
 int
-qdisk_open(char *name)
+qdisk_open(char *name, target_info_t *disk)
 {
-	int fd;
-	int retval;
+	int ret;
+	int ssz;
 
 	/*
 	 * Open for synchronous writes to insure all writes go directly
 	 * to disk.
 	 */
-	fd = open(name, O_RDWR | O_SYNC | O_DIRECT);
-	if (fd < 0) {
-		return fd;
+	disk->d_fd = open(name, O_RDWR | O_SYNC | O_DIRECT);
+	if (disk->d_fd < 0)
+		return disk->d_fd;
+
+	ret = ioctl(disk->d_fd, BLKSSZGET, &ssz);
+	if (ret < 0) {
+		perror("qdisk_open: ioctl(BLKSSZGET)");
+		return -1;
 	}
 
-	/* Check to verify that the partition is large enough.*/
-	retval = lseek(fd, END_OF_DISK, SEEK_SET);
+	disk->d_blksz = ssz;
+	disk->d_pagesz = sysconf(_SC_PAGESIZE);
 
-	if (retval < 0) {
+	/* Check to verify that the partition is large enough.*/
+	ret = lseek(disk->d_fd, END_OF_DISK(disk->d_blksz), SEEK_SET);
+	if (ret < 0) {
 		perror("open_partition: seek");
 		return -1;
 	}
 
-	if (retval < END_OF_DISK) {
+	if (ret < END_OF_DISK(disk->d_blksz)) {
 		fprintf(stderr, "Partition %s too small\n", name);
 		errno = EINVAL;
 		return -1;
 	}
 
 	/* Set close-on-exec bit */
-        retval = fcntl(fd, F_GETFD, 0);
-        if (retval < 0) {
-                close(fd);
+        ret = fcntl(disk->d_fd, F_GETFD, 0);
+        if (ret < 0) {
+		perror("open_partition: fcntl(F_GETFD)");
+                close(disk->d_fd);
                 return -1;
         }
 
-        retval |= FD_CLOEXEC;
-        if (fcntl(fd, F_SETFD, retval) < 0) {
-		perror("open_partition: fcntl");
-                close(fd);
+        ret |= FD_CLOEXEC;
+        if (fcntl(disk->d_fd, F_SETFD, ret) < 0) {
+		perror("open_partition: fcntl(F_SETFD)");
+                close(disk->d_fd);
                 return -1;
         }
 
-	return fd;
+	return 0;
 }
 
 
@@ -263,17 +272,17 @@ qdisk_open(char *name)
  * Returns - value from close syscall.
  */
 int
-qdisk_close(int *fd)
+qdisk_close(target_info_t *disk)
 {
 	int retval;
 
-	if (!fd || *fd < 0) {
+	if (!disk || disk->d_fd < 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
-	retval = close(*fd);
-	*fd = -1;
+	retval = close(disk->d_fd);
+	disk->d_fd = -1;
 
 	return retval;
 }
@@ -288,7 +297,7 @@ int
 qdisk_validate(char *name)
 {
 	struct stat stat_st, *stat_ptr;
-	int fd;
+	target_info_t disk;
 	stat_ptr = &stat_st;
 
 	if (stat(name, stat_ptr) < 0) {
@@ -310,26 +319,25 @@ qdisk_validate(char *name)
 	/*
 	 * Verify read/write permission.
 	 */
-	fd = qdisk_open(name);
-	if (fd < 0) {
+	if (qdisk_open(name, &disk) < 0) {
 		fprintf(stderr, "%s: open of %s for RDWR failed: %s\n",
 			__FUNCTION__, name, strerror(errno));
 		return -1;
 	}
-	qdisk_close(&fd);
+	qdisk_close(&disk);
 	return 0;
 }
 
 
 static int
-diskRawReadShadow(int fd, off_t readOffset, char *buf, int len)
+diskRawReadShadow(target_info_t *disk, off_t readOffset, char *buf, int len)
 {
 	int ret;
 	shared_header_t *hdrp;
 	char *data;
 	int datalen;
 
-	ret = lseek(fd, readOffset, SEEK_SET);
+	ret = lseek(disk->d_fd, readOffset, SEEK_SET);
 	if (ret != readOffset) {
 #if 0
 		fprintf(stderr,
@@ -340,7 +348,7 @@ diskRawReadShadow(int fd, off_t readOffset, char *buf, int len)
 		return -1;
 	}
 
-	ret = diskRawRead(fd, buf, len);
+	ret = diskRawRead(disk, buf, len);
 	if (ret != len) {
 #if 0
 		fprintf(stderr, "diskRawReadShadow: aligned read "
@@ -375,7 +383,7 @@ diskRawReadShadow(int fd, off_t readOffset, char *buf, int len)
  * Here we check for alignment and do a bounceio if necessary.
  */
 static int
-diskRawRead(int fd, char *buf, int len)
+diskRawRead(target_info_t *disk, char *buf, int len)
 {
 	void *alignedBuf;
 	int readret;
@@ -383,21 +391,24 @@ diskRawRead(int fd, char *buf, int len)
 	int readlen;
 	int bounceNeeded = 1;
 
-	if ((((unsigned long) buf & (unsigned long) 0x3ff) == 0) &&
-	    ((len % 512) == 0)) {
+	
+	/* was 3ff, which is (512<<1-1) */
+	if ((((unsigned long) buf &
+	      (unsigned long) ((disk->d_blksz << 1) -1)) == 0) &&
+	    ((len % (disk->d_blksz)) == 0)) {
 		bounceNeeded = 0;
 	}
 
 	if (bounceNeeded == 0) {
 		/* Already aligned and even multiple of 512, no bounceio
 		 * required. */
-		return (read(fd, buf, len));
+		return (read(disk->d_fd, buf, len));
 	}
 
-	if (len > 512) {
+	if (len > disk->d_blksz) {
 		fprintf(stderr,
 			"diskRawRead: not setup for reads larger than %d.\n",
-		       512);
+		       (int)disk->d_blksz);
 		return (-1);
 	}
 	/*
@@ -406,8 +417,8 @@ diskRawRead(int fd, char *buf, int len)
 	 * XXX - if the on-disk offsets don't provide enough room we're cooked!
 	 */
 	extraLength = 0;
-	if (len % 512) {
-		extraLength = 512 - (len % 512);
+	if (len % disk->d_blksz) {
+		extraLength = disk->d_blksz - (len % disk->d_blksz);
 	}
 
 	readlen = len;
@@ -415,18 +426,18 @@ diskRawRead(int fd, char *buf, int len)
 		readlen += extraLength;
 	}
 
-	readret = posix_memalign((void **)&alignedBuf, 512, 512);
+	readret = posix_memalign((void **)&alignedBuf, disk->d_pagesz, disk->d_blksz);
 	if (readret < 0) {
 		return -1;
 	}
 
-	readret = read(fd, alignedBuf, readlen);
+	readret = read(disk->d_fd, alignedBuf, readlen);
 	if (readret > 0) {
 		if (readret > len) {
-			bcopy(alignedBuf, buf, len);
+			memcpy(alignedBuf, buf, len);
 			readret = len;
 		} else {
-			bcopy(alignedBuf, buf, readret);
+			memcpy(alignedBuf, buf, readret);
 		}
 	}
 
@@ -445,7 +456,7 @@ diskRawRead(int fd, char *buf, int len)
  * Here we check for alignment and do a bounceio if necessary.
  */
 static int
-diskRawWrite(int fd, char *buf, int len)
+diskRawWrite(target_info_t *disk, char *buf, int len)
 {
 	void *alignedBuf;
 	int ret;
@@ -453,31 +464,33 @@ diskRawWrite(int fd, char *buf, int len)
 	int writelen;
 	int bounceNeeded = 1;
 
-	if ((((unsigned long) buf & (unsigned long) 0x3ff) == 0) &&
-	    ((len % 512) == 0)) {
+	/* was 3ff, which is (512<<1-1) */
+	if ((((unsigned long) buf &
+	      (unsigned long) ((disk->d_blksz << 1) -1)) == 0) &&
+	    ((len % (disk->d_blksz)) == 0)) {
 		bounceNeeded = 0;
 	}
+
 	if (bounceNeeded == 0) {
 		/* Already aligned and even multiple of 512, no bounceio
 		 * required. */
-		return (write(fd, buf, len));
+		return (write(disk->d_fd, buf, len));
 	}
 
-	if (len > 512) {
+	if (len > disk->d_blksz) {
 		fprintf(stderr,
-		       "diskRawWrite: not setup for larger than %d.\n",
-		       512);
+			"diskRawRead: not setup for reads larger than %d.\n",
+		       (int)disk->d_blksz);
 		return (-1);
 	}
-
 	/*
 	 * All IOs must be of size which is a multiple of 512.  Here we
 	 * just add in enough extra to accommodate.
 	 * XXX - if the on-disk offsets don't provide enough room we're cooked!
 	 */
 	extraLength = 0;
-	if (len % 512) {
-		extraLength = 512 - (len % 512);
+	if (len % disk->d_blksz) {
+		extraLength = disk->d_blksz - (len % disk->d_blksz);
 	}
 
 	writelen = len;
@@ -485,13 +498,20 @@ diskRawWrite(int fd, char *buf, int len)
 		writelen += extraLength;
 	}
 
-	ret = posix_memalign((void **)&alignedBuf, 512,512);
+	ret = posix_memalign((void **)&alignedBuf, disk->d_pagesz, disk->d_blksz);
 	if (ret < 0) {
+		return -1;
+	}
+
+	if (len > disk->d_blksz) {
+		fprintf(stderr,
+		       "diskRawWrite: not setup for larger than %d.\n",
+		       (int)disk->d_blksz);
 		return (-1);
 	}
 
-	bcopy(buf, alignedBuf, len);
-	ret = write(fd, alignedBuf, writelen);
+	memcpy(buf, alignedBuf, len);
+	ret = write(disk->d_fd, alignedBuf, writelen);
 	if (ret > len) {
 		ret = len;
 	}
@@ -507,7 +527,7 @@ diskRawWrite(int fd, char *buf, int len)
 
 
 static int
-diskRawWriteShadow(int fd, __off64_t writeOffset, char *buf, int len)
+diskRawWriteShadow(target_info_t *disk, __off64_t writeOffset, char *buf, int len)
 {
 	off_t retval_seek;
 	ssize_t retval_write;
@@ -519,7 +539,7 @@ diskRawWriteShadow(int fd, __off64_t writeOffset, char *buf, int len)
 		return (-1);
 	}
 
-	retval_seek = lseek(fd, writeOffset, SEEK_SET);
+	retval_seek = lseek(disk->d_fd, writeOffset, SEEK_SET);
 	if (retval_seek != writeOffset) {
 		fprintf(stderr,
 		       "diskRawWriteShadow: can't seek to offset %d\n",
@@ -527,7 +547,7 @@ diskRawWriteShadow(int fd, __off64_t writeOffset, char *buf, int len)
 		return (-1);
 	}
 
-	retval_write = diskRawWrite(fd, buf, len);
+	retval_write = diskRawWrite(disk, buf, len);
 	if (retval_write != len) {
 		if (retval_write == -1) {
 			fprintf(stderr, "%s: %s\n", __FUNCTION__,
@@ -544,10 +564,10 @@ diskRawWriteShadow(int fd, __off64_t writeOffset, char *buf, int len)
 
 
 int
-qdisk_read(int fd, __off64_t offset, void *buf, int count)
+qdisk_read(target_info_t *disk, __off64_t offset, void *buf, int count)
 {
-	void *hdrbuf;
 	shared_header_t *hdrp;
+	void *ptr;
 	char *data;
 	size_t total;
 	int rv;
@@ -557,25 +577,25 @@ qdisk_read(int fd, __off64_t offset, void *buf, int count)
 	 * Raw blocks are 512 byte aligned.
 	 */
 	total = count + sizeof(shared_header_t);
-	if (total < 512)
-		total = 512;
+	if (total < disk->d_blksz)
+		total = disk->d_blksz;
 
 	/* Round it up */
-	if (total % 512) 
-		total = total + (512 * !!(total % 512)) - (total % 512);
+	if (total % disk->d_blksz) 
+		total = total + (disk->d_blksz * !!(total % disk->d_blksz)) - (total % disk->d_blksz);
 
-	hdrbuf = NULL;
-	rv = posix_memalign((void **)&hdrbuf, sysconf(_SC_PAGESIZE), total);
+	ptr = NULL;
+	rv = posix_memalign((void **)&ptr, disk->d_pagesz, disk->d_blksz);
 	if (rv < 0)
 		return -1;
 
-	if (hdrbuf == NULL) 
+	if (ptr == NULL) 
 		return -1;
 
-	hdrp = (shared_header_t *)hdrbuf;
+	hdrp = (shared_header_t *)ptr;
 	data = (char *)hdrp + sizeof(shared_header_t);
 
-	rv = diskRawReadShadow(fd, offset, (char *)hdrp, total);
+	rv = diskRawReadShadow(disk, offset, (char *)hdrp, disk->d_blksz);
 	
 	if (rv == -1) {
 		return -1;
@@ -590,19 +610,19 @@ qdisk_read(int fd, __off64_t offset, void *buf, int count)
 		       count - hdrp->h_length);
 	}
 
-	free(hdrbuf);
+	free(hdrp);
 	return count;
 }
 
 
 int
-qdisk_write(int fd, __off64_t offset, const void *buf, int count)
+qdisk_write(target_info_t *disk, __off64_t offset, const void *buf, int count)
 {
 	size_t maxsize;
-	void *hdrbuf;
 	shared_header_t *hdrp;
+	void *ptr;
 	char *data;
-	size_t total = 0, rv = -1, psz = 512; //sysconf(_SC_PAGESIZE);
+	size_t total = 0, rv = -1, psz = disk->d_blksz; //sysconf(_SC_PAGESIZE);
 
 	maxsize = psz - (sizeof(shared_header_t));
 	if (count >= (maxsize + sizeof(shared_header_t))) {
@@ -614,7 +634,6 @@ qdisk_write(int fd, __off64_t offset, const void *buf, int count)
 
 	/*
 	 * Calculate the total length of the buffer, including the header.
-	 * Raw blocks are 512 byte aligned.
 	 */
 	total = count + sizeof(shared_header_t);
 	if (total < psz)
@@ -624,17 +643,17 @@ qdisk_write(int fd, __off64_t offset, const void *buf, int count)
 	if (total % psz) 
 		total = total + (psz * !!(total % psz)) - (total % psz);
 
-	hdrbuf = NULL;
-	rv = posix_memalign((void **)&hdrbuf, sysconf(_SC_PAGESIZE), total);
+	ptr = NULL;
+	rv = posix_memalign((void **)&ptr, disk->d_pagesz, total);
 	if (rv < 0) {
 		perror("posix_memalign");
 		return -1;
 	}
-	hdrp = (shared_header_t *)hdrbuf;
 
 	/* 
 	 * Copy the data into our new buffer
 	 */
+	hdrp = (shared_header_t *)ptr;
 	data = (char *)hdrp + sizeof(shared_header_t);
 	memcpy(data, buf, count);
 
@@ -649,12 +668,12 @@ qdisk_write(int fd, __off64_t offset, const void *buf, int count)
 	 * about locking here.
 	 */
 	if (total == psz)
-		rv = diskRawWriteShadow(fd, offset, (char *)hdrp, psz);
+		rv = diskRawWriteShadow(disk, offset, (char *)hdrp, psz);
 
 	if (rv == -1)
 		perror("diskRawWriteShadow");
 	
-	free(hdrbuf);
+	free((char *)hdrp);
 	if (rv == -1)
 		return -1;
 	return count;
@@ -662,11 +681,11 @@ qdisk_write(int fd, __off64_t offset, const void *buf, int count)
 
 
 static int
-header_init(int fd, char *label)
+header_init(target_info_t *disk, char *label)
 {
 	quorum_header_t qh;
 
-	if (qdisk_read(fd, OFFSET_HEADER, &qh, sizeof(qh)) == sizeof(qh)) {
+	if (qdisk_read(disk, OFFSET_HEADER, &qh, sizeof(qh)) == sizeof(qh)) {
 		swab_quorum_header_t(&qh);
 		if (qh.qh_magic == HEADER_MAGIC_OLD) {
 			printf("Warning: Red Hat Cluster Manager 1.2.x "
@@ -685,14 +704,18 @@ header_init(int fd, char *label)
 	/* Copy in the cluster/label name */
 	snprintf(qh.qh_cluster, sizeof(qh.qh_cluster)-1, "%s", label);
 
+	qh.qh_version = VERSION_MAGIC_V2;
 	if ((qh.qh_timestamp = (uint64_t)time(NULL)) <= 0) {
 		perror("time");
 		return -1;
 	}
 
 	qh.qh_magic = HEADER_MAGIC_NUMBER;
+	qh.qh_blksz = disk->d_blksz;
+	qh.qh_kernsz = 0;
+
 	swab_quorum_header_t(&qh);
-	if (qdisk_write(fd, OFFSET_HEADER, &qh, sizeof(qh)) != sizeof(qh)) {
+	if (qdisk_write(disk, OFFSET_HEADER, &qh, sizeof(qh)) != sizeof(qh)) {
 		return -1;
 	}
 
@@ -703,24 +726,24 @@ header_init(int fd, char *label)
 int
 qdisk_init(char *partname, char *label)
 {
-	int fd;
+	target_info_t disk;
 	status_block_t ps, wps;
-	int nid;
+	int nid, ret;
 	time_t t;
 
-	fd = qdisk_validate(partname);
-	if (fd < 0) {
+	ret = qdisk_validate(partname);
+	if (ret < 0) {
 		perror("qdisk_verify");
 		return -1;
 	}
 
-	fd = qdisk_open(partname);
-	if (fd < 0) {
+	ret = qdisk_open(partname, &disk);
+	if (ret < 0) {
 		perror("qdisk_open");
 		return -1;
 	}
 
-	if (header_init(fd, label) < 0) {
+	if (header_init(&disk, label) < 0) {
 		return -1;
 	}
 
@@ -748,14 +771,14 @@ qdisk_init(char *partname, char *label)
 		wps = ps;
 		swab_status_block_t(&wps);
 
-		if (qdisk_write(fd, qdisk_nodeid_offset(nid), &wps, sizeof(wps)) < 0) {
+		if (qdisk_write(&disk, qdisk_nodeid_offset(nid, disk.d_blksz), &wps, sizeof(wps)) < 0) {
 			printf("Error writing node ID block %d\n", nid);
-			qdisk_close(&fd);
+			qdisk_close(&disk);
 			return -1;
 		}
 	}
 
-	qdisk_close(&fd);
+	qdisk_close(&disk);
 
 	return 0;
 }
diff --git a/cman/qdisk/disk.h b/cman/qdisk/disk.h
index bc4bb91..8c9a424 100644
--- a/cman/qdisk/disk.h
+++ b/cman/qdisk/disk.h
@@ -72,7 +72,8 @@ typedef enum {
 	RF_DEBUG = 0x4,
 	RF_PARANOID = 0x8,
 	RF_ALLOW_KILL = 0x10,
-	RF_UPTIME = 0x20
+	RF_UPTIME = 0x20,
+	RF_CMAN_LABEL = 0x40
 } run_flag_t;
 
 
@@ -86,6 +87,9 @@ typedef enum {
 #define STATE_MAGIC_NUMBER	0x47bacef8	/* Status block */
 #define SHARED_HEADER_MAGIC	0x00DEBB1E	/* Per-block headeer */
 
+/* Version magic. */
+#define VERSION_MAGIC_V2	0x389fabc4
+
 
 typedef struct __attribute__ ((packed)) {
 	uint32_t	ps_magic;
@@ -152,16 +156,21 @@ typedef struct __attribute__ ((packed)) {
  */
 typedef struct __attribute__ ((packed)) {
 	uint32_t	qh_magic;
-	uint32_t	qh_align;	   // 64-bit-ism: alignment fixer.
+	uint32_t	qh_version;	   // 
 	uint64_t	qh_timestamp;	   // time of last update
 	char 		qh_updatehost[128];// Hostname who put this here...
-	char		qh_cluster[128];   // Cluster name
+	char		qh_cluster[120];   // Cluster name; CMAN only 
+					   // supports 16 chars.
+	uint32_t	qh_blksz;          // Known block size @ creation
+	uint32_t	qh_kernsz;	   // Ingored
 } quorum_header_t;
 
 #define swab_quorum_header_t(ptr) \
 {\
 	swab32((ptr)->qh_magic); \
-	swab32((ptr)->qh_align); \
+	swab32((ptr)->qh_version); \
+	swab32((ptr)->qh_blksz); \
+	swab32((ptr)->qh_kernsz); \
 	swab64((ptr)->qh_timestamp); \
 }
 
@@ -196,31 +205,35 @@ typedef struct __attribute__ ((packed)) {
 
 /* Offsets from RHCM 1.2.x */
 #define OFFSET_HEADER	0
-#define HEADER_SIZE	4096		/* Page size for now */
+#define HEADER_SIZE(ssz)		(ssz<4096?4096:ssz)
 
-#define OFFSET_FIRST_STATUS_BLOCK	(OFFSET_HEADER + HEADER_SIZE)
-#define SPACE_PER_STATUS_BLOCK		4096 /* Page size for now */
+#define OFFSET_FIRST_STATUS_BLOCK(ssz)	(OFFSET_HEADER + HEADER_SIZE(ssz))
+#define SPACE_PER_STATUS_BLOCK(ssz)	(ssz<4096?4096:ssz)
 #define STATUS_BLOCK_COUNT		MAX_NODES_DISK
 
-#define SPACE_PER_MESSAGE_BLOCK		(4096)
-#define	MESSAGE_BLOCK_COUNT		MAX_NODES_DISK
-
-#define END_OF_DISK			(OFFSET_FIRST_STATUS_BLOCK + \
+#define END_OF_DISK(ssz)		(OFFSET_FIRST_STATUS_BLOCK(ssz) + \
 					 (MAX_NODES_DISK + 1) * \
-					 SPACE_PER_STATUS_BLOCK) \
+					 SPACE_PER_STATUS_BLOCK(ssz)) \
 
 
+typedef struct {
+	int d_fd;
+	int _pad_;
+	size_t d_blksz;
+	size_t d_pagesz;
+} target_info_t;
+
 
 /* From disk.c */
-int qdisk_open(char *name);
-int qdisk_close(int *fd);
+int qdisk_open(char *name, target_info_t *disk);
+int qdisk_close(target_info_t *disk);
 int qdisk_init(char *name, char *clustername);
 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 qdisk_read(target_info_t *disk, __off64_t ofs, void *buf, int len);
+int qdisk_write(target_info_t *disk, __off64_t ofs, const void *buf, int len);
 
-#define qdisk_nodeid_offset(nodeid) \
-	(OFFSET_FIRST_STATUS_BLOCK + (SPACE_PER_STATUS_BLOCK * (nodeid - 1)))
+#define qdisk_nodeid_offset(nodeid, ssz) \
+	(OFFSET_FIRST_STATUS_BLOCK(ssz) + (SPACE_PER_STATUS_BLOCK(ssz) * (nodeid - 1)))
 
 /* From disk_utils.c */
 #define HISTORY_LENGTH 60
@@ -231,11 +244,12 @@ typedef struct {
 	uint16_t pad0;
 } disk_msg_t;
 
+
 typedef struct {
 	uint64_t qc_incarnation;
 	struct timeval qc_average;
 	struct timeval qc_last[HISTORY_LENGTH];
-	int qc_fd;
+	target_info_t qc_disk;
 	int qc_my_id;
 	int qc_writes;
 	int qc_interval;
@@ -250,12 +264,14 @@ typedef struct {
 	disk_node_state_t qc_disk_status;
 	disk_node_state_t qc_status;
 	int qc_master;		/* Master?! */
-	int _pad_;
+	int qc_status_sock;
 	run_flag_t qc_flags;
 	cman_handle_t qc_ch;
 	char *qc_device;
 	char *qc_label;
 	char *qc_status_file;
+	char *qc_cman_label;
+	char *qc_status_sockname;
 } qd_ctx;
 
 typedef struct {
@@ -272,14 +288,14 @@ typedef struct {
 
 int qd_write_status(qd_ctx *ctx, int nid, disk_node_state_t state,
 		    disk_msg_t *msg, memb_mask_t mask, memb_mask_t master);
-int qd_read_print_status(int fd, int nid);
+int qd_read_print_status(target_info_t *disk, int nid);
 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 *devdir, const char *label,
+int find_partitions(const char *label,
 		    char *devname, size_t devlen, int print);
-int check_device(char *device, char *label, quorum_header_t *qh);
+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 eb5e6fa..f5539c0 100644
--- a/cman/qdisk/disk_util.c
+++ b/cman/qdisk/disk_util.c
@@ -201,8 +201,9 @@ qd_write_status(qd_ctx *ctx, int nid, disk_node_state_t state,
 	if (get_time(&start, ctx->qc_flags&RF_UPTIME) < 0)
 		utime_ok = 0;
 	swab_status_block_t(&ps);
-	if (qdisk_write(ctx->qc_fd, qdisk_nodeid_offset(nid), &ps,
-			sizeof(ps)) < 0) {
+	if (qdisk_write(&ctx->qc_disk,
+			qdisk_nodeid_offset(nid, ctx->qc_disk.d_blksz),
+			&ps, sizeof(ps)) < 0) {
 		printf("Error writing node ID block %d\n", nid);
 		return -1;
 	}
@@ -223,12 +224,12 @@ qd_write_status(qd_ctx *ctx, int nid, disk_node_state_t state,
 
 
 int
-qd_print_status(status_block_t *ps)
+qd_print_status(target_info_t *disk, status_block_t *ps)
 {
 	int x;
 
 	printf("Data @ offset %d:\n",
-	       (int)qdisk_nodeid_offset(ps->ps_nodeid));
+	       (int)qdisk_nodeid_offset(ps->ps_nodeid, disk->d_blksz));
 	printf("status_block_t {\n");
 	printf("\t.ps_magic = %08x;\n", (int)ps->ps_magic);
 	printf("\t.ps_nodeid = %d;\n", (int)ps->ps_nodeid);
@@ -261,11 +262,11 @@ qd_print_status(status_block_t *ps)
 
 
 int
-qd_read_print_status(int fd, int nid)
+qd_read_print_status(target_info_t *disk, int nid)
 {
 	status_block_t ps;
 
-	if (fd < 0) {
+	if (!disk || disk->d_fd < 0) {
 		errno = EINVAL;
 		return -1;
 	}
@@ -275,13 +276,13 @@ qd_read_print_status(int fd, int nid)
 		return -1;
 	}
 
-	if (qdisk_read(fd, qdisk_nodeid_offset(nid), &ps,
+	if (qdisk_read(disk, qdisk_nodeid_offset(nid, disk->d_blksz), &ps,
 			sizeof(ps)) < 0) {
 		printf("Error reading node ID block %d\n", nid);
 		return -1;
 	}
 	swab_status_block_t(&ps);
-	qd_print_status(&ps);
+	qd_print_status(disk, &ps);
 
 	return 0;
 }
@@ -322,6 +323,7 @@ qd_init(qd_ctx *ctx, cman_handle_t ch, int me)
 	ctx->qc_incarnation = generate_token();
 	ctx->qc_ch = ch;
 	ctx->qc_my_id = me;
+	ctx->qc_status_sock = -1;
 
 	return 0;
 }
@@ -339,6 +341,5 @@ qd_destroy(qd_ctx *ctx)
 		free(ctx->qc_device);
 		ctx->qc_device = NULL;
 	}
-	close(ctx->qc_fd);
-	ctx->qc_fd = -1;
+	qdisk_close(&ctx->qc_disk);
 }
diff --git a/cman/qdisk/main.c b/cman/qdisk/main.c
index 8bd8c7d..b953367 100644
--- a/cman/qdisk/main.c
+++ b/cman/qdisk/main.c
@@ -36,6 +36,7 @@
 #include <time.h>
 #include <sys/reboot.h>
 #include <sys/time.h>
+#include <sys/un.h>
 #include <linux/reboot.h>
 #include <sched.h>
 #include <signal.h>
@@ -147,7 +148,8 @@ read_node_blocks(qd_ctx *ctx, node_info_t *ni, int max)
 
 		sb = &ni[x].ni_status;
 
-		if (qdisk_read(ctx->qc_fd, qdisk_nodeid_offset(x+1),
+		if (qdisk_read(&ctx->qc_disk,
+			       qdisk_nodeid_offset(x+1, ctx->qc_disk.d_blksz),
 			       sb, sizeof(*sb)) < 0) {
 			clulog(LOG_WARNING,"Error reading node ID block %d\n",
 			       x+1);
@@ -252,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) {
@@ -285,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),
@@ -462,12 +464,14 @@ quorum_init(qd_ctx *ctx, node_info_t *ni, int max, struct h_data *h, int maxh)
 	if (qdisk_validate(ctx->qc_device) < 0)
 		return -1;
 
-	ctx->qc_fd = qdisk_open(ctx->qc_device);
-	if (ctx->qc_fd < 0) {
+	if (qdisk_open(ctx->qc_device, &ctx->qc_disk) < 0) {
 		clulog(LOG_CRIT, "Failed to open %s: %s\n", ctx->qc_device,
 		       strerror(errno));
 		return -1;
 	}
+
+	clulog(LOG_DEBUG, "I/O Size: %d  Page Size: %d\n",
+	       ctx->qc_disk.d_blksz, ctx->qc_disk.d_pagesz);
 	
 	if (h && maxh) {
 		start_score_thread(ctx, h, maxh);
@@ -622,23 +626,7 @@ check_votes(qd_ctx *ctx, node_info_t *ni, int max, disk_msg_t *msg)
 
 
 char *
-state_str(disk_node_state_t s)
-{
-	switch (s) {
-	case S_NONE:
-		return "None";
-	case S_EVICT:
-		return "Evicted";
-	case S_INIT:
-		return "Initializing";
-	case S_RUN:
-		return "Running";
-	case S_MASTER:
-		return "Master";
-	default:
-		return "ILLEGAL";
-	}
-}
+state_str(disk_node_state_t s);
 
 
 void
@@ -1210,30 +1198,14 @@ get_config_data(char *cluster_name, qd_ctx *ctx, struct h_data *h, int maxh,
 	}
 	if (ctx->qc_master_wait <= ctx->qc_tko_up)
 		ctx->qc_master_wait = ctx->qc_tko_up + 1;
-
+		
 	/* Get votes */
-
-	/* check if votes is set in cluster.conf */
 	snprintf(query, sizeof(query), "/cluster/quorumd/@votes");
 	if (ccs_get(ccsfd, query, &val) == 0) {
 		ctx->qc_votes = atoi(val);
 		free(val);
 		if (ctx->qc_votes < 0)
 			ctx->qc_votes = 0;
-	} else { /* if votes is not set, default to node_num - 1 */
-		int nodes = 0, error;
-		for (;;) {
-			error = ccs_get_list(ccsfd, "/cluster/clusternodes/child::*", &val);
-			if (error || !val)
-				break;
-
-			nodes++;
-		}
-		nodes--;
-		if (nodes < 0)
-			nodes = 0;
-
-		ctx->qc_votes = nodes;
 	}
 
 	/* Get device */
@@ -1254,6 +1226,12 @@ get_config_data(char *cluster_name, qd_ctx *ctx, struct h_data *h, int maxh,
 		ctx->qc_status_file = val;
 	}
 
+	/* Get status socket */
+	snprintf(query, sizeof(query), "/cluster/quorumd/@status_sock");
+	if (ccs_get(ccsfd, query, &val) == 0) {
+		ctx->qc_status_sockname = val;
+	}
+
 	/* Get min score */
 	snprintf(query, sizeof(query), "/cluster/quorumd/@min_score");
 	if (ccs_get(ccsfd, query, &val) == 0) {
@@ -1302,6 +1280,15 @@ get_config_data(char *cluster_name, qd_ctx *ctx, struct h_data *h, int maxh,
 			ctx->qc_flags &= ~RF_REBOOT;
 		free(val);
 	}
+
+	/* Get cman_label */
+	snprintf(query, sizeof(query), "/cluster/quorumd/@cman_label");
+	if (ccs_get(ccsfd, query, &val) == 0) {
+		if (strlen(val) > 0) {
+			ctx->qc_flags |= RF_CMAN_LABEL;
+			ctx->qc_cman_label = val;
+		}
+	}
 	
 	/*
 	 * Get flag to see if we're supposed to kill cman if qdisk is not 
@@ -1366,6 +1353,7 @@ get_config_data(char *cluster_name, qd_ctx *ctx, struct h_data *h, int maxh,
 	clulog(LOG_DEBUG,
 	       "Quorum Daemon: %d heuristics, %d interval, %d tko, %d votes\n",
 	       *cfh, ctx->qc_interval, ctx->qc_tko, ctx->qc_votes);
+	clulog(LOG_DEBUG, "Run Flags: %08x\n", ctx->qc_flags);
 
 	ccs_disconnect(ccsfd);
 
@@ -1400,21 +1388,22 @@ int
 main(int argc, char **argv)
 {
 	cman_node_t me;
-	int cfh, rv, forked = 0, nfd = -1;
+	int cfh, rv, forked = 0, nfd = -1, ret = -1;
 	qd_ctx ctx;
-	cman_handle_t ch;
+	cman_handle_t ch = NULL;
 	node_info_t ni[MAX_NODES_DISK];
 	struct h_data h[10];
 	char debug = 0, foreground = 0;
 	char device[128];
 	pid_t pid;
+	quorum_header_t qh;
 
 	if (check_process_running(argv[0], &pid) && pid !=getpid()) {
 		printf("QDisk services already running\n");
 		return 0;
 	}
 	
-	while ((rv = getopt(argc, argv, "fdQ")) != EOF) {
+	while ((rv = getopt(argc, argv, "fdQs")) != EOF) {
 		switch (rv) {
 		case 'd':
 			debug = 1;
@@ -1438,7 +1427,7 @@ main(int argc, char **argv)
 			break;
 		}
 	}
-	
+
 #if (defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2)
 	ch = cman_admin_init(NULL);
 #else
@@ -1447,7 +1436,7 @@ main(int argc, char **argv)
 	if (!ch) {
 		if (!foreground && !forked) {
 			if (daemon_init(argv[0]) < 0)
-				return -1;
+				goto out;
 			else
 				forked = 1;
 		}
@@ -1468,7 +1457,7 @@ main(int argc, char **argv)
 	while (cman_get_node(ch, CMAN_NODEID_US, &me) < 0) {
 		if (!foreground && !forked) {
 			if (daemon_init(argv[0]) < 0)
-				return -1;
+				goto out;
 			else
 				forked = 1;
 		}
@@ -1488,20 +1477,19 @@ main(int argc, char **argv)
 	if (get_config_data(NULL, &ctx, h, 10, &cfh, debug) < 0) {
 		clulog_and_print(LOG_CRIT, "Configuration failed\n");
 		check_stop_cman(&ctx);
-		return -1;
+		goto out;
 	}
 	
 	if (ctx.qc_label) {
-		memset(device, 0, sizeof(device));
-		if (find_partitions("/dev",
-				    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);
-			return -1;
+			goto out;
 		}
+		/* XXX Multiple matches: do we care? */
 
 		if (ctx.qc_device)
 			free(ctx.qc_device);
@@ -1511,18 +1499,29 @@ 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, NULL) != 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);
 			check_stop_cman(&ctx);
-			return -1;
+			goto out;
+		}
+
+		if (qh.qh_version == VERSION_MAGIC_V2 &&
+                    qh.qh_blksz != rv) {
+			clulog(LOG_CRIT,
+			       "Specified device %s does match kernel's "
+			       "reported sector size (%d != %d)\n",
+			       ctx.qc_device,
+			       ctx.qc_disk.d_blksz, rv);
+			check_stop_cman(&ctx);
+			goto out;
 		}
 	}
 
 	if (!foreground && !forked) {
                 if (daemon_init(argv[0]) < 0)
-			return -1;
+			goto out;
 	}
 	
 	set_priority(ctx.qc_sched, ctx.qc_sched_prio);
@@ -1530,13 +1529,19 @@ main(int argc, char **argv)
 	if (quorum_init(&ctx, ni, MAX_NODES_DISK, h, cfh) < 0) {
 		clulog_and_print(LOG_CRIT, "Initialization failed\n");
 		check_stop_cman(&ctx);
-		return -1;
+		goto out;
 	}
 
+	ret = 0;
+
 	if (!_running)
-		return 0;
+		goto out;
 	
-	cman_register_quorum_device(ctx.qc_ch, ctx.qc_device, ctx.qc_votes);
+	cman_register_quorum_device(ctx.qc_ch,
+				    (ctx.qc_flags&RF_CMAN_LABEL)? 
+				        ctx.qc_cman_label:
+                                        ctx.qc_device,
+				    ctx.qc_votes);
 	/*
 		XXX this always returns -1 / EBUSY even when it works?!!!
 		
@@ -1546,16 +1551,18 @@ main(int argc, char **argv)
 				 "Could not register %s with CMAN; "
 				 "return = %d; error = %s\n",
 				 ctx.qc_device, rv, strerror(errno));
-		return -1;
+		goto out;
 	}
 	*/
-
 	if (quorum_loop(&ctx, ni, MAX_NODES_DISK) == 0)
 		cman_unregister_quorum_device(ctx.qc_ch);
 
 	quorum_logout(&ctx);
+	/* free cman handle to avoid leak in cman */
+out:
+	cman_finish(ctx.qc_ch);
 	qd_destroy(&ctx);
 
-	return 0;
+	return ret;
 }
 
diff --git a/cman/qdisk/mkqdisk.c b/cman/qdisk/mkqdisk.c
index fab5ea4..19cb5e2 100644
--- a/cman/qdisk/mkqdisk.c
+++ b/cman/qdisk/mkqdisk.c
@@ -37,23 +37,24 @@ main(int argc, char **argv)
 {
 	char device[128];
 	char *newdev = NULL, *newlabel = NULL;
-	int rv;
+	int rv, verbose_level = 1;
 
 	printf("mkqdisk v" RELEASE_VERSION "\n\n");
 
-	while ((rv = getopt(argc, argv, "Lf:c:l:h")) != EOF) {
+	while ((rv = getopt(argc, argv, "Ldf:c:l:h")) != EOF) {
 		switch (rv) {
+		case 'd':
+			++verbose_level;
+			break;
 		case 'L':
 			/* List */
 			close(2);
-			return find_partitions("/dev",
-					       NULL, NULL, 0, 1);
+			return find_partitions(NULL, NULL, 0, verbose_level);
 			break;
 		case 'f':
 			close(2);
-			return find_partitions("/dev",
-					       optarg, device,
-					       sizeof(device), 1);
+			return find_partitions( optarg, device,
+					       sizeof(device), verbose_level);
 		case 'c':
 			newdev = optarg;
 			break;
diff --git a/cman/qdisk/proc.c b/cman/qdisk/proc.c
index acde85a..5623e7e 100644
--- a/cman/qdisk/proc.c
+++ b/cman/qdisk/proc.c
@@ -26,35 +26,46 @@
 #include <disk.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <platform.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <dirent.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, quorum_header_t *qh)
+check_device(char *device, char *label, quorum_header_t *qh,
+	     int flags)
 {
-	int fd = -1, ret = -1;
+	int ret = -1;
 	quorum_header_t qh_local;
+	target_info_t disk;
 
 	if (!qh)
 		qh = &qh_local;
 
-	fd = qdisk_validate(device);
-	if (fd < 0) {
+	ret = qdisk_validate(device);
+	if (ret < 0) {
 		perror("qdisk_verify");
 		return -1;
 	}
 
-	fd = qdisk_open(device);
-	if (fd < 0) {
+	ret = qdisk_open(device, &disk);
+	if (ret < 0) {
 		perror("qdisk_open");
 		return -1;
 	}
 
-	if (qdisk_read(fd, OFFSET_HEADER, qh, sizeof(*qh)) == sizeof(*qh)) {
+	ret = -1;
+	if (qdisk_read(&disk, 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)) {
@@ -63,68 +74,206 @@ check_device(char *device, char *label, quorum_header_t *qh)
                 }
         }
 
-	qdisk_close(&fd);
+	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 &&
+            disk.d_blksz != qh->qh_blksz) {
+		ret = -1;
+	}
+
+	qdisk_close(&disk);
 
 	return ret;
 }
 
 
-int
-find_partitions(const char *devdir, const char *label,
-	        char *devname, size_t devlen, int print)
+void
+filter_devs(struct devnode *node, void *v_args)
 {
-	struct dirent **namelist;
-	struct stat sb;
-	char newpath[256];
-	int n;
+	struct device_args *args = (struct device_args *)v_args;
 	quorum_header_t qh;
+	quorum_header_t *ret_qh = NULL;
+	int ret;
 
-	n = scandir(devdir, &namelist, 0, alphasort);
-	if (n <= 0)
-		return -1;
+	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)
+{
+	switch (s) {
+	case S_NONE:
+		return "None";
+	case S_EVICT:
+		return "Evicted";
+	case S_INIT:
+		return "Initializing";
+	case S_RUN:
+		return "Running";
+	case S_MASTER:
+		return "Master";
+	default:
+		return "ILLEGAL";
+	}
+}
+
+
+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 *)&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);
+	printf("\tAverage Cycle speed: %d.%06d seconds\n", 
+		sb->ps_ca_sec, sb->ps_ca_usec);
+	printf("\tLast Cycle speed: %d.%06d seconds\n", 
+		sb->ps_lc_sec, sb->ps_lc_usec);
+	printf("\tIncarnation: %08x%08x\n",
+		(int)(sb->ps_incarnation>>32&0xffffffff),
+		(int)(sb->ps_incarnation&0xffffffff));
+
+}
+
+
+void
+read_info(char *dev)
+{
+	target_info_t ti;
+	int x;
+	status_block_t sb;
+
+	if (qdisk_open(dev, &ti) < 0) {
+		printf("Could not read from %s: %s\n",
+		       dev, strerror(errno));
+		return;
+	}
+
+	for (x = 0; x < MAX_NODES_DISK; x++) {
+
+		if (qdisk_read(&ti,
+			       qdisk_nodeid_offset(x+1, ti.d_blksz),
+			       &sb, sizeof(sb)) < 0) {
+			printf("Error reading node ID block %d\n",
+			       x+1);
+			continue;
+		}
+		swab_status_block_t(&sb);
+		print_status_block(&sb);
+	}
+
+	qdisk_close(&ti);
+}
 
-	while (n--) {
-		/* filter out:
-		 * . and ..
-		 * .static and .udev that are typical udev dirs that we don't want to scan
-		 */
-		if (strcmp(namelist[n]->d_name, ".") &&
-		    strcmp(namelist[n]->d_name, "..") &&
-		    strcmp(namelist[n]->d_name, ".static") &&
-		    strcmp(namelist[n]->d_name, ".udev")) {
-			snprintf(newpath, sizeof(newpath), "%s/%s", devdir, namelist[n]->d_name);
-			if (!lstat(newpath, &sb)) {
-				/* dive into directories */
-				if (S_ISDIR(sb.st_mode)) {
-					if (!find_partitions(newpath, label, devname, devlen, print)) {
-						if (devname && (strlen(devname) > 0))
-							return 0;
-					}
-				}
-				/* check if it's a block device */
-				if (S_ISBLK(sb.st_mode)) {
-					if (!check_device(newpath, (char *)label, &qh)) {
-						if (print) {
-							time_t timestamp = qh.qh_timestamp;
-							printf("%s:\n", newpath);
-							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 (devname && devlen) {
-							strncpy(devname, newpath, devlen);
-							return 0;
-						}
-					}
-				}
+
+void
+print_qdisk_info(struct devnode *dn)
+{
+	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);
+	}
+}
+
+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;
+			}
+
+			print_qdisk_info(dn);
+			if (print >= 2) {
+				/* Print node stuff */
+				read_info(dn->devpath->path);
 			}
 		}
-		free(namelist[n]);
 	}
 
+	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__ */
diff --git a/config/copyright.cf b/config/copyright.cf
index 0ff3bab..54f1c33 100644
--- a/config/copyright.cf
+++ b/config/copyright.cf
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) Red Hat, Inc. 2004-2007  All rights reserved.
+**  Copyright (C) Red Hat, Inc. 2004-2008  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -14,7 +14,7 @@
 #ifndef __COPYRIGHT_DOT_CF__
 #define __COPYRIGHT_DOT_CF__
 
-#define REDHAT_COPYRIGHT ("Copyright (C) Red Hat, Inc.  2004-2007  All rights reserved.")
+#define REDHAT_COPYRIGHT ("Copyright (C) Red Hat, Inc.  2004-2008  All rights reserved.")
 
 #endif  /*  __COPYRIGHT_DOT_CF__  */
 


hooks/post-receive
--
Cluster Project



More information about the Cluster-cvs mailing list