aio-dio-regress: fix aio-dio-extend-stat on s390
authorJeff Moyer <jmoyer@redhat.com>
Wed, 3 Jun 2009 20:11:24 +0000 (15:11 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Wed, 3 Jun 2009 20:11:24 +0000 (15:11 -0500)
Hi,

The following patch queries the sector size of the underlying device so
that we can size the write buffer appropriately.  Without this patch, we
try to do an O_DIRECT write of 1KB to a device that has a sector size of
4KB.  This returns EINVAL, of course.  I also noticed that the test was
not checking the right fields for the return code.  It was checking the
original iocb's nbytes field instead of event->res.  So, I fixed that.

Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
src/aio-dio-regress/aio-dio-extend-stat.c

index c274e58204fea951ed7c0b1ae3922c185031382b..0f30d6f70773e85b326444e596aa9df16726a573 100644 (file)
@@ -28,6 +28,8 @@
 #include <fcntl.h>
 #include <pthread.h>
 #include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
 
 #ifndef O_DIRECT
 #define O_DIRECT         040000 /* direct disk access hint */
@@ -45,6 +47,7 @@
  */
 
 #define BUFSIZE 1024
+int bufsize;
 
 static unsigned char buf[BUFSIZE] __attribute((aligned (4096)));
 
@@ -70,26 +73,72 @@ struct io_event ioevents[MAX_AIO_EVENTS];
 
 volatile int submittedSize = 0; //synchronization
 
+int get_sector_size(dev_t dev)
+{
+       int fd, sector_size;
+       char *nodename = "bogus_node";
+       
+       if (mknod(nodename, S_IFBLK|0600, dev) != 0) {
+               if (errno == EPERM)
+                       printf("This test requires root priviledges\n");
+               fail("mknod failed with %d\n", errno);
+       }
+
+       fd = open(nodename, O_RDONLY);
+       if (fd < 0)
+               fail("failed to open device node: %d\n", errno);
+
+       if (ioctl(fd, BLKSSZGET, &sector_size) < 0)
+               fail("BLKSSZGET failed: %d\n", errno);
+       close(fd);
+       unlink(nodename);
+
+       return sector_size;
+}
+
 int main(int argc, char **argv)
 {
        pthread_t thread_read; 
        pthread_t thread_write;
        int i;
        int ret;
+       int sector_size;
+       struct stat st;
 
        if (argc != 2)
                fail("only arg should be file name\n");
 
-       for (i = 0; i < BUFSIZE; ++i)
-               buf[i] = 'A' + (char)(i % ('Z'-'A'+1));
-
-       buf[BUFSIZE-1] = '\n';
-
        handle = open(argv[1], O_CREAT | O_TRUNC | O_DIRECT | O_RDWR, 0600); 
        if (handle == -1) 
                fail("failed to open test file %s, errno: %d\n",
                        argv[1], errno);
 
+       if (fstat(handle, &st) == -1)
+               fail("initial stat of empty file failed with %d\n", errno);
+
+       sector_size = get_sector_size(st.st_dev);
+       if (sector_size < 0)
+               fail("failed to retrieve the sector size of the device\n");
+
+       /*
+        * When this test was written, it used a buffer size of 1024 bytes.  It is
+        * not clear to me at this time whether that was significant.  It may have
+        * been easier to trigger the problem when writing less than the file system
+        * block size, for example, or less than the system page size.  To try to
+        * limit this change in scope to those platforms that have a device with a
+        * larger underlying sector size, the following bogosity is used.  ;-)
+        * -JEM
+        */
+       if (sector_size > 512)
+               bufsize = sector_size;
+       else
+               bufsize = BUFSIZE;
+
+       for (i = 0; i < bufsize; ++i)
+               buf[i] = 'A' + (char)(i % ('Z'-'A'+1));
+
+       buf[bufsize-1] = '\n';
+
        memset(&ctxp, 0, sizeof(ctxp));
        ret = io_setup(MAX_AIO_EVENTS, &ctxp);
        if (ret)
@@ -106,8 +155,8 @@ int main(int argc, char **argv)
                iocbs[i]->aio_lio_opcode = IO_CMD_PWRITE;
                iocbs[i]->aio_reqprio = 0;
                iocbs[i]->u.c.buf = buf;
-               iocbs[i]->u.c.nbytes = BUFSIZE;
-               iocbs[i]->u.c.offset = BUFSIZE*i;
+               iocbs[i]->u.c.nbytes = bufsize;
+               iocbs[i]->u.c.offset = bufsize*i;
        }
 
        pthread_create(&thread_read, NULL, (void*)&fun_read, NULL);
@@ -140,20 +189,19 @@ void fun_read(void *ptr)
 
                n -= r;
                for (i = 0; i < r; ++i) {
-                       if (ioevents[i].obj->u.c.nbytes != BUFSIZE)
-                               fail("error in block: expacted %d bytes, "
-                                    "receiced %ld\n", BUFSIZE,
-                                    ioevents[i].obj->u.c.nbytes);
+                       struct io_event *event = &ioevents[i];
+                       if (event->res != bufsize)
+                               fail("error in block: expected %d bytes, "
+                                    "received %ld\n", bufsize,
+                                    event->obj->u.c.nbytes);
 
-                       exSize = ioevents[i].obj->u.c.offset +
-                                ioevents[i].obj->u.c.nbytes;
+                       exSize = event->obj->u.c.offset + event->obj->u.c.nbytes;
                        fstat(handle, &filestat);
                        if (filestat.st_size < exSize)
                                fail("write of %lu bytes @%llu finished, "
                                     "expected filesize at least %llu, but "
-                                    "got %ld\n", ioevents[i].obj->u.c.nbytes,
-                                    ioevents[i].obj->u.c.offset, exSize,
-                                    filestat.st_size);
+                                    "got %ld\n", event->obj->u.c.nbytes,
+                                    event->obj->u.c.offset, exSize, filestat.st_size);
                }
        }
 }