Linux Archive

Linux Archive (http://www.linux-archive.org/)
-   Cluster Development (http://www.linux-archive.org/cluster-development/)
-   -   Cluster Project branch, master, updated. gfs-kernel_0_1_22-87-gf4a6e5e (http://www.linux-archive.org/cluster-development/59294-cluster-project-branch-master-updated-gfs-kernel_0_1_22-87-gf4a6e5e.html)

03-20-2008 03:51 PM

Cluster Project branch, master, updated. gfs-kernel_0_1_22-87-gf4a6e5e
 
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=f4a6e5e1e8 1f8355cd0f50f032e6f443db17ade9

The branch, master has been updated
via f4a6e5e1e81f8355cd0f50f032e6f443db17ade9 (commit)
from a1493bc4efd6ffdfa4064eb1105b300d47ea12b3 (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 f4a6e5e1e81f8355cd0f50f032e6f443db17ade9
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 | 13 +-
cman/qdisk/disk.c | 207 ++++++++-------
cman/qdisk/disk.h | 62 +++--
cman/qdisk/disk_util.c | 23 +-
cman/qdisk/main.c | 157 ++++++-----
cman/qdisk/mkqdisk.c | 15 +-
cman/qdisk/proc.c | 263 ++++++++++++++----
cman/qdisk/scandisk.c | 713 ++++++++++++++++++++++++++++++++++++++++++++++++
cman/qdisk/scandisk.h | 100 +++++++
9 files changed, 1282 insertions(+), 271 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..e5c7f27 100644
--- a/cman/qdisk/Makefile
+++ b/cman/qdisk/Makefile
@@ -29,8 +29,11 @@ CFLAGS += -I${ccsincdir} -I${cmanincdir}
CFLAGS += -I$(S)
CFLAGS += -I${incdir}

-EXTRA_LDFLAGS += -L${cmanlibdir} -L${ccslibdir} -lcman -lccs
-EXTRA_LDFLAGS += -lpthread
+EXTRA_LDFLAGS += -lcman -lccs
+#
+# XXX Fabio has a way to clean up the devmapper requirement
+#
+EXTRA_LDFLAGS += -lpthread -ldevmapper

OBJS1= main.o
score.o
@@ -44,14 +47,16 @@ OBJS2= mkqdisk.o
SHAREDOBJS= disk.o
crc32.o
disk_util.o
- proc.o
+ proc.o
+ scandisk.o


${TARGET1}: ${SHAREDOBJS} ${OBJS1}
$(CC) -o $@ $^ $(LDFLAGS) $(EXTRA_LDFLAGS)

+# XXX Remove $(EXTRA_LDFLAGS) when libdevmapper is no longer required
${TARGET2}: ${SHAREDOBJS} ${OBJS2}
- $(CC) -o $@ $^ $(LDFLAGS)
+ $(CC) -o $@ $^ $(LDFLAGS) $(EXTRA_LDFLAGS)

depends:
$(MAKE) -C ../lib all
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
", 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
",
__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.
",
- 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.
",
- 512);
+ "diskRawRead: not setup for reads larger than %d.
",
+ (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.
",
+ (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
",
@@ -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
", __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
", 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..a3d73d8 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(__sparc64__)
+#if defined(__sparc__) || defined(__hppa__) || defined(__sparc64__) || defined (__hppa64__)
rv = fscanf(fp,"%ld.%d %ld.%d
", &tv->tv_sec, &tv->tv_usec,
&junk.tv_sec, &junk.tv_usec);
#else
@@ -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
", 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:
",
- (int)qdisk_nodeid_offset(ps->ps_nodeid));
+ (int)qdisk_nodeid_offset(ps->ps_nodeid, disk->d_blksz));
printf("status_block_t {
");
printf(" .ps_magic = %08x;
", (int)ps->ps_magic);
printf(" .ps_nodeid = %d;
", (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
", 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
",
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
",
- 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
",
+ 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
", ctx->qc_device,
strerror(errno));
return -1;
}
+
+ clulog(LOG_DEBUG, "I/O Size: %d Page Size: %d
",
+ 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
",
*cfh, ctx->qc_interval, ctx->qc_tko, ctx->qc_votes);
+ clulog(LOG_DEBUG, "Run Flags: %08x
", 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
");
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
");
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
",
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
",
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
", 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)
",
+ 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
");
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
",
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 "

");

- 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..6c7ef48 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,202 @@ 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)
+{
+ if (sb->ps_state == S_NONE)
+ return;
+ printf("Status block for node %d
", sb->ps_nodeid);
+ printf(" Last updated by node %d
", sb->ps_updatenode);
+ printf(" Last updated on %s", ctime((time_t *)&sb->ps_timestamp));
+ printf(" State: %s
", state_str(sb->ps_state));
+ printf(" Flags: %04x
", sb->ps_flags);
+ printf(" Score: %d/%d
", sb->ps_score, sb->ps_scoremax);
+ printf(" Average Cycle speed: %d.%06d seconds
",
+ sb->ps_ca_sec, sb->ps_ca_usec);
+ printf(" Last Cycle speed: %d.%06d seconds
",
+ sb->ps_lc_sec, sb->ps_lc_usec);
+ printf(" Incarnation: %08x%08x
",
+ (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
",
+ dev, strerror(errno));
+ return;
+ }

- 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:
", newpath);
- printf(" Magic: %08x
", qh.qh_magic);
- printf(" Label: %s
", qh.qh_cluster);
- printf(" Created: %s",
- ctime((time_t *)&timestamp));
- printf(" Host: %s

", qh.qh_updatehost);
- }
-
- if (devname && devlen) {
- strncpy(devname, newpath, devlen);
- return 0;
- }
- }
- }
+ 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
",
+ x+1);
+ continue;
+ }
+ swab_status_block_t(&sb);
+ print_status_block(&sb);
+ }
+
+ qdisk_close(&ti);
+}
+
+
+void
+print_qdisk_info(struct devnode *dn)
+{
+ quorum_header_t *qh = (quorum_header_t *)dn->filter;
+
+ printf("%s:
", dn->devpath->path);
+ printf(" Magic: %08x
", qh->qh_magic);
+ printf(" Label: %s
", qh->qh_cluster);
+ printf(" Created: %s",
+ ctime((time_t *)&(qh->qh_timestamp)));
+ printf(" Host: %s
", qh->qh_updatehost);
+ printf(" Kernel Sector Size: %d
", qh->qh_kernsz);
+ if (qh->qh_version == VERSION_MAGIC_V2) {
+ printf(" Recorded Sector Size: %d

", (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..b0bd8a6
--- /dev/null
+++ b/cman/qdisk/scandisk.c
@@ -0,0 +1,713 @@
+/************************************************** ****************************
+************************************************* ******************************
+**
+** Copyright (C) 2008 Fabio M. Di Nitto <fabbione@fabbione.net>.
+** 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
+** 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 <libdevmapper.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;
+}
+
+/* TODO: add more stuff from devmapper to understand if a maj/min
+ * is a slave or a holder. If we have sysfs this is of no use.
+ */
+
+/* scanmapper uses libdevmapper to identify devices that are not real
+ *
+ * ret:
+ * can't fail for now
+ */
+static int scanmapper(struct devlisthead *devlisthead)
+{
+ struct devnode *startnode = devlisthead->devnode;
+
+ while (startnode) {
+ if (dm_is_dm_major(startnode->maj) > 0)
+ startnode->mapper = 1;
+ startnode = startnode->next;
+ }
+
+ 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
", &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
", &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..b103a3c
--- /dev/null
+++ b/cman/qdisk/scandisk.h
@@ -0,0 +1,100 @@
+/************************************************** ****************************
+************************************************* ******************************
+**
+** Copyright (C) 2008 Fabio M. Di Nitto <fabbione@fabbione.net>.
+** 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
+** 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


All times are GMT. The time now is 07:54 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.