#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"
+#define MSG_DIRECTIO_PENDING "directio checker is waiting on aio"
+
+#define LOG(prio, fmt, args...) condlog(prio, "directio: " fmt, ##args)
struct directio_context {
int running;
static int
check_state(int fd, struct directio_context *ct)
{
- struct timespec timeout = { .tv_sec = 2 };
+ struct timespec timeout = { .tv_nsec = 5 };
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);
+ LOG(4, "called for %x", (unsigned) sb.st_rdev);
}
if (!ct->running) {
struct iocb *ios[1] = { &ct->io };
- condlog(3, "directio: starting new request");
+ LOG(3, "starting new request");
memset(&ct->io, 0, sizeof(struct iocb));
io_prep_pread(&ct->io, fd, ct->ptr, ct->blksize, 0);
if (io_submit(ct->ioctx, 1, ios) != 1) {
- condlog(3, "directio: io_submit error %i", errno);
+ LOG(3, "io_submit error %i", errno);
return PATH_UNCHECKED;
}
}
- ct->running = 1;
+ ct->running++;
r = io_getevents(ct->ioctx, 1L, 1L, &event, &timeout);
+ LOG(3, "async io getevents returns %li (errno=%s)", r, strerror(errno));
+
if (r < 1L) {
- condlog(3, "directio: timeout r=%li errno=%i", r, errno);
- rc = PATH_DOWN;
+ if (ct->running > ASYNC_TIMEOUT_SEC) {
+ LOG(3, "abort check on timeout");
+ rc = PATH_DOWN;
+ } else
+ rc = PATH_PENDING;
} else {
- condlog(3, "directio: io finished %lu/%lu", event.res,
- event.res2);
+ LOG(3, "io finished %lu/%lu", event.res, event.res2);
ct->running = 0;
rc = (event.res == ct->blksize) ? PATH_UP : PATH_DOWN;
}
case PATH_UP:
MSG(c, MSG_DIRECTIO_UP);
break;
+ case PATH_PENDING:
+ MSG(c, MSG_DIRECTIO_PENDING);
+ break;
default:
break;
}