2 * Copyright (c) 2005 Hannes Reinecke, Suse
12 #include <sys/ioctl.h>
16 #include "path_state.h"
19 #define MSG_DIRECTIO_UNKNOWN "directio checker is not available"
20 #define MSG_DIRECTIO_UP "directio checker reports path is up"
21 #define MSG_DIRECTIO_DOWN "directio checker reports path is down"
23 struct readsector0_checker_context {
28 direct_read (int fd, unsigned char * buff, int size)
34 flags = fcntl(fd,F_GETFL);
37 return PATH_UNCHECKED;
40 if (!(flags & O_DIRECT)) {
42 if (fcntl(fd,F_SETFL,flags) < 0) {
43 return PATH_UNCHECKED;
48 while ( (res = read(fd,buff,size)) < 0 && errno == EINTR );
50 if (errno == EINVAL) {
51 /* O_DIRECT is not available */
52 retval = PATH_UNCHECKED;
53 } else if (errno == ENOMEM) {
64 /* No point in checking for errors */
65 fcntl(fd,F_SETFL,flags);
72 directio (int fd, char *msg, void **context)
74 unsigned char *buf, *ptr;
75 struct readsector0_checker_context * ctxt = NULL;
76 unsigned long pgsize, numsect;
79 pgsize = getpagesize();
82 * caller passed in a context : use its address
85 ctxt = (struct readsector0_checker_context *) (*context);
88 * passed in context is uninitialized or volatile context :
92 ctxt = malloc(sizeof(struct readsector0_checker_context));
93 memset(ctxt, 0, sizeof(struct readsector0_checker_context));
96 MSG("cannot allocate context");
108 if (ioctl(fd, BLKGETSIZE, &numsect) < 0) {
109 MSG("cannot get number of sectors, set default");
113 if (ioctl(fd, BLKBSZGET, &blksize) < 0) {
114 MSG("cannot get blocksize, set default");
118 if (blksize > 4096) {
120 * Sanity check for DASD; BSZGET is broken
127 * Blocksize is 0, assume we can't write
130 MSG(MSG_DIRECTIO_DOWN);
135 buf = (unsigned char *)malloc(blksize + pgsize);
139 ptr = (unsigned char *)(((unsigned long)buf + pgsize - 1) &
141 ret = direct_read(fd, ptr, blksize);
146 MSG(MSG_DIRECTIO_UNKNOWN);
149 MSG(MSG_DIRECTIO_DOWN);
152 MSG(MSG_DIRECTIO_UP);
161 * caller told us he doesn't want to keep the context :