All of lore.kernel.org
 help / color / mirror / Atom feed
* multipath-tools/libcheckers directio.c
@ 2007-07-26 19:27 bmarzins
  0 siblings, 0 replies; 2+ messages in thread
From: bmarzins @ 2007-07-26 19:27 UTC (permalink / raw)
  To: dm-cvs, dm-devel

CVSROOT:	/cvs/dm
Module name:	multipath-tools
Branch: 	RHEL4_FC5
Changes by:	bmarzins@sourceware.org	2007-07-26 19:27:14

Modified files:
	libcheckers    : directio.c 

Log message:
	Fix for #235081. Now using async directio callout.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libcheckers/directio.c.diff?cvsroot=dm&only_with_tag=RHEL4_FC5&r1=1.2&r2=1.2.2.1

--- multipath-tools/libcheckers/directio.c	2005/11/16 20:24:57	1.2
+++ multipath-tools/libcheckers/directio.c	2007/07/26 19:27:13	1.2.2.1
@@ -12,90 +12,149 @@
 #include <sys/ioctl.h>
 #include <linux/fs.h>
 #include <errno.h>
+#include <linux/kdev_t.h>
+#include <asm/unistd.h>
 
+#include "libaio.h"
 #include "path_state.h"
 #include "checkers.h"
+#include "../libmultipath/debug.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;
+struct directio_context {
+	int             running;
+	int             blksize;
+	unsigned char * buf;
+	unsigned char * ptr;
+	io_context_t    ioctx;
+	struct iocb     io;
 };
 
 static int
-direct_read (int fd, unsigned char * buff, int size)
+check_state(int fd, struct directio_context *ct)
 {
 	long flags;
 	int reset_flags = 0;
-	int res, retval;
+	struct timespec timeout = { .tv_sec = 2 };
+	struct io_event event;
+	struct stat     sb;
+	int             rc = PATH_UNCHECKED;
+	long            r;
 
-	flags = fcntl(fd,F_GETFL);
-
-	if (flags < 0) {
-		return PATH_UNCHECKED;
-	}
+	flags = fcntl(fd, F_GETFL);
+	if (flags < 0)
+		goto out;
 
 	if (!(flags & O_DIRECT)) {
 		flags |= O_DIRECT;
-		if (fcntl(fd,F_SETFL,flags) < 0) {
-			return PATH_UNCHECKED;
-		}
+		if (fcntl(fd, F_SETFL, flags) < 0)
+			goto out;
 		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;
+	if (fstat(fd, &sb) == 0) {
+		condlog(4, "directio: called for %x", (unsigned) sb.st_rdev);
+	}
+
+	if (!ct->running) {
+		struct iocb *ios[1] = { &ct->io };
+
+		condlog(3, "directio: starting new request");
+		memset(&ct->io, 0, sizeof(struct iocb));
+		io_prep_pread(&ct->io, fd, ct->ptr, ct->blksize, 0);
+		if (syscall(__NR_io_submit, ct->ioctx, 1, ios) != 1) {
+			condlog(3, "directio: io_submit error %i", errno);
+			rc = PATH_UNCHECKED;
+			goto out;
 		}
+	}
+	ct->running = 1;
+
+	r = syscall(__NR_io_getevents, ct->ioctx, 1L, 1L, &event, &timeout);
+	if (r < 1L) {
+		condlog(3, "directio: timeout r=%li errno=%i", r, errno);
+		rc = PATH_DOWN;
 	} else {
-		retval = PATH_UP;
+		condlog(3, "directio: io finished %lu/%lu", event.res,
+				event.res2);
+		ct->running = 0;
+		rc = (event.res == ct->blksize) ? PATH_UP : PATH_DOWN;
 	}
-	
+
+out:
 	if (reset_flags) {
 		flags &= ~O_DIRECT;
 		/* No point in checking for errors */
-		fcntl(fd,F_SETFL,flags);
+		fcntl(fd, F_SETFL, flags);
 	}
+	return rc;
+}
 
-	return retval;
+void
+cleanup_context (struct directio_context *ctxt)
+{
+	if (ctxt->buf)
+		free(ctxt->buf);
+	syscall(__NR_io_destroy, ctxt->ioctx);
+	free(ctxt);
 }
 
 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();
+	struct directio_context * ctxt = NULL;
+	int ret;
 	
 	/*
 	 * caller passed in a context : use its address
 	 */
 	if (context)
-		ctxt = (struct readsector0_checker_context *) (*context);
+		ctxt = (struct directio_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));
-
+		unsigned long pgsize = getpagesize();
+	
+		ctxt = malloc(sizeof(struct directio_context));
 		if (!ctxt) {
-			MSG("cannot allocate context");
-			return -1;
+			condlog(0, "cannot allocate context");
+			goto fail;
+		}
+		memset(ctxt, 0, sizeof(struct directio_context));
+		if (syscall(__NR_io_setup, 1, &ctxt->ioctx) != 0) {
+			condlog(0, "io_setup failed");
+			goto fail;
+		}
+		if (ioctl(fd, BLKBSZGET, &ctxt->blksize) < 0) {
+			condlog(3, "cannot get blocksize, set default");
+			ctxt->blksize = 512;
 		}
+		if (ctxt->blksize > 4096) {
+			/*
+			 * Sanity check for DASD; BSZGET is broken
+			 */
+			ctxt->blksize = 4096;
+		}
+		if (!ctxt->blksize){
+			condlog(3, "blocksize is zero? Assuming path down\n");
+			MSG(MSG_DIRECTIO_DOWN);
+			ret = PATH_DOWN;
+			goto out;
+		}
+		ctxt->buf = (unsigned char *)malloc(ctxt->blksize + pgsize);
+		if (!ctxt->buf){
+			condlog(0, "cannot allocate context buffer\n");
+			goto fail;
+		}
+
+		ctxt->ptr = (unsigned char *) (((unsigned long)ctxt->buf + pgsize - 1) & (~(pgsize - 1)));
+
 		if (context)
 			*context = ctxt;
 	}
@@ -104,41 +163,7 @@
 		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 = (unsigned char *)(((unsigned long)buf + pgsize - 1) &
-				(~(pgsize - 1))); 
-	ret = direct_read(fd, ptr, blksize);
+	ret = check_state(fd, ctxt);
 
 	switch (ret)
 	{
@@ -154,7 +179,6 @@
 	default:
 		break;
 	}
-	free(buf);
 
 out:
 	/*
@@ -162,7 +186,13 @@
 	 * free it
 	 */
 	if (!context)
-		free(ctxt);
+		cleanup_context(ctxt);
 
 	return ret;
+fail:
+	if (context)
+		*context = NULL;
+	if (ctxt)
+		cleanup_context(ctxt);
+	return -1;
 }

^ permalink raw reply	[flat|nested] 2+ messages in thread
* multipath-tools/libcheckers directio.c
@ 2007-06-12 21:07 bmarzins
  0 siblings, 0 replies; 2+ messages in thread
From: bmarzins @ 2007-06-12 21:07 UTC (permalink / raw)
  To: dm-cvs, dm-devel

CVSROOT:	/cvs/dm
Module name:	multipath-tools
Branch: 	RHEL5_FC6
Changes by:	bmarzins@sourceware.org	2007-06-12 21:07:46

Modified files:
	libcheckers    : directio.c 

Log message:
	Fix for bz#214838. multipath now uses libaio to do the directio checks.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/multipath-tools/libcheckers/directio.c.diff?cvsroot=dm&only_with_tag=RHEL5_FC6&r1=1.3&r2=1.3.2.1

--- multipath-tools/libcheckers/directio.c	2006/06/06 18:32:43	1.3
+++ multipath-tools/libcheckers/directio.c	2007/06/12 21:07:46	1.3.2.1
@@ -12,28 +12,44 @@
 #include <sys/ioctl.h>
 #include <linux/fs.h>
 #include <errno.h>
+#include <linux/kdev_t.h>
+#include <asm/unistd.h>
 
+#include "libaio.h"
 #include "checkers.h"
+#include "../libmultipath/debug.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 directio_context {
-	int blksize; 
-	unsigned char *buf;
-	unsigned char *ptr;
+	int		running;
+	int		reset_flags;
+	int		blksize;
+	unsigned char *	buf;
+	unsigned char * ptr;
+	io_context_t	ioctx;
+	struct iocb	io;
 };
 
+
 int directio_init (struct checker * c)
 {
 	unsigned long pgsize = getpagesize();
 	struct directio_context * ct;
+	long flags;
 
 	ct = malloc(sizeof(struct directio_context));
 	if (!ct)
 		return 1;
-	c->context = (void *)ct;
+	memset(ct, 0, sizeof(struct directio_context));
+
+	if (syscall(__NR_io_setup, 1, &ct->ioctx) != 0) {
+		condlog(1, "io_setup failed");
+		free(ct);
+		return 1;
+	}
 
 	if (ioctl(c->fd, BLKBSZGET, &ct->blksize) < 0) {
 		MSG(c, "cannot get blocksize, set default");
@@ -50,11 +66,28 @@
 	ct->buf = (unsigned char *)malloc(ct->blksize + pgsize);
 	if (!ct->buf)
 		goto out;
-	ct->ptr = (unsigned char *)(((unsigned long)ct->buf + pgsize - 1) &
-		  (~(pgsize - 1))); 
 
+	flags = fcntl(c->fd, F_GETFL);
+	if (flags < 0)
+		goto out;
+	if (!(flags & O_DIRECT)) {
+		flags |= O_DIRECT;
+		if (fcntl(c->fd, F_SETFL, flags) < 0)
+			goto out;
+		ct->reset_flags = 1;
+	}
+
+	ct->ptr = (unsigned char *) (((unsigned long)ct->buf + pgsize - 1) &
+		  (~(pgsize - 1)));
+
+	/* Sucessfully initialized, return the context. */
+	c->context = (void *) ct;
 	return 0;
+
 out:
+	if (ct->buf)
+		free(ct->buf);
+	syscall(__NR_io_destroy, ct->ioctx);
 	free(ct);
 	return 1;
 }
@@ -62,56 +95,63 @@
 void directio_free (struct checker * c)
 {
 	struct directio_context * ct = (struct directio_context *)c->context;
+	long flags;
 
 	if (!ct)
 		return;
+
+	if (ct->reset_flags) {
+		if ((flags = fcntl(c->fd, F_GETFL)) >= 0) {
+			flags &= ~O_DIRECT;
+			/* No point in checking for errors */
+			fcntl(c->fd, F_SETFL, flags);
+		}
+	}
+
 	if (ct->buf)
 		free(ct->buf);
+	syscall(__NR_io_destroy, ct->ioctx);
 	free(ct);
 }
 
 static int
-direct_read (int fd, unsigned char * buff, int size)
+check_state(int fd, struct directio_context *ct)
 {
-	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) {
+	struct timespec	timeout = { .tv_sec = 2 };
+	struct io_event event;
+	struct stat	sb;
+	int		rc = PATH_UNCHECKED;
+	long		r;
+
+	if (fstat(fd, &sb) == 0) {
+		condlog(4, "directio: called for %x", (unsigned) sb.st_rdev);
+	}
+
+	if (!ct->running) {
+		struct iocb *ios[1] = { &ct->io };
+
+		condlog(3, "directio: starting new request");
+		memset(&ct->io, 0, sizeof(struct iocb));
+		io_prep_pread(&ct->io, fd, ct->ptr, ct->blksize, 0);
+		if (syscall(__NR_io_submit, ct->ioctx, 1, ios) != 1) {
+			condlog(3, "directio: io_submit error %i", errno);
 			return PATH_UNCHECKED;
 		}
-		reset_flags = 1;
 	}
+	ct->running = 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;
-		}
+	r = syscall(__NR_io_getevents, ct->ioctx, 1L, 1L, &event, &timeout);
+	if (r < 1L) {
+		condlog(3, "directio: timeout r=%li errno=%i", r, errno);
+		rc = PATH_DOWN;
 	} else {
-		retval = PATH_UP;
-	}
-	
-	if (reset_flags) {
-		flags &= ~O_DIRECT;
-		/* No point in checking for errors */
-		fcntl(fd,F_SETFL,flags);
+		condlog(3, "directio: io finished %lu/%lu", event.res,
+			event.res2);
+		ct->running = 0;
+		rc = (event.res == ct->blksize) ? PATH_UP : PATH_DOWN;
 	}
 
-	return retval;
+	return rc;
 }
 
 int directio (struct checker * c)
@@ -119,7 +159,10 @@
 	int ret;
 	struct directio_context * ct = (struct directio_context *)c->context;
 
-	ret = direct_read(c->fd, ct->ptr, ct->blksize);
+	if (!ct)
+		return PATH_UNCHECKED;
+
+	ret = check_state(c->fd, ct);
 
 	switch (ret)
 	{

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-07-26 19:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-26 19:27 multipath-tools/libcheckers directio.c bmarzins
  -- strict thread matches above, loose matches on Subject: below --
2007-06-12 21:07 bmarzins

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.