aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNed Bass <[email protected]>2015-04-10 15:17:30 -0700
committerBrian Behlendorf <[email protected]>2016-06-24 13:12:43 -0700
commit81285582b9898374e98d1d6d55ccac8340408d72 (patch)
tree9f68608b0dfd603e4565fd965d94b5f48f9b6423
parentd14fa5dba1ad0e68e803435ac48ec1ea78121699 (diff)
xattrtest: allow verify with -R and other improvements
- Use a fixed buffer of random bytes when random xattr values are in effect. This eliminates the potential performance bottleneck of reading from /dev/urandom for each file. This also allows us to verify xattrs in random value mode. - Show the rate of operations per second in addition to elapsed time for each phase of the test. This may be useful for benchmarking. - Set default xattr size to 6 so that verify doesn't fail if user doesn't specify a size. We need at least six bytes to store the leading "size=X" string that is used for verification. - Allow user to execute just one phase of the test. Acceptable values for -o and their meanings are: 1 - run the create phase 2 - run the setxattr phase 3 - run the getxattr phase 4 - run the unlink phase Signed-off-by: Ned Bass <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]>
-rw-r--r--tests/zfs-tests/cmd/xattrtest/xattrtest.c192
1 files changed, 124 insertions, 68 deletions
diff --git a/tests/zfs-tests/cmd/xattrtest/xattrtest.c b/tests/zfs-tests/cmd/xattrtest/xattrtest.c
index 22f798db2..6b07d141a 100644
--- a/tests/zfs-tests/cmd/xattrtest/xattrtest.c
+++ b/tests/zfs-tests/cmd/xattrtest/xattrtest.c
@@ -51,7 +51,7 @@ extern char *program_invocation_short_name;
program_invocation_short_name, __FILE__, __LINE__, \
__func__, ## __VA_ARGS__);
-static const char shortopts[] = "hvycdn:f:x:s:p:t:e:rRk";
+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' },
@@ -68,9 +68,19 @@ static const struct option longopts[] = {
{ "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;
@@ -78,18 +88,22 @@ static int dropcaches = 0;
static int nth = 0;
static int files = 1000;
static int xattrs = 1;
-static int size = 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> ]\n", argv[0]);
+ " [-s <bytes>] [-p <path>] [-t <script> ] [-o <phase>]\n",
+ argv[0]);
+
fprintf(stderr,
" --help -h This help\n"
" --verbose -v Increase verbosity\n"
@@ -105,9 +119,12 @@ usage(int argc, char **argv) {
" --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");
+ " --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 (0);
+ return (1);
}
static int
@@ -115,7 +132,7 @@ parse_args(int argc, char **argv)
{
long seed = time(NULL);
int c;
- int rc;
+ int rc = 0;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
@@ -126,9 +143,9 @@ parse_args(int argc, char **argv)
break;
case 'y':
verify = 1;
- if (value_is_random != 0) {
+ if (phase != PHASE_ALL) {
fprintf(stderr,
- "Error: -y and -R are incompatible.\n");
+ "Error: -y and -o are incompatible.\n");
rc = 1;
}
break;
@@ -144,8 +161,8 @@ parse_args(int argc, char **argv)
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);
+ fprintf(stderr, "Error: the -s value may not "
+ "be greater than %d\n", XATTR_SIZE_MAX);
rc = 1;
}
break;
@@ -169,15 +186,24 @@ parse_args(int argc, char **argv)
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;
+ 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;
@@ -204,6 +230,7 @@ parse_args(int argc, char **argv)
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");
}
@@ -319,12 +346,22 @@ timeval_sub(struct timeval *delta, struct timeval *tv1, struct timeval *tv2)
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, delta;
+ struct timeval start, stop;
+ double seconds;
file = malloc(PATH_MAX);
if (file == NULL) {
@@ -366,9 +403,9 @@ create_files(void)
}
(void) gettimeofday(&stop, NULL);
- timeval_sub(&delta, &stop, &start);
- fprintf(stdout, "create: %d.%d seconds\n",
- (int)delta.tv_sec, (int)delta.tv_usec);
+ seconds = timeval_sub_seconds(&stop, &start);
+ fprintf(stdout, "create: %f seconds %f creates/second\n",
+ seconds, files / seconds);
rc = post_hook("post");
out:
@@ -408,7 +445,8 @@ setxattrs(void)
char name[XATTR_NAME_MAX];
char *value = NULL;
char *file = NULL;
- struct timeval start, stop, delta;
+ struct timeval start, stop;
+ double seconds;
value = malloc(XATTR_SIZE_MAX);
if (value == NULL) {
@@ -439,19 +477,9 @@ setxattrs(void)
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);
- }
+ 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) {
@@ -463,9 +491,9 @@ setxattrs(void)
}
(void) gettimeofday(&stop, NULL);
- timeval_sub(&delta, &stop, &start);
- fprintf(stdout, "setxattr: %d.%d seconds\n",
- (int)delta.tv_sec, (int)delta.tv_usec);
+ seconds = timeval_sub_seconds(&stop, &start);
+ fprintf(stdout, "setxattr: %f seconds %f setxattrs/second\n",
+ seconds, (files * xattrs) / seconds);
rc = post_hook("post");
out:
@@ -484,9 +512,12 @@ 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, delta;
+ struct timeval start, stop;
+ double seconds;
verify_value = malloc(XATTR_SIZE_MAX);
if (verify_value == NULL) {
@@ -504,6 +535,9 @@ getxattrs(void)
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;
@@ -530,28 +564,30 @@ getxattrs(void)
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;
- }
+ 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);
- timeval_sub(&delta, &stop, &start);
- fprintf(stdout, "getxattr: %d.%d seconds\n",
- (int)delta.tv_sec, (int)delta.tv_usec);
+ seconds = timeval_sub_seconds(&stop, &start);
+ fprintf(stdout, "getxattr: %f seconds %f getxattrs/second\n",
+ seconds, (files * xattrs) / seconds);
rc = post_hook("post");
out:
@@ -572,7 +608,8 @@ unlink_files(void)
{
int i, rc;
char *file = NULL;
- struct timeval start, stop, delta;
+ struct timeval start, stop;
+ double seconds;
file = malloc(PATH_MAX);
if (file == NULL) {
@@ -598,9 +635,9 @@ unlink_files(void)
}
(void) gettimeofday(&stop, NULL);
- timeval_sub(&delta, &stop, &start);
- fprintf(stdout, "unlink: %d.%d seconds\n",
- (int)delta.tv_sec, (int)delta.tv_usec);
+ seconds = timeval_sub_seconds(&stop, &start);
+ fprintf(stdout, "unlink: %f seconds %f unlinks/second\n",
+ seconds, files / seconds);
rc = post_hook("post");
out:
@@ -619,19 +656,38 @@ main(int argc, char **argv)
if (rc)
return (rc);
- rc = create_files();
- if (rc)
- return (rc);
+ if (value_is_random) {
+ size_t rndsz = sizeof (xattrbytes);
- rc = setxattrs();
- if (rc)
- return (rc);
+ 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));
+ }
- rc = getxattrs();
- if (rc)
- return (rc);
+ 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) {
+ if (!keep_files && (phase == PHASE_ALL || phase == PHASE_UNLINK)) {
rc = unlink_files();
if (rc)
return (rc);