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 @@
|
||||
SUBDIRS = cmd include tests
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
/commands.cfg
|
||||
/default.cfg
|
||||
@@ -0,0 +1,10 @@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/include
|
||||
dist_pkgdata_SCRIPTS = \
|
||||
commands.cfg \
|
||||
default.cfg \
|
||||
libtest.shlib \
|
||||
math.shlib \
|
||||
properties.shlib
|
||||
|
||||
EXTRA_DIST = \
|
||||
zfs_commands.cfg
|
||||
@@ -0,0 +1,119 @@
|
||||
export AWK="@AWK@"
|
||||
export BLOCKDEV="@BLOCKDEV@"
|
||||
export BASENAME="@BASENAME@"
|
||||
export BC="@BC@"
|
||||
export BUNZIP2="@BUNZIP2@"
|
||||
export BZCAT="@BZCAT@"
|
||||
export CAT="@CAT@"
|
||||
export CD="@CD@"
|
||||
export CHACL="@CHACL@"
|
||||
export CHGRP="@CHGRP@"
|
||||
export CHMOD="@CHMOD@"
|
||||
export CHOWN="@CHOWN@"
|
||||
export CKSUM="@CKSUM@"
|
||||
export CMP="@CMP@"
|
||||
export COMPRESS="@COMPRESS@"
|
||||
export COREADM="@COREADM@"
|
||||
export CP="@CP@"
|
||||
export CPIO="@CPIO@"
|
||||
export CUT="@CUT@"
|
||||
export DATE="@DATE@"
|
||||
export DD="@DD@"
|
||||
export DF="@DF@"
|
||||
export DIFF="@DIFF@"
|
||||
export DIRCMP="@DIRCMP@"
|
||||
export DIRNAME="@DIRNAME@"
|
||||
export DU="@DU@"
|
||||
export DUMPADM="@DUMPADM@"
|
||||
export ECHO="@ECHO@"
|
||||
export EGREP="@EGREP@"
|
||||
export FDISK="@FDISK@"
|
||||
export FGREP="@FGREP@"
|
||||
export FILE="@FILE@"
|
||||
export FIND="@FIND@"
|
||||
export FORMAT="@FORMAT@"
|
||||
export FSCK="@FSCK@"
|
||||
export GETENT="@GETENT@"
|
||||
export GETFACL="@GETFACL@"
|
||||
export GETMAJOR="@GETMAJOR@"
|
||||
export GNUDD="@GNUDD@"
|
||||
export GREP="@GREP@"
|
||||
export GROUPADD="@GROUPADD@"
|
||||
export GROUPDEL="@GROUPDEL@"
|
||||
export GROUPMOD="@GROUPMOD@"
|
||||
export HEAD="@HEAD@"
|
||||
export HOSTNAME="@HOSTNAME@"
|
||||
export ID="@ID@"
|
||||
export ISAINFO="@ISAINFO@"
|
||||
export KILL="@KILL@"
|
||||
export KSH="@KSH@"
|
||||
export KSTAT="@KSTAT@"
|
||||
export LOCKFS="@LOCKFS@"
|
||||
export LOFIADM="@LOFIADM@"
|
||||
export LOGNAME="@LOGNAME@"
|
||||
export LS="@LS@"
|
||||
export MD5SUM="@MD5SUM@"
|
||||
export MKDIR="@MKDIR@"
|
||||
export MKNOD="@MKNOD@"
|
||||
export MKTEMP="@MKTEMP@"
|
||||
export MNTTAB="@MNTTAB@"
|
||||
export MODINFO="@MODINFO@"
|
||||
export MODUNLOAD="@MODUNLOAD@"
|
||||
export MOUNT="@MOUNT@"
|
||||
export MV="@MV@"
|
||||
export NAWK="@AWK@"
|
||||
export NEWFS="@NEWFS@"
|
||||
export NPROC="@NPROC@"
|
||||
export PAGESIZE="@PAGESIZE@"
|
||||
export PFEXEC="@PFEXEC@"
|
||||
export PGREP="@PGREP@"
|
||||
export PING="@PING@"
|
||||
export PKGINFO="@PKGINFO@"
|
||||
export PKILL="@PKILL@"
|
||||
export PRINTF="@PRINTF@"
|
||||
export PRTVTOC="@PRTVTOC@"
|
||||
export PS="@PS@"
|
||||
export PSRINFO="@PSRINFO@"
|
||||
export PYTHON="@PYTHON@"
|
||||
export REBOOT="@REBOOT@"
|
||||
export RM="@RM@"
|
||||
export RMDIR="@RMDIR@"
|
||||
export RSH="@RSH@"
|
||||
export SED="@SED@"
|
||||
export SETFACL="@SETFACL@"
|
||||
export SHARE="@SHARE@"
|
||||
export SHUF="@SHUF@"
|
||||
export SLEEP="@SLEEP@"
|
||||
export SORT="@SORT@"
|
||||
export STRINGS="@STRINGS@"
|
||||
export SU="@SU@"
|
||||
export SUM="@SUM@"
|
||||
export SVCADM="@SVCADM@"
|
||||
export SVCS="@SVCS@"
|
||||
export SWAP="@SWAP@"
|
||||
export SWAPADD="@SWAPADD@"
|
||||
export SYNC="@SYNC@"
|
||||
export TAIL="@TAIL@"
|
||||
export TAR="@TAR@"
|
||||
export TOUCH="@TOUCH@"
|
||||
export TR="@TR@"
|
||||
export TRUE="@TRUE@"
|
||||
export TRUNCATE="@TRUNCATE@"
|
||||
export UDEVADM="@UDEVADM@"
|
||||
export UFSDUMP="@UFSDUMP@"
|
||||
export UFSRESTORE="@UFSRESTORE@"
|
||||
export UMASK="@UMASK@"
|
||||
export UMOUNT="@UMOUNT@"
|
||||
export UMOUNTALL="@UMOUNTALL@"
|
||||
export UNAME="@UNAME@"
|
||||
export UNCOMPRESS="@UNCOMPRESS@"
|
||||
export UNIQ="@UNIQ@"
|
||||
export UNSHARE="@UNSHARE@"
|
||||
export USERADD="@USERADD@"
|
||||
export USERDEL="@USERDEL@"
|
||||
export USERMOD="@USERMOD@"
|
||||
export WAIT="@WAIT@"
|
||||
export WC="@WC@"
|
||||
export ZONEADM="@ZONEADM@"
|
||||
export ZONECFG="@ZONECFG@"
|
||||
export ZONENAME="@ZONENAME@"
|
||||
@@ -0,0 +1,200 @@
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2016 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/commands.cfg
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
# Optionally override the installed ZFS commands to run in-tree
|
||||
if [[ -f "$STF_SUITE/include/zfs_commands.cfg" ]]; then
|
||||
. $STF_SUITE/include/zfs_commands.cfg
|
||||
fi
|
||||
|
||||
# Define run length constants
|
||||
export RT_LONG="3"
|
||||
export RT_MEDIUM="2"
|
||||
export RT_SHORT="1"
|
||||
|
||||
# Define macro for zone test
|
||||
export ZONE_POOL="zonepool"
|
||||
export ZONE_CTR="zonectr"
|
||||
|
||||
# Common paths
|
||||
bindir=@bindir@
|
||||
sbindir=@sbindir@
|
||||
helperdir=@datarootdir@/@PACKAGE@/zfs-tests/bin
|
||||
|
||||
# ZFS Commands
|
||||
ZDB=${ZDB:-${sbindir}/zdb}
|
||||
ZFS=${ZFS:-${sbindir}/zfs}
|
||||
ZHACK=${ZHACK:-${sbindir}/zhack}
|
||||
ZINJECT=${ZINJECT:-${sbindir}/zinject}
|
||||
ZPOOL=${ZPOOL:-${sbindir}/zpool}
|
||||
ZTEST=${ZTEST:-${sbindir}/ztest}
|
||||
ZPIOS=${ZPIOS:-${sbindir}/zpios}
|
||||
|
||||
# Test Suite Specific Commands
|
||||
export CHG_USR_EXEC=${CHG_USR_EXEC:-${helperdir}/chg_usr_exec}
|
||||
export DEVNAME2DEVID=${DEVNAME2DEVID:-${helperdir}/devname2devid}
|
||||
export DIR_RD_UPDATE=${DIR_RD_UPDATE:-${helperdir}/dir_rd_update}
|
||||
export FILE_CHECK=${FILE_CHECK:-${helperdir}/file_check}
|
||||
export FILE_TRUNC=${FILE_TRUNC:-${helperdir}/file_trunc}
|
||||
export FILE_WRITE=${FILE_WRITE:-${helperdir}/file_write}
|
||||
export LARGEST_FILE=${LARGEST_FILE:-${helperdir}/largest_file}
|
||||
export MKBUSY=${MKBUSY:-${helperdir}/mkbusy}
|
||||
export MKFILE=${MKFILE:-${helperdir}/mkfile}
|
||||
export MKFILES=${MKFILES:-${helperdir}/mkfiles}
|
||||
export MKTREE=${MKTREE:-${helperdir}/mktree}
|
||||
export MMAP_EXEC=${MMAP_EXEC:-${helperdir}/mmap_exec}
|
||||
export MMAPWRITE=${MMAPWRITE:-${helperdir}/mmapwrite}
|
||||
export RANDFREE_FILE=${RANDFREE_FILE:-${helperdir}/randfree_file}
|
||||
export READMMAP=${READMMAP:-${helperdir}/readmmap}
|
||||
export RENAME_DIR=${RENAME_DIR:-${helperdir}/rename_dir}
|
||||
export RM_LNKCNT_ZERO_FILE=${RM_LNKCNT_ZERO_FILE:-${helperdir}/rm_lnkcnt_zero_file}
|
||||
export THREADSAPPEND=${THREADSAPPEND:-${helperdir}/threadsappend}
|
||||
export XATTRTEST=${XATTRTEST:-${helpdir}/xattrtest}
|
||||
|
||||
# ensure we're running in the C locale, since
|
||||
# localised messages may result in test failures
|
||||
export LC_ALL="C"
|
||||
export LANG="C"
|
||||
|
||||
#
|
||||
# pattern to ignore from 'zpool list'.
|
||||
#
|
||||
export NO_POOLS="no pools available"
|
||||
|
||||
# pattern to ignore from 'zfs list'.
|
||||
export NO_DATASETS="no datasets available"
|
||||
|
||||
export TEST_BASE_DIR="/var/tmp"
|
||||
|
||||
# Default to compression ON
|
||||
export COMPRESSION_PROP=on
|
||||
|
||||
# Default to using the checksum
|
||||
export CHECKSUM_PROP=on
|
||||
|
||||
# some common variables used by test scripts :
|
||||
|
||||
# some test pool names
|
||||
export TESTPOOL=testpool.$$
|
||||
export TESTPOOL1=testpool1.$$
|
||||
export TESTPOOL2=testpool2.$$
|
||||
export TESTPOOL3=testpool3.$$
|
||||
|
||||
# some test file system names
|
||||
export TESTFS=testfs.$$
|
||||
export TESTFS1=testfs1.$$
|
||||
export TESTFS2=testfs2.$$
|
||||
export TESTFS3=testfs3.$$
|
||||
|
||||
# some test directory names
|
||||
export TESTDIR=${TEST_BASE_DIR%%/}/testdir$$
|
||||
export TESTDIR0=${TEST_BASE_DIR%%/}/testdir0$$
|
||||
export TESTDIR1=${TEST_BASE_DIR%%/}/testdir1$$
|
||||
export TESTDIR2=${TEST_BASE_DIR%%/}/testdir2$$
|
||||
|
||||
export ZFSROOT=
|
||||
|
||||
export TESTSNAP=testsnap$$
|
||||
export TESTSNAP1=testsnap1$$
|
||||
export TESTSNAP2=testsnap2$$
|
||||
export TESTCLONE=testclone$$
|
||||
export TESTCLONE1=testclone1$$
|
||||
export TESTCLONE2=testclone2$$
|
||||
export TESTCLCT=testclct$$
|
||||
export TESTCTR=testctr$$
|
||||
export TESTCTR1=testctr1$$
|
||||
export TESTCTR2=testctr2$$
|
||||
export TESTVOL=testvol$$
|
||||
export TESTVOL1=testvol1$$
|
||||
export TESTVOL2=testvol2$$
|
||||
export TESTFILE0=testfile0.$$
|
||||
export TESTFILE1=testfile1.$$
|
||||
export TESTFILE2=testfile2.$$
|
||||
|
||||
export LONGPNAME="poolname50charslong_012345678901234567890123456789"
|
||||
export LONGFSNAME="fsysname50charslong_012345678901234567890123456789"
|
||||
export SNAPFS="$TESTPOOL/$TESTFS@$TESTSNAP"
|
||||
export SNAPFS1="$TESTPOOL/$TESTVOL@$TESTSNAP"
|
||||
|
||||
export VOLSIZE=150m
|
||||
export BIGVOLSIZE=1eb
|
||||
|
||||
# Default to limit disks to be checked
|
||||
export MAX_FINDDISKSNUM=6
|
||||
|
||||
# For iscsi target support
|
||||
export ISCSITGTFILE=/tmp/iscsitgt_file
|
||||
export ISCSITGT_FMRI=svc:/system/iscsitgt:default
|
||||
|
||||
#
|
||||
# finally, if we're running in a local zone
|
||||
# we take some additional actions
|
||||
if ! is_global_zone; then
|
||||
reexport_pool
|
||||
fi
|
||||
|
||||
export ZFS_VERSION=5
|
||||
export ZFS_ALL_VERSIONS="1 2 3 4 5"
|
||||
|
||||
for i in $ZFS_ALL_VERSIONS; do
|
||||
eval 'export ZFS_VERSION_$i="v${i}-fs"'
|
||||
done
|
||||
|
||||
if is_linux; then
|
||||
unpack_opts="--sparse -xf"
|
||||
pack_opts="--sparse -cf"
|
||||
verbose=" -v"
|
||||
unpack_preserve=" -xpf"
|
||||
pack_preserve=" -cpf"
|
||||
|
||||
ZVOL_DEVDIR="/dev/zvol"
|
||||
ZVOL_RDEVDIR="/dev/zvol"
|
||||
DEV_DSKDIR="/dev"
|
||||
DEV_RDSKDIR="/dev"
|
||||
|
||||
NEWFS_DEFAULT_FS="ext2"
|
||||
else
|
||||
unpack_opts="xv"
|
||||
pack_opts="cf"
|
||||
verbose="v"
|
||||
unpack_preserve="xpf"
|
||||
pack_preserve="cpf"
|
||||
|
||||
ZVOL_DEVDIR="/dev/zvol/dsk"
|
||||
ZVOL_RDEVDIR="/dev/zvol/rdsk"
|
||||
DEV_DSKDIR="/dev/dsk"
|
||||
DEV_RDSKDIR="/dev/rdsk"
|
||||
|
||||
NEWFS_DEFAULT_FS="ufs"
|
||||
fi
|
||||
export unpack_opts pack_opts verbose unpack_preserve pack_preserve \
|
||||
ZVOL_DEVDIR ZVOL_RDEVDIR NEWFS_DEFAULT_FS DEV_DSKDIR DEV_RDSKDIR
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Return 0 if the percentage difference between $a and $b is $percent or
|
||||
# greater. Return 1 if the percentage is lower or if we would divide by
|
||||
# zero. For use like this:
|
||||
#
|
||||
# Do $action if the calculated percentage is greater or equal to that passed in:
|
||||
# within_percent A B P && $action
|
||||
# Do $action if the calculated percentage is less than that passed in:
|
||||
# within_percent A B P || $action
|
||||
#
|
||||
function within_percent
|
||||
{
|
||||
typeset a=$1
|
||||
typeset b=$1
|
||||
typeset percent=$3
|
||||
|
||||
# Set $a or $b to $2 such that a >= b
|
||||
[[ '1' = $($ECHO "if ($2 > $a) 1" | $BC) ]] && a=$2 || b=$2
|
||||
|
||||
# Prevent division by 0
|
||||
[[ $a =~ [1-9] ]] || return 1
|
||||
|
||||
typeset p=$($ECHO "scale=2; $b * 100 / $a" | $BC)
|
||||
log_note "Comparing $a and $b given $percent% (calculated: $p%)"
|
||||
[[ '1' = $($ECHO "scale=2; if ($p >= $percent) 1" | $BC) ]] && return 0
|
||||
|
||||
return 1
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
typeset -a compress_props=('on' 'off' 'lzjb' 'gzip' 'gzip-1' 'gzip-2' 'gzip-3'
|
||||
'gzip-4' 'gzip-5' 'gzip-6' 'gzip-7' 'gzip-8' 'gzip-9' 'zle')
|
||||
|
||||
typeset -a checksum_props=('on' 'off' 'fletcher2' 'fletcher4' 'sha256')
|
||||
|
||||
#
|
||||
# Given the property array passed in, return 'num_props' elements to the
|
||||
# user, excluding any elements below 'start.' This allows us to exclude
|
||||
# 'off' and 'on' which can be either unwanted, or a duplicate of another
|
||||
# property respectively.
|
||||
#
|
||||
function get_rand_prop
|
||||
{
|
||||
typeset prop_array=($(eval echo \${$1[@]}))
|
||||
typeset -i num_props=$2
|
||||
typeset -i start=$3
|
||||
typeset retstr=""
|
||||
|
||||
[[ -z $prop_array || -z $num_props || -z $start ]] && \
|
||||
log_fail "get_rand_prop: bad arguments"
|
||||
|
||||
typeset prop_max=$((${#prop_array[@]} - 1))
|
||||
typeset -i i
|
||||
for i in $($SHUF -i $start-$prop_max -n $num_props); do
|
||||
retstr="${prop_array[$i]} $retstr"
|
||||
done
|
||||
echo $retstr
|
||||
}
|
||||
|
||||
function get_rand_compress
|
||||
{
|
||||
get_rand_prop compress_props $1 2
|
||||
}
|
||||
|
||||
function get_rand_compress_any
|
||||
{
|
||||
get_rand_prop compress_props $1 0
|
||||
}
|
||||
|
||||
function get_rand_checksum
|
||||
{
|
||||
get_rand_prop checksum_props $1 2
|
||||
}
|
||||
|
||||
function get_rand_checksum_any
|
||||
{
|
||||
get_rand_prop checksum_props $1 0
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
../../../zfs-script-config.sh
|
||||
@@ -0,0 +1 @@
|
||||
SUBDIRS = functional stress
|
||||
@@ -0,0 +1,55 @@
|
||||
SUBDIRS = \
|
||||
acl \
|
||||
atime \
|
||||
bootfs \
|
||||
cache \
|
||||
cachefile \
|
||||
casenorm \
|
||||
clean_mirror \
|
||||
cli_root \
|
||||
cli_user \
|
||||
compression \
|
||||
ctime \
|
||||
delegate \
|
||||
devices \
|
||||
exec \
|
||||
features \
|
||||
grow_pool \
|
||||
grow_replicas \
|
||||
history \
|
||||
inheritance \
|
||||
inuse \
|
||||
large_files \
|
||||
largest_pool \
|
||||
link_count \
|
||||
migration \
|
||||
mmap \
|
||||
mount \
|
||||
mv_files \
|
||||
nestedfs \
|
||||
no_space \
|
||||
nopwrite \
|
||||
online_offline \
|
||||
pool_names \
|
||||
poolversion \
|
||||
privilege \
|
||||
quota \
|
||||
redundancy \
|
||||
refquota \
|
||||
refreserv \
|
||||
rename_dirs \
|
||||
replacement \
|
||||
reservation \
|
||||
rootpool \
|
||||
rsend \
|
||||
scrub_mirror \
|
||||
slog \
|
||||
snapshot \
|
||||
snapused \
|
||||
sparse \
|
||||
threadsappend \
|
||||
truncate \
|
||||
userquota \
|
||||
write_dirs \
|
||||
xattr \
|
||||
zvol
|
||||
@@ -0,0 +1,6 @@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/acl
|
||||
dist_pkgdata_SCRIPTS = \
|
||||
acl.cfg \
|
||||
acl_common.kshlib
|
||||
|
||||
SUBDIRS = posix
|
||||
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
export NISSTAFILE=/var/tmp/nis_state
|
||||
export TESTFILE=testfile$$
|
||||
export TESTFILE0=testfile0.$$
|
||||
export TESTFILE2=testfile2.$$
|
||||
|
||||
# Define super user 'zfstest'
|
||||
export ZFS_ACL_ADMIN=zfstest
|
||||
|
||||
export ZFS_ACL_STAFF_GROUP=zfsgrp
|
||||
export ZFS_ACL_STAFF1=staff1
|
||||
export ZFS_ACL_STAFF2=staff2
|
||||
|
||||
export ZFS_ACL_OTHER_GROUP=othergrp
|
||||
export ZFS_ACL_OTHER1=other1
|
||||
export ZFS_ACL_OTHER2=other2
|
||||
|
||||
# Define the current user who run 'usr_exec'
|
||||
export ZFS_ACL_CUR_USER=""
|
||||
|
||||
# Define global error string
|
||||
export ZFS_ACL_ERR_STR=""
|
||||
|
||||
# Define test file and test directory which will be operated by chmod
|
||||
export testfile=$TESTDIR/testfile
|
||||
export testdir=$TESTDIR/testdir
|
||||
|
||||
# Define several directories for trivial ACLs function test.
|
||||
export RES_DIR=$TESTDIR/RES
|
||||
export INI_DIR=$TESTDIR/INIT
|
||||
export TST_DIR=$TESTDIR/TEST
|
||||
export TMP_DIR=$TESTDIR/TMP
|
||||
|
||||
# Define test files and their attributes files number for trivial
|
||||
# ACLs function test
|
||||
export NUM_FILE=5
|
||||
export NUM_ATTR=10
|
||||
@@ -0,0 +1,626 @@
|
||||
#
|
||||
# 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 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/acl/acl.cfg
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Get the given file/directory access mode
|
||||
#
|
||||
# $1 object -- file or directroy
|
||||
#
|
||||
function get_mode #<obj>
|
||||
{
|
||||
typeset obj=$1
|
||||
if (( ${#obj} == 0 )); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
$LS -ld $obj | $AWK '{print $1}'
|
||||
}
|
||||
|
||||
#
|
||||
# Get the given file/directory ACL
|
||||
#
|
||||
# $1 object -- file or directroy
|
||||
#
|
||||
function get_acl #<obj>
|
||||
{
|
||||
typeset obj=$1
|
||||
if (( ${#obj} == 0 )); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
$LS -vd $obj | $NAWK '(NR != 1) {print $0}'
|
||||
}
|
||||
|
||||
#
|
||||
# Get the given file/directory ACL
|
||||
#
|
||||
# $1 object -- file or directroy
|
||||
#
|
||||
function get_compact_acl #<obj>
|
||||
{
|
||||
typeset obj=$1
|
||||
if (( ${#obj} == 0 )); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
$LS -Vd $obj | $NAWK '(NR != 1) {print $0}'
|
||||
}
|
||||
|
||||
#
|
||||
# Check the given two files/directories have the same ACLs
|
||||
#
|
||||
# Return 0, if source object acl is equal to target object acl.
|
||||
#
|
||||
# $1 source object
|
||||
# $2 target object
|
||||
#
|
||||
function compare_acls #<src> <tgt>
|
||||
{
|
||||
typeset src=$1
|
||||
typeset tgt=$2
|
||||
|
||||
(( ${#src} == 0 || ${#tgt} == 0 )) && return 1
|
||||
[[ $src == $tgt ]] && return 0
|
||||
|
||||
typeset tmpsrc=/tmp/compare_acls.src.$$
|
||||
typeset tmptgt=/tmp/compare_acls.tgt.$$
|
||||
|
||||
get_acl $src > $tmpsrc
|
||||
get_acl $tgt > $tmptgt
|
||||
typeset -i ret=0
|
||||
$DIFF $tmpsrc $tmptgt > /dev/null 2>&1
|
||||
ret=$?
|
||||
$RM -f $tmpsrc $tmptgt
|
||||
|
||||
if (( ret != 0 )); then
|
||||
return $ret
|
||||
fi
|
||||
|
||||
get_compact_acl $src > $tmpsrc
|
||||
get_compact_acl $tgt > $tmptgt
|
||||
$DIFF $tmpsrc $tmptgt > /dev/null 2>&1
|
||||
ret=$?
|
||||
$RM -f $tmpsrc $tmptgt
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
#
|
||||
# Check that the given two objects have the same modes.
|
||||
# Return 0, if their modes are equal with each other. Otherwise, return 1.
|
||||
#
|
||||
# $1 source object
|
||||
# $2 target object
|
||||
#
|
||||
function compare_modes #<src> <tgt>
|
||||
{
|
||||
typeset src=$1
|
||||
typeset tgt=$2
|
||||
typeset -i i=0
|
||||
set -A mode
|
||||
|
||||
(( ${#src} == 0 || ${#tgt} == 0 )) && return 1
|
||||
[[ $src == $tgt ]] && return 0
|
||||
|
||||
typeset obj
|
||||
for obj in $src $tgt
|
||||
do
|
||||
mode[i]=$(get_mode $obj)
|
||||
|
||||
(( i = i + 1 ))
|
||||
done
|
||||
|
||||
[[ ${mode[0]} != ${mode[1]} ]] && return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Check that the given two objects have the same xattrs.
|
||||
# Return 0, if their xattrs are equal with each other. Otherwise, return 1.
|
||||
#
|
||||
# $1 source object
|
||||
# $2 target object
|
||||
#
|
||||
function compare_xattrs #<src> <tgt>
|
||||
{
|
||||
typeset src=$1
|
||||
typeset tgt=$2
|
||||
|
||||
(( ${#src} == 0 || ${#tgt} == 0 )) && return 1
|
||||
[[ $src == $tgt ]] && return 0
|
||||
|
||||
typeset tmpsrc=/tmp/compare_xattrs.src.$$
|
||||
typeset tmptgt=/tmp/compare_xattrs.tgt.$$
|
||||
|
||||
get_xattr $src > $tmpsrc
|
||||
get_xattr $tgt > $tmptgt
|
||||
typeset -i ret=0
|
||||
$DIFF $tmpsrc $tmptgt > /dev/null 2>&1
|
||||
ret=$?
|
||||
$RM -f $tmpsrc $tmptgt
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
#
|
||||
# Check '+' is set for a given file/directory with 'ls [-l]' command
|
||||
#
|
||||
# $1 object -- file or directory.
|
||||
#
|
||||
function plus_sign_check_l #<obj>
|
||||
{
|
||||
typeset obj=$1
|
||||
if (( ${#obj} == 0 )); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
$LS -ld $obj | $AWK '{print $1}' | $GREP "+\>" > /dev/null
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
#
|
||||
# Check '+' is set for a given file/directory with 'ls [-v]' command
|
||||
#
|
||||
# $1 object -- file or directory.
|
||||
#
|
||||
function plus_sign_check_v #<obj>
|
||||
{
|
||||
typeset obj=$1
|
||||
if (( ${#obj} == 0 )); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
$LS -vd $obj | $NAWK '(NR == 1) {print $1}' | $GREP "+\>" > /dev/null
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
#
|
||||
# A wrapper function of c program
|
||||
#
|
||||
# $1 legal login name
|
||||
# $2-n commands and options
|
||||
#
|
||||
function chgusr_exec #<login_name> <commands> [...]
|
||||
{
|
||||
$CHG_USR_EXEC $@
|
||||
return $?
|
||||
}
|
||||
|
||||
#
|
||||
# Export the current user for the following usr_exec operating.
|
||||
#
|
||||
# $1 legal login name
|
||||
#
|
||||
function set_cur_usr #<login_name>
|
||||
{
|
||||
export ZFS_ACL_CUR_USER=$1
|
||||
}
|
||||
|
||||
#
|
||||
# Run commands by $ZFS_ACL_CUR_USER
|
||||
#
|
||||
# $1-n commands and options
|
||||
#
|
||||
function usr_exec #<commands> [...]
|
||||
{
|
||||
$CHG_USR_EXEC "$ZFS_ACL_CUR_USER" $@
|
||||
return $?
|
||||
}
|
||||
|
||||
#
|
||||
# Count how many ACEs for the speficied file or directory.
|
||||
#
|
||||
# $1 file or directroy name
|
||||
#
|
||||
function count_ACE #<file or dir name>
|
||||
{
|
||||
if [[ ! -e $1 ]]; then
|
||||
log_note "Need input file or directroy name."
|
||||
return 1
|
||||
fi
|
||||
|
||||
$LS -vd $1 | $NAWK 'BEGIN {count=0}
|
||||
(NR != 1)&&(/[0-9]:/) {count++}
|
||||
END {print count}'
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Get specified number ACE content of specified file or directory.
|
||||
#
|
||||
# $1 file or directory name
|
||||
# $2 specified number
|
||||
#
|
||||
function get_ACE #<file or dir name> <specified number> <verbose|compact>
|
||||
{
|
||||
if [[ ! -e $1 || $2 -ge $(count_ACE $1) ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
typeset file=$1
|
||||
typeset -i num=$2
|
||||
typeset format=${3:-verbose}
|
||||
typeset -i next_num=-1
|
||||
|
||||
typeset tmpfile=/tmp/tmp_get_ACE.$$
|
||||
typeset line=""
|
||||
typeset args
|
||||
|
||||
case $format in
|
||||
verbose) args="-vd"
|
||||
;;
|
||||
compact) args="-Vd"
|
||||
;;
|
||||
*) log_fail "Invalid parameter as ($format), " \
|
||||
"only verbose|compact is supported."
|
||||
;;
|
||||
esac
|
||||
|
||||
$LS $args $file > $tmpfile
|
||||
(( $? != 0 )) && log_fail "FAIL: $LS $args $file > $tmpfile"
|
||||
while read line; do
|
||||
[[ -z $line ]] && continue
|
||||
if [[ $args == -vd ]]; then
|
||||
if [[ $line == "$num":* ]]; then
|
||||
(( next_num = num + 1 ))
|
||||
fi
|
||||
if [[ $line == "$next_num":* ]]; then
|
||||
break
|
||||
fi
|
||||
if (( next_num != -1 )); then
|
||||
print -n $line
|
||||
fi
|
||||
else
|
||||
if (( next_num == num )); then
|
||||
print -n $line
|
||||
fi
|
||||
(( next_num += 1 ))
|
||||
fi
|
||||
done < $tmpfile
|
||||
|
||||
$RM -f $tmpfile
|
||||
(( $? != 0 )) && log_fail "FAIL: $RM -f $tmpfile"
|
||||
}
|
||||
|
||||
#
|
||||
# Cleanup exist user/group.
|
||||
#
|
||||
function cleanup_user_group
|
||||
{
|
||||
del_user $ZFS_ACL_ADMIN
|
||||
|
||||
del_user $ZFS_ACL_STAFF1
|
||||
del_user $ZFS_ACL_STAFF2
|
||||
del_group $ZFS_ACL_STAFF_GROUP
|
||||
|
||||
del_user $ZFS_ACL_OTHER1
|
||||
del_user $ZFS_ACL_OTHER2
|
||||
del_group $ZFS_ACL_OTHER_GROUP
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Clean up testfile and test directory
|
||||
#
|
||||
function cleanup
|
||||
{
|
||||
if [[ -d $TESTDIR ]]; then
|
||||
cd $TESTDIR
|
||||
$RM -rf $TESTDIR/*
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# According to specified access or acl_spec, do relevant operating by using the
|
||||
# specified user.
|
||||
#
|
||||
# $1 specified user
|
||||
# $2 node
|
||||
# $3 acl_spec or access
|
||||
#
|
||||
function rwx_node #user node acl_spec|access
|
||||
{
|
||||
typeset user=$1
|
||||
typeset node=$2
|
||||
typeset acl_spec=$3
|
||||
|
||||
if [[ $user == "" || $node == "" || $acl_spec == "" ]]; then
|
||||
log_note "node or acl_spec are not defined."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -d $node ]]; then
|
||||
case $acl_spec in
|
||||
*:read_data:*|read_data)
|
||||
chgusr_exec $user $LS -l $node > /dev/null 2>&1
|
||||
return $? ;;
|
||||
*:write_data:*|write_data)
|
||||
if [[ -f ${node}/tmpfile ]]; then
|
||||
log_must $RM -f ${node}/tmpfile
|
||||
fi
|
||||
chgusr_exec $user $TOUCH ${node}/tmpfile > \
|
||||
/dev/null 2>&1
|
||||
return $? ;;
|
||||
*"execute:"*|execute)
|
||||
chgusr_exec $user $FIND $node > /dev/null 2>&1
|
||||
return $? ;;
|
||||
esac
|
||||
else
|
||||
case $acl_spec in
|
||||
*:read_data:*|read_data)
|
||||
chgusr_exec $user $CAT $node > /dev/null 2>&1
|
||||
return $? ;;
|
||||
*:write_data:*|write_data)
|
||||
chgusr_exec $user $DD if=/usr/bin/ls of=$node > \
|
||||
/dev/null 2>&1
|
||||
return $? ;;
|
||||
*"execute:"*|execute)
|
||||
ZFS_ACL_ERR_STR=$(chgusr_exec $user $node 2>&1)
|
||||
return $? ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Get the given file/directory xattr
|
||||
#
|
||||
# $1 object -- file or directroy
|
||||
#
|
||||
function get_xattr #<obj>
|
||||
{
|
||||
typeset obj=$1
|
||||
typeset xattr
|
||||
if (( ${#obj} == 0 )); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
for xattr in `$RUNAT $obj $LS | \
|
||||
/usr/xpg4/bin/egrep -v -e SUNWattr_ro -e SUNWattr_rw` ; do
|
||||
$RUNAT $obj $SUM $xattr
|
||||
done
|
||||
}
|
||||
|
||||
#
|
||||
# Get the owner of a file/directory
|
||||
#
|
||||
function get_owner #node
|
||||
{
|
||||
typeset node=$1
|
||||
typeset value
|
||||
|
||||
if [[ -z $node ]]; then
|
||||
log_fail "node are not defined."
|
||||
fi
|
||||
|
||||
if [[ -d $node ]]; then
|
||||
value=$($LS -dl $node | $AWK '{print $3}')
|
||||
elif [[ -e $node ]]; then
|
||||
value=$($LS -l $node | $AWK '{print $3}')
|
||||
fi
|
||||
|
||||
$ECHO $value
|
||||
}
|
||||
|
||||
#
|
||||
# Get the group of a file/directory
|
||||
#
|
||||
function get_group #node
|
||||
{
|
||||
typeset node=$1
|
||||
typeset value
|
||||
|
||||
if [[ -z $node ]]; then
|
||||
log_fail "node are not defined."
|
||||
fi
|
||||
|
||||
if [[ -d $node ]]; then
|
||||
value=$($LS -dl $node | $AWK '{print $4}')
|
||||
elif [[ -e $node ]]; then
|
||||
value=$($LS -l $node | $AWK '{print $4}')
|
||||
fi
|
||||
|
||||
$ECHO $value
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Get the group name that a UID belongs to
|
||||
#
|
||||
function get_user_group #uid
|
||||
{
|
||||
typeset uid=$1
|
||||
typeset value
|
||||
|
||||
if [[ -z $uid ]]; then
|
||||
log_fail "UID not defined."
|
||||
fi
|
||||
|
||||
value=$(id $uid)
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
value=${value##*\(}
|
||||
value=${value%%\)*}
|
||||
$ECHO $value
|
||||
else
|
||||
log_fail "Invalid UID (uid)."
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Get the specified item of the specified string
|
||||
#
|
||||
# $1: Item number, count from 0.
|
||||
# $2-n: strings
|
||||
#
|
||||
function getitem
|
||||
{
|
||||
typeset -i n=$1
|
||||
shift
|
||||
|
||||
(( n += 1 ))
|
||||
eval echo \${$n}
|
||||
}
|
||||
|
||||
#
|
||||
# This function calculate the specified directory files checksum and write
|
||||
# to the specified array.
|
||||
#
|
||||
# $1 directory in which the files will be cksum.
|
||||
# $2 file array name which was used to store file cksum information.
|
||||
# $3 attribute array name which was used to store attribute information.
|
||||
#
|
||||
function cksum_files #<dir> <file_array_name> <attribute_array_name>
|
||||
{
|
||||
typeset dir=$1
|
||||
typeset farr_name=$2
|
||||
typeset aarr_name=$3
|
||||
|
||||
[[ ! -d $dir ]] && return
|
||||
typeset oldpwd=$PWD
|
||||
cd $dir
|
||||
typeset files=$($LS file*)
|
||||
|
||||
typeset -i i=0
|
||||
typeset -i n=0
|
||||
while (( i < NUM_FILE )); do
|
||||
typeset f=$(getitem $i $files)
|
||||
eval $farr_name[$i]=\$\(\$CKSUM $f\)
|
||||
|
||||
typeset -i j=0
|
||||
while (( j < NUM_ATTR )); do
|
||||
eval $aarr_name[$n]=\$\(\$RUNAT \$f \$CKSUM \
|
||||
attribute.$j\)
|
||||
|
||||
(( j += 1 ))
|
||||
(( n += 1 ))
|
||||
done
|
||||
|
||||
(( i += 1 ))
|
||||
done
|
||||
|
||||
cd $oldpwd
|
||||
}
|
||||
|
||||
#
|
||||
# This function compare two cksum results array.
|
||||
#
|
||||
# $1 The array name which stored the cksum before operation.
|
||||
# $2 The array name which stored the cksum after operation.
|
||||
#
|
||||
function compare_cksum #<array1> <array2>
|
||||
{
|
||||
typeset before=$1
|
||||
typeset after=$2
|
||||
eval typeset -i count=\${#$before[@]}
|
||||
|
||||
typeset -i i=0
|
||||
while (( i < count )); do
|
||||
eval typeset var1=\${$before[$i]}
|
||||
eval typeset var2=\${$after[$i]}
|
||||
|
||||
if [[ $var1 != $var2 ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
(( i += 1 ))
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# This function calculate all the files cksum information in current directory
|
||||
# and output them to the specified file.
|
||||
#
|
||||
# $1 directory from which the files will be cksum.
|
||||
# $2 cksum output file
|
||||
#
|
||||
function record_cksum #<outfile>
|
||||
{
|
||||
typeset dir=$1
|
||||
typeset outfile=$2
|
||||
|
||||
[[ ! -d ${outfile%/*} ]] && usr_exec $MKDIR -p ${outfile%/*}
|
||||
|
||||
usr_exec cd $dir ; $FIND . -depth -type f -exec cksum {} \\\; | \
|
||||
$SORT > $outfile
|
||||
usr_exec cd $dir ; $FIND . -depth -type f -xattr -exec runat {} \
|
||||
cksum attribute* \\\; | $SORT >> $outfile
|
||||
}
|
||||
|
||||
#
|
||||
# The function create_files creates the directories and files that the script
|
||||
# will operate on to test extended attribute functionality.
|
||||
#
|
||||
# $1 The base directory in which to create directories and files.
|
||||
#
|
||||
function create_files #<directory>
|
||||
{
|
||||
typeset basedir=$1
|
||||
|
||||
[[ ! -d $basedir ]] && usr_exec $MKDIR -m 777 $basedir
|
||||
[[ ! -d $RES_DIR ]] && usr_exec $MKDIR -m 777 $RES_DIR
|
||||
[[ ! -d $INI_DIR ]] && usr_exec $MKDIR -m 777 $INI_DIR
|
||||
[[ ! -d $TST_DIR ]] && usr_exec $MKDIR -m 777 $TST_DIR
|
||||
[[ ! -d $TMP_DIR ]] && usr_exec $MKDIR -m 777 $TMP_DIR
|
||||
|
||||
#
|
||||
# Create the original file and its attribute files.
|
||||
#
|
||||
[[ ! -a $RES_DIR/file ]] && \
|
||||
usr_exec $FILE_WRITE -o create -f $RES_DIR/file \
|
||||
-b 1024 -d 0 -c 1
|
||||
[[ ! -a $RES_DIR/attribute ]] && \
|
||||
usr_exec $CP $RES_DIR/file $RES_DIR/attribute
|
||||
|
||||
typeset oldpwd=$PWD
|
||||
cd $INI_DIR
|
||||
|
||||
typeset -i i=0
|
||||
while (( i < NUM_FILE )); do
|
||||
typeset dstfile=$INI_DIR/file.$$.$i
|
||||
usr_exec $CP $RES_DIR/file $dstfile
|
||||
|
||||
typeset -i j=0
|
||||
while (( j < NUM_ATTR )); do
|
||||
usr_exec $RUNAT $dstfile \
|
||||
$CP $RES_DIR/attribute ./attribute.$j
|
||||
(( j += 1 ))
|
||||
done
|
||||
|
||||
(( i += 1 ))
|
||||
done
|
||||
|
||||
cd $oldpwd
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/acl/posix
|
||||
dist_pkgdata_SCRIPTS = \
|
||||
cleanup.ksh \
|
||||
setup.ksh \
|
||||
posix_001_pos.ksh \
|
||||
posix_002_pos.ksh
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/acl/acl_common.kshlib
|
||||
|
||||
cleanup_user_group
|
||||
|
||||
default_cleanup
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify that user can access file/directory if acltype=posixacl.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Test access to file (mode=rw-)
|
||||
# a. Can modify file
|
||||
# b. Can't create new file
|
||||
# b. Can't execute file
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
log_assert "Verify acltype=posixacl works on file"
|
||||
|
||||
# Test access to FILE
|
||||
log_note "Testing access to FILE"
|
||||
log_must $TOUCH $TESTDIR/file.0
|
||||
log_must $SETFACL -m g:zfsgrp:rw $TESTDIR/file.0
|
||||
$GETFACL $TESTDIR/file.0 2> /dev/null | $EGREP -q "^group:zfsgrp:rw-$"
|
||||
if [ "$?" -eq "0" ]; then
|
||||
# Should be able to write to file
|
||||
log_must $SU staff1 -c "$ECHO \"$ECHO test > /dev/null\" > $TESTDIR/file.0"
|
||||
|
||||
# Should NOT be able to create new file
|
||||
log_mustnot $SU staff1 -c "$TOUCH $TESTDIR/file.1"
|
||||
|
||||
# Root should be able to run file, but not user
|
||||
chmod +x $TESTDIR/file.0
|
||||
log_must $TESTDIR/file.0
|
||||
log_mustnot $SU staff1 -c $TESTDIR/file.0
|
||||
|
||||
log_pass "POSIX ACL mode works on files"
|
||||
else
|
||||
log_fail "Group 'zfsgrp' does not have 'rw' as specified"
|
||||
fi
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify that user can access file/directory if acltype=posixacl.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Test access to directory (mode=-wx)
|
||||
# a. Can create file in dir
|
||||
# b. Can't list directory
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
log_assert "Verify acltype=posixacl works on directory"
|
||||
|
||||
# Test access to DIRECTORY
|
||||
log_note "Testing access to DIRECTORY"
|
||||
log_must $MKDIR $TESTDIR/dir.0
|
||||
log_must $SETFACL -m g:zfsgrp:wx $TESTDIR/dir.0
|
||||
$GETFACL $TESTDIR/dir.0 2> /dev/null | $EGREP -q "^group:zfsgrp:-wx$"
|
||||
if [ "$?" -eq "0" ]; then
|
||||
# Should be able to create file in directory
|
||||
log_must $SU staff1 -c "$TOUCH $TESTDIR/dir.0/file.0"
|
||||
|
||||
# Should NOT be able to list files in directory
|
||||
log_mustnot $SU staff1 -c "$LS -l $TESTDIR/dir.0"
|
||||
|
||||
log_pass "POSIX ACL mode works on directories"
|
||||
else
|
||||
log_fail "Group 'zfsgrp' does not have 'rwx' as specified"
|
||||
fi
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/acl/acl_common.kshlib
|
||||
|
||||
log_must $GETFACL --version
|
||||
log_must $SETFACL --version
|
||||
|
||||
cleanup_user_group
|
||||
|
||||
# Create staff group and add user to it
|
||||
log_must add_group $ZFS_ACL_STAFF_GROUP
|
||||
log_must add_user $ZFS_ACL_STAFF_GROUP $ZFS_ACL_STAFF1
|
||||
|
||||
DISK=${DISKS%% *}
|
||||
default_setup_noexit $DISK
|
||||
log_must $CHMOD 777 $TESTDIR
|
||||
|
||||
# Use POSIX ACLs on filesystem
|
||||
log_must $ZFS set acltype=posixacl $TESTPOOL/$TESTFS
|
||||
log_must $ZFS set xattr=sa $TESTPOOL/$TESTFS
|
||||
|
||||
log_pass
|
||||
@@ -0,0 +1,8 @@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/atime
|
||||
dist_pkgdata_SCRIPTS = \
|
||||
atime.cfg \
|
||||
atime_common.kshlib \
|
||||
cleanup.ksh \
|
||||
setup.ksh \
|
||||
atime_001_pos.ksh \
|
||||
atime_002_neg.ksh
|
||||
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
export TESTCLONE=testclone$$
|
||||
export TESTSNAP=testsnap$$
|
||||
|
||||
export TESTFILE=testfile
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/atime/atime_common.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# When atime=on, verify the access time for files is updated when read. It
|
||||
# is available to fs and clone. To snapshot, it is unavailable.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create pool and fs.
|
||||
# 2. Create '$TESTFILE' for fs.
|
||||
# 3. Create snapshot and clone.
|
||||
# 4. Setting atime=on on datasets except snapshot, and read '$TESTFILE'.
|
||||
# 5. Expect the access time is updated on datasets except snapshot.
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
log_assert "Setting atime=on, the access time for files is updated when read."
|
||||
log_onexit cleanup
|
||||
|
||||
#
|
||||
# Create $TESTFILE, snapshot and clone.
|
||||
#
|
||||
setup_snap_clone
|
||||
|
||||
for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
|
||||
do
|
||||
typeset mtpt=$(get_prop mountpoint $dst)
|
||||
|
||||
if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
|
||||
mtpt=$(snapshot_mountpoint $dst)
|
||||
log_mustnot check_atime_updated $mtpt/$TESTFILE
|
||||
else
|
||||
log_must $ZFS set atime=on $dst
|
||||
log_must check_atime_updated $mtpt/$TESTFILE
|
||||
fi
|
||||
done
|
||||
|
||||
log_pass "Verify the property atime=on passed."
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/atime/atime_common.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# When atime=off, verify the access time for files is not updated when read.
|
||||
# It is available to pool, fs snapshot and clone.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create pool, fs.
|
||||
# 2. Create '$TESTFILE' for fs.
|
||||
# 3. Create snapshot and clone.
|
||||
# 4. Setting atime=off on dataset and read '$TESTFILE'.
|
||||
# 5. Verify the access time is not updated.
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
log_assert "Setting atime=off, the access time for files will not be updated \
|
||||
when read."
|
||||
log_onexit cleanup
|
||||
|
||||
#
|
||||
# Create $TESTFILE, snapshot and clone.
|
||||
#
|
||||
setup_snap_clone
|
||||
|
||||
for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
|
||||
do
|
||||
typeset mtpt=$(get_prop mountpoint $dst)
|
||||
|
||||
if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
|
||||
mtpt=$(snapshot_mountpoint $dst)
|
||||
else
|
||||
log_must $ZFS set atime=off $dst
|
||||
fi
|
||||
|
||||
log_mustnot check_atime_updated $mtpt/$TESTFILE
|
||||
done
|
||||
|
||||
log_pass "Verify the property atime=off passed."
|
||||
@@ -0,0 +1,78 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/atime/atime.cfg
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Check if the access time for specified file is updated.
|
||||
#
|
||||
# $1 Given an absolute path to a file name
|
||||
#
|
||||
# Return value:
|
||||
# 0 -> The access time is updated.
|
||||
# 1 -> The access time is not updated.
|
||||
#
|
||||
function check_atime_updated
|
||||
{
|
||||
typeset filename=$1
|
||||
|
||||
if is_linux; then
|
||||
typeset before=$(stat -c %X $filename)
|
||||
sleep 2
|
||||
else
|
||||
typeset before=$($LS -Eu $filename | $AWK '{print $7}')
|
||||
fi
|
||||
|
||||
log_must $CAT $filename
|
||||
|
||||
if is_linux; then
|
||||
typeset after=$(stat -c %X $filename)
|
||||
else
|
||||
typeset after=$($LS -Eu $filename | $AWK '{print $7}')
|
||||
fi
|
||||
|
||||
if [[ $before != $after ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function setup_snap_clone
|
||||
{
|
||||
# Create two file to verify snapshot.
|
||||
log_must $TOUCH $TESTDIR/$TESTFILE
|
||||
|
||||
create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
|
||||
create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE
|
||||
}
|
||||
|
||||
function cleanup
|
||||
{
|
||||
destroy_clone $TESTPOOL/$TESTCLONE
|
||||
destroy_snapshot $TESTPOOL/$TESTFS@$TESTSNAP
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
default_cleanup
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
DISK=${DISKS%% *}
|
||||
default_setup $DISK
|
||||
@@ -0,0 +1,12 @@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/bootfs
|
||||
dist_pkgdata_SCRIPTS = \
|
||||
cleanup.ksh \
|
||||
setup.ksh \
|
||||
bootfs_001_pos.ksh \
|
||||
bootfs_002_neg.ksh \
|
||||
bootfs_003_pos.ksh \
|
||||
bootfs_004_neg.ksh \
|
||||
bootfs_005_neg.ksh \
|
||||
bootfs_006_pos.ksh \
|
||||
bootfs_007_neg.ksh \
|
||||
bootfs_008_neg.ksh
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
# Copyright 2015 Nexenta Systems, Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Valid datasets and snapshots are accepted as bootfs property values
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a set of datasets and snapshots in a test pool
|
||||
# 2. Try setting them as boot filesystems
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
if poolexists $TESTPOOL ; then
|
||||
log_must $ZPOOL destroy $TESTPOOL
|
||||
fi
|
||||
|
||||
if [[ -f $VDEV ]]; then
|
||||
log_must $RM -f $VDEV
|
||||
fi
|
||||
}
|
||||
|
||||
$ZPOOL set 2>&1 | $GREP bootfs > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
log_unsupported "bootfs pool property not supported on this release."
|
||||
fi
|
||||
|
||||
log_assert "Valid datasets are accepted as bootfs property values"
|
||||
log_onexit cleanup
|
||||
|
||||
typeset VDEV=$TESTDIR/bootfs_001_pos_a.$$.dat
|
||||
|
||||
log_must $MKFILE 400m $VDEV
|
||||
create_pool "$TESTPOOL" "$VDEV"
|
||||
log_must $ZFS create $TESTPOOL/$TESTFS
|
||||
|
||||
log_must $ZFS snapshot $TESTPOOL/$TESTFS@snap
|
||||
log_must $ZFS clone $TESTPOOL/$TESTFS@snap $TESTPOOL/clone
|
||||
|
||||
log_must $ZPOOL set bootfs=$TESTPOOL/$TESTFS $TESTPOOL
|
||||
log_must $ZPOOL set bootfs=$TESTPOOL/$TESTFS@snap $TESTPOOL
|
||||
log_must $ZPOOL set bootfs=$TESTPOOL/clone $TESTPOOL
|
||||
|
||||
log_must $ZFS promote $TESTPOOL/clone
|
||||
log_must $ZPOOL set bootfs=$TESTPOOL/clone $TESTPOOL
|
||||
log_pass "Valid datasets are accepted as bootfs property values"
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
# Copyright 2015 Nexenta Systems, Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Invalid datasets are rejected as boot property values
|
||||
#
|
||||
# STRATEGY:
|
||||
#
|
||||
# 1. Create a zvol
|
||||
# 2. Verify that we can't set the bootfs to that dataset
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
if datasetexists $TESTPOOL/vol
|
||||
then
|
||||
log_must $ZFS destroy $TESTPOOL/vol
|
||||
fi
|
||||
if poolexists $TESTPOOL
|
||||
then
|
||||
log_must $ZPOOL destroy $TESTPOOL
|
||||
fi
|
||||
if [[ -f $VDEV ]]; then
|
||||
log_must $RM -f $VDEV
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
$ZPOOL set 2>&1 | $GREP bootfs > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
log_unsupported "bootfs pool property not supported on this release."
|
||||
fi
|
||||
|
||||
log_assert "Invalid datasets are rejected as boot property values"
|
||||
log_onexit cleanup
|
||||
|
||||
typeset VDEV=$TESTDIR/bootfs_002_neg_a.$$.dat
|
||||
|
||||
log_must $MKFILE 400m $VDEV
|
||||
create_pool "$TESTPOOL" "$VDEV"
|
||||
log_must $ZFS create -V 10m $TESTPOOL/vol
|
||||
block_device_wait
|
||||
|
||||
log_mustnot $ZPOOL set bootfs=$TESTPOOL/vol $TESTPOOL
|
||||
|
||||
log_pass "Invalid datasets are rejected as boot property values"
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Valid pool names are accepted
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Using a list of valid pool names
|
||||
# 2. Create a filesystem in that pool
|
||||
# 2. Verify we can set the bootfs to that filesystem
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
set -A pools "pool.$$" "pool123" "mypool"
|
||||
|
||||
function cleanup {
|
||||
if poolexists $POOL ; then
|
||||
log_must $ZPOOL destroy $POOL
|
||||
fi
|
||||
$RM /bootfs_003.$$.dat
|
||||
}
|
||||
|
||||
|
||||
$ZPOOL set 2>&1 | $GREP bootfs > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
log_unsupported "bootfs pool property not supported on this release."
|
||||
fi
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Valid pool names are accepted by zpool set bootfs"
|
||||
$MKFILE 64m $TESTDIR/bootfs_003.$$.dat
|
||||
|
||||
typeset -i i=0;
|
||||
|
||||
while [ $i -lt "${#pools[@]}" ]
|
||||
do
|
||||
POOL=${pools[$i]}
|
||||
log_must $ZPOOL create $POOL $TESTDIR/bootfs_003.$$.dat
|
||||
log_must $ZFS create $POOL/$TESTFS
|
||||
|
||||
log_must $ZPOOL set bootfs=$POOL/$TESTFS $POOL
|
||||
RES=$($ZPOOL get bootfs $POOL | $TAIL -1 | $AWK '{print $3}' )
|
||||
if [ $RES != "$POOL/$TESTFS" ]
|
||||
then
|
||||
log_fail "Expected $RES == $POOL/$TESTFS"
|
||||
fi
|
||||
log_must $ZPOOL destroy $POOL
|
||||
i=$(( $i + 1 ))
|
||||
done
|
||||
|
||||
log_pass "Valid pool names are accepted by zpool set bootfs"
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Invalid pool names are rejected by zpool set bootfs
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Try to set bootfs on some non-existent pools
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
set -A pools "pool//$$" "pool%d123" "mirror" "c0t0d0s0" "pool*23*" "*po!l" \
|
||||
"%s££%^"
|
||||
|
||||
function cleanup {
|
||||
if poolexists $POOL; then
|
||||
log_must $ZPOOL destroy $POOL
|
||||
fi
|
||||
$RM /bootfs_004.$$.dat
|
||||
}
|
||||
|
||||
|
||||
$ZPOOL set 2>&1 | $GREP bootfs > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
log_unsupported "bootfs pool property not supported on this release."
|
||||
fi
|
||||
|
||||
log_assert "Invalid pool names are rejected by zpool set bootfs"
|
||||
log_onexit cleanup
|
||||
|
||||
# here, we build up a large string and add it to the list of pool names
|
||||
# a word to the ksh-wary, ${#array[@]} gives you the
|
||||
# total number of entries in an array, so array[${#array[@]}]
|
||||
# will index the last entry+1, ksh arrays start at index 0.
|
||||
COUNT=0
|
||||
while [ $COUNT -le 1025 ]
|
||||
do
|
||||
bigname="${bigname}o"
|
||||
COUNT=$(( $COUNT + 1 ))
|
||||
done
|
||||
pools[${#pools[@]}]="$bigname"
|
||||
|
||||
|
||||
|
||||
$MKFILE 64m $TESTDIR/bootfs_004.$$.dat
|
||||
|
||||
typeset -i i=0;
|
||||
|
||||
while [ $i -lt "${#pools[@]}" ]
|
||||
do
|
||||
POOL=${pools[$i]}/$TESTFS
|
||||
log_mustnot $ZPOOL create $POOL $TESTDIR/bootfs_004.$$.dat
|
||||
log_mustnot $ZFS create $POOL/$TESTFS
|
||||
log_mustnot $ZPOOL set bootfs=$POOL/$TESTFS $POOL
|
||||
|
||||
i=$(( $i + 1 ))
|
||||
done
|
||||
|
||||
log_pass "Invalid pool names are rejected by zpool set bootfs"
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Boot properties cannot be set on pools with older versions
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Copy and import some pools of older versions
|
||||
# 2. Create a filesystem on each
|
||||
# 3. Verify that zpool set bootfs fails on each
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
|
||||
#
|
||||
# we need destroy pools that created on top of $TESTPOOL first
|
||||
#
|
||||
typeset pool_name
|
||||
for config in $CONFIGS; do
|
||||
pool_name=$(eval $ECHO \$ZPOOL_VERSION_${config}_NAME)
|
||||
if poolexists $pool_name; then
|
||||
log_must $ZPOOL destroy $pool_name
|
||||
fi
|
||||
done
|
||||
|
||||
if poolexists $TESTPOOL ; then
|
||||
log_must $ZPOOL destroy $TESTPOOL
|
||||
fi
|
||||
}
|
||||
|
||||
log_assert "Boot properties cannot be set on pools with older versions"
|
||||
|
||||
# These are configs from zpool_upgrade.cfg - see that file for more info.
|
||||
CONFIGS="1 2 3"
|
||||
|
||||
log_onexit cleanup
|
||||
log_must $ZPOOL create -f $TESTPOOL $DISKS
|
||||
|
||||
for config in $CONFIGS
|
||||
do
|
||||
create_old_pool $config
|
||||
POOL_NAME=$(eval $ECHO \$ZPOOL_VERSION_${config}_NAME)
|
||||
log_must $ZFS create $POOL_NAME/$TESTFS
|
||||
log_mustnot $ZPOOL set bootfs=$POOL_NAME/$TESTFS $POOL_NAME
|
||||
log_must destroy_upgraded_pool $config
|
||||
done
|
||||
|
||||
log_pass "Boot properties cannot be set on pools with older versions"
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Pools of correct vdev types accept boot property
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. create pools of each vdev type (raid, raidz, raidz2, mirror + hotspares)
|
||||
# 2. verify we can set bootfs on each pool type according to design
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
|
||||
$ZPOOL set 2>&1 | $GREP bootfs > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
log_unsupported "bootfs pool property not supported on this release."
|
||||
fi
|
||||
|
||||
VDEV1=$TESTDIR/bootfs_006_pos_a.$$.dat
|
||||
VDEV2=$TESTDIR/bootfs_006_pos_b.$$.dat
|
||||
VDEV3=$TESTDIR/bootfs_006_pos_c.$$.dat
|
||||
VDEV4=$TESTDIR/bootfs_006_pos_d.$$.dat
|
||||
|
||||
function verify_bootfs { # $POOL
|
||||
POOL=$1
|
||||
log_must $ZFS create $POOL/$TESTFS
|
||||
|
||||
log_must $ZPOOL set bootfs=$POOL/$TESTFS $POOL
|
||||
VAL=$($ZPOOL get bootfs $POOL | $TAIL -1 | $AWK '{print $3}' )
|
||||
if [ $VAL != "$POOL/$TESTFS" ]
|
||||
then
|
||||
log_must $ZPOOL status -v $POOL
|
||||
log_fail \
|
||||
"set/get failed on $POOL - expected $VAL == $POOL/$TESTFS"
|
||||
fi
|
||||
log_must $ZPOOL destroy $POOL
|
||||
}
|
||||
|
||||
function verify_no_bootfs { # $POOL
|
||||
POOL=$1
|
||||
log_must $ZFS create $POOL/$TESTFS
|
||||
log_mustnot $ZPOOL set bootfs=$POOL/$TESTFS $POOL
|
||||
VAL=$($ZPOOL get bootfs $POOL | $TAIL -1 | $AWK '{print $3}' )
|
||||
if [ $VAL == "$POOL/$TESTFS" ]
|
||||
then
|
||||
log_must $ZPOOL status -v $POOL
|
||||
log_fail "set/get unexpectedly failed $VAL != $POOL/$TESTFS"
|
||||
fi
|
||||
log_must $ZPOOL destroy $POOL
|
||||
}
|
||||
|
||||
function cleanup {
|
||||
if poolexists $TESTPOOL
|
||||
then
|
||||
log_must $ZPOOL destroy $TESTPOOL
|
||||
fi
|
||||
log_must $RM $VDEV1 $VDEV2 $VDEV3 $VDEV4
|
||||
}
|
||||
|
||||
log_assert "Pools of correct vdev types accept boot property"
|
||||
|
||||
|
||||
|
||||
log_onexit cleanup
|
||||
log_must $MKFILE 64m $VDEV1 $VDEV2 $VDEV3 $VDEV4
|
||||
|
||||
|
||||
## the following configurations are supported bootable pools
|
||||
|
||||
# normal
|
||||
log_must $ZPOOL create $TESTPOOL $VDEV1
|
||||
verify_bootfs $TESTPOOL
|
||||
|
||||
# normal + hotspare
|
||||
log_must $ZPOOL create $TESTPOOL $VDEV1 spare $VDEV2
|
||||
verify_bootfs $TESTPOOL
|
||||
|
||||
# mirror
|
||||
log_must $ZPOOL create $TESTPOOL mirror $VDEV1 $VDEV2
|
||||
verify_bootfs $TESTPOOL
|
||||
|
||||
# mirror + hotspare
|
||||
log_must $ZPOOL create $TESTPOOL mirror $VDEV1 $VDEV2 spare $VDEV3
|
||||
verify_bootfs $TESTPOOL
|
||||
|
||||
## the following configurations are not supported as bootable pools
|
||||
|
||||
# stripe
|
||||
log_must $ZPOOL create $TESTPOOL $VDEV1 $VDEV2
|
||||
verify_no_bootfs $TESTPOOL
|
||||
|
||||
# stripe + hotspare
|
||||
log_must $ZPOOL create $TESTPOOL $VDEV1 $VDEV2 spare $VDEV3
|
||||
verify_no_bootfs $TESTPOOL
|
||||
|
||||
# raidz
|
||||
log_must $ZPOOL create $TESTPOOL raidz $VDEV1 $VDEV2
|
||||
verify_no_bootfs $TESTPOOL
|
||||
|
||||
# raidz + hotspare
|
||||
log_must $ZPOOL create $TESTPOOL raidz $VDEV1 $VDEV2 spare $VDEV3
|
||||
verify_no_bootfs $TESTPOOL
|
||||
|
||||
# raidz2
|
||||
log_must $ZPOOL create $TESTPOOL raidz2 $VDEV1 $VDEV2 $VDEV3
|
||||
verify_no_bootfs $TESTPOOL
|
||||
|
||||
# raidz2 + hotspare
|
||||
log_must $ZPOOL create $TESTPOOL raidz2 $VDEV1 $VDEV2 $VDEV3 spare $VDEV4
|
||||
verify_no_bootfs $TESTPOOL
|
||||
|
||||
log_pass "Pools of correct vdev types accept boot property"
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Setting bootfs on a pool which was configured with the whole disk
|
||||
# (i.e. EFI) will fail
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. create a pool with a whole disk
|
||||
# 2. create a filesystem on this pool
|
||||
# 3. verify we can not set bootfs on the filesystem we just created.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
if poolexists $TESTPOOL ; then
|
||||
destroy_pool "$TESTPOOL"
|
||||
fi
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
DISK=${DISKS%% *}
|
||||
typeset EFI_BOOTFS=$TESTPOOL/efs
|
||||
typeset assert_mesg="setting bootfs on a pool which was configured with the \
|
||||
whole disk will fail"
|
||||
|
||||
log_assert $assert_mesg
|
||||
create_pool "$TESTPOOL" "$DISK"
|
||||
log_must $ZFS create $EFI_BOOTFS
|
||||
|
||||
if is_linux; then
|
||||
log_must $ZPOOL set bootfs=$EFI_BOOTFS $TESTPOOL
|
||||
else
|
||||
log_mustnot $ZPOOL set bootfs=$EFI_BOOTFS $TESTPOOL
|
||||
fi
|
||||
|
||||
log_pass $assert_mesg
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
# Copyright 2015 Nexenta Systems, Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Setting bootfs on a pool which was configured with the whole disk
|
||||
# (i.e. EFI) works.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. create a pool with a whole disk
|
||||
# 2. create a filesystem on this pool
|
||||
# 3. verify we can set bootfs on the filesystem we just created.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
if poolexists $TESTPOOL ; then
|
||||
destroy_pool "$TESTPOOL"
|
||||
fi
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
DISK=${DISKS%% *}
|
||||
typeset EFI_BOOTFS=$TESTPOOL/efs
|
||||
typeset assert_mesg="setting bootfs on a pool which was configured with the \
|
||||
whole disk works"
|
||||
|
||||
log_assert $assert_mesg
|
||||
create_pool "$TESTPOOL" "$DISK"
|
||||
log_must $ZFS create $EFI_BOOTFS
|
||||
|
||||
log_must $ZPOOL set bootfs=$EFI_BOOTFS $TESTPOOL
|
||||
|
||||
log_pass $assert_mesg
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# 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 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# setting bootfs on a dataset which has gzip compression enabled will fail
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. create pools based on a valid vdev
|
||||
# 2. create a filesytem on this pool and set the compression property to gzip1-9
|
||||
# 3. set the pool's bootfs property to filesystem we just configured which
|
||||
# should fail
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
if poolexists $TESTPOOL ; then
|
||||
destroy_pool "$TESTPOOL"
|
||||
fi
|
||||
|
||||
if [[ -f $VDEV ]]; then
|
||||
log_must $RM -f $VDEV
|
||||
fi
|
||||
}
|
||||
|
||||
typeset assert_msg="setting bootfs on a dataset which has gzip \
|
||||
compression enabled will fail"
|
||||
|
||||
typeset VDEV=$TESTDIR/bootfs_008_neg_a.$$.dat
|
||||
typeset COMP_FS=$TESTPOOL/COMP_FS
|
||||
|
||||
log_onexit cleanup
|
||||
log_assert $assert_msg
|
||||
|
||||
log_must $MKFILE 300m $VDEV
|
||||
log_must $ZPOOL create $TESTPOOL $VDEV
|
||||
log_must $ZFS create $COMP_FS
|
||||
|
||||
typeset -i i=0
|
||||
set -A gtype "gzip" "gzip-1" "gzip-2" "gzip-3" "gzip-4" "gzip-5" \
|
||||
"gzip-6" "gzip-7" "gzip-8" "gzip-9"
|
||||
|
||||
while (( i < ${#gtype[@]} )); do
|
||||
log_must $ZFS set compression=${gtype[i]} $COMP_FS
|
||||
log_mustnot $ZPOOL set bootfs=$COMP_FS $TESTPOOL
|
||||
log_must $ZFS set compression=off $COMP_FS
|
||||
(( i += 1 ))
|
||||
done
|
||||
|
||||
log_pass $assert_msg
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
#! /bin/ksh -p
|
||||
#
|
||||
# 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 (c) 2015 by Lawrence Livermore National Security, LLC
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
[[ -e $TESTDIR ]] && $RM -rf $TESTDIR
|
||||
|
||||
log_pass
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
#! /bin/ksh -p
|
||||
#
|
||||
# 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 (c) 2015 by Lawrence Livermore National Security, LLC.
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_must $MKDIR $TESTDIR
|
||||
|
||||
log_pass
|
||||
@@ -0,0 +1,17 @@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cache
|
||||
dist_pkgdata_SCRIPTS = \
|
||||
cache.cfg \
|
||||
cache.kshlib \
|
||||
cleanup.ksh \
|
||||
setup.ksh \
|
||||
cache_001_pos.ksh \
|
||||
cache_002_pos.ksh \
|
||||
cache_003_pos.ksh \
|
||||
cache_004_neg.ksh \
|
||||
cache_005_neg.ksh \
|
||||
cache_006_pos.ksh \
|
||||
cache_007_neg.ksh \
|
||||
cache_008_neg.ksh \
|
||||
cache_009_pos.ksh \
|
||||
cache_010_neg.ksh \
|
||||
cache_011_pos.ksh
|
||||
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or http://www.opensolaris.org/os/licensing.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
function set_disks
|
||||
{
|
||||
set -A disk_array $(find_disks $DISKS)
|
||||
|
||||
typeset -i DISK_ARRAY_NUM=0
|
||||
|
||||
if (( ${#disk_array[*]} <= 1 )); then
|
||||
export DISK=${DISKS%% *}
|
||||
else
|
||||
export DISK=""
|
||||
typeset -i i=0
|
||||
while (( i < ${#disk_array[*]} )); do
|
||||
export DISK${i}="${disk_array[$i]}"
|
||||
DISKSARRAY="$DISKSARRAY ${disk_array[$i]}"
|
||||
(( i = i + 1 ))
|
||||
done
|
||||
export DISK_ARRAY_NUM=$i
|
||||
export DISKSARRAY
|
||||
fi
|
||||
|
||||
if (( $DISK_ARRAY_NUM == 0 )); then
|
||||
export disk=$DISK
|
||||
else
|
||||
export disk=$DISK0
|
||||
fi
|
||||
}
|
||||
|
||||
set_disks
|
||||
|
||||
export SIZE=64M
|
||||
|
||||
export VDIR=$TESTDIR/disk.cache
|
||||
export VDIR2=$TESTDIR/disk2.cache
|
||||
|
||||
export VDEV="$VDIR/a $VDIR/b $VDIR/c"
|
||||
export LDEV="$DISK0"
|
||||
export VDEV2="$VDIR2/a $VDIR2/b $VDIR2/c"
|
||||
export LDEV2="$DISK1"
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
#
|
||||
# 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 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
# Use is subject to license terms.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
function cleanup
|
||||
{
|
||||
if datasetexists $TESTPOOL ; then
|
||||
log_must $ZPOOL destroy -f $TESTPOOL
|
||||
fi
|
||||
if datasetexists $TESTPOOL2 ; then
|
||||
log_must $ZPOOL destroy -f $TESTPOOL2
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Try zpool status/iostat for given pool
|
||||
#
|
||||
# $1 pool
|
||||
#
|
||||
function display_status
|
||||
{
|
||||
typeset pool=$1
|
||||
|
||||
typeset -i ret=0
|
||||
$ZPOOL status -xv $pool > /dev/null 2>&1
|
||||
ret=$?
|
||||
|
||||
$ZPOOL iostat > /dev/null 2>&1
|
||||
((ret |= $?))
|
||||
|
||||
typeset mntpnt=$(get_prop mountpoint $pool)
|
||||
$DD if=/dev/random of=$mntpnt/testfile.$$ &
|
||||
typeset pid=$!
|
||||
|
||||
$ZPOOL iostat -v 1 3 > /dev/null
|
||||
((ret |= $?))
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
#
|
||||
# Verify the given cache device have correct type and status
|
||||
#
|
||||
# $1 pool name
|
||||
# $2 device name
|
||||
# $3 device status
|
||||
# $4 device type
|
||||
#
|
||||
function verify_cache_device
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset device=$2
|
||||
typeset status=$3
|
||||
typeset type=$4
|
||||
|
||||
if [[ -z $pool || -z $device || -z $status ]]; then
|
||||
log_fail "Usage: verify_cache_device <pool> <device> " \
|
||||
"<status> [type]"
|
||||
fi
|
||||
|
||||
if [[ $WRAPPER == *"smi"* ]]; then
|
||||
$ECHO $device | $EGREP "^c[0-F]+([td][0-F]+)+$" > /dev/null 2>&1
|
||||
if (( $? == 0 )); then
|
||||
device=${device}s2
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Get all the cache devices and status table like below
|
||||
#
|
||||
# mirror:/disks/d ONLINE mirror:/disks/e ONLINE stripe:/disks/f ONLINE
|
||||
#
|
||||
set -A dev_stat_tab $($ZPOOL status -v $pool | $NAWK 'BEGIN {start=0} \
|
||||
/\tcache/ {start=1}
|
||||
/\tmirror/ || /\tspares/ || /^$/ {start=0}
|
||||
(start==1) && /\t (\/|[a-zA-Z])/ \
|
||||
{print "stripe:" $1 " " $2}
|
||||
(start==1) && /\t (\/|[a-zA-Z])/ \
|
||||
{print "mirror:" $1 " " $2}
|
||||
# When hotspare is replacing
|
||||
(start==1) && /\t (\/|[a-zA-Z])/ \
|
||||
{print "mirror:" $1 " " $2}'
|
||||
)
|
||||
|
||||
typeset -i i=0
|
||||
typeset find=0
|
||||
while (( i < ${#dev_stat_tab[@]} )); do
|
||||
typeset dev=${dev_stat_tab[$i]}
|
||||
typeset stat=${dev_stat_tab[((i+1))]}
|
||||
|
||||
case $dev in
|
||||
stripe:$device)
|
||||
if [[ "$type" == 'mirror' ]]; then
|
||||
log_note "Unexpected type: mirror"
|
||||
return 1
|
||||
else
|
||||
if [[ $stat != $status ]]; then
|
||||
log_note "Status($stat) " \
|
||||
"!= Expected stat($status)"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
mirror:$device)
|
||||
if [[ -z "$type" || $type == 'stripe' ]]; then
|
||||
log_note "Unexpected type: stripe"
|
||||
return 1
|
||||
else
|
||||
if [[ $stat != $status ]]; then
|
||||
log_note "Status($stat) " \
|
||||
"!= Expected stat($status)"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
((i += 2))
|
||||
done
|
||||
|
||||
log_note "Can not find device: $device"
|
||||
return 1
|
||||
}
|
||||
|
||||
function verify_cache_support
|
||||
{
|
||||
$ZPOOL upgrade -v | $GREP "Cache devices" > /dev/null 2>&1
|
||||
return $?
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user