Imported Upstream version 0.7.0
[platform/upstream/multipath-tools.git] / libmultipath / checkers / directio.c
index 44e5eff..ce60e4c 100644 (file)
@@ -12,8 +12,7 @@
 #include <sys/ioctl.h>
 #include <linux/fs.h>
 #include <errno.h>
-#include <linux/kdev_t.h>
-#include <asm/unistd.h>
+#include <unistd.h>
 #include <libaio.h>
 
 #include "checkers.h"
@@ -83,7 +82,7 @@ int libcheck_init (struct checker * c)
        ct->ptr = (unsigned char *) (((unsigned long)ct->buf + pgsize - 1) &
                  (~(pgsize - 1)));
 
-       /* Sucessfully initialized, return the context. */
+       /* Successfully initialized, return the context. */
        c->context = (void *) ct;
        return 0;
 
@@ -105,9 +104,11 @@ void libcheck_free (struct checker * c)
 
        if (ct->reset_flags) {
                if ((flags = fcntl(c->fd, F_GETFL)) >= 0) {
+                       int ret __attribute__ ((unused));
+
                        flags &= ~O_DIRECT;
                        /* No point in checking for errors */
-                       fcntl(c->fd, F_SETFL, flags);
+                       ret = fcntl(c->fd, F_SETFL, flags);
                }
        }
 
@@ -117,8 +118,13 @@ void libcheck_free (struct checker * c)
        free(ct);
 }
 
+void libcheck_repair (struct checker * c)
+{
+       return;
+}
+
 static int
-check_state(int fd, struct directio_context *ct, int sync)
+check_state(int fd, struct directio_context *ct, int sync, int timeout_secs)
 {
        struct timespec timeout = { .tv_nsec = 5 };
        struct io_event event;
@@ -129,9 +135,9 @@ check_state(int fd, struct directio_context *ct, int sync)
        if (fstat(fd, &sb) == 0) {
                LOG(4, "called for %x", (unsigned) sb.st_rdev);
        }
-       if (sync) {
+       if (sync > 0) {
                LOG(4, "called in synchronous mode");
-               timeout.tv_sec  = ASYNC_TIMEOUT_SEC;
+               timeout.tv_sec  = timeout_secs;
                timeout.tv_nsec = 0;
        }
 
@@ -154,10 +160,22 @@ check_state(int fd, struct directio_context *ct, int sync)
        if (r < 0 ) {
                LOG(3, "async io getevents returned %li (errno=%s)", r,
                    strerror(errno));
+               ct->running = 0;
                rc = PATH_UNCHECKED;
        } else if (r < 1L) {
-               if (ct->running > ASYNC_TIMEOUT_SEC || sync) {
+               if (ct->running > timeout_secs || sync) {
+                       struct iocb *ios[1] = { &ct->io };
+
                        LOG(3, "abort check on timeout");
+                       r = io_cancel(ct->ioctx, ios[0], &event);
+                       /*
+                        * Only reset ct->running if we really
+                        * could abort the pending I/O
+                        */
+                       if (r)
+                               LOG(3, "io_cancel error %i", errno);
+                       else
+                               ct->running = 0;
                        rc = PATH_DOWN;
                } else {
                        LOG(3, "async io pending");
@@ -180,7 +198,7 @@ int libcheck_check (struct checker * c)
        if (!ct)
                return PATH_UNCHECKED;
 
-       ret = check_state(c->fd, ct, c->sync);
+       ret = check_state(c->fd, ct, c->sync, c->timeout);
 
        switch (ret)
        {