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