diff options
Diffstat (limited to 'tests/zfs-tests/cmd')
-rw-r--r-- | tests/zfs-tests/cmd/Makefile.am | 1 | ||||
-rw-r--r-- | tests/zfs-tests/cmd/randwritecomp/.gitignore | 1 | ||||
-rw-r--r-- | tests/zfs-tests/cmd/randwritecomp/Makefile.am | 9 | ||||
-rw-r--r-- | tests/zfs-tests/cmd/randwritecomp/randwritecomp.c | 194 |
4 files changed, 205 insertions, 0 deletions
diff --git a/tests/zfs-tests/cmd/Makefile.am b/tests/zfs-tests/cmd/Makefile.am index 0673fcbf6..751836ae4 100644 --- a/tests/zfs-tests/cmd/Makefile.am +++ b/tests/zfs-tests/cmd/Makefile.am @@ -18,6 +18,7 @@ SUBDIRS = \ mmapwrite \ nvlist_to_lua \ randfree_file \ + randwritecomp \ readmmap \ rename_dir \ rm_lnkcnt_zero_file \ diff --git a/tests/zfs-tests/cmd/randwritecomp/.gitignore b/tests/zfs-tests/cmd/randwritecomp/.gitignore new file mode 100644 index 000000000..fb231c678 --- /dev/null +++ b/tests/zfs-tests/cmd/randwritecomp/.gitignore @@ -0,0 +1 @@ +/randwritecomp diff --git a/tests/zfs-tests/cmd/randwritecomp/Makefile.am b/tests/zfs-tests/cmd/randwritecomp/Makefile.am new file mode 100644 index 000000000..0002291fa --- /dev/null +++ b/tests/zfs-tests/cmd/randwritecomp/Makefile.am @@ -0,0 +1,9 @@ +include $(top_srcdir)/config/Rules.am + +pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin + +DEFAULT_INCLUDES += \ + -I$(top_srcdir)/include + +pkgexec_PROGRAMS = randwritecomp +randwritecomp_SOURCES = randwritecomp.c diff --git a/tests/zfs-tests/cmd/randwritecomp/randwritecomp.c b/tests/zfs-tests/cmd/randwritecomp/randwritecomp.c new file mode 100644 index 000000000..708d5ee90 --- /dev/null +++ b/tests/zfs-tests/cmd/randwritecomp/randwritecomp.c @@ -0,0 +1,194 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2017 by Delphix. All rights reserved. + */ + +/* + * The following is defined so the source can use + * lrand48() and srand48(). + */ +#define __EXTENSIONS__ + +#include <stdint.h> +#include <string.h> +#include "../file_common.h" + +/* + * The following sample was derived from real-world data + * of a production Oracle database. + */ +static uint64_t size_distribution[] = { + 0, + 1499018, + 352084, + 1503485, + 4206227, + 5626657, + 5387001, + 3733756, + 2233094, + 874652, + 238635, + 81434, + 33357, + 13106, + 2009, + 1, + 23660, +}; + + +static uint64_t distribution_n; + +static uint8_t randbuf[BLOCKSZ]; + +static void +rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset) +{ + size_t nleft = nbytes; + ssize_t nwrite = 0; + + nwrite = pwrite(fd, buf, nbytes, offset); + if (nwrite < 0) { + perror("pwrite"); + exit(EXIT_FAILURE); + } + + nleft -= nwrite; + if (nleft != 0) { + (void) fprintf(stderr, "warning: pwrite: " + "wrote %zu out of %zu bytes\n", + (nbytes - nleft), nbytes); + } +} + +static void +fillbuf(char *buf) +{ + uint64_t rv = lrand48() % distribution_n; + uint64_t sum = 0; + + uint64_t i; + for (i = 0; + i < sizeof (size_distribution) / sizeof (size_distribution[0]); + i++) { + sum += size_distribution[i]; + if (rv < sum) + break; + } + + bcopy(randbuf, buf, BLOCKSZ); + if (i == 0) + bzero(buf, BLOCKSZ - 10); + else if (i < 16) + bzero(buf, BLOCKSZ - i * 512 + 256); + /*LINTED: E_BAD_PTR_CAST_ALIGN*/ + ((uint32_t *)buf)[0] = lrand48(); +} + +static void +exit_usage(void) +{ + (void) printf("usage: "); + (void) printf("randwritecomp <file> [-s] [nwrites]\n"); + exit(EXIT_FAILURE); +} + +static void +sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n) +{ + for (int64_t i = 0; n == -1 || i < n; i++) { + fillbuf(buf); + + static uint64_t j = 0; + if (j == 0) + j = lrand48() % nblocks; + rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ); + j++; + if (j >= nblocks) + j = 0; + } +} + +static void +random_writes(int fd, char *buf, uint64_t nblocks, int64_t n) +{ + for (int64_t i = 0; n == -1 || i < n; i++) { + fillbuf(buf); + rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ); + } +} + +int +main(int argc, char *argv[]) +{ + int fd, err; + char *filename = NULL; + char buf[BLOCKSZ]; + struct stat ss; + uint64_t nblocks; + int64_t n = -1; + int sequential = 0; + + if (argc < 2) + exit_usage(); + + argv++; + if (strcmp("-s", argv[0]) == 0) { + sequential = 1; + argv++; + } + + if (argv[0] == NULL) + exit_usage(); + else + filename = argv[0]; + + argv++; + if (argv[0] != NULL) + n = strtoull(argv[0], NULL, 0); + + fd = open(filename, O_RDWR|O_CREAT, 0666); + err = fstat(fd, &ss); + if (err != 0) { + (void) fprintf(stderr, + "error: fstat returned error code %d\n", err); + exit(EXIT_FAILURE); + } + + nblocks = ss.st_size / BLOCKSZ; + if (nblocks == 0) { + (void) fprintf(stderr, "error: " + "file is too small (min allowed size is %d bytes)\n", + BLOCKSZ); + exit(EXIT_FAILURE); + } + + srand48(getpid()); + for (int i = 0; i < BLOCKSZ; i++) + randbuf[i] = lrand48(); + + distribution_n = 0; + for (uint64_t i = 0; + i < sizeof (size_distribution) / sizeof (size_distribution[0]); + i++) { + distribution_n += size_distribution[i]; + } + + if (sequential) + sequential_writes(fd, buf, nblocks, n); + else + random_writes(fd, buf, nblocks, n); + + return (0); +} |