diff -purN multipath-tools-0.4.4.orig/libcheckers/checkers.h multipath-tools-0.4.4/libcheckers/checkers.h --- multipath-tools-0.4.4.orig/libcheckers/checkers.h 2005-03-29 16:21:40.000000000 +0200 +++ multipath-tools-0.4.4/libcheckers/checkers.h 2005-08-04 15:20:52.000000000 +0200 @@ -9,6 +9,7 @@ enum checkers { CHECKER_RESERVED, TUR, READSECTOR0, + DIRECTIO, EMC_CLARIION, HP_SW }; @@ -20,6 +21,7 @@ void *get_checker_addr (int); int get_checker_name (char *, int); int emc_clariion (int fd, char * msg, void ** ctxt); +int directio (int fd, char * msg, void ** ctxt); int readsector0 (int fd, char * msg, void ** ctxt); int tur (int fd, char * msg, void ** ctxt); diff -purN multipath-tools-0.4.4.orig/libcheckers/directio.c multipath-tools-0.4.4/libcheckers/directio.c --- multipath-tools-0.4.4.orig/libcheckers/directio.c 1970-01-01 01:00:00.000000000 +0100 +++ multipath-tools-0.4.4/libcheckers/directio.c 2005-08-04 15:19:10.000000000 +0200 @@ -0,0 +1,165 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "path_state.h" +#include "checkers.h" + +#define MSG_DIRECTIO_UNKNOWN "directio checker is not available" +#define MSG_DIRECTIO_UP "directio checker reports path is up" +#define MSG_DIRECTIO_DOWN "directio checker reports path is down" + +struct readsector0_checker_context { + void * dummy; +}; + +static int +direct_read (int fd, unsigned char * buff, int size) +{ + long flags; + int reset_flags = 0; + int res, retval; + + flags = fcntl(fd,F_GETFL); + + if (flags < 0) { + return PATH_UNCHECKED; + } + + if (!(flags & O_DIRECT)) { + flags |= O_DIRECT; + if (fcntl(fd,F_SETFL,flags) < 0) { + return PATH_UNCHECKED; + } + reset_flags = 1; + } + + while ( (res = read(fd,buff,size)) < 0 && errno == EINTR ); + if (res < 0) { + if (errno == EINVAL) { + /* O_DIRECT is not available */ + retval = PATH_UNCHECKED; + } else if (errno == ENOMEM) { + retval = PATH_UP; + } else { + retval = PATH_DOWN; + } + } else { + retval = PATH_UP; + } + + if (reset_flags) { + flags &= ~O_DIRECT; + /* No point in checking for errors */ + fcntl(fd,F_SETFL,flags); + } + + return retval; +} + +extern int +directio (int fd, char *msg, void **context) +{ + unsigned char *buf, *ptr; + struct readsector0_checker_context * ctxt = NULL; + unsigned long pgsize, numsect; + int ret, blksize; + + pgsize = getpagesize(); + + /* + * caller passed in a context : use its address + */ + if (context) + ctxt = (struct readsector0_checker_context *) (*context); + + /* + * passed in context is uninitialized or volatile context : + * initialize it + */ + if (!ctxt) { + ctxt = malloc(sizeof(struct readsector0_checker_context)); + memset(ctxt, 0, sizeof(struct readsector0_checker_context)); + + if (!ctxt) { + MSG("cannot allocate context"); + return -1; + } + if (context) + *context = ctxt; + } + if (fd <= 0) { + MSG("no usable fd"); + ret = -1; + goto out; + } + + if (ioctl(fd, BLKGETSIZE, &numsect) < 0) { + MSG("cannot get number of sectors, set default"); + numsect = 0; + } + + if (ioctl(fd, BLKBSZGET, &blksize) < 0) { + MSG("cannot get blocksize, set default"); + blksize = 512; + } + + if (blksize > 4096) { + /* + * Sanity check for DASD; BSZGET is broken + */ + blksize = 4096; + } + + if (!blksize) { + /* + * Blocksize is 0, assume we can't write + * to this device. + */ + MSG(MSG_DIRECTIO_DOWN); + ret = PATH_DOWN; + goto out; + } + + buf = (unsigned char *)malloc(blksize + pgsize); + if (!buf){ + goto out; + } + ptr = (char *)(((unsigned long)buf + pgsize - 1) & + (~(pgsize - 1))); + ret = direct_read(fd, ptr, blksize); + + switch (ret) + { + case PATH_UNCHECKED: + MSG(MSG_DIRECTIO_UNKNOWN); + break; + case PATH_DOWN: + MSG(MSG_DIRECTIO_DOWN); + break; + case PATH_UP: + MSG(MSG_DIRECTIO_UP); + break; + default: + break; + } + free(buf); + +out: + /* + * caller told us he doesn't want to keep the context : + * free it + */ + if (!context) + free(ctxt); + + return ret; +} diff -purN multipath-tools-0.4.4.orig/libcheckers/Makefile multipath-tools-0.4.4/libcheckers/Makefile --- multipath-tools-0.4.4.orig/libcheckers/Makefile 2005-04-04 12:09:58.000000000 +0200 +++ multipath-tools-0.4.4/libcheckers/Makefile 2005-08-04 15:19:20.000000000 +0200 @@ -6,7 +6,7 @@ BUILD = glibc include ../Makefile.inc -OBJS = readsector0.o tur.o selector.o emc_clariion.o hp_sw.o +OBJS = readsector0.o tur.o selector.o directio.o emc_clariion.o hp_sw.o all: $(BUILD) diff -purN multipath-tools-0.4.4.orig/libcheckers/selector.c multipath-tools-0.4.4/libcheckers/selector.c --- multipath-tools-0.4.4.orig/libcheckers/selector.c 2005-03-29 16:27:46.000000000 +0200 +++ multipath-tools-0.4.4/libcheckers/selector.c 2005-08-04 15:20:27.000000000 +0200 @@ -10,6 +10,8 @@ get_checker_id (char * str) return TUR; if (0 == strncmp(str, "readsector0", 11)) return READSECTOR0; + if (0 == strncmp(str, "directio", 8)) + return DIRECTIO; if (0 == strncmp(str, "emc_clariion", 12)) return EMC_CLARIION; return -1; @@ -27,6 +29,9 @@ get_checker_addr (int id) case READSECTOR0: checker = &readsector0; break; + case DIRECTIO: + checker = &directio; + break; case EMC_CLARIION: checker = &emc_clariion; break; @@ -49,6 +54,9 @@ get_checker_name (char * str, int id) case READSECTOR0: s = "readsector0"; break; + case DIRECTIO: + s = "directio"; + break; case EMC_CLARIION: s = "emc_clariion"; break;