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