/*
*
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "test.h"
#include "config.h"
char *TCID = "aio01";
int TST_TOTAL = 6;
#ifdef HAVE_LIBAIO
#include <libaio.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;
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}
};
tst_parse_opts(argc, argv, options, &help);
bufsize = (bflag ? atoi(optb) : 8192);
nr = (nflag ? atoi(optn) : 10);
if (Fflag) {
sprintf(fname, "%s", 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 < (int)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, "test requires libaio and it's development packages");
}
#endif