xref: /freebsd-src/sys/contrib/openzfs/tests/zfs-tests/cmd/file/randwritecomp.c (revision be181ee2a28aa2b4b0e76684bce9f673ef668874)
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