1*61145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2716fd348SMartin Matuska /*
3716fd348SMartin Matuska * This file and its contents are supplied under the terms of the
4716fd348SMartin Matuska * Common Development and Distribution License ("CDDL"), version 1.0.
5716fd348SMartin Matuska * You may only use this file in accordance with the terms of version
6716fd348SMartin Matuska * 1.0 of the CDDL.
7716fd348SMartin Matuska *
8716fd348SMartin Matuska * A full copy of the text of the CDDL should have accompanied this
9716fd348SMartin Matuska * source. A copy of the CDDL is also available via the Internet at
10716fd348SMartin Matuska * http://www.illumos.org/license/CDDL.
11716fd348SMartin Matuska */
12716fd348SMartin Matuska
13716fd348SMartin Matuska /*
14716fd348SMartin Matuska * Copyright (c) 2017 by Delphix. All rights reserved.
15716fd348SMartin Matuska */
16716fd348SMartin Matuska
17716fd348SMartin Matuska #include <stdint.h>
18716fd348SMartin Matuska #include <string.h>
19716fd348SMartin Matuska #include "file_common.h"
20716fd348SMartin Matuska
21716fd348SMartin Matuska /*
22716fd348SMartin Matuska * The following sample was derived from real-world data
23716fd348SMartin Matuska * of a production Oracle database.
24716fd348SMartin Matuska */
25716fd348SMartin Matuska static const uint64_t size_distribution[] = {
26716fd348SMartin Matuska 0,
27716fd348SMartin Matuska 1499018,
28716fd348SMartin Matuska 352084,
29716fd348SMartin Matuska 1503485,
30716fd348SMartin Matuska 4206227,
31716fd348SMartin Matuska 5626657,
32716fd348SMartin Matuska 5387001,
33716fd348SMartin Matuska 3733756,
34716fd348SMartin Matuska 2233094,
35716fd348SMartin Matuska 874652,
36716fd348SMartin Matuska 238635,
37716fd348SMartin Matuska 81434,
38716fd348SMartin Matuska 33357,
39716fd348SMartin Matuska 13106,
40716fd348SMartin Matuska 2009,
41716fd348SMartin Matuska 1,
42716fd348SMartin Matuska 23660,
43716fd348SMartin Matuska };
44716fd348SMartin Matuska
45716fd348SMartin Matuska
46716fd348SMartin Matuska static uint64_t distribution_n;
47716fd348SMartin Matuska
48716fd348SMartin Matuska static uint8_t randbuf[BLOCKSZ];
49716fd348SMartin Matuska
50716fd348SMartin Matuska static void
rwc_pwrite(int fd,const void * buf,size_t nbytes,off_t offset)51716fd348SMartin Matuska rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
52716fd348SMartin Matuska {
53716fd348SMartin Matuska size_t nleft = nbytes;
54716fd348SMartin Matuska ssize_t nwrite = 0;
55716fd348SMartin Matuska
56716fd348SMartin Matuska nwrite = pwrite(fd, buf, nbytes, offset);
57716fd348SMartin Matuska if (nwrite < 0) {
58716fd348SMartin Matuska perror("pwrite");
59716fd348SMartin Matuska exit(EXIT_FAILURE);
60716fd348SMartin Matuska }
61716fd348SMartin Matuska
62716fd348SMartin Matuska nleft -= nwrite;
63716fd348SMartin Matuska if (nleft != 0) {
64716fd348SMartin Matuska (void) fprintf(stderr, "warning: pwrite: "
65716fd348SMartin Matuska "wrote %zu out of %zu bytes\n",
66716fd348SMartin Matuska (nbytes - nleft), nbytes);
67716fd348SMartin Matuska }
68716fd348SMartin Matuska }
69716fd348SMartin Matuska
70716fd348SMartin Matuska static void
fillbuf(char * buf)71716fd348SMartin Matuska fillbuf(char *buf)
72716fd348SMartin Matuska {
73716fd348SMartin Matuska uint64_t rv = lrand48() % distribution_n;
74716fd348SMartin Matuska uint64_t sum = 0;
75716fd348SMartin Matuska
76716fd348SMartin Matuska uint64_t i;
77716fd348SMartin Matuska for (i = 0;
78716fd348SMartin Matuska i < sizeof (size_distribution) / sizeof (size_distribution[0]);
79716fd348SMartin Matuska i++) {
80716fd348SMartin Matuska sum += size_distribution[i];
81716fd348SMartin Matuska if (rv < sum)
82716fd348SMartin Matuska break;
83716fd348SMartin Matuska }
84716fd348SMartin Matuska
85716fd348SMartin Matuska memcpy(buf, randbuf, BLOCKSZ);
86716fd348SMartin Matuska if (i == 0)
87716fd348SMartin Matuska memset(buf, 0, BLOCKSZ - 10);
88716fd348SMartin Matuska else if (i < 16)
89716fd348SMartin Matuska memset(buf, 0, BLOCKSZ - i * 512 + 256);
90716fd348SMartin Matuska /*LINTED: E_BAD_PTR_CAST_ALIGN*/
91716fd348SMartin Matuska ((uint32_t *)buf)[0] = lrand48();
92716fd348SMartin Matuska }
93716fd348SMartin Matuska
94716fd348SMartin Matuska static void
exit_usage(void)95716fd348SMartin Matuska exit_usage(void)
96716fd348SMartin Matuska {
97716fd348SMartin Matuska (void) puts("usage: randwritecomp [-s] file [nwrites]");
98716fd348SMartin Matuska exit(EXIT_FAILURE);
99716fd348SMartin Matuska }
100716fd348SMartin Matuska
101716fd348SMartin Matuska static void
sequential_writes(int fd,char * buf,uint64_t nblocks,int64_t n)102716fd348SMartin Matuska sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
103716fd348SMartin Matuska {
104716fd348SMartin Matuska for (int64_t i = 0; n == -1 || i < n; i++) {
105716fd348SMartin Matuska fillbuf(buf);
106716fd348SMartin Matuska
107716fd348SMartin Matuska static uint64_t j = 0;
108716fd348SMartin Matuska if (j == 0)
109716fd348SMartin Matuska j = lrand48() % nblocks;
110716fd348SMartin Matuska rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ);
111716fd348SMartin Matuska j++;
112716fd348SMartin Matuska if (j >= nblocks)
113716fd348SMartin Matuska j = 0;
114716fd348SMartin Matuska }
115716fd348SMartin Matuska }
116716fd348SMartin Matuska
117716fd348SMartin Matuska static void
random_writes(int fd,char * buf,uint64_t nblocks,int64_t n)118716fd348SMartin Matuska random_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
119716fd348SMartin Matuska {
120716fd348SMartin Matuska for (int64_t i = 0; n == -1 || i < n; i++) {
121716fd348SMartin Matuska fillbuf(buf);
122716fd348SMartin Matuska rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ);
123716fd348SMartin Matuska }
124716fd348SMartin Matuska }
125716fd348SMartin Matuska
126716fd348SMartin Matuska int
main(int argc,char * argv[])127716fd348SMartin Matuska main(int argc, char *argv[])
128716fd348SMartin Matuska {
129716fd348SMartin Matuska int fd, err;
130716fd348SMartin Matuska char *filename = NULL;
131716fd348SMartin Matuska char buf[BLOCKSZ];
132716fd348SMartin Matuska struct stat ss;
133716fd348SMartin Matuska uint64_t nblocks;
134716fd348SMartin Matuska int64_t n = -1;
135716fd348SMartin Matuska int sequential = 0;
136716fd348SMartin Matuska
137716fd348SMartin Matuska if (argc < 2)
138716fd348SMartin Matuska exit_usage();
139716fd348SMartin Matuska
140716fd348SMartin Matuska argv++;
141716fd348SMartin Matuska if (strcmp("-s", argv[0]) == 0) {
142716fd348SMartin Matuska sequential = 1;
143716fd348SMartin Matuska argv++;
144716fd348SMartin Matuska }
145716fd348SMartin Matuska
146716fd348SMartin Matuska if (argv[0] == NULL)
147716fd348SMartin Matuska exit_usage();
148716fd348SMartin Matuska else
149716fd348SMartin Matuska filename = argv[0];
150716fd348SMartin Matuska
151716fd348SMartin Matuska argv++;
152716fd348SMartin Matuska if (argv[0] != NULL)
153716fd348SMartin Matuska n = strtoull(argv[0], NULL, 0);
154716fd348SMartin Matuska
155716fd348SMartin Matuska fd = open(filename, O_RDWR|O_CREAT, 0666);
156be181ee2SMartin Matuska if (fd == -1) {
157be181ee2SMartin Matuska (void) fprintf(stderr, "open(%s) failed: %s\n", filename,
158be181ee2SMartin Matuska strerror(errno));
159be181ee2SMartin Matuska exit(EXIT_FAILURE);
160be181ee2SMartin Matuska }
161716fd348SMartin Matuska err = fstat(fd, &ss);
162716fd348SMartin Matuska if (err != 0) {
163716fd348SMartin Matuska (void) fprintf(stderr,
164716fd348SMartin Matuska "error: fstat returned error code %d\n", err);
165716fd348SMartin Matuska exit(EXIT_FAILURE);
166716fd348SMartin Matuska }
167716fd348SMartin Matuska
168716fd348SMartin Matuska nblocks = ss.st_size / BLOCKSZ;
169716fd348SMartin Matuska if (nblocks == 0) {
170716fd348SMartin Matuska (void) fprintf(stderr, "error: "
171716fd348SMartin Matuska "file is too small (min allowed size is %d bytes)\n",
172716fd348SMartin Matuska BLOCKSZ);
173716fd348SMartin Matuska exit(EXIT_FAILURE);
174716fd348SMartin Matuska }
175716fd348SMartin Matuska
176716fd348SMartin Matuska srand48(getpid());
177716fd348SMartin Matuska for (int i = 0; i < BLOCKSZ; i++)
178716fd348SMartin Matuska randbuf[i] = lrand48();
179716fd348SMartin Matuska
180716fd348SMartin Matuska distribution_n = 0;
181716fd348SMartin Matuska for (uint64_t i = 0;
182716fd348SMartin Matuska i < sizeof (size_distribution) / sizeof (size_distribution[0]);
183716fd348SMartin Matuska i++) {
184716fd348SMartin Matuska distribution_n += size_distribution[i];
185716fd348SMartin Matuska }
186716fd348SMartin Matuska
187716fd348SMartin Matuska if (sequential)
188716fd348SMartin Matuska sequential_writes(fd, buf, nblocks, n);
189716fd348SMartin Matuska else
190716fd348SMartin Matuska random_writes(fd, buf, nblocks, n);
191716fd348SMartin Matuska
192716fd348SMartin Matuska return (0);
193716fd348SMartin Matuska }
194