From 6b26794772a4acbe8df1cc48d7a169011268d97e Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Wed, 3 Jun 2009 15:11:24 -0500 Subject: [PATCH] aio-dio-regress: fix aio-dio-extend-stat on s390 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 Reviewed-by: Eric Sandeen --- src/aio-dio-regress/aio-dio-extend-stat.c | 80 ++++++++++++++++++----- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/src/aio-dio-regress/aio-dio-extend-stat.c b/src/aio-dio-regress/aio-dio-extend-stat.c index c274e582..0f30d6f7 100644 --- a/src/aio-dio-regress/aio-dio-extend-stat.c +++ b/src/aio-dio-regress/aio-dio-extend-stat.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #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, §or_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); } } } -- 2.39.5