| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2003 |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| * the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* |
| * NAME |
| * aiotest1.c |
| * |
| * DESCRIPTION |
| * Perform aio read, write operations for given number of requests. |
| * Submit i/o for each request individually. |
| * Repeat the test for each of the following cases and measure time. |
| * Testblock1: Write one request at a time. |
| * Testblock2: Read one request at a time. |
| * Testblock3: Prepare, Write one request at a time. |
| * Testblock4: Prepare, Read one request at a time. |
| * Testblock5: Prepare, Write/Read one request at a time. |
| * Testblock6: Prepare, Write/Read/Verify one request at a time. |
| * |
| * Author |
| * 08/24/2002 Narasimha Sharoff nsharoff@us.ibm.com |
| */ |
| |
| /* |
| * History |
| * 04/18/2003 nsharoff@us.ibm.com |
| * Updated |
| * 05/21/2003 Paul Larson plars@linuxtestproject.org |
| * Rewrote the test under LTP, using LTP test harness |
| * and other minor improvements and fixes |
| */ |
| |
| #define _XOPEN_SOURCE 600 |
| |
| #include "test.h" |
| #include "config.h" |
| |
| char *TCID = "aio01"; |
| int TST_TOTAL = 6; |
| |
| #ifdef HAVE_LIBAIO_H |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <time.h> |
| #include <errno.h> |
| #include <libaio.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/time.h> |
| #include <sys/resource.h> |
| |
| static void help(void); |
| static void setup(void); |
| static void cleanup(void); |
| |
| #define mapsize (1 << 14) |
| |
| int fd; |
| char *maddr; |
| |
| size_t bufsize; /* Size of I/O, 8k default */ |
| io_context_t io_ctx; /* I/O Context */ |
| struct iocb **iocbs; /* I/O Control Blocks */ |
| char *srcbuf, *dstbuf; |
| char fname[128]; |
| char tbuf[80]; |
| int pos, nr; |
| struct stat s; |
| |
| struct test_case_t { |
| off_t newsize; |
| char *desc; |
| } TC[] = { |
| { |
| mapsize - 8192, "ftruncate mmaped file to a smaller size"}, { |
| mapsize + 1024, "ftruncate mmaped file to a larger size"}, { |
| 0, "ftruncate mmaped file to 0 size"},}; |
| |
| int main(int argc, char **argv) |
| { |
| int i, j, sec, usec; |
| int failflag = 0; |
| int bflag = 0, nflag = 0, Fflag = 0; |
| char *optb, *optn, *optF; |
| const char *msg; |
| struct io_event event; |
| static struct timespec ts; |
| struct timeval stv, etv; |
| |
| option_t options[] = { |
| {"b:", &bflag, &optb}, |
| {"n:", &nflag, &optn}, |
| {"F:", &Fflag, &optF}, |
| {NULL, NULL, NULL} |
| }; |
| |
| msg = parse_opts(argc, argv, options, &help); |
| if (msg != NULL) { |
| tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| tst_exit(); |
| } |
| |
| bufsize = (bflag ? atoi(optb) : 8192); |
| nr = (nflag ? atoi(optn) : 10); |
| if (Fflag) { |
| sprintf(fname, optF); |
| } else { |
| sprintf(fname, "aiofile"); |
| } |
| |
| setup(); |
| |
| /* TEST 1 */ |
| pos = 0; |
| gettimeofday(&stv, NULL); |
| io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); |
| for (i = 0; i < nr; i++) { |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 1: io_submit failed - retval=%ld" |
| ", errno=%d", TEST_RETURN, TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| gettimeofday(&etv, NULL); |
| } |
| if (!failflag) { |
| sec = etv.tv_sec - stv.tv_sec; |
| usec = etv.tv_usec - stv.tv_usec; |
| if (usec < 0) { |
| usec += 1000000; |
| sec--; |
| } |
| tst_resm(TPASS, "Test 1: %d writes in %3d.%06d sec", |
| nr, sec, usec); |
| } |
| |
| /* TEST 2 */ |
| pos = 0; |
| failflag = 0; |
| gettimeofday(&stv, NULL); |
| io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); |
| for (i = 0; i < nr; i++) { |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 2: io_submit failed - retval=%ld" |
| ", errno=%d", TEST_RETURN, TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| gettimeofday(&etv, NULL); |
| } |
| if (!failflag) { |
| sec = etv.tv_sec - stv.tv_sec; |
| usec = etv.tv_usec - stv.tv_usec; |
| if (usec < 0) { |
| usec += 1000000; |
| sec--; |
| } |
| tst_resm(TPASS, "Test 2: %d reads in %3d.%06d sec", |
| nr, sec, usec); |
| } |
| |
| /* TEST 3 */ |
| pos = 0; |
| failflag = 0; |
| gettimeofday(&stv, NULL); |
| for (i = 0; i < nr; i++) { |
| io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 3: io_submit failed - retval=%ld" |
| ", errno=%d", TEST_RETURN, TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| gettimeofday(&etv, NULL); |
| } |
| if (!failflag) { |
| sec = etv.tv_sec - stv.tv_sec; |
| usec = etv.tv_usec - stv.tv_usec; |
| if (usec < 0) { |
| usec += 1000000; |
| sec--; |
| } |
| tst_resm(TPASS, "Test 3: %d prep,writes in %3d.%06d sec", |
| nr, sec, usec); |
| } |
| |
| /* TEST 4 */ |
| pos = 0; |
| failflag = 0; |
| gettimeofday(&stv, NULL); |
| for (i = 0; i < nr; i++) { |
| io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 4: io_submit failed - retval=%ld" |
| ", errno=%d", TEST_RETURN, TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| gettimeofday(&etv, NULL); |
| } |
| if (!failflag) { |
| sec = etv.tv_sec - stv.tv_sec; |
| usec = etv.tv_usec - stv.tv_usec; |
| if (usec < 0) { |
| usec += 1000000; |
| sec--; |
| } |
| tst_resm(TPASS, "Test 4: %d prep,reads in %3d.%06d sec", |
| nr, sec, usec); |
| } |
| |
| /* TEST 5 */ |
| pos = 0; |
| failflag = 0; |
| gettimeofday(&stv, NULL); |
| for (i = 0; i < nr; i++) { |
| io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 5: write io_submit failed - " |
| "retval=%ld, errno=%d", TEST_RETURN, |
| TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 5: read io_submit failed - " |
| "retval=%ld, errno=%d", TEST_RETURN, |
| TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| gettimeofday(&etv, NULL); |
| } |
| if (!failflag) { |
| sec = etv.tv_sec - stv.tv_sec; |
| usec = etv.tv_usec - stv.tv_usec; |
| if (usec < 0) { |
| usec += 1000000; |
| sec--; |
| } |
| tst_resm(TPASS, "Test 5: %d reads and writes in %3d.%06d sec", |
| nr, sec, usec); |
| } |
| |
| /* TEST 6 */ |
| pos = 0; |
| failflag = 0; |
| gettimeofday(&stv, NULL); |
| for (i = 0; i < nr; i++) { |
| io_prep_pwrite(iocbs[0], fd, srcbuf, bufsize, pos); |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 6: write io_submit failed - " |
| "retval=%ld, errno=%d", TEST_RETURN, |
| TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| io_prep_pread(iocbs[0], fd, dstbuf, bufsize, pos); |
| ts.tv_sec = 30; |
| ts.tv_nsec = 0; |
| do { |
| TEST(io_submit(io_ctx, 1, iocbs)); |
| } while (TEST_RETURN == -EAGAIN); |
| if (TEST_RETURN < 0) { |
| tst_resm(TFAIL, "Test 6: read io_submit failed - " |
| "retval=%ld, errno=%d", TEST_RETURN, |
| TEST_ERRNO); |
| failflag = 1; |
| continue; |
| } |
| while (io_getevents(io_ctx, 1, 1, &event, &ts) != 1) ; |
| for (j = 0; j < bufsize; j++) { |
| if (srcbuf[j] != dstbuf[j]) { |
| tst_resm(TFAIL, "Test 6: compare failed - " |
| "read: %c, " "actual: %c", |
| dstbuf[j], srcbuf[j]); |
| break; |
| } |
| } |
| gettimeofday(&etv, NULL); |
| } |
| if (!failflag) { |
| sec = etv.tv_sec - stv.tv_sec; |
| usec = etv.tv_usec - stv.tv_usec; |
| if (usec < 0) { |
| usec += 1000000; |
| sec--; |
| } |
| tst_resm(TPASS, "Test 6: %d read,write,verify in %d.%06d sec", |
| i, sec, usec); |
| } |
| |
| cleanup(); |
| |
| tst_exit(); |
| } |
| |
| static void help(void) |
| { |
| printf(" -b n Buffersize\n"); |
| printf(" -n n Number of requests\n"); |
| printf(" -F s Filename to run the tests against\n"); |
| } |
| |
| static void setup(void) |
| { |
| int ret; |
| |
| tst_sig(NOFORK, DEF_HANDLER, cleanup); |
| |
| /* Pause if option was specified */ |
| TEST_PAUSE; |
| |
| tst_tmpdir(); |
| |
| if ((fd = open(fname, O_RDWR | O_CREAT, 0600)) < 0) |
| tst_brkm(TFAIL, cleanup, "failed to open %s " |
| "file, errno: %d", fname, errno); |
| stat(fname, &s); |
| if ((iocbs = malloc(sizeof(int) * nr)) == NULL) |
| tst_brkm(TFAIL, cleanup, "malloc for iocbs failed - " |
| "errno: %d", errno); |
| if ((iocbs[0] = malloc(sizeof(struct iocb))) == NULL) |
| tst_brkm(TFAIL, cleanup, "malloc for iocbs elements failed - " |
| "errno: %d", errno); |
| if (S_ISCHR(s.st_mode)) { |
| if ((ret = |
| posix_memalign((void **)&srcbuf, bufsize, bufsize)) != 0) |
| tst_brkm(TFAIL, cleanup, |
| "posix_memalign for srcbuf " |
| "failed - errno: %d", errno); |
| if ((ret = |
| posix_memalign((void **)&dstbuf, bufsize, bufsize)) != 0) |
| tst_brkm(TFAIL, cleanup, |
| "posix_memalign for dstbuf " |
| "failed - errno: %d", errno); |
| } else { |
| if ((srcbuf = malloc(sizeof(char) * bufsize)) == NULL) |
| tst_brkm(TFAIL, cleanup, "malloc for srcbuf " |
| "failed - errno: %d", errno); |
| if ((dstbuf = malloc(sizeof(char) * bufsize)) == NULL) |
| tst_brkm(TFAIL, cleanup, "malloc for dstbuf " |
| "failed - errno: %d", errno); |
| } |
| memset((void *)srcbuf, 65, bufsize); |
| if ((ret = io_queue_init(1, &io_ctx)) != 0) |
| tst_brkm(TFAIL, cleanup, "io_queue_init failed: %s", |
| strerror(ret)); |
| } |
| |
| static void cleanup(void) |
| { |
| free(dstbuf); |
| free(srcbuf); |
| free(iocbs[0]); |
| free(iocbs); |
| close(fd); |
| io_queue_release(io_ctx); |
| tst_rmdir(); |
| |
| } |
| |
| #else |
| |
| int main(void) |
| { |
| tst_brkm(TCONF, NULL, "libaio missing"); |
| } |
| |
| #endif |