mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Add the ZFS Test Suite
Add the ZFS Test Suite and test-runner framework from illumos.
This is a continuation of the work done by Turbo Fredriksson to
port the ZFS Test Suite to Linux. While this work was originally
conceived as a stand alone project integrating it directly with
the ZoL source tree has several advantages:
* Allows the ZFS Test Suite to be packaged in zfs-test package.
* Facilitates easy integration with the CI testing.
* Users can locally run the ZFS Test Suite to validate ZFS.
This testing should ONLY be done on a dedicated test system
because the ZFS Test Suite in its current form is destructive.
* Allows the ZFS Test Suite to be run directly in the ZoL source
tree enabled developers to iterate quickly during development.
* Developers can easily add/modify tests in the framework as
features are added or functionality is changed. The tests
will then always be in sync with the implementation.
Full documentation for how to run the ZFS Test Suite is available
in the tests/README.md file.
Warning: This test suite is designed to be run on a dedicated test
system. It will make modifications to the system including, but
not limited to, the following.
* Adding new users
* Adding new groups
* Modifying the following /proc files:
* /proc/sys/kernel/core_pattern
* /proc/sys/kernel/core_uses_pid
* Creating directories under /
Notes:
* Not all of the test cases are expected to pass and by default
these test cases are disabled. The failures are primarily due
to assumption made for illumos which are invalid under Linux.
* When updating these test cases it should be done in as generic
a way as possible so the patch can be submitted back upstream.
Most existing library functions have been updated to be Linux
aware, and the following functions and variables have been added.
* Functions:
* is_linux - Used to wrap a Linux specific section.
* block_device_wait - Waits for block devices to be added to /dev/.
* Variables: Linux Illumos
* ZVOL_DEVDIR "/dev/zvol" "/dev/zvol/dsk"
* ZVOL_RDEVDIR "/dev/zvol" "/dev/zvol/rdsk"
* DEV_DSKDIR "/dev" "/dev/dsk"
* DEV_RDSKDIR "/dev" "/dev/rdsk"
* NEWFS_DEFAULT_FS "ext2" "ufs"
* Many of the disabled test cases fail because 'zfs/zpool destroy'
returns EBUSY. This is largely causes by the asynchronous nature
of device handling on Linux and is expected, the impacted test
cases will need to be updated to handle this.
* There are several test cases which have been disabled because
they can trigger a deadlock. A primary example of this is to
recursively create zpools within zpools. These tests have been
disabled until the root issue can be addressed.
* Illumos specific utilities such as (mkfile) should be added to
the tests/zfs-tests/cmd/ directory. Custom programs required by
the test scripts can also be added here.
* SELinux should be either is permissive mode or disabled when
running the tests. The test cases should be updated to conform
to a standard policy.
* Redundant test functionality has been removed (zfault.sh).
* Existing test scripts (zconfig.sh) should be migrated to use
the framework for consistency and ease of testing.
* The DISKS environment variable currently only supports loopback
devices because of how the ZFS Test Suite expects partitions to
be named (p1, p2, etc). Support must be added to generate the
correct partition name based on the device location and name.
* The ZFS Test Suite is part of the illumos code base at:
https://github.com/illumos/illumos-gate/tree/master/usr/src/test
Original-patch-by: Turbo Fredriksson <turbo@bayour.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #6
Closes #1534
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
EXTRA_DIST = file_common.h
|
||||
|
||||
SUBDIRS = \
|
||||
chg_usr_exec \
|
||||
devname2devid \
|
||||
dir_rd_update \
|
||||
file_check \
|
||||
file_trunc \
|
||||
file_write \
|
||||
largest_file \
|
||||
mkbusy \
|
||||
mkfile \
|
||||
mkfiles \
|
||||
mktree \
|
||||
mmap_exec \
|
||||
mmapwrite \
|
||||
randfree_file \
|
||||
readmmap \
|
||||
rename_dir \
|
||||
rm_lnkcnt_zero_file \
|
||||
threadsappend \
|
||||
xattrtest
|
||||
@@ -0,0 +1 @@
|
||||
/chg_usr_exec
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = chg_usr_exec
|
||||
chg_usr_exec_SOURCES = chg_usr_exec.c
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#define EXECSHELL "/bin/sh"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *plogin = NULL;
|
||||
char cmds[BUFSIZ] = { 0 };
|
||||
char sep[] = " ";
|
||||
struct passwd *ppw = NULL;
|
||||
int i, len;
|
||||
|
||||
if (argc < 3 || strlen(argv[1]) == 0) {
|
||||
(void) printf("\tUsage: %s <login> <commands> ...\n", argv[0]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
plogin = argv[1];
|
||||
len = 0;
|
||||
for (i = 2; i < argc; i++) {
|
||||
(void) snprintf(cmds+len, sizeof (cmds)-len,
|
||||
"%s%s", argv[i], sep);
|
||||
len += strlen(argv[i]) + strlen(sep);
|
||||
}
|
||||
|
||||
if ((ppw = getpwnam(plogin)) == NULL) {
|
||||
perror("getpwnam");
|
||||
return (errno);
|
||||
}
|
||||
if (setgid(ppw->pw_gid) != 0) {
|
||||
perror("setgid");
|
||||
return (errno);
|
||||
}
|
||||
if (setuid(ppw->pw_uid) != 0) {
|
||||
perror("setuid");
|
||||
return (errno);
|
||||
}
|
||||
|
||||
if (execl(EXECSHELL, "sh", "-c", cmds, (char *)NULL) != 0) {
|
||||
perror("execl: " EXECSHELL);
|
||||
return (errno);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/devname2devid
|
||||
@@ -0,0 +1,7 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
# DISABLED: Not supported under Linux
|
||||
# pkgdata_PROGRAMS = devname2devid
|
||||
# devname2devid_SOURCES = devname2devid.c
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <devid.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/*
|
||||
* Usage: devname2devid <devicepath>
|
||||
*
|
||||
* Examples:
|
||||
* # ./devname2devid /dev/dsk/c1t4d0s0
|
||||
* devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/a
|
||||
* # ./devname2devid /dev/dsk/c1t4d0
|
||||
* devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/wd
|
||||
* # ./devname2devid /dev/dsk/c1t4d0s1
|
||||
* devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/b
|
||||
* #
|
||||
*
|
||||
* This program accepts a disk or disk slice path and prints a
|
||||
* device id.
|
||||
*
|
||||
* Exit values:
|
||||
* 0 - means success
|
||||
* 1 - means failure
|
||||
*
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
ddi_devid_t devid;
|
||||
char *minor_name, *devidstr, *device;
|
||||
#ifdef DEBUG
|
||||
devid_nmlist_t *list = NULL;
|
||||
char *search_path;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (argc == 1) {
|
||||
(void) printf("%s <devicepath> [search path]\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
device = argv[1];
|
||||
|
||||
if ((fd = open(device, O_RDONLY|O_NDELAY)) < 0) {
|
||||
perror(device);
|
||||
exit(1);
|
||||
}
|
||||
if (devid_get(fd, &devid) != 0) {
|
||||
perror("devid_get");
|
||||
exit(1);
|
||||
}
|
||||
if (devid_get_minor_name(fd, &minor_name) != 0) {
|
||||
perror("devid_get_minor_name");
|
||||
exit(1);
|
||||
}
|
||||
if ((devidstr = devid_str_encode(devid, minor_name)) == 0) {
|
||||
perror("devid_str_encode");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void) printf("devid %s\n", devidstr);
|
||||
|
||||
devid_str_free(devidstr);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (argc == 3) {
|
||||
search_path = argv[2];
|
||||
} else {
|
||||
search_path = "/dev/rdsk";
|
||||
}
|
||||
|
||||
if (devid_deviceid_to_nmlist(search_path, devid, DEVID_MINOR_NAME_ALL,
|
||||
&list)) {
|
||||
perror("devid_deviceid_to_nmlist");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* loop through list and process device names and numbers */
|
||||
for (i = 0; list[i].devname != NULL; i++) {
|
||||
(void) printf("devname: %s %p\n", list[i].devname, list[i].dev);
|
||||
}
|
||||
devid_free_nmlist(list);
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
devid_str_free(minor_name);
|
||||
devid_free(devid);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/dir_rd_update
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = dir_rd_update
|
||||
dir_rd_update_SOURCES = dir_rd_update.c
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assertion:
|
||||
*
|
||||
* A read operation and directory update operation performed
|
||||
* concurrently on the same directory can lead to deadlock
|
||||
* on a UFS logging file system, but not on a ZFS file system.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#define TMP_DIR /tmp
|
||||
|
||||
static char dirpath[256];
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *cp1 = "";
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
int testdd = 0;
|
||||
pid_t pid;
|
||||
static const int op_num = 5;
|
||||
|
||||
if (argc == 1) {
|
||||
(void) printf("Usage: %s <mount point>\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
dirpath[i] = 0;
|
||||
}
|
||||
|
||||
cp1 = argv[1];
|
||||
(void) strcpy(&dirpath[0], (const char *)cp1);
|
||||
(void) strcat(&dirpath[strlen(dirpath)], "TMP_DIR");
|
||||
|
||||
ret = mkdir(dirpath, 0777);
|
||||
if (ret != 0) {
|
||||
if (errno != EEXIST) {
|
||||
(void) printf("%s: mkdir(<%s>, 0777) failed: errno "
|
||||
"(decimal)=%d\n", argv[0], dirpath, errno);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
testdd = open(dirpath, O_RDONLY|O_RSYNC|O_SYNC|O_DSYNC);
|
||||
if (testdd < 0) {
|
||||
(void) printf("%s: open(<%s>, O_RDONLY|O_RSYNC|O_SYNC|O_DSYNC)"
|
||||
" failed: errno (decimal)=%d\n", argv[0], dirpath, errno);
|
||||
exit(-1);
|
||||
} else {
|
||||
(void) close(testdd);
|
||||
}
|
||||
pid = fork();
|
||||
if (pid > 0) {
|
||||
int fd = open(dirpath, O_RDONLY|O_RSYNC|O_SYNC|O_DSYNC);
|
||||
char buf[16];
|
||||
int rdret;
|
||||
int j = 0;
|
||||
|
||||
while (j < op_num) {
|
||||
(void) sleep(1);
|
||||
rdret = read(fd, buf, 16);
|
||||
if (rdret == -1) {
|
||||
(void) printf("readdir failed");
|
||||
}
|
||||
j++;
|
||||
}
|
||||
} else if (pid == 0) {
|
||||
int fd = open(dirpath, O_RDONLY);
|
||||
int chownret;
|
||||
int k = 0;
|
||||
|
||||
while (k < op_num) {
|
||||
(void) sleep(1);
|
||||
chownret = fchown(fd, 0, 0);
|
||||
if (chownret == -1) {
|
||||
(void) printf("chown failed");
|
||||
}
|
||||
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/file_check
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = file_check
|
||||
file_check_SOURCES = file_check.c
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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;
|
||||
int64_t read_count = 0;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
read_count += n;
|
||||
} while (n == bigbuffersize);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.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 @@
|
||||
/file_trunc
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = file_trunc
|
||||
file_trunc_SOURCES = file_trunc.c
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/errno.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);
|
||||
}
|
||||
|
||||
while (i < count) {
|
||||
(void) do_write(fd);
|
||||
(void) do_trunc(fd);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
(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);
|
||||
}
|
||||
|
||||
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 @@
|
||||
/file_write
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = file_write
|
||||
file_write_SOURCES = file_write.c
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
typedef unsigned char uchar_t;
|
||||
typedef long long longlong_t;
|
||||
typedef longlong_t offset_t;
|
||||
|
||||
static unsigned char bigbuffer[BIGBUFFERSIZE];
|
||||
|
||||
/*
|
||||
* Writes (or appends) a given value to a file repeatedly.
|
||||
* See header file for defaults.
|
||||
*/
|
||||
|
||||
static void usage(char *);
|
||||
|
||||
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':
|
||||
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);
|
||||
|
||||
/*
|
||||
* Prepare the buffer and determine the requested operation
|
||||
*/
|
||||
nxtfillchar = fillchar;
|
||||
k = 0;
|
||||
|
||||
for (i = 0; i < block_size; i++) {
|
||||
bigbuffer[i] = nxtfillchar;
|
||||
|
||||
if (fillchar == 0) {
|
||||
if ((k % DATA_RANGE) == 0) {
|
||||
k = 0;
|
||||
}
|
||||
nxtfillchar = k++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, data = %s%d\n", filename, block_size,
|
||||
write_count, offset,
|
||||
(fillchar == 0) ? "0->" : "",
|
||||
(fillchar == 0) ? DATA_RANGE : fillchar);
|
||||
}
|
||||
|
||||
for (i = 0; i < write_count; i++) {
|
||||
ssize_t n;
|
||||
|
||||
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"
|
||||
"\twhere [data] equal to zero causes chars "
|
||||
"0->%d to be repeated throughout\n", prog, DATA_RANGE);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/largest_file
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = largest_file
|
||||
largest_file_SOURCES = largest_file.c
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef long long offset_t;
|
||||
#define MAXOFFSET_T LLONG_MAX
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
*
|
||||
* 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];
|
||||
char *testfile;
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
(void) sigset(SIGXFSZ, sigxfsz);
|
||||
|
||||
testfile = strdup(argv[1]);
|
||||
|
||||
fd = open(testfile, O_CREAT | O_RDWR, mode);
|
||||
if (fd < 0) {
|
||||
perror("Failed to create testfile");
|
||||
err = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
llseek_ret = lseek64(fd, offset, SEEK_SET);
|
||||
if (llseek_ret < 0) {
|
||||
perror("Failed to seek to end of testfile");
|
||||
err = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_ret = write(fd, mybuf, 1);
|
||||
if (write_ret < 0) {
|
||||
perror("Failed to write to end of file");
|
||||
err = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
llseek_ret = lseek64(fd, offset, SEEK_CUR);
|
||||
if (llseek_ret < 0) {
|
||||
perror("Failed to seek to end of file");
|
||||
err = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_ret = write(fd, mybuf, 1);
|
||||
if (write_ret < 0) {
|
||||
if (errno == EFBIG) {
|
||||
(void) printf("write errno=EFBIG: success\n");
|
||||
err = 0;
|
||||
} else {
|
||||
perror("Did not receive EFBIG");
|
||||
err = errno;
|
||||
}
|
||||
} else {
|
||||
(void) printf("write completed successfully, test failed\n");
|
||||
err = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
(void) unlink(testfile);
|
||||
free(testfile);
|
||||
return (err);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(char *name)
|
||||
{
|
||||
(void) printf("%s <testfile>\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
sigxfsz(int signo)
|
||||
{
|
||||
(void) printf("\nlargest_file: sigxfsz() caught SIGXFSZ\n");
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mkbusy
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = mkbusy
|
||||
mkbusy_SOURCES = mkbusy.c
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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) 2012 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Make a directory busy. If the argument is an existing file or directory,
|
||||
* simply open it directly and pause. If not, verify that the parent directory
|
||||
* exists, and create a new file in that directory.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef enum boolean { B_FALSE, B_TRUE } boolean_t;
|
||||
|
||||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
(void) fprintf(stderr, "Usage: %s <dirname|filename>\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
fail(char *err, int rval)
|
||||
{
|
||||
perror(err);
|
||||
exit(rval);
|
||||
}
|
||||
|
||||
static void
|
||||
daemonize(void)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
fail("fork", 1);
|
||||
} else if (pid != 0) {
|
||||
(void) fprintf(stdout, "%ld\n", (long)pid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
(void) setsid();
|
||||
(void) close(0);
|
||||
(void) close(1);
|
||||
(void) close(2);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ret, c;
|
||||
boolean_t isdir = B_FALSE;
|
||||
boolean_t fflag = B_FALSE;
|
||||
boolean_t rflag = B_FALSE;
|
||||
struct stat sbuf;
|
||||
char *fpath = NULL;
|
||||
char *prog = argv[0];
|
||||
|
||||
while ((c = getopt(argc, argv, "fr")) != -1) {
|
||||
switch (c) {
|
||||
/* Open the file or directory read only */
|
||||
case 'r':
|
||||
rflag = B_TRUE;
|
||||
break;
|
||||
/* Run in the foreground */
|
||||
case 'f':
|
||||
fflag = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
usage(prog);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1)
|
||||
usage(prog);
|
||||
|
||||
if ((ret = stat(argv[0], &sbuf)) != 0) {
|
||||
char *arg, *dname, *fname;
|
||||
int arglen, dlen, flen;
|
||||
char *slash;
|
||||
|
||||
/*
|
||||
* The argument supplied doesn't exist. Copy the path, and
|
||||
* remove the trailing slash if presnt.
|
||||
*/
|
||||
if ((arg = strdup(argv[0])) == NULL)
|
||||
fail("strdup", 1);
|
||||
arglen = strlen(arg);
|
||||
if (arg[arglen - 1] == '/')
|
||||
arg[arglen - 1] = '\0';
|
||||
|
||||
/*
|
||||
* Get the directory and file names, using the current directory
|
||||
* if the provided path doesn't specify a directory at all.
|
||||
*/
|
||||
if ((slash = strrchr(arg, '/')) == NULL) {
|
||||
dname = strdup(".");
|
||||
fname = strdup(arg);
|
||||
} else {
|
||||
*slash = '\0';
|
||||
dname = strdup(arg);
|
||||
fname = strdup(slash + 1);
|
||||
}
|
||||
free(arg);
|
||||
if (dname == NULL || fname == NULL)
|
||||
fail("strdup", 1);
|
||||
dlen = strlen(dname);
|
||||
flen = strlen(fname);
|
||||
|
||||
/* The directory portion of the path must exist */
|
||||
if ((ret = stat(dname, &sbuf)) != 0 || !(sbuf.st_mode &
|
||||
S_IFDIR))
|
||||
usage(prog);
|
||||
|
||||
if ((fpath = (char *)malloc(dlen + 1 + flen + 1)) == NULL)
|
||||
fail("malloc", 1);
|
||||
(void) memset(fpath, '\0', dlen + 1 + flen + 1);
|
||||
|
||||
(void) strncpy(fpath, dname, dlen);
|
||||
fpath[dlen] = '/';
|
||||
(void) strncat(fpath, fname, flen);
|
||||
free(dname);
|
||||
free(fname);
|
||||
} else if ((sbuf.st_mode & S_IFMT) == S_IFREG ||
|
||||
(sbuf.st_mode & S_IFMT) == S_IFLNK ||
|
||||
(sbuf.st_mode & S_IFMT) == S_IFCHR ||
|
||||
(sbuf.st_mode & S_IFMT) == S_IFBLK) {
|
||||
fpath = strdup(argv[0]);
|
||||
} else if ((sbuf.st_mode & S_IFMT) == S_IFDIR) {
|
||||
fpath = strdup(argv[0]);
|
||||
isdir = B_TRUE;
|
||||
} else {
|
||||
usage(prog);
|
||||
}
|
||||
|
||||
if (fpath == NULL)
|
||||
fail("strdup", 1);
|
||||
|
||||
if (isdir == B_FALSE) {
|
||||
int fd, flags;
|
||||
mode_t mode = S_IRUSR | S_IWUSR;
|
||||
|
||||
flags = rflag == B_FALSE ? O_CREAT | O_RDWR : O_RDONLY;
|
||||
|
||||
if ((fd = open(fpath, flags, mode)) < 0)
|
||||
fail("open", 1);
|
||||
} else {
|
||||
DIR *dp;
|
||||
|
||||
if ((dp = opendir(fpath)) == NULL)
|
||||
fail("opendir", 1);
|
||||
}
|
||||
free(fpath);
|
||||
|
||||
if (fflag == B_FALSE)
|
||||
daemonize();
|
||||
(void) pause();
|
||||
|
||||
/* NOTREACHED */
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mkfile
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = mkfile
|
||||
mkfile_SOURCES = mkfile.c
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (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 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libintl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define BLOCK_SIZE 512 /* bytes */
|
||||
#define KILOBYTE 1024
|
||||
#define MEGABYTE (KILOBYTE * KILOBYTE)
|
||||
#define GIGABYTE (KILOBYTE * MEGABYTE)
|
||||
|
||||
#define FILE_MODE (S_ISVTX + S_IRUSR + S_IWUSR)
|
||||
|
||||
typedef long long offset_t;
|
||||
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *opts;
|
||||
off_t size;
|
||||
size_t len;
|
||||
size_t mult = 1;
|
||||
char *buf = NULL;
|
||||
size_t bufsz = 0;
|
||||
int errors = 0;
|
||||
int i;
|
||||
int verbose = 0; /* option variable */
|
||||
int nobytes = 0; /* option variable */
|
||||
int saverr;
|
||||
|
||||
if (argc == 1)
|
||||
usage();
|
||||
|
||||
while (argv[1] && argv[1][0] == '-') {
|
||||
opts = &argv[1][0];
|
||||
while (*(++opts)) {
|
||||
switch (*opts) {
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'n':
|
||||
nobytes++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if (argc < 3)
|
||||
usage();
|
||||
|
||||
len = strlen(argv[1]);
|
||||
if (len && isalpha(argv[1][len-1])) {
|
||||
switch (argv[1][len-1]) {
|
||||
case 'k':
|
||||
case 'K':
|
||||
mult = KILOBYTE;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
mult = BLOCK_SIZE;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
mult = MEGABYTE;
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
mult = GIGABYTE;
|
||||
break;
|
||||
default:
|
||||
(void) fprintf(stderr,
|
||||
gettext("unknown size %s\n"), argv[1]);
|
||||
usage();
|
||||
}
|
||||
|
||||
for (i = 0; i <= (len-2); i++) {
|
||||
if (!isdigit(argv[1][i])) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("unknown size %s\n"), argv[1]);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argv[1][len-1] = '\0';
|
||||
}
|
||||
size = ((off_t)atoll(argv[1]) * (off_t)mult);
|
||||
|
||||
argv++;
|
||||
argc--;
|
||||
|
||||
while (argc > 1) {
|
||||
int fd;
|
||||
|
||||
if (verbose)
|
||||
(void) fprintf(stdout, gettext("%s %lld bytes\n"),
|
||||
argv[1], (offset_t)size);
|
||||
fd = open(argv[1], O_CREAT|O_TRUNC|O_RDWR, FILE_MODE);
|
||||
if (fd < 0) {
|
||||
saverr = errno;
|
||||
(void) fprintf(stderr,
|
||||
gettext("Could not open %s: %s\n"),
|
||||
argv[1], strerror(saverr));
|
||||
errors++;
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
if (lseek(fd, (off_t)size-1, SEEK_SET) < 0) {
|
||||
saverr = errno;
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Could not seek to offset %ld in %s: %s\n"),
|
||||
(unsigned long)size-1, argv[1], strerror(saverr));
|
||||
(void) close(fd);
|
||||
errors++;
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
} else if (write(fd, "", 1) != 1) {
|
||||
saverr = errno;
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Could not set length of %s: %s\n"),
|
||||
argv[1], strerror(saverr));
|
||||
(void) close(fd);
|
||||
errors++;
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!nobytes) {
|
||||
off_t written = 0;
|
||||
struct stat64 st;
|
||||
|
||||
if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
|
||||
saverr = errno;
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Could not seek to beginning of %s: %s\n"),
|
||||
argv[1], strerror(saverr));
|
||||
(void) close(fd);
|
||||
errors++;
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
if (fstat64(fd, &st) < 0) {
|
||||
saverr = errno;
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Could not fstat64 %s: %s\n"),
|
||||
argv[1], strerror(saverr));
|
||||
(void) close(fd);
|
||||
errors++;
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
if (bufsz != st.st_blksize) {
|
||||
if (buf)
|
||||
free(buf);
|
||||
bufsz = (size_t)st.st_blksize;
|
||||
buf = calloc(bufsz, 1);
|
||||
if (buf == NULL) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Could not allocate buffer of"
|
||||
" size %d\n"), (int)bufsz);
|
||||
(void) close(fd);
|
||||
bufsz = 0;
|
||||
errors++;
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (written < size) {
|
||||
ssize_t result;
|
||||
size_t bytes = (size_t)MIN(bufsz, size-written);
|
||||
|
||||
if ((result = write(fd, buf, bytes)) !=
|
||||
(ssize_t)bytes) {
|
||||
saverr = errno;
|
||||
if (result < 0)
|
||||
result = 0;
|
||||
written += result;
|
||||
(void) fprintf(stderr, gettext(
|
||||
"%s: initialized %lu of %lu bytes: %s\n"),
|
||||
argv[1], (unsigned long)written,
|
||||
(unsigned long)size,
|
||||
strerror(saverr));
|
||||
errors++;
|
||||
break;
|
||||
}
|
||||
written += bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* A write(2) call in the above loop failed so
|
||||
* close out this file and go on (error was
|
||||
* already incremented when the write(2) failed).
|
||||
*/
|
||||
if (written < size) {
|
||||
(void) close(fd);
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (close(fd) < 0) {
|
||||
saverr = errno;
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Error encountered when closing %s: %s\n"),
|
||||
argv[1], strerror(saverr));
|
||||
errors++;
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only set the modes (including the sticky bit) if we
|
||||
* had no problems. It is not an error for the chmod(2)
|
||||
* to fail, but do issue a warning.
|
||||
*/
|
||||
if (chmod(argv[1], FILE_MODE) < 0)
|
||||
(void) fprintf(stderr, gettext(
|
||||
"warning: couldn't set mode to %#o\n"), FILE_MODE);
|
||||
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
return (errors);
|
||||
}
|
||||
|
||||
static void usage()
|
||||
{
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Usage: mkfile [-nv] <size>[g|k|b|m] <name1> [<name2>] ...\n"));
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mkfiles
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = mkfiles
|
||||
mkfiles_SOURCES = mkfiles.c
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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) 2016 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#define MAX_INT_LENGTH 10
|
||||
|
||||
static void
|
||||
usage(char *msg, int exit_value)
|
||||
{
|
||||
(void) fprintf(stderr, "mkfiles basename max_file [min_file]\n");
|
||||
(void) fprintf(stderr, "%s\n", msg);
|
||||
exit(exit_value);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
unsigned int numfiles = 0;
|
||||
unsigned int first_file = 0;
|
||||
unsigned int i;
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
if (argc < 3 || argc > 4)
|
||||
usage("Invalid number of arguments", -1);
|
||||
|
||||
if (sscanf(argv[2], "%u", &numfiles) != 1)
|
||||
usage("Invalid maximum file", -2);
|
||||
|
||||
if (argc == 4 && sscanf(argv[3], "%u", &first_file) != 1)
|
||||
usage("Invalid first file", -3);
|
||||
|
||||
if (numfiles < first_file)
|
||||
usage("First file larger than last file", -3);
|
||||
|
||||
for (i = first_file; i <= numfiles; i++) {
|
||||
int fd;
|
||||
(void) snprintf(buf, MAXPATHLEN, "%s%u", argv[1], i);
|
||||
if ((fd = open(buf, O_CREAT | O_EXCL, O_RDWR)) == -1) {
|
||||
(void) fprintf(stderr, "Failed to create %s %s\n", buf,
|
||||
strerror(errno));
|
||||
return (-4);
|
||||
}
|
||||
(void) close(fd);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mktree
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = mktree
|
||||
mktree_SOURCES = mktree.c
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <attr/xattr.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#define TYPE_D 'D'
|
||||
#define TYPE_F 'F'
|
||||
|
||||
static char fdname[MAXPATHLEN] = {0};
|
||||
static char *pbasedir = NULL;
|
||||
static int nlevel = 2;
|
||||
static int ndir = 2;
|
||||
static int nfile = 2;
|
||||
|
||||
static void usage(char *this);
|
||||
static void crtfile(char *pname);
|
||||
static char *getfdname(char *pdir, char type, int level, int dir, int file);
|
||||
static int mktree(char *pbasedir, int level);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c, ret;
|
||||
|
||||
while ((c = getopt(argc, argv, "b:l:d:f:")) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
pbasedir = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
nlevel = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
ndir = atoi(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
nfile = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
if (nlevel < 0 || ndir < 0 || nfile < 0 || pbasedir == NULL) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
ret = mktree(pbasedir, 1);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(char *this)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"\tUsage: %s -b <base_dir> -l [nlevel] -d [ndir] -f [nfile]\n",
|
||||
this);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
mktree(char *pdir, int level)
|
||||
{
|
||||
int d, f;
|
||||
char dname[MAXPATHLEN] = {0};
|
||||
char fname[MAXPATHLEN] = {0};
|
||||
|
||||
if (level > nlevel) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
for (d = 0; d < ndir; d++) {
|
||||
(void) memset(dname, '\0', sizeof (dname));
|
||||
(void) strcpy(dname, getfdname(pdir, TYPE_D, level, d, 0));
|
||||
|
||||
if (mkdir(dname, 0777) != 0) {
|
||||
(void) fprintf(stderr, "mkdir(%s) failed."
|
||||
"\n[%d]: %s.\n",
|
||||
dname, errno, strerror(errno));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* No sub-directory need be created, only create files in it.
|
||||
*/
|
||||
if (mktree(dname, level+1) != 0) {
|
||||
for (f = 0; f < nfile; f++) {
|
||||
(void) memset(fname, '\0', sizeof (fname));
|
||||
(void) strcpy(fname,
|
||||
getfdname(dname, TYPE_F, level+1, d, f));
|
||||
crtfile(fname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (f = 0; f < nfile; f++) {
|
||||
(void) memset(fname, '\0', sizeof (fname));
|
||||
(void) strcpy(fname, getfdname(pdir, TYPE_F, level, d, f));
|
||||
crtfile(fname);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char *
|
||||
getfdname(char *pdir, char type, int level, int dir, int file)
|
||||
{
|
||||
(void) snprintf(fdname, sizeof (fdname),
|
||||
"%s/%c-l%dd%df%d", pdir, type, level, dir, file);
|
||||
return (fdname);
|
||||
}
|
||||
|
||||
static void
|
||||
crtfile(char *pname)
|
||||
{
|
||||
int fd = -1;
|
||||
int i, size;
|
||||
char *context = "0123456789ABCDF";
|
||||
char *pbuf;
|
||||
|
||||
if (pname == NULL) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size = sizeof (char) * 1024;
|
||||
pbuf = (char *)valloc(size);
|
||||
for (i = 0; i < size / strlen(context); i++) {
|
||||
int offset = i * strlen(context);
|
||||
(void) snprintf(pbuf+offset, size-offset, "%s", context);
|
||||
}
|
||||
|
||||
if ((fd = open(pname, O_CREAT|O_RDWR, 0777)) < 0) {
|
||||
(void) fprintf(stderr, "open(%s, O_CREAT|O_RDWR, 0777) failed."
|
||||
"\n[%d]: %s.\n", pname, errno, strerror(errno));
|
||||
exit(errno);
|
||||
}
|
||||
if (write(fd, pbuf, 1024) < 1024) {
|
||||
(void) fprintf(stderr, "write(fd, pbuf, 1024) failed."
|
||||
"\n[%d]: %s.\n", errno, strerror(errno));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
if (fsetxattr(fd, "xattr", pbuf, 1024, 0) < 0) {
|
||||
(void) fprintf(stderr, "fsetxattr(fd, \"xattr\", pbuf, "
|
||||
"1024, 0) failed.\n[%d]: %s.\n", errno, strerror(errno));
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
free(pbuf);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mmap_exec
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = mmap_exec
|
||||
mmap_exec_SOURCES = mmap_exec.c
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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) 2013 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
struct stat statbuf;
|
||||
|
||||
if (argc != 2) {
|
||||
(void) printf("Error: missing binary name.\n");
|
||||
(void) printf("Usage:\n\t%s <binary name>\n",
|
||||
argv[0]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
if ((fd = open(argv[1], O_RDONLY)) < 0) {
|
||||
perror("open");
|
||||
return (errno);
|
||||
}
|
||||
if (fstat(fd, &statbuf) < 0) {
|
||||
perror("fstat");
|
||||
return (errno);
|
||||
}
|
||||
|
||||
if (mmap(0, statbuf.st_size,
|
||||
PROT_EXEC, MAP_SHARED, fd, 0) == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return (errno);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/mmapwrite
|
||||
@@ -0,0 +1,7 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = mmapwrite
|
||||
mmapwrite_SOURCES = mmapwrite.c
|
||||
mmapwrite_LDADD = -lpthread
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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 <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* Bug Id: 5032643
|
||||
*
|
||||
* Simply writing to a file and mmaping that file at the same time can
|
||||
* result in deadlock. Nothing perverse like writing from the file's
|
||||
* own mapping is required.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void *
|
||||
mapper(void *fdp)
|
||||
{
|
||||
void *addr;
|
||||
int fd = *(int *)fdp;
|
||||
|
||||
if ((addr =
|
||||
mmap(0, 8192, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
for (;;) {
|
||||
if (mmap(addr, 8192, PROT_READ,
|
||||
MAP_SHARED|MAP_FIXED, fd, 0) == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return ((void *)1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
char buf[BUFSIZ];
|
||||
pthread_t tid;
|
||||
|
||||
if (argc != 2) {
|
||||
(void) printf("usage: %s <file name>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void) pthread_setconcurrency(2);
|
||||
if (pthread_create(&tid, NULL, mapper, &fd) != 0) {
|
||||
perror("pthread_create");
|
||||
exit(1);
|
||||
}
|
||||
for (;;) {
|
||||
if (write(fd, buf, sizeof (buf)) == -1) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/randfree_file
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = randfree_file
|
||||
randfree_file_SOURCES = randfree_file.c
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 <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;
|
||||
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]);
|
||||
|
||||
buf = (char *)malloc(filesize);
|
||||
|
||||
if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0) {
|
||||
perror("open");
|
||||
return (1);
|
||||
}
|
||||
if (write(fd, buf, filesize) < filesize) {
|
||||
perror("write");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
||||
start_off, off_len) < 0) {
|
||||
perror("fallocate");
|
||||
return (1);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/readmmap
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = readmmap
|
||||
readmmap_SOURCES = readmmap.c
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
* BugId 5047993 : Getting bad read data.
|
||||
*
|
||||
* Usage: readmmap <filename>
|
||||
*
|
||||
* where:
|
||||
* filename is an absolute path to the file name.
|
||||
*
|
||||
* Return values:
|
||||
* 1 : error
|
||||
* 0 : no errors
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *filename = "badfile";
|
||||
size_t size = 4395;
|
||||
size_t idx = 0;
|
||||
char *buf = NULL;
|
||||
char *map = NULL;
|
||||
int fd = -1, bytes, retval = 0;
|
||||
unsigned seed;
|
||||
|
||||
if (argc < 2 || optind == argc) {
|
||||
(void) fprintf(stderr,
|
||||
"usage: %s <file name>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((buf = calloc(1, size)) == NULL) {
|
||||
perror("calloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
filename = argv[optind];
|
||||
|
||||
(void) remove(filename);
|
||||
|
||||
fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
perror("open to create");
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
bytes = write(fd, buf, size);
|
||||
if (bytes != size) {
|
||||
(void) printf("short write: %d != %zd\n", bytes, size);
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
map = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (map == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
seed = time(NULL);
|
||||
srandom(seed);
|
||||
|
||||
idx = random() % size;
|
||||
map[idx] = 1;
|
||||
|
||||
if (msync(map, size, MS_SYNC) != 0) {
|
||||
perror("msync");
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (munmap(map, size) != 0) {
|
||||
perror("munmap");
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
bytes = pread(fd, buf, size, 0);
|
||||
if (bytes != size) {
|
||||
(void) printf("short read: %d != %zd\n", bytes, size);
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (buf[idx] != 1) {
|
||||
(void) printf(
|
||||
"bad data from read! got buf[%zd]=%d, expected 1\n",
|
||||
idx, buf[idx]);
|
||||
retval = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
(void) printf("good data from read: buf[%zd]=1\n", idx);
|
||||
end:
|
||||
if (fd != -1) {
|
||||
(void) close(fd);
|
||||
}
|
||||
if (buf != NULL) {
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return (retval);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/rename_dir
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = rename_dir
|
||||
rename_dir_SOURCES = rename_dir.c
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assertion:
|
||||
* Create two directory trees in zfs filesystem, and rename
|
||||
* directory across the directory structure. ZFS can handle
|
||||
* the race situation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Need to create the following directory structures before
|
||||
* running this program:
|
||||
*
|
||||
* mkdir -p 1/2/3/4/5 a/b/c/d/e
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argvp[])
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
break;
|
||||
case 0:
|
||||
while (i > 0) {
|
||||
int c_count = 0;
|
||||
if (rename("a/b/c", "1/2/3/c") == 0)
|
||||
c_count++;
|
||||
if (rename("1/2/3/c", "a/b/c") == 0)
|
||||
c_count++;
|
||||
if (c_count) {
|
||||
(void) fprintf(stderr, "c_count: %d", c_count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
while (i > 0) {
|
||||
int p_count = 0;
|
||||
if (rename("1", "a/b/c/d/e/1") == 0)
|
||||
p_count++;
|
||||
if (rename("a/b/c/d/e/1", "1") == 0)
|
||||
p_count++;
|
||||
if (p_count) {
|
||||
(void) fprintf(stderr, "p_count: %d", p_count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/rm_lnkcnt_zero_file
|
||||
@@ -0,0 +1,7 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = rm_lnkcnt_zero_file
|
||||
rm_lnkcnt_zero_file_SOURCES = rm_lnkcnt_zero_file.c
|
||||
rm_lnkcnt_zero_file_LDADD = -lpthread
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
* The purpose of this test is to see if the bug reported (#4723351) for
|
||||
* UFS exists when using a ZFS file system.
|
||||
* --------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
#define _REENTRANT 1
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
|
||||
static const int TRUE = 1;
|
||||
static char *filebase;
|
||||
|
||||
static int
|
||||
pickidx(void)
|
||||
{
|
||||
return (random() % 1000);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
mover(void *a)
|
||||
{
|
||||
char buf[256];
|
||||
int idx, len, ret;
|
||||
|
||||
len = strlen(filebase) + 5;
|
||||
|
||||
while (TRUE) {
|
||||
idx = pickidx();
|
||||
(void) snprintf(buf, len, "%s.%03d", filebase, idx);
|
||||
ret = rename(filebase, buf);
|
||||
if (ret < 0 && errno != ENOENT)
|
||||
(void) perror("renaming file");
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
cleaner(void *a)
|
||||
{
|
||||
char buf[256];
|
||||
int idx, len, ret;
|
||||
|
||||
len = strlen(filebase) + 5;
|
||||
|
||||
while (TRUE) {
|
||||
idx = pickidx();
|
||||
(void) snprintf(buf, len, "%s.%03d", filebase, idx);
|
||||
ret = remove(buf);
|
||||
if (ret < 0 && errno != ENOENT)
|
||||
(void) perror("removing file");
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void *
|
||||
writer(void *a)
|
||||
{
|
||||
int *fd = (int *)a;
|
||||
int ret;
|
||||
|
||||
while (TRUE) {
|
||||
(void) close (*fd);
|
||||
*fd = open(filebase, O_APPEND | O_RDWR | O_CREAT, 0644);
|
||||
if (*fd < 0)
|
||||
perror("refreshing file");
|
||||
ret = write(*fd, "test\n", 5);
|
||||
if (ret != 5)
|
||||
perror("writing file");
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
pthread_t tid;
|
||||
|
||||
if (argc == 1) {
|
||||
(void) printf("Usage: %s <filebase>\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
filebase = argv[1];
|
||||
fd = open(filebase, O_APPEND | O_RDWR | O_CREAT, 0644);
|
||||
if (fd < 0) {
|
||||
perror("creating test file");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
(void) pthread_setconcurrency(4); /* 3 threads + main */
|
||||
(void) pthread_create(&tid, NULL, mover, NULL);
|
||||
(void) pthread_create(&tid, NULL, cleaner, NULL);
|
||||
(void) pthread_create(&tid, NULL, writer, (void *) &fd);
|
||||
|
||||
while (TRUE) {
|
||||
int ret;
|
||||
struct stat st;
|
||||
|
||||
ret = stat(filebase, &st);
|
||||
if (ret == 0 && (st.st_nlink > 2 || st.st_nlink < 1)) {
|
||||
(void) printf("st.st_nlink = %d, exiting\n", \
|
||||
(int)st.st_nlink);
|
||||
exit(0);
|
||||
}
|
||||
(void) sleep(1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/threadsappend
|
||||
@@ -0,0 +1,7 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = threadsappend
|
||||
threadsappend_SOURCES = threadsappend.c
|
||||
threadsappend_LDADD = -lpthread
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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) 2013 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* The size of the output file, "go.out", should be 80*8192*2 = 1310720
|
||||
*
|
||||
* $ cd /tmp; go; ls -l go.out
|
||||
* done.
|
||||
* -rwxr-xr-x 1 jdm staff 1310720 Apr 13 19:45 go.out
|
||||
* $ cd /zfs; go; ls -l go.out
|
||||
* done.
|
||||
* -rwxr-xr-x 1 jdm staff 663552 Apr 13 19:45 go.out
|
||||
*
|
||||
* The file on zfs is short as it does not appear that zfs is making the
|
||||
* implicit seek to EOF and the actual write atomic. From the SUSv3
|
||||
* interface spec, behavior is undefined if concurrent writes are performed
|
||||
* from multi-processes to a single file. So I don't know if this is a
|
||||
* standards violation, but I cannot find any such disclaimers in our
|
||||
* man pages. This issue came up at a customer site in another context, and
|
||||
* the suggestion was to open the file with O_APPEND, but that wouldn't
|
||||
* help with zfs(see 4977529). Also see bug# 5031301.
|
||||
*/
|
||||
|
||||
static int outfd = 0;
|
||||
|
||||
static void *
|
||||
go(void *data)
|
||||
{
|
||||
int ret, i = 0, n = *(int *)data;
|
||||
char buf[8192] = {0};
|
||||
(void) memset(buf, n, sizeof (buf));
|
||||
|
||||
for (i = 0; i < 80; i++) {
|
||||
ret = write(outfd, buf, sizeof (buf));
|
||||
if (ret != sizeof (buf))
|
||||
perror("write");
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage: zfs_threadsappend <file name>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
pthread_t tid;
|
||||
int ret = 0;
|
||||
long ncpus = 0;
|
||||
int i;
|
||||
|
||||
if (argc != 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (ncpus < 0) {
|
||||
(void) fprintf(stderr,
|
||||
"Invalid return from sysconf(_SC_NPROCESSORS_ONLN)"
|
||||
" : errno (decimal)=%d\n", errno);
|
||||
exit(1);
|
||||
}
|
||||
if (ncpus < 2) {
|
||||
(void) fprintf(stderr,
|
||||
"Must execute this binary on a multi-processor system\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
outfd = open(argv[optind++], O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777);
|
||||
if (outfd == -1) {
|
||||
(void) fprintf(stderr,
|
||||
"zfs_threadsappend: "
|
||||
"open(%s, O_RDWR|O_CREAT|O_APPEND|O_TRUNC, 0777)"
|
||||
" failed\n", argv[optind]);
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ret = pthread_create(&tid, NULL, go, (void *)&i);
|
||||
if (ret != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"zfs_threadsappend: thr_create(#%d) "
|
||||
"failed error=%d\n", i+1, ret);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
while (pthread_join(tid, NULL) == 0)
|
||||
continue;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/xattrtest
|
||||
@@ -0,0 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
pkgexec_PROGRAMS = xattrtest
|
||||
xattrtest_SOURCES = xattrtest.c
|
||||
@@ -0,0 +1,641 @@
|
||||
/*
|
||||
* 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 2016 Lawrence Livermore National Security, LLC.
|
||||
*/
|
||||
|
||||
/*
|
||||
* An extended attribute (xattr) correctness test. This program creates
|
||||
* N files and sets M attrs on them of size S. Optionally is will verify
|
||||
* a pattern stored in the xattr.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <attr/xattr.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
extern char *program_invocation_short_name;
|
||||
|
||||
#define ERROR(fmt, ...) \
|
||||
fprintf(stderr, "%s: %s:%d: %s: " fmt "\n", \
|
||||
program_invocation_short_name, __FILE__, __LINE__, \
|
||||
__func__, ## __VA_ARGS__);
|
||||
|
||||
static const char shortopts[] = "hvycdn:f:x:s:p:t:e:rRk";
|
||||
static const struct option longopts[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "verbose", no_argument, 0, 'v' },
|
||||
{ "verify", no_argument, 0, 'y' },
|
||||
{ "nth", required_argument, 0, 'n' },
|
||||
{ "files", required_argument, 0, 'f' },
|
||||
{ "xattrs", required_argument, 0, 'x' },
|
||||
{ "size", required_argument, 0, 's' },
|
||||
{ "path", required_argument, 0, 'p' },
|
||||
{ "synccaches", no_argument, 0, 'c' },
|
||||
{ "dropcaches", no_argument, 0, 'd' },
|
||||
{ "script", required_argument, 0, 't' },
|
||||
{ "seed", required_argument, 0, 'e' },
|
||||
{ "random", no_argument, 0, 'r' },
|
||||
{ "randomvalue", no_argument, 0, 'R' },
|
||||
{ "keep", no_argument, 0, 'k' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static int verbose = 0;
|
||||
static int verify = 0;
|
||||
static int synccaches = 0;
|
||||
static int dropcaches = 0;
|
||||
static int nth = 0;
|
||||
static int files = 1000;
|
||||
static int xattrs = 1;
|
||||
static int size = 1;
|
||||
static int size_is_random = 0;
|
||||
static int value_is_random = 0;
|
||||
static int keep_files = 0;
|
||||
static char path[PATH_MAX] = "/tmp/xattrtest";
|
||||
static char script[PATH_MAX] = "/bin/true";
|
||||
|
||||
static int
|
||||
usage(int argc, char **argv) {
|
||||
fprintf(stderr,
|
||||
"usage: %s [-hvycdrRk] [-n <nth>] [-f <files>] [-x <xattrs>]\n"
|
||||
" [-s <bytes>] [-p <path>] [-t <script> ]\n", argv[0]);
|
||||
fprintf(stderr,
|
||||
" --help -h This help\n"
|
||||
" --verbose -v Increase verbosity\n"
|
||||
" --verify -y Verify xattr contents\n"
|
||||
" --nth -n <nth> Print every nth file\n"
|
||||
" --files -f <files> Set xattrs on N files\n"
|
||||
" --xattrs -x <xattrs> Set N xattrs on each file\n"
|
||||
" --size -s <bytes> Set N bytes per xattr\n"
|
||||
" --path -p <path> Path to files\n"
|
||||
" --synccaches -c Sync caches between phases\n"
|
||||
" --dropcaches -d Drop caches between phases\n"
|
||||
" --script -t <script> Exec script between phases\n"
|
||||
" --seed -e <seed> Random seed value\n"
|
||||
" --random -r Randomly sized xattrs [16-size]\n"
|
||||
" --randomvalue -R Random xattr values\n"
|
||||
" --keep -k Don't unlink files\n\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_args(int argc, char **argv)
|
||||
{
|
||||
long seed = time(NULL);
|
||||
int c;
|
||||
int rc;
|
||||
|
||||
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
return (usage(argc, argv));
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'y':
|
||||
verify = 1;
|
||||
if (value_is_random != 0) {
|
||||
fprintf(stderr,
|
||||
"Error: -y and -R are incompatible.\n");
|
||||
rc = 1;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
nth = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'f':
|
||||
files = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'x':
|
||||
xattrs = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 's':
|
||||
size = strtol(optarg, NULL, 0);
|
||||
if (size > XATTR_SIZE_MAX) {
|
||||
fprintf(stderr, "Error: the size may not be "
|
||||
"greater than %d\n", XATTR_SIZE_MAX);
|
||||
rc = 1;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
strncpy(path, optarg, PATH_MAX);
|
||||
break;
|
||||
case 'c':
|
||||
synccaches = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dropcaches = 1;
|
||||
break;
|
||||
case 't':
|
||||
strncpy(script, optarg, PATH_MAX);
|
||||
break;
|
||||
case 'e':
|
||||
seed = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'r':
|
||||
size_is_random = 1;
|
||||
break;
|
||||
case 'R':
|
||||
value_is_random = 1;
|
||||
if (verify != 0) {
|
||||
fprintf(stderr,
|
||||
"Error: -y and -R are incompatible.\n");
|
||||
rc = 1;
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
keep_files = 1;
|
||||
break;
|
||||
default:
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
|
||||
srandom(seed);
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stdout, "verbose: %d\n", verbose);
|
||||
fprintf(stdout, "verify: %d\n", verify);
|
||||
fprintf(stdout, "nth: %d\n", nth);
|
||||
fprintf(stdout, "files: %d\n", files);
|
||||
fprintf(stdout, "xattrs: %d\n", xattrs);
|
||||
fprintf(stdout, "size: %d\n", size);
|
||||
fprintf(stdout, "path: %s\n", path);
|
||||
fprintf(stdout, "synccaches: %d\n", synccaches);
|
||||
fprintf(stdout, "dropcaches: %d\n", dropcaches);
|
||||
fprintf(stdout, "script: %s\n", script);
|
||||
fprintf(stdout, "seed: %ld\n", seed);
|
||||
fprintf(stdout, "random size: %d\n", size_is_random);
|
||||
fprintf(stdout, "random value: %d\n", value_is_random);
|
||||
fprintf(stdout, "keep: %d\n", keep_files);
|
||||
fprintf(stdout, "%s", "\n");
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
drop_caches(void)
|
||||
{
|
||||
char file[] = "/proc/sys/vm/drop_caches";
|
||||
int fd, rc;
|
||||
|
||||
fd = open(file, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
ERROR("Error %d: open(\"%s\", O_WRONLY)\n", errno, file);
|
||||
return (errno);
|
||||
}
|
||||
|
||||
rc = write(fd, "3", 1);
|
||||
if ((rc == -1) || (rc != 1)) {
|
||||
ERROR("Error %d: write(%d, \"3\", 1)\n", errno, fd);
|
||||
return (errno);
|
||||
}
|
||||
|
||||
rc = close(fd);
|
||||
if (rc == -1) {
|
||||
ERROR("Error %d: close(%d)\n", errno, fd);
|
||||
return (errno);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
run_process(const char *path, char *argv[])
|
||||
{
|
||||
pid_t pid;
|
||||
int rc, devnull_fd;
|
||||
|
||||
pid = vfork();
|
||||
if (pid == 0) {
|
||||
devnull_fd = open("/dev/null", O_WRONLY);
|
||||
|
||||
if (devnull_fd < 0)
|
||||
_exit(-1);
|
||||
|
||||
(void) dup2(devnull_fd, STDOUT_FILENO);
|
||||
(void) dup2(devnull_fd, STDERR_FILENO);
|
||||
close(devnull_fd);
|
||||
|
||||
(void) execvp(path, argv);
|
||||
_exit(-1);
|
||||
} else if (pid > 0) {
|
||||
int status;
|
||||
|
||||
while ((rc = waitpid(pid, &status, 0)) == -1 && errno == EINTR);
|
||||
|
||||
if (rc < 0 || !WIFEXITED(status))
|
||||
return (-1);
|
||||
|
||||
return (WEXITSTATUS(status));
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
post_hook(char *phase)
|
||||
{
|
||||
char *argv[3] = { script, phase, (char *)0 };
|
||||
int rc;
|
||||
|
||||
if (synccaches)
|
||||
sync();
|
||||
|
||||
if (dropcaches) {
|
||||
rc = drop_caches();
|
||||
if (rc)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
rc = run_process(script, argv);
|
||||
if (rc)
|
||||
return (rc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define USEC_PER_SEC 1000000
|
||||
|
||||
static void
|
||||
timeval_normalize(struct timeval *tv, time_t sec, suseconds_t usec)
|
||||
{
|
||||
while (usec >= USEC_PER_SEC) {
|
||||
usec -= USEC_PER_SEC;
|
||||
sec++;
|
||||
}
|
||||
|
||||
while (usec < 0) {
|
||||
usec += USEC_PER_SEC;
|
||||
sec--;
|
||||
}
|
||||
|
||||
tv->tv_sec = sec;
|
||||
tv->tv_usec = usec;
|
||||
}
|
||||
|
||||
static void
|
||||
timeval_sub(struct timeval *delta, struct timeval *tv1, struct timeval *tv2)
|
||||
{
|
||||
timeval_normalize(delta,
|
||||
tv1->tv_sec - tv2->tv_sec,
|
||||
tv1->tv_usec - tv2->tv_usec);
|
||||
}
|
||||
|
||||
static int
|
||||
create_files(void)
|
||||
{
|
||||
int i, rc;
|
||||
char *file = NULL;
|
||||
struct timeval start, stop, delta;
|
||||
|
||||
file = malloc(PATH_MAX);
|
||||
if (file == NULL) {
|
||||
rc = ENOMEM;
|
||||
ERROR("Error %d: malloc(%d) bytes for file name\n",
|
||||
rc, PATH_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void) gettimeofday(&start, NULL);
|
||||
|
||||
for (i = 1; i <= files; i++) {
|
||||
(void) sprintf(file, "%s/file-%d", path, i);
|
||||
|
||||
if (nth && ((i % nth) == 0))
|
||||
fprintf(stdout, "create: %s\n", file);
|
||||
|
||||
rc = unlink(file);
|
||||
if ((rc == -1) && (errno != ENOENT)) {
|
||||
ERROR("Error %d: unlink(%s)\n", errno, file);
|
||||
rc = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = open(file, O_CREAT, 0644);
|
||||
if (rc == -1) {
|
||||
ERROR("Error %d: open(%s, O_CREATE, 0644)\n",
|
||||
errno, file);
|
||||
rc = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = close(rc);
|
||||
if (rc == -1) {
|
||||
ERROR("Error %d: close(%d)\n", errno, rc);
|
||||
rc = errno;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
(void) gettimeofday(&stop, NULL);
|
||||
timeval_sub(&delta, &stop, &start);
|
||||
fprintf(stdout, "create: %d.%d seconds\n",
|
||||
(int)delta.tv_sec, (int)delta.tv_usec);
|
||||
|
||||
rc = post_hook("post");
|
||||
out:
|
||||
if (file)
|
||||
free(file);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
get_random_bytes(char *buf, size_t bytes)
|
||||
{
|
||||
int rand;
|
||||
ssize_t bytes_read = 0;
|
||||
|
||||
rand = open("/dev/urandom", O_RDONLY);
|
||||
|
||||
if (rand < 0)
|
||||
return (rand);
|
||||
|
||||
while (bytes_read < bytes) {
|
||||
ssize_t rc = read(rand, buf + bytes_read, bytes - bytes_read);
|
||||
if (rc < 0)
|
||||
break;
|
||||
bytes_read += rc;
|
||||
}
|
||||
|
||||
(void) close(rand);
|
||||
|
||||
return (bytes_read);
|
||||
}
|
||||
|
||||
static int
|
||||
setxattrs(void)
|
||||
{
|
||||
int i, j, rnd_size = size, shift, rc = 0;
|
||||
char name[XATTR_NAME_MAX];
|
||||
char *value = NULL;
|
||||
char *file = NULL;
|
||||
struct timeval start, stop, delta;
|
||||
|
||||
value = malloc(XATTR_SIZE_MAX);
|
||||
if (value == NULL) {
|
||||
rc = ENOMEM;
|
||||
ERROR("Error %d: malloc(%d) bytes for xattr value\n",
|
||||
rc, XATTR_SIZE_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = malloc(PATH_MAX);
|
||||
if (file == NULL) {
|
||||
rc = ENOMEM;
|
||||
ERROR("Error %d: malloc(%d) bytes for file name\n",
|
||||
rc, PATH_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void) gettimeofday(&start, NULL);
|
||||
|
||||
for (i = 1; i <= files; i++) {
|
||||
(void) sprintf(file, "%s/file-%d", path, i);
|
||||
|
||||
if (nth && ((i % nth) == 0))
|
||||
fprintf(stdout, "setxattr: %s\n", file);
|
||||
|
||||
for (j = 1; j <= xattrs; j++) {
|
||||
if (size_is_random)
|
||||
rnd_size = (random() % (size - 16)) + 16;
|
||||
|
||||
(void) sprintf(name, "user.%d", j);
|
||||
if (value_is_random) {
|
||||
rc = get_random_bytes(value, rnd_size);
|
||||
if (rc < rnd_size) {
|
||||
ERROR("Error %d: get_random_bytes() "
|
||||
"wanted %d got %d\n", errno,
|
||||
rnd_size, rc);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
shift = sprintf(value, "size=%d ", rnd_size);
|
||||
memset(value + shift, 'x', XATTR_SIZE_MAX -
|
||||
shift);
|
||||
}
|
||||
|
||||
rc = lsetxattr(file, name, value, rnd_size, 0);
|
||||
if (rc == -1) {
|
||||
ERROR("Error %d: lsetxattr(%s, %s, ..., %d)\n",
|
||||
errno, file, name, rnd_size);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(void) gettimeofday(&stop, NULL);
|
||||
timeval_sub(&delta, &stop, &start);
|
||||
fprintf(stdout, "setxattr: %d.%d seconds\n",
|
||||
(int)delta.tv_sec, (int)delta.tv_usec);
|
||||
|
||||
rc = post_hook("post");
|
||||
out:
|
||||
if (file)
|
||||
free(file);
|
||||
|
||||
if (value)
|
||||
free(value);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
getxattrs(void)
|
||||
{
|
||||
int i, j, rnd_size, shift, rc = 0;
|
||||
char name[XATTR_NAME_MAX];
|
||||
char *verify_value = NULL;
|
||||
char *value = NULL;
|
||||
char *file = NULL;
|
||||
struct timeval start, stop, delta;
|
||||
|
||||
verify_value = malloc(XATTR_SIZE_MAX);
|
||||
if (verify_value == NULL) {
|
||||
rc = ENOMEM;
|
||||
ERROR("Error %d: malloc(%d) bytes for xattr verify\n",
|
||||
rc, XATTR_SIZE_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = malloc(XATTR_SIZE_MAX);
|
||||
if (value == NULL) {
|
||||
rc = ENOMEM;
|
||||
ERROR("Error %d: malloc(%d) bytes for xattr value\n",
|
||||
rc, XATTR_SIZE_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
file = malloc(PATH_MAX);
|
||||
if (file == NULL) {
|
||||
rc = ENOMEM;
|
||||
ERROR("Error %d: malloc(%d) bytes for file name\n",
|
||||
rc, PATH_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void) gettimeofday(&start, NULL);
|
||||
|
||||
for (i = 1; i <= files; i++) {
|
||||
(void) sprintf(file, "%s/file-%d", path, i);
|
||||
|
||||
if (nth && ((i % nth) == 0))
|
||||
fprintf(stdout, "getxattr: %s\n", file);
|
||||
|
||||
for (j = 1; j <= xattrs; j++) {
|
||||
(void) sprintf(name, "user.%d", j);
|
||||
|
||||
rc = lgetxattr(file, name, value, XATTR_SIZE_MAX);
|
||||
if (rc == -1) {
|
||||
ERROR("Error %d: lgetxattr(%s, %s, ..., %d)\n",
|
||||
errno, file, name, XATTR_SIZE_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
sscanf(value, "size=%d [a-z]", &rnd_size);
|
||||
shift = sprintf(verify_value, "size=%d ",
|
||||
rnd_size);
|
||||
memset(verify_value + shift, 'x',
|
||||
XATTR_SIZE_MAX - shift);
|
||||
|
||||
if (rnd_size != rc ||
|
||||
memcmp(verify_value, value, rnd_size)) {
|
||||
ERROR("Error %d: verify failed\n "
|
||||
"verify: %s\nvalue: %s\n",
|
||||
EINVAL, verify_value, value);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(void) gettimeofday(&stop, NULL);
|
||||
timeval_sub(&delta, &stop, &start);
|
||||
fprintf(stdout, "getxattr: %d.%d seconds\n",
|
||||
(int)delta.tv_sec, (int)delta.tv_usec);
|
||||
|
||||
rc = post_hook("post");
|
||||
out:
|
||||
if (file)
|
||||
free(file);
|
||||
|
||||
if (value)
|
||||
free(value);
|
||||
|
||||
if (verify_value)
|
||||
free(verify_value);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
unlink_files(void)
|
||||
{
|
||||
int i, rc;
|
||||
char *file = NULL;
|
||||
struct timeval start, stop, delta;
|
||||
|
||||
file = malloc(PATH_MAX);
|
||||
if (file == NULL) {
|
||||
rc = ENOMEM;
|
||||
ERROR("Error %d: malloc(%d) bytes for file name\n",
|
||||
rc, PATH_MAX);
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void) gettimeofday(&start, NULL);
|
||||
|
||||
for (i = 1; i <= files; i++) {
|
||||
(void) sprintf(file, "%s/file-%d", path, i);
|
||||
|
||||
if (nth && ((i % nth) == 0))
|
||||
fprintf(stdout, "unlink: %s\n", file);
|
||||
|
||||
rc = unlink(file);
|
||||
if ((rc == -1) && (errno != ENOENT)) {
|
||||
ERROR("Error %d: unlink(%s)\n", errno, file);
|
||||
return (errno);
|
||||
}
|
||||
}
|
||||
|
||||
(void) gettimeofday(&stop, NULL);
|
||||
timeval_sub(&delta, &stop, &start);
|
||||
fprintf(stdout, "unlink: %d.%d seconds\n",
|
||||
(int)delta.tv_sec, (int)delta.tv_usec);
|
||||
|
||||
rc = post_hook("post");
|
||||
out:
|
||||
if (file)
|
||||
free(file);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = parse_args(argc, argv);
|
||||
if (rc)
|
||||
return (rc);
|
||||
|
||||
rc = create_files();
|
||||
if (rc)
|
||||
return (rc);
|
||||
|
||||
rc = setxattrs();
|
||||
if (rc)
|
||||
return (rc);
|
||||
|
||||
rc = getxattrs();
|
||||
if (rc)
|
||||
return (rc);
|
||||
|
||||
if (!keep_files) {
|
||||
rc = unlink_files();
|
||||
if (rc)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
Reference in New Issue
Block a user