aboutsummaryrefslogtreecommitdiffstats
path: root/tests/zfs-tests/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'tests/zfs-tests/cmd')
-rw-r--r--tests/zfs-tests/cmd/Makefile.am1
-rw-r--r--tests/zfs-tests/cmd/randwritecomp/.gitignore1
-rw-r--r--tests/zfs-tests/cmd/randwritecomp/Makefile.am9
-rw-r--r--tests/zfs-tests/cmd/randwritecomp/randwritecomp.c194
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);
+}