diff options
Diffstat (limited to 'sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_write.c')
-rw-r--r-- | sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_write.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_write.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_write.c new file mode 100644 index 000000000000..9a4b7c51d698 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/file/file_write.c @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "file_common.h" +#include <libgen.h> +#include <string.h> +#include <inttypes.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#include <stdint.h> + +static unsigned char bigbuffer[BIGBUFFERSIZE]; + +/* + * Writes (or appends) a given value to a file repeatedly. + * See header file for defaults. + */ + +static void usage(char *); + +/* + * pseudo-randomize the buffer + */ +static void randomize_buffer(int block_size) { + int i; + char rnd = rand() & 0xff; + for (i = 0; i < block_size; i++) + bigbuffer[i] ^= rnd; +} + +int +main(int argc, char **argv) +{ + int bigfd; + int c; + int oflag = 0; + int err = 0; + int k; + long i; + int64_t good_writes = 0; + uchar_t nxtfillchar; + char *prog = argv[0]; + /* + * Default Parameters + */ + int write_count = BIGFILESIZE; + uchar_t fillchar = DATA; + int block_size = BLOCKSZ; + char *filename = NULL; + char *operation = NULL; + offset_t noffset, offset = 0; + int verbose = 0; + int rsync = 0; + int wsync = 0; + + /* + * Process Arguments + */ + while ((c = getopt(argc, argv, "b:c:d:s:f:o:vwr")) != -1) { + switch (c) { + case 'b': + block_size = atoi(optarg); + break; + case 'c': + write_count = atoi(optarg); + break; + case 'd': + if (optarg[0] == 'R') + fillchar = 'R'; /* R = random data */ + else + fillchar = atoi(optarg); + break; + case 's': + offset = atoll(optarg); + break; + case 'f': + filename = optarg; + break; + case 'o': + operation = optarg; + break; + case 'v': + verbose = 1; + break; + case 'w': + wsync = 1; + break; + case 'r': + rsync = 1; + break; + case '?': + (void) printf("unknown arg %c\n", optopt); + usage(prog); + break; + } + } + + /* + * Validate Parameters + */ + if (!filename) { + (void) printf("Filename not specified (-f <file>)\n"); + err++; + } + + if (!operation) { + (void) printf("Operation not specified (-o <operation>).\n"); + err++; + } + + if (block_size > BIGBUFFERSIZE) { + (void) printf("block_size is too large max==%d.\n", + BIGBUFFERSIZE); + err++; + } + + if (err) { + usage(prog); /* no return */ + return (1); + } + + /* + * Prepare the buffer and determine the requested operation + */ + nxtfillchar = fillchar; + k = 0; + + if (fillchar == 'R') + srand(time(NULL)); + + for (i = 0; i < block_size; i++) { + bigbuffer[i] = nxtfillchar; + + if (fillchar == 0) { + if ((k % DATA_RANGE) == 0) { + k = 0; + } + nxtfillchar = k++; + } else if (fillchar == 'R') { + nxtfillchar = rand() & 0xff; + } + } + + /* + * using the strncmp of operation will make the operation match the + * first shortest match - as the operations are unique from the first + * character this means that we match single character operations + */ + if ((strncmp(operation, "create", strlen(operation) + 1)) == 0 || + (strncmp(operation, "overwrite", strlen(operation) + 1)) == 0) { + oflag = (O_RDWR|O_CREAT); + } else if ((strncmp(operation, "append", strlen(operation) + 1)) == 0) { + oflag = (O_RDWR|O_APPEND); + } else { + (void) printf("valid operations are <create|append> not '%s'\n", + operation); + usage(prog); + } + + if (rsync) { + oflag = oflag | O_RSYNC; + } + + if (wsync) { + oflag = oflag | O_SYNC; + } + + /* + * Given an operation (create/overwrite/append), open the file + * accordingly and perform a write of the appropriate type. + */ + if ((bigfd = open(filename, oflag, 0666)) == -1) { + (void) printf("open %s: failed [%s]%d. Aborting!\n", filename, + strerror(errno), errno); + exit(errno); + } + noffset = lseek64(bigfd, offset, SEEK_SET); + if (noffset != offset) { + (void) printf("llseek %s (%lld/%lld) failed [%s]%d.Aborting!\n", + filename, offset, noffset, strerror(errno), errno); + exit(errno); + } + + if (verbose) { + (void) printf("%s: block_size = %d, write_count = %d, " + "offset = %lld, ", filename, block_size, + write_count, offset); + if (fillchar == 'R') { + (void) printf("data = [random]\n"); + } else { + (void) printf("data = %s%d\n", + (fillchar == 0) ? "0->" : "", + (fillchar == 0) ? DATA_RANGE : fillchar); + } + } + + for (i = 0; i < write_count; i++) { + ssize_t n; + if (fillchar == 'R') + randomize_buffer(block_size); + + if ((n = write(bigfd, &bigbuffer, block_size)) == -1) { + (void) printf("write failed (%ld), good_writes = %" + PRId64 ", " "error: %s[%d]\n", + (long)n, good_writes, + strerror(errno), + errno); + exit(errno); + } + good_writes++; + } + + if (verbose) { + (void) printf("Success: good_writes = %" PRId64 "(%" + PRId64 ")\n", good_writes, (good_writes * block_size)); + } + + return (0); +} + +static void +usage(char *prog) +{ + (void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name" + " [-b block_size]\n" + "\t[-s offset] [-c write_count] [-d data]\n\n" + "Where [data] equal to zero causes chars " + "0->%d to be repeated throughout, or [data]\n" + "equal to 'R' for pseudorandom data.\n", + prog, DATA_RANGE); + + exit(1); +} |