mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-28 20:09:35 +03:00
02730c333c
Enable picky cstyle checks and resolve the new warnings. The vast majority of the changes needed were to handle minor issues with whitespace formatting. This patch contains no functional changes. Non-whitespace changes are as follows: * 8 times ; to { } in for/while loop * fix missing ; in cmd/zed/agents/zfs_diagnosis.c * comment (confim -> confirm) * change endline , to ; in cmd/zpool/zpool_main.c * a number of /* BEGIN CSTYLED */ /* END CSTYLED */ blocks * /* CSTYLED */ markers * change == 0 to ! * ulong to unsigned long in module/zfs/dsl_scan.c * rearrangement of module_param lines in module/zfs/metaslab.c * add { } block around statement after for_each_online_node Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov> Reviewed-by: Håkan Johansson <f96hajo@chalmers.se> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #5465
703 lines
15 KiB
C
703 lines
15 KiB
C
/*
|
|
* 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:rRko:";
|
|
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' },
|
|
{ "only", required_argument, 0, 'o' },
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
enum phases {
|
|
PHASE_ALL = 0,
|
|
PHASE_CREATE,
|
|
PHASE_SETXATTR,
|
|
PHASE_GETXATTR,
|
|
PHASE_UNLINK,
|
|
PHASE_INVAL
|
|
};
|
|
|
|
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 = 6;
|
|
static int size_is_random = 0;
|
|
static int value_is_random = 0;
|
|
static int keep_files = 0;
|
|
static int phase = PHASE_ALL;
|
|
static char path[PATH_MAX] = "/tmp/xattrtest";
|
|
static char script[PATH_MAX] = "/bin/true";
|
|
static char xattrbytes[XATTR_SIZE_MAX];
|
|
|
|
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> ] [-o <phase>]\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"
|
|
" --only -o <num> Only run phase N\n"
|
|
" 0=all, 1=create, 2=setxattr,\n"
|
|
" 3=getxattr, 4=unlink\n\n");
|
|
|
|
return (1);
|
|
}
|
|
|
|
static int
|
|
parse_args(int argc, char **argv)
|
|
{
|
|
long seed = time(NULL);
|
|
int c;
|
|
int rc = 0;
|
|
|
|
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 (phase != PHASE_ALL) {
|
|
fprintf(stderr,
|
|
"Error: -y and -o 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 -s value may not "
|
|
"be greater than %d\n", XATTR_SIZE_MAX);
|
|
rc = 1;
|
|
}
|
|
break;
|
|
case 'p':
|
|
strncpy(path, optarg, PATH_MAX);
|
|
path[PATH_MAX - 1] = '\0';
|
|
break;
|
|
case 'c':
|
|
synccaches = 1;
|
|
break;
|
|
case 'd':
|
|
dropcaches = 1;
|
|
break;
|
|
case 't':
|
|
strncpy(script, optarg, PATH_MAX);
|
|
script[PATH_MAX - 1] = '\0';
|
|
break;
|
|
case 'e':
|
|
seed = strtol(optarg, NULL, 0);
|
|
break;
|
|
case 'r':
|
|
size_is_random = 1;
|
|
break;
|
|
case 'R':
|
|
value_is_random = 1;
|
|
break;
|
|
case 'k':
|
|
keep_files = 1;
|
|
break;
|
|
case 'o':
|
|
phase = strtol(optarg, NULL, 0);
|
|
if (phase <= PHASE_ALL || phase >= PHASE_INVAL) {
|
|
fprintf(stderr, "Error: the -o value must be "
|
|
"greater than %d and less than %d\n",
|
|
PHASE_ALL, PHASE_INVAL);
|
|
rc = 1;
|
|
}
|
|
if (verify == 1) {
|
|
fprintf(stderr,
|
|
"Error: -y and -o are incompatible.\n");
|
|
rc = 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, "only: %d\n", phase);
|
|
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);
|
|
(void) close(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 double
|
|
timeval_sub_seconds(struct timeval *tv1, struct timeval *tv2)
|
|
{
|
|
struct timeval delta;
|
|
|
|
timeval_sub(&delta, tv1, tv2);
|
|
return ((double)delta.tv_usec / USEC_PER_SEC + delta.tv_sec);
|
|
}
|
|
|
|
static int
|
|
create_files(void)
|
|
{
|
|
int i, rc;
|
|
char *file = NULL;
|
|
struct timeval start, stop;
|
|
double seconds;
|
|
|
|
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);
|
|
seconds = timeval_sub_seconds(&stop, &start);
|
|
fprintf(stdout, "create: %f seconds %f creates/second\n",
|
|
seconds, files / seconds);
|
|
|
|
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;
|
|
double seconds;
|
|
|
|
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);
|
|
shift = sprintf(value, "size=%d ", rnd_size);
|
|
memcpy(value + shift, xattrbytes,
|
|
sizeof (xattrbytes) - 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);
|
|
seconds = timeval_sub_seconds(&stop, &start);
|
|
fprintf(stdout, "setxattr: %f seconds %f setxattrs/second\n",
|
|
seconds, (files * xattrs) / seconds);
|
|
|
|
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 *verify_string;
|
|
char *value = NULL;
|
|
char *value_string;
|
|
char *file = NULL;
|
|
struct timeval start, stop;
|
|
double seconds;
|
|
|
|
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;
|
|
}
|
|
|
|
verify_string = value_is_random ? "<random>" : verify_value;
|
|
value_string = value_is_random ? "<random>" : value;
|
|
|
|
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)
|
|
continue;
|
|
|
|
sscanf(value, "size=%d [a-z]", &rnd_size);
|
|
shift = sprintf(verify_value, "size=%d ",
|
|
rnd_size);
|
|
memcpy(verify_value + shift, xattrbytes,
|
|
sizeof (xattrbytes) - shift);
|
|
|
|
if (rnd_size != rc ||
|
|
memcmp(verify_value, value, rnd_size)) {
|
|
ERROR("Error %d: verify failed\n "
|
|
"verify: %s\n value: %s\n", EINVAL,
|
|
verify_string, value_string);
|
|
rc = 1;
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
|
|
(void) gettimeofday(&stop, NULL);
|
|
seconds = timeval_sub_seconds(&stop, &start);
|
|
fprintf(stdout, "getxattr: %f seconds %f getxattrs/second\n",
|
|
seconds, (files * xattrs) / seconds);
|
|
|
|
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;
|
|
double seconds;
|
|
|
|
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);
|
|
free(file);
|
|
return (errno);
|
|
}
|
|
}
|
|
|
|
(void) gettimeofday(&stop, NULL);
|
|
seconds = timeval_sub_seconds(&stop, &start);
|
|
fprintf(stdout, "unlink: %f seconds %f unlinks/second\n",
|
|
seconds, files / seconds);
|
|
|
|
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);
|
|
|
|
if (value_is_random) {
|
|
size_t rndsz = sizeof (xattrbytes);
|
|
|
|
rc = get_random_bytes(xattrbytes, rndsz);
|
|
if (rc < rndsz) {
|
|
ERROR("Error %d: get_random_bytes() wanted %zd "
|
|
"got %d\n", errno, rndsz, rc);
|
|
return (rc);
|
|
}
|
|
} else {
|
|
memset(xattrbytes, 'x', sizeof (xattrbytes));
|
|
}
|
|
|
|
if (phase == PHASE_ALL || phase == PHASE_CREATE) {
|
|
rc = create_files();
|
|
if (rc)
|
|
return (rc);
|
|
}
|
|
|
|
if (phase == PHASE_ALL || phase == PHASE_SETXATTR) {
|
|
rc = setxattrs();
|
|
if (rc)
|
|
return (rc);
|
|
}
|
|
|
|
if (phase == PHASE_ALL || phase == PHASE_GETXATTR) {
|
|
rc = getxattrs();
|
|
if (rc)
|
|
return (rc);
|
|
}
|
|
|
|
if (!keep_files && (phase == PHASE_ALL || phase == PHASE_UNLINK)) {
|
|
rc = unlink_files();
|
|
if (rc)
|
|
return (rc);
|
|
}
|
|
|
|
return (0);
|
|
}
|