diff --git a/lustre/ChangeLog b/lustre/ChangeLog index b7581af559a1c65e57c369616460912982f4824f..c10a3e1805fec3439f60343f108ca89f35a3dfea 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -1692,6 +1692,11 @@ Description: Replace RW_LOCK_UNLOCKED() macro with rwlock_init(). Details : Replace RW_LOCK_UNLOCKED() with rwlock_init() as the former doesn't work with lockdep. +Severity : normal +Bugzilla : 16450 +Description: Add rwv.c test program. +Details : New testing program exercising readv(2) and writev(2) (Qian). + -------------------------------------------------------------------------------- 2007-08-10 Cluster File Systems, Inc. <info@clusterfs.com> diff --git a/lustre/tests/Makefile.am b/lustre/tests/Makefile.am index 4f59ac43da45e06dded1a41e18534ad3452aa1a0..2a1568601fdf36fbf5bc9acee8dc6ec3d1721f0c 100644 --- a/lustre/tests/Makefile.am +++ b/lustre/tests/Makefile.am @@ -41,7 +41,7 @@ noinst_PROGRAMS += small_write multiop sleeptest ll_sparseness_verify cmknod noinst_PROGRAMS += ll_sparseness_write mrename ll_dirstripe_verify mkdirmany noinst_PROGRAMS += openfilleddirunlink rename_many memhog iopentest1 iopentest2 noinst_PROGRAMS += mmap_sanity flock_test writemany reads flocks_test -noinst_PROGRAMS += ll_getstripe_info write_time_limit +noinst_PROGRAMS += ll_getstripe_info write_time_limit rwv if MPITESTS noinst_PROGRAMS += parallel_grouplock write_append_truncate createmany_mpi mdsrate endif diff --git a/lustre/tests/rwv.c b/lustre/tests/rwv.c new file mode 100644 index 0000000000000000000000000000000000000000..96856e92befb291679ea88bc1e51134bf641940a --- /dev/null +++ b/lustre/tests/rwv.c @@ -0,0 +1,200 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/uio.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> + +#include <liblustre.h> +#include <lnet/lnetctl.h> +#include <obd.h> +#include <lustre_lib.h> +#include <obd_lov.h> +#include <lustre/liblustreapi.h> + +#define ACT_NONE 0 +#define ACT_READ 1 +#define ACT_WRITE 2 +#define ACT_SEEK 4 +#define ACT_READHOLE 8 +#define ACT_VERIFY 16 + +void usage() +{ + printf("usage: rwv -f filename <-r|-w> [-a] [-z] [-d] [-v]" + "[-s offset] -n iovcnt SIZE1 SIZE2 SIZE3...\n"); + printf("-a append IO (O_APPEND)\n"); + printf("-r file read (O_RDONLY)\n"); + printf("-w file write (O_WRONLY)\n"); + printf("-s set the start pos of the read/write test\n"); + printf("-z test for read hitting hole\n"); + printf("-d create flags (O_LOV_DELAY_CREATE)\n"); + printf("-v verify the data content of read\n"); +} + +int data_verify(struct iovec *iov, int iovcnt, char c) +{ + int i; + + for (i = 0; i < iovcnt; i++) { + size_t count = iov[i].iov_len; + char *s = iov[i].iov_base; + + for (; count > 0; ++s, count--) { + if (*s != c) { + printf("Data mismatch %x: %x\n", *s, c); + return 1; + } + } + } + return 0; +} + +int main(int argc, char** argv) +{ + int c; + int fd; + int rc = 0; + int flags = 0; + int iovcnt = 0; + int act = ACT_NONE; + char pad = 0xba; + char *end; + char *fname = "FILE"; + unsigned long len = 0; + struct iovec *iov; + off64_t offset = 0; + + while ((c = getopt(argc, argv, "f:n:s:rwahvdz")) != -1) { + switch (c) { + case 'f': + fname = optarg; + break; + case 'n': + iovcnt = strtoul(optarg, &end, 0); + if (*end) { + printf("Bad iov count: %s\n", optarg); + return 1; + } + if (iovcnt > UIO_MAXIOV || iovcnt <= 0) { + printf("Wrong iov count\n"); + return 1; + } + break; + case 's': + act |= ACT_SEEK; + offset = strtoull(optarg, &end, 0); + if (*end) { + printf("Bad seek offset: %s\n", optarg); + return 1; + } + break; + case 'w': + act |= ACT_WRITE; + break; + case 'r': + act |= ACT_READ; + break; + case 'a': + flags |= O_APPEND; + break; + case 'd': + flags |= O_LOV_DELAY_CREATE; + break; + case 'z': + pad = 0; + act |= ACT_READHOLE; + break; + case 'v': + act |= ACT_VERIFY; + break; + case 'h': + usage(); + break; + } + } + + if (act == ACT_NONE) { + usage(); + return 1; + } + + if ((act & ACT_READ) && (act & ACT_WRITE)) { + printf("Read and write test should be exclusive\n"); + return 1; + } + + if (argc - optind < iovcnt) { + printf("Not enough parameters for iov size\n"); + return 1; + } + + iov = (struct iovec *)malloc(iovcnt * sizeof(struct iovec)); + if (iov == NULL) { + printf("No memory %s\n", strerror(errno)); + return 1; + } + + for (c = 0; c < iovcnt; c++) { + struct iovec *iv = &iov[c]; + + iv->iov_len = strtoul(argv[optind++], &end, 0); + if (*end) { + printf("Error iov size\n"); + GOTO(out, rc = 1); + } + iv->iov_base = mmap(NULL, iv->iov_len, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, 0, 0); + if (iv->iov_base == MAP_FAILED) { + printf("No memory %s\n", strerror(errno)); + GOTO(out, rc = 1); + } + if (act & ACT_WRITE) + memset(iv->iov_base, pad, iv->iov_len); + len += iv->iov_len; + } + + fd = open(fname, O_LARGEFILE | O_RDWR | O_CREAT | flags, 0644); + if (fd == -1) { + printf("Cannot open %s:%s\n", fname, strerror(errno)); + return 1; + } + + if ((act & ACT_SEEK) && (lseek64(fd, offset, SEEK_SET) < 0)) { + printf("Cannot seek %s\n", strerror(errno)); + GOTO(out, rc == 1); + } + + if (act & ACT_WRITE) { + rc = writev(fd, iov, iovcnt); + if (rc != len) { + printf("Write error: %s (rc = %d, len = %ld)\n", + strerror(errno), rc, len); + GOTO(out, rc = 1); + } + } else if (act & ACT_READ) { + rc = readv(fd, iov, iovcnt); + if (rc != len) { + printf("Read error: %s rc = %d\n", strerror(errno), rc); + GOTO(out, rc = 1); + } + + /* It should return zeroed buf if the read hits hole.*/ + if (((act & ACT_READHOLE) || (act & ACT_VERIFY)) && + data_verify(iov, iovcnt, pad)) + GOTO(out, rc = 1); + } + + rc = 0; +out: + if (iov) + free(iov); + return rc; +}