1*86714001SSerapheim Dimitropoulos /*
2*86714001SSerapheim Dimitropoulos  * This file and its contents are supplied under the terms of the
3*86714001SSerapheim Dimitropoulos  * Common Development and Distribution License ("CDDL"), version 1.0.
4*86714001SSerapheim Dimitropoulos  * You may only use this file in accordance with the terms of version
5*86714001SSerapheim Dimitropoulos  * 1.0 of the CDDL.
6*86714001SSerapheim Dimitropoulos  *
7*86714001SSerapheim Dimitropoulos  * A full copy of the text of the CDDL should have accompanied this
8*86714001SSerapheim Dimitropoulos  * source.  A copy of the CDDL is also available via the Internet at
9*86714001SSerapheim Dimitropoulos  * http://www.illumos.org/license/CDDL.
10*86714001SSerapheim Dimitropoulos  */
11*86714001SSerapheim Dimitropoulos 
12*86714001SSerapheim Dimitropoulos /*
13*86714001SSerapheim Dimitropoulos  * Copyright (c) 2017 by Delphix. All rights reserved.
14*86714001SSerapheim Dimitropoulos  */
15*86714001SSerapheim Dimitropoulos 
16*86714001SSerapheim Dimitropoulos /*
17*86714001SSerapheim Dimitropoulos  * The following is defined so the source can use
18*86714001SSerapheim Dimitropoulos  * lrand48() and srand48().
19*86714001SSerapheim Dimitropoulos  */
20*86714001SSerapheim Dimitropoulos #define	__EXTENSIONS__
21*86714001SSerapheim Dimitropoulos 
22*86714001SSerapheim Dimitropoulos #include "../file_common.h"
23*86714001SSerapheim Dimitropoulos 
24*86714001SSerapheim Dimitropoulos /*
25*86714001SSerapheim Dimitropoulos  * The following sample was derived from real-world data
26*86714001SSerapheim Dimitropoulos  * of a production Oracle database.
27*86714001SSerapheim Dimitropoulos  */
28*86714001SSerapheim Dimitropoulos static uint64_t size_distribution[] = {
29*86714001SSerapheim Dimitropoulos 	0,
30*86714001SSerapheim Dimitropoulos 	1499018,
31*86714001SSerapheim Dimitropoulos 	352084,
32*86714001SSerapheim Dimitropoulos 	1503485,
33*86714001SSerapheim Dimitropoulos 	4206227,
34*86714001SSerapheim Dimitropoulos 	5626657,
35*86714001SSerapheim Dimitropoulos 	5387001,
36*86714001SSerapheim Dimitropoulos 	3733756,
37*86714001SSerapheim Dimitropoulos 	2233094,
38*86714001SSerapheim Dimitropoulos 	874652,
39*86714001SSerapheim Dimitropoulos 	238635,
40*86714001SSerapheim Dimitropoulos 	81434,
41*86714001SSerapheim Dimitropoulos 	33357,
42*86714001SSerapheim Dimitropoulos 	13106,
43*86714001SSerapheim Dimitropoulos 	2009,
44*86714001SSerapheim Dimitropoulos 	1,
45*86714001SSerapheim Dimitropoulos 	23660,
46*86714001SSerapheim Dimitropoulos };
47*86714001SSerapheim Dimitropoulos 
48*86714001SSerapheim Dimitropoulos 
49*86714001SSerapheim Dimitropoulos static uint64_t distribution_n;
50*86714001SSerapheim Dimitropoulos 
51*86714001SSerapheim Dimitropoulos static uint8_t randbuf[BLOCKSZ];
52*86714001SSerapheim Dimitropoulos 
53*86714001SSerapheim Dimitropoulos static void
rwc_pwrite(int fd,const void * buf,size_t nbytes,off_t offset)54*86714001SSerapheim Dimitropoulos rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
55*86714001SSerapheim Dimitropoulos {
56*86714001SSerapheim Dimitropoulos 	size_t nleft = nbytes;
57*86714001SSerapheim Dimitropoulos 	ssize_t nwrite = 0;
58*86714001SSerapheim Dimitropoulos 
59*86714001SSerapheim Dimitropoulos 	nwrite = pwrite(fd, buf, nbytes, offset);
60*86714001SSerapheim Dimitropoulos 	if (nwrite < 0) {
61*86714001SSerapheim Dimitropoulos 		perror("pwrite");
62*86714001SSerapheim Dimitropoulos 		exit(EXIT_FAILURE);
63*86714001SSerapheim Dimitropoulos 	}
64*86714001SSerapheim Dimitropoulos 
65*86714001SSerapheim Dimitropoulos 	nleft -= nwrite;
66*86714001SSerapheim Dimitropoulos 	if (nleft != 0) {
67*86714001SSerapheim Dimitropoulos 		(void) fprintf(stderr, "warning: pwrite: "
68*86714001SSerapheim Dimitropoulos 		    "wrote %zu out of %zu bytes\n",
69*86714001SSerapheim Dimitropoulos 		    (nbytes - nleft), nbytes);
70*86714001SSerapheim Dimitropoulos 	}
71*86714001SSerapheim Dimitropoulos }
72*86714001SSerapheim Dimitropoulos 
73*86714001SSerapheim Dimitropoulos static void
fillbuf(char * buf)74*86714001SSerapheim Dimitropoulos fillbuf(char *buf)
75*86714001SSerapheim Dimitropoulos {
76*86714001SSerapheim Dimitropoulos 	uint64_t rv = lrand48() % distribution_n;
77*86714001SSerapheim Dimitropoulos 	uint64_t sum = 0;
78*86714001SSerapheim Dimitropoulos 
79*86714001SSerapheim Dimitropoulos 	uint64_t i;
80*86714001SSerapheim Dimitropoulos 	for (i = 0;
81*86714001SSerapheim Dimitropoulos 	    i < sizeof (size_distribution) / sizeof (size_distribution[0]);
82*86714001SSerapheim Dimitropoulos 	    i++) {
83*86714001SSerapheim Dimitropoulos 		sum += size_distribution[i];
84*86714001SSerapheim Dimitropoulos 		if (rv < sum)
85*86714001SSerapheim Dimitropoulos 			break;
86*86714001SSerapheim Dimitropoulos 	}
87*86714001SSerapheim Dimitropoulos 
88*86714001SSerapheim Dimitropoulos 	bcopy(randbuf, buf, BLOCKSZ);
89*86714001SSerapheim Dimitropoulos 	if (i == 0)
90*86714001SSerapheim Dimitropoulos 		bzero(buf, BLOCKSZ - 10);
91*86714001SSerapheim Dimitropoulos 	else if (i < 16)
92*86714001SSerapheim Dimitropoulos 		bzero(buf, BLOCKSZ - i * 512 + 256);
93*86714001SSerapheim Dimitropoulos 	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
94*86714001SSerapheim Dimitropoulos 	((uint32_t *)buf)[0] = lrand48();
95*86714001SSerapheim Dimitropoulos }
96*86714001SSerapheim Dimitropoulos 
97*86714001SSerapheim Dimitropoulos static void
exit_usage(void)98*86714001SSerapheim Dimitropoulos exit_usage(void)
99*86714001SSerapheim Dimitropoulos {
100*86714001SSerapheim Dimitropoulos 	(void) printf("usage: ");
101*86714001SSerapheim Dimitropoulos 	(void) printf("randwritecomp <file> [-s] [nwrites]\n");
102*86714001SSerapheim Dimitropoulos 	exit(EXIT_FAILURE);
103*86714001SSerapheim Dimitropoulos }
104*86714001SSerapheim Dimitropoulos 
105*86714001SSerapheim Dimitropoulos static void
sequential_writes(int fd,char * buf,uint64_t nblocks,int64_t n)106*86714001SSerapheim Dimitropoulos sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
107*86714001SSerapheim Dimitropoulos {
108*86714001SSerapheim Dimitropoulos 	for (int64_t i = 0; n == -1 || i < n; i++) {
109*86714001SSerapheim Dimitropoulos 		fillbuf(buf);
110*86714001SSerapheim Dimitropoulos 
111*86714001SSerapheim Dimitropoulos 		static uint64_t j = 0;
112*86714001SSerapheim Dimitropoulos 		if (j == 0)
113*86714001SSerapheim Dimitropoulos 			j = lrand48() % nblocks;
114*86714001SSerapheim Dimitropoulos 		rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ);
115*86714001SSerapheim Dimitropoulos 		j++;
116*86714001SSerapheim Dimitropoulos 		if (j >= nblocks)
117*86714001SSerapheim Dimitropoulos 			j = 0;
118*86714001SSerapheim Dimitropoulos 	}
119*86714001SSerapheim Dimitropoulos }
120*86714001SSerapheim Dimitropoulos 
121*86714001SSerapheim Dimitropoulos static void
random_writes(int fd,char * buf,uint64_t nblocks,int64_t n)122*86714001SSerapheim Dimitropoulos random_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
123*86714001SSerapheim Dimitropoulos {
124*86714001SSerapheim Dimitropoulos 	for (int64_t i = 0; n == -1 || i < n; i++) {
125*86714001SSerapheim Dimitropoulos 		fillbuf(buf);
126*86714001SSerapheim Dimitropoulos 		rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ);
127*86714001SSerapheim Dimitropoulos 	}
128*86714001SSerapheim Dimitropoulos }
129*86714001SSerapheim Dimitropoulos 
130*86714001SSerapheim Dimitropoulos int
main(int argc,char * argv[])131*86714001SSerapheim Dimitropoulos main(int argc, char *argv[])
132*86714001SSerapheim Dimitropoulos {
133*86714001SSerapheim Dimitropoulos 	int fd, err;
134*86714001SSerapheim Dimitropoulos 	char *filename = NULL;
135*86714001SSerapheim Dimitropoulos 	char buf[BLOCKSZ];
136*86714001SSerapheim Dimitropoulos 	struct stat ss;
137*86714001SSerapheim Dimitropoulos 	uint64_t nblocks;
138*86714001SSerapheim Dimitropoulos 	int64_t n = -1;
139*86714001SSerapheim Dimitropoulos 	int sequential = 0;
140*86714001SSerapheim Dimitropoulos 
141*86714001SSerapheim Dimitropoulos 	if (argc < 2)
142*86714001SSerapheim Dimitropoulos 		exit_usage();
143*86714001SSerapheim Dimitropoulos 
144*86714001SSerapheim Dimitropoulos 	argv++;
145*86714001SSerapheim Dimitropoulos 	if (strcmp("-s", argv[0]) == 0) {
146*86714001SSerapheim Dimitropoulos 		sequential = 1;
147*86714001SSerapheim Dimitropoulos 		argv++;
148*86714001SSerapheim Dimitropoulos 	}
149*86714001SSerapheim Dimitropoulos 
150*86714001SSerapheim Dimitropoulos 	if (argv[0] == NULL)
151*86714001SSerapheim Dimitropoulos 		exit_usage();
152*86714001SSerapheim Dimitropoulos 	else
153*86714001SSerapheim Dimitropoulos 		filename = argv[0];
154*86714001SSerapheim Dimitropoulos 
155*86714001SSerapheim Dimitropoulos 	argv++;
156*86714001SSerapheim Dimitropoulos 	if (argv[0] != NULL)
157*86714001SSerapheim Dimitropoulos 		n = strtoull(argv[0], NULL, 0);
158*86714001SSerapheim Dimitropoulos 
159*86714001SSerapheim Dimitropoulos 	fd = open(filename, O_RDWR|O_CREAT, 0666);
160*86714001SSerapheim Dimitropoulos 	err = fstat(fd, &ss);
161*86714001SSerapheim Dimitropoulos 	if (err != 0) {
162*86714001SSerapheim Dimitropoulos 		(void) fprintf(stderr,
163*86714001SSerapheim Dimitropoulos 		    "error: fstat returned error code %d\n", err);
164*86714001SSerapheim Dimitropoulos 		exit(EXIT_FAILURE);
165*86714001SSerapheim Dimitropoulos 	}
166*86714001SSerapheim Dimitropoulos 
167*86714001SSerapheim Dimitropoulos 	nblocks = ss.st_size / BLOCKSZ;
168*86714001SSerapheim Dimitropoulos 	if (nblocks == 0) {
169*86714001SSerapheim Dimitropoulos 		(void) fprintf(stderr, "error: "
170*86714001SSerapheim Dimitropoulos 		    "file is too small (min allowed size is %d bytes)\n",
171*86714001SSerapheim Dimitropoulos 		    BLOCKSZ);
172*86714001SSerapheim Dimitropoulos 		exit(EXIT_FAILURE);
173*86714001SSerapheim Dimitropoulos 	}
174*86714001SSerapheim Dimitropoulos 
175*86714001SSerapheim Dimitropoulos 	srand48(getpid());
176*86714001SSerapheim Dimitropoulos 	for (int i = 0; i < BLOCKSZ; i++)
177*86714001SSerapheim Dimitropoulos 		randbuf[i] = lrand48();
178*86714001SSerapheim Dimitropoulos 
179*86714001SSerapheim Dimitropoulos 	distribution_n = 0;
180*86714001SSerapheim Dimitropoulos 	for (uint64_t i = 0;
181*86714001SSerapheim Dimitropoulos 	    i < sizeof (size_distribution) / sizeof (size_distribution[0]);
182*86714001SSerapheim Dimitropoulos 	    i++) {
183*86714001SSerapheim Dimitropoulos 		distribution_n += size_distribution[i];
184*86714001SSerapheim Dimitropoulos 	}
185*86714001SSerapheim Dimitropoulos 
186*86714001SSerapheim Dimitropoulos 	if (sequential)
187*86714001SSerapheim Dimitropoulos 		sequential_writes(fd, buf, nblocks, n);
188*86714001SSerapheim Dimitropoulos 	else
189*86714001SSerapheim Dimitropoulos 		random_writes(fd, buf, nblocks, n);
190*86714001SSerapheim Dimitropoulos 
191*86714001SSerapheim Dimitropoulos 	return (0);
192*86714001SSerapheim Dimitropoulos }
193