mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
tests: cmd: don't recurse
This confers an >10x speedup on t/z-t/cmd builds (12s -> 1.1s), gets rid of 23 redundant identical automake specs and gitignores, and groups the binaries with their common headers Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: John Kennedy <john.kennedy@delphix.com> Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> Closes #13259
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 http://www.opensolaris.org/os/licensing.
|
||||
* 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"
|
||||
|
||||
static unsigned char bigbuffer[BIGBUFFERSIZE];
|
||||
|
||||
/*
|
||||
* Given a filename, check that the file consists entirely
|
||||
* of a particular pattern. If the pattern is not specified a
|
||||
* default will be used. For default values see file_common.h
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int bigfd;
|
||||
long i, n;
|
||||
unsigned char fillchar = DATA;
|
||||
int bigbuffersize = BIGBUFFERSIZE;
|
||||
|
||||
/*
|
||||
* Validate arguments
|
||||
*/
|
||||
if (argc < 2) {
|
||||
(void) printf("Usage: %s filename [pattern]\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argv[2]) {
|
||||
fillchar = atoi(argv[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the file contents and check every character
|
||||
* against the supplied pattern. Abort if the
|
||||
* pattern check fails.
|
||||
*/
|
||||
if ((bigfd = open(argv[1], O_RDONLY)) == -1) {
|
||||
(void) printf("open %s failed %d\n", argv[1], errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
do {
|
||||
if ((n = read(bigfd, &bigbuffer, bigbuffersize)) == -1) {
|
||||
(void) printf("read failed (%ld), %d\n", n, errno);
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (bigbuffer[i] != fillchar) {
|
||||
(void) printf("error %s: 0x%x != 0x%x)\n",
|
||||
argv[1], bigbuffer[i], fillchar);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} while (n == bigbuffersize);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 http://www.opensolaris.org/os/licensing.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef FILE_COMMON_H
|
||||
#define FILE_COMMON_H
|
||||
|
||||
/*
|
||||
* header file for file_* utilities. These utilities
|
||||
* are used by the test cases to perform various file
|
||||
* operations (append writes, for example).
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BLOCKSZ 8192
|
||||
#define DATA 0xa5
|
||||
#define DATA_RANGE 120
|
||||
#define BIGBUFFERSIZE 0x800000
|
||||
#define BIGFILESIZE 20
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FILE_COMMON_H */
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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 http://www.opensolaris.org/os/licensing.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define FSIZE 256*1024*1024
|
||||
#define BSIZE 512
|
||||
|
||||
/* Initialize Globals */
|
||||
static long fsize = FSIZE;
|
||||
static size_t bsize = BSIZE;
|
||||
static int count = 0;
|
||||
static int rflag = 0;
|
||||
static int seed = 0;
|
||||
static int vflag = 0;
|
||||
static int errflag = 0;
|
||||
static off_t offset = 0;
|
||||
static char *filename = NULL;
|
||||
|
||||
static void usage(char *execname);
|
||||
static void parse_options(int argc, char *argv[]);
|
||||
static void do_write(int fd);
|
||||
static void do_trunc(int fd);
|
||||
|
||||
static void
|
||||
usage(char *execname)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage: %s [-b blocksize] [-c count] [-f filesize]"
|
||||
" [-o offset] [-s seed] [-r] [-v] filename\n", execname);
|
||||
(void) exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i = 0;
|
||||
int fd = -1;
|
||||
|
||||
parse_options(argc, argv);
|
||||
|
||||
fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
for (i = 0; count == 0 || i < count; i++) {
|
||||
(void) do_write(fd);
|
||||
(void) do_trunc(fd);
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, optopt;
|
||||
|
||||
count = fsize / bsize;
|
||||
seed = time(NULL);
|
||||
while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
bsize = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
count = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
fsize = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
offset = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
rflag++;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
seed = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
vflag++;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
(void) fprintf(stderr,
|
||||
"Option -%c requires an operand\n", optopt);
|
||||
errflag++;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
(void) fprintf(stderr,
|
||||
"Unrecognized option: -%c\n", optopt);
|
||||
errflag++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (errflag) {
|
||||
(void) usage(argv[0]);
|
||||
}
|
||||
}
|
||||
if (argc <= optind) {
|
||||
(void) fprintf(stderr,
|
||||
"No filename specified\n");
|
||||
usage(argv[0]);
|
||||
}
|
||||
filename = argv[optind];
|
||||
|
||||
if (vflag) {
|
||||
(void) fprintf(stderr, "Seed = %d\n", seed);
|
||||
}
|
||||
srandom(seed);
|
||||
}
|
||||
|
||||
static void
|
||||
do_write(int fd)
|
||||
{
|
||||
off_t roffset = 0;
|
||||
char *buf = NULL;
|
||||
char *rbuf = NULL;
|
||||
|
||||
buf = (char *)calloc(1, bsize);
|
||||
rbuf = (char *)calloc(1, bsize);
|
||||
if (buf == NULL || rbuf == NULL) {
|
||||
perror("malloc");
|
||||
exit(4);
|
||||
}
|
||||
|
||||
roffset = random() % fsize;
|
||||
if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
|
||||
perror("lseek");
|
||||
exit(5);
|
||||
}
|
||||
|
||||
(void) strcpy(buf, "ZFS Test Suite Truncation Test");
|
||||
if (write(fd, buf, bsize) < bsize) {
|
||||
perror("write");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
if (rflag) {
|
||||
if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) {
|
||||
perror("lseek");
|
||||
exit(7);
|
||||
}
|
||||
|
||||
if (read(fd, rbuf, bsize) < bsize) {
|
||||
perror("read");
|
||||
exit(8);
|
||||
}
|
||||
|
||||
if (memcmp(buf, rbuf, bsize) != 0) {
|
||||
perror("memcmp");
|
||||
exit(9);
|
||||
}
|
||||
}
|
||||
if (vflag) {
|
||||
(void) fprintf(stderr,
|
||||
"Wrote to offset %" PRId64 "\n", (offset + roffset));
|
||||
if (rflag) {
|
||||
(void) fprintf(stderr,
|
||||
"Read back from offset %" PRId64 "\n",
|
||||
(offset + roffset));
|
||||
}
|
||||
}
|
||||
|
||||
(void) free(buf);
|
||||
(void) free(rbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
do_trunc(int fd)
|
||||
{
|
||||
off_t roffset = 0;
|
||||
|
||||
roffset = random() % fsize;
|
||||
if (ftruncate64(fd, (offset + roffset)) < 0) {
|
||||
perror("truncate");
|
||||
exit(7);
|
||||
}
|
||||
|
||||
if (vflag) {
|
||||
(void) fprintf(stderr, "Truncated at offset %" PRId64 "\n",
|
||||
(offset + roffset));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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 http://www.opensolaris.org/os/licensing.
|
||||
* 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 psudorandom data.\n",
|
||||
prog, DATA_RANGE);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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 http://www.opensolaris.org/os/licensing.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "file_common.h"
|
||||
#include <sys/param.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stdtypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
*
|
||||
* Assertion:
|
||||
* The last byte of the largest file size can be
|
||||
* accessed without any errors. Also, the writing
|
||||
* beyond the last byte of the largest file size
|
||||
* will produce an errno of EFBIG.
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
* If the write() system call below returns a "1",
|
||||
* then the last byte can be accessed.
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
static void sigxfsz(int);
|
||||
static void usage(char *);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int fd = 0;
|
||||
offset_t offset = (MAXOFFSET_T - 1);
|
||||
offset_t llseek_ret = 0;
|
||||
int write_ret = 0;
|
||||
int err = 0;
|
||||
char mybuf[5] = "aaaa\0";
|
||||
char *testfile;
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
struct sigaction sa;
|
||||
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
if (sigemptyset(&sa.sa_mask) == -1)
|
||||
return (errno);
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_handler = sigxfsz;
|
||||
if (sigaction(SIGXFSZ, &sa, NULL) == -1)
|
||||
return (errno);
|
||||
|
||||
testfile = strdup(argv[1]);
|
||||
|
||||
fd = open(testfile, O_CREAT | O_RDWR, mode);
|
||||
if (fd < 0) {
|
||||
err = errno;
|
||||
perror("Failed to create testfile");
|
||||
free(testfile);
|
||||
return (err);
|
||||
}
|
||||
|
||||
llseek_ret = lseek64(fd, offset, SEEK_SET);
|
||||
if (llseek_ret < 0) {
|
||||
err = errno;
|
||||
perror("Failed to seek to end of testfile");
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_ret = write(fd, mybuf, 1);
|
||||
if (write_ret < 0) {
|
||||
err = errno;
|
||||
perror("Failed to write to end of file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
llseek_ret = lseek64(fd, offset, SEEK_CUR);
|
||||
if (llseek_ret < 0) {
|
||||
err = errno;
|
||||
perror("Failed to seek to end of file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_ret = write(fd, mybuf, 1);
|
||||
if (write_ret < 0) {
|
||||
if (errno == EFBIG || errno == EINVAL) {
|
||||
(void) printf("write errno=EFBIG|EINVAL: success\n");
|
||||
err = 0;
|
||||
} else {
|
||||
err = errno;
|
||||
perror("Did not receive EFBIG");
|
||||
}
|
||||
} else {
|
||||
(void) printf("write completed successfully, test failed\n");
|
||||
err = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
(void) unlink(testfile);
|
||||
free(testfile);
|
||||
close(fd);
|
||||
return (err);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(char *name)
|
||||
{
|
||||
(void) printf("%s <testfile>\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
sigxfsz(int signo)
|
||||
{
|
||||
(void) signo;
|
||||
(void) printf("\nlargest_file: sigxfsz() caught SIGXFSZ\n");
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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 http://www.opensolaris.org/os/licensing.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "file_common.h"
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <linux/falloc.h>
|
||||
|
||||
/*
|
||||
* Create a file with assigned size and then free the specified
|
||||
* section of the file
|
||||
*/
|
||||
|
||||
static void usage(char *progname);
|
||||
|
||||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage: %s [-l filesize] [-s start-offset]"
|
||||
"[-n section-len] filename\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *filename = NULL;
|
||||
char *buf = NULL;
|
||||
size_t filesize = 0;
|
||||
off_t start_off = 0;
|
||||
off_t off_len = 0;
|
||||
int fd, ch;
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
while ((ch = getopt(argc, argv, "l:s:n:")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'l':
|
||||
filesize = atoll(optarg);
|
||||
break;
|
||||
case 's':
|
||||
start_off = atoll(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
off_len = atoll(optarg);
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc - 1)
|
||||
filename = argv[optind];
|
||||
else
|
||||
usage(argv[0]);
|
||||
|
||||
if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0) {
|
||||
perror("open");
|
||||
return (1);
|
||||
}
|
||||
|
||||
buf = (char *)calloc(1, filesize);
|
||||
if (buf == NULL) {
|
||||
perror("write");
|
||||
close(fd);
|
||||
return (1);
|
||||
}
|
||||
memset(buf, 'c', filesize);
|
||||
|
||||
if (write(fd, buf, filesize) < filesize) {
|
||||
free(buf);
|
||||
perror("write");
|
||||
close(fd);
|
||||
return (1);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
#if defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)
|
||||
if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
||||
start_off, off_len) < 0) {
|
||||
perror("fallocate");
|
||||
close(fd);
|
||||
return (1);
|
||||
}
|
||||
#else /* !(defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE)) */
|
||||
{
|
||||
perror("FALLOC_FL_PUNCH_HOLE unsupported");
|
||||
close(fd);
|
||||
return (1);
|
||||
}
|
||||
#endif /* defined(FALLOC_FL_PUNCH_HOLE) && defined(FALLOC_FL_KEEP_SIZE) */
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "file_common.h"
|
||||
|
||||
/*
|
||||
* The following sample was derived from real-world data
|
||||
* of a production Oracle database.
|
||||
*/
|
||||
static const uint64_t size_distribution[] = {
|
||||
0,
|
||||
1499018,
|
||||
352084,
|
||||
1503485,
|
||||
4206227,
|
||||
5626657,
|
||||
5387001,
|
||||
3733756,
|
||||
2233094,
|
||||
874652,
|
||||
238635,
|
||||
81434,
|
||||
33357,
|
||||
13106,
|
||||
2009,
|
||||
1,
|
||||
23660,
|
||||
};
|
||||
|
||||
|
||||
static uint64_t distribution_n;
|
||||
|
||||
static uint8_t randbuf[BLOCKSZ];
|
||||
|
||||
static void
|
||||
rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
|
||||
{
|
||||
size_t nleft = nbytes;
|
||||
ssize_t nwrite = 0;
|
||||
|
||||
nwrite = pwrite(fd, buf, nbytes, offset);
|
||||
if (nwrite < 0) {
|
||||
perror("pwrite");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nleft -= nwrite;
|
||||
if (nleft != 0) {
|
||||
(void) fprintf(stderr, "warning: pwrite: "
|
||||
"wrote %zu out of %zu bytes\n",
|
||||
(nbytes - nleft), nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fillbuf(char *buf)
|
||||
{
|
||||
uint64_t rv = lrand48() % distribution_n;
|
||||
uint64_t sum = 0;
|
||||
|
||||
uint64_t i;
|
||||
for (i = 0;
|
||||
i < sizeof (size_distribution) / sizeof (size_distribution[0]);
|
||||
i++) {
|
||||
sum += size_distribution[i];
|
||||
if (rv < sum)
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(buf, randbuf, BLOCKSZ);
|
||||
if (i == 0)
|
||||
memset(buf, 0, BLOCKSZ - 10);
|
||||
else if (i < 16)
|
||||
memset(buf, 0, BLOCKSZ - i * 512 + 256);
|
||||
/*LINTED: E_BAD_PTR_CAST_ALIGN*/
|
||||
((uint32_t *)buf)[0] = lrand48();
|
||||
}
|
||||
|
||||
static void
|
||||
exit_usage(void)
|
||||
{
|
||||
(void) puts("usage: randwritecomp [-s] file [nwrites]");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
|
||||
{
|
||||
for (int64_t i = 0; n == -1 || i < n; i++) {
|
||||
fillbuf(buf);
|
||||
|
||||
static uint64_t j = 0;
|
||||
if (j == 0)
|
||||
j = lrand48() % nblocks;
|
||||
rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ);
|
||||
j++;
|
||||
if (j >= nblocks)
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
random_writes(int fd, char *buf, uint64_t nblocks, int64_t n)
|
||||
{
|
||||
for (int64_t i = 0; n == -1 || i < n; i++) {
|
||||
fillbuf(buf);
|
||||
rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fd, err;
|
||||
char *filename = NULL;
|
||||
char buf[BLOCKSZ];
|
||||
struct stat ss;
|
||||
uint64_t nblocks;
|
||||
int64_t n = -1;
|
||||
int sequential = 0;
|
||||
|
||||
if (argc < 2)
|
||||
exit_usage();
|
||||
|
||||
argv++;
|
||||
if (strcmp("-s", argv[0]) == 0) {
|
||||
sequential = 1;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argv[0] == NULL)
|
||||
exit_usage();
|
||||
else
|
||||
filename = argv[0];
|
||||
|
||||
argv++;
|
||||
if (argv[0] != NULL)
|
||||
n = strtoull(argv[0], NULL, 0);
|
||||
|
||||
fd = open(filename, O_RDWR|O_CREAT, 0666);
|
||||
err = fstat(fd, &ss);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"error: fstat returned error code %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nblocks = ss.st_size / BLOCKSZ;
|
||||
if (nblocks == 0) {
|
||||
(void) fprintf(stderr, "error: "
|
||||
"file is too small (min allowed size is %d bytes)\n",
|
||||
BLOCKSZ);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
srand48(getpid());
|
||||
for (int i = 0; i < BLOCKSZ; i++)
|
||||
randbuf[i] = lrand48();
|
||||
|
||||
distribution_n = 0;
|
||||
for (uint64_t i = 0;
|
||||
i < sizeof (size_distribution) / sizeof (size_distribution[0]);
|
||||
i++) {
|
||||
distribution_n += size_distribution[i];
|
||||
}
|
||||
|
||||
if (sequential)
|
||||
sequential_writes(fd, buf, nblocks, n);
|
||||
else
|
||||
random_writes(fd, buf, nblocks, n);
|
||||
|
||||
return (0);
|
||||
}
|
||||
Reference in New Issue
Block a user