]> git.proxmox.com Git - mirror_zfs-debian.git/blob - tests/zfs-tests/cmd/file_write/file_write.c
New upstream version 0.7.2
[mirror_zfs-debian.git] / tests / zfs-tests / cmd / file_write / file_write.c
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "../file_common.h"
28 #include <libgen.h>
29 #include <string.h>
30 #include <inttypes.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <time.h>
35 #include <stdint.h>
36
37 typedef unsigned char uchar_t;
38 typedef long long longlong_t;
39 typedef longlong_t offset_t;
40
41 static unsigned char bigbuffer[BIGBUFFERSIZE];
42
43 /*
44 * Writes (or appends) a given value to a file repeatedly.
45 * See header file for defaults.
46 */
47
48 static void usage(char *);
49
50 /*
51 * psudo-randomize the buffer
52 */
53 void randomize_buffer(int block_size) {
54 int i;
55 char rnd = rand() & 0xff;
56 for (i = 0; i < block_size; i++)
57 bigbuffer[i] ^= rnd;
58 }
59
60 int
61 main(int argc, char **argv)
62 {
63 int bigfd;
64 int c;
65 int oflag = 0;
66 int err = 0;
67 int k;
68 long i;
69 int64_t good_writes = 0;
70 uchar_t nxtfillchar;
71 char *prog = argv[0];
72 /*
73 * Default Parameters
74 */
75 int write_count = BIGFILESIZE;
76 uchar_t fillchar = DATA;
77 int block_size = BLOCKSZ;
78 char *filename = NULL;
79 char *operation = NULL;
80 offset_t noffset, offset = 0;
81 int verbose = 0;
82 int rsync = 0;
83 int wsync = 0;
84
85 /*
86 * Process Arguments
87 */
88 while ((c = getopt(argc, argv, "b:c:d:s:f:o:vwr")) != -1) {
89 switch (c) {
90 case 'b':
91 block_size = atoi(optarg);
92 break;
93 case 'c':
94 write_count = atoi(optarg);
95 break;
96 case 'd':
97 if (optarg[0] == 'R')
98 fillchar = 'R'; /* R = random data */
99 else
100 fillchar = atoi(optarg);
101 break;
102 case 's':
103 offset = atoll(optarg);
104 break;
105 case 'f':
106 filename = optarg;
107 break;
108 case 'o':
109 operation = optarg;
110 break;
111 case 'v':
112 verbose = 1;
113 break;
114 case 'w':
115 wsync = 1;
116 break;
117 case 'r':
118 rsync = 1;
119 break;
120 case '?':
121 (void) printf("unknown arg %c\n", optopt);
122 usage(prog);
123 break;
124 }
125 }
126
127 /*
128 * Validate Parameters
129 */
130 if (!filename) {
131 (void) printf("Filename not specified (-f <file>)\n");
132 err++;
133 }
134
135 if (!operation) {
136 (void) printf("Operation not specified (-o <operation>).\n");
137 err++;
138 }
139
140 if (block_size > BIGBUFFERSIZE) {
141 (void) printf("block_size is too large max==%d.\n",
142 BIGBUFFERSIZE);
143 err++;
144 }
145
146 if (err) {
147 usage(prog); /* no return */
148 return (1);
149 }
150
151 /*
152 * Prepare the buffer and determine the requested operation
153 */
154 nxtfillchar = fillchar;
155 k = 0;
156
157 if (fillchar == 'R')
158 srand(time(NULL));
159
160 for (i = 0; i < block_size; i++) {
161 bigbuffer[i] = nxtfillchar;
162
163 if (fillchar == 0) {
164 if ((k % DATA_RANGE) == 0) {
165 k = 0;
166 }
167 nxtfillchar = k++;
168 } else if (fillchar == 'R') {
169 nxtfillchar = rand() & 0xff;
170 }
171 }
172
173 /*
174 * using the strncmp of operation will make the operation match the
175 * first shortest match - as the operations are unique from the first
176 * character this means that we match single character operations
177 */
178 if ((strncmp(operation, "create", strlen(operation) + 1)) == 0 ||
179 (strncmp(operation, "overwrite", strlen(operation) + 1)) == 0) {
180 oflag = (O_RDWR|O_CREAT);
181 } else if ((strncmp(operation, "append", strlen(operation) + 1)) == 0) {
182 oflag = (O_RDWR|O_APPEND);
183 } else {
184 (void) printf("valid operations are <create|append> not '%s'\n",
185 operation);
186 usage(prog);
187 }
188
189 if (rsync) {
190 oflag = oflag | O_RSYNC;
191 }
192
193 if (wsync) {
194 oflag = oflag | O_SYNC;
195 }
196
197 /*
198 * Given an operation (create/overwrite/append), open the file
199 * accordingly and perform a write of the appropriate type.
200 */
201 if ((bigfd = open(filename, oflag, 0666)) == -1) {
202 (void) printf("open %s: failed [%s]%d. Aborting!\n", filename,
203 strerror(errno), errno);
204 exit(errno);
205 }
206 noffset = lseek64(bigfd, offset, SEEK_SET);
207 if (noffset != offset) {
208 (void) printf("llseek %s (%lld/%lld) failed [%s]%d.Aborting!\n",
209 filename, offset, noffset, strerror(errno), errno);
210 exit(errno);
211 }
212
213 if (verbose) {
214 (void) printf("%s: block_size = %d, write_count = %d, "
215 "offset = %lld, ", filename, block_size,
216 write_count, offset);
217 if (fillchar == 'R') {
218 (void) printf("data = [random]\n");
219 } else {
220 (void) printf("data = %s%d\n",
221 (fillchar == 0) ? "0->" : "",
222 (fillchar == 0) ? DATA_RANGE : fillchar);
223 }
224 }
225
226 for (i = 0; i < write_count; i++) {
227 ssize_t n;
228 if (fillchar == 'R')
229 randomize_buffer(block_size);
230
231 if ((n = write(bigfd, &bigbuffer, block_size)) == -1) {
232 (void) printf("write failed (%ld), good_writes = %"
233 PRId64 ", " "error: %s[%d]\n",
234 (long)n, good_writes,
235 strerror(errno),
236 errno);
237 exit(errno);
238 }
239 good_writes++;
240 }
241
242 if (verbose) {
243 (void) printf("Success: good_writes = %" PRId64 "(%"
244 PRId64 ")\n", good_writes, (good_writes * block_size));
245 }
246
247 return (0);
248 }
249
250 static void
251 usage(char *prog)
252 {
253 (void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name"
254 " [-b block_size]\n"
255 "\t[-s offset] [-c write_count] [-d data]\n\n"
256 "Where [data] equal to zero causes chars "
257 "0->%d to be repeated throughout, or [data]\n"
258 "equal to 'R' for psudorandom data.\n",
259 prog, DATA_RANGE);
260
261 exit(1);
262 }