mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 11:18:52 +03:00
Adding Direct IO Support
Adding O_DIRECT support to ZFS to bypass the ARC for writes/reads.
O_DIRECT support in ZFS will always ensure there is coherency between
buffered and O_DIRECT IO requests. This ensures that all IO requests,
whether buffered or direct, will see the same file contents at all
times. Just as in other FS's , O_DIRECT does not imply O_SYNC. While
data is written directly to VDEV disks, metadata will not be synced
until the associated TXG is synced.
For both O_DIRECT read and write request the offset and request sizes,
at a minimum, must be PAGE_SIZE aligned. In the event they are not,
then EINVAL is returned unless the direct property is set to always (see
below).
For O_DIRECT writes:
The request also must be block aligned (recordsize) or the write
request will take the normal (buffered) write path. In the event that
request is block aligned and a cached copy of the buffer in the ARC,
then it will be discarded from the ARC forcing all further reads to
retrieve the data from disk.
For O_DIRECT reads:
The only alignment restrictions are PAGE_SIZE alignment. In the event
that the requested data is in buffered (in the ARC) it will just be
copied from the ARC into the user buffer.
For both O_DIRECT writes and reads the O_DIRECT flag will be ignored in
the event that file contents are mmap'ed. In this case, all requests
that are at least PAGE_SIZE aligned will just fall back to the buffered
paths. If the request however is not PAGE_SIZE aligned, EINVAL will
be returned as always regardless if the file's contents are mmap'ed.
Since O_DIRECT writes go through the normal ZIO pipeline, the
following operations are supported just as with normal buffered writes:
Checksum
Compression
Encryption
Erasure Coding
There is one caveat for the data integrity of O_DIRECT writes that is
distinct for each of the OS's supported by ZFS.
FreeBSD - FreeBSD is able to place user pages under write protection so
any data in the user buffers and written directly down to the
VDEV disks is guaranteed to not change. There is no concern
with data integrity and O_DIRECT writes.
Linux - Linux is not able to place anonymous user pages under write
protection. Because of this, if the user decides to manipulate
the page contents while the write operation is occurring, data
integrity can not be guaranteed. However, there is a module
parameter `zfs_vdev_direct_write_verify` that controls the
if a O_DIRECT writes that can occur to a top-level VDEV before
a checksum verify is run before the contents of the I/O buffer
are committed to disk. In the event of a checksum verification
failure the write will return EIO. The number of O_DIRECT write
checksum verification errors can be observed by doing
`zpool status -d`, which will list all verification errors that
have occurred on a top-level VDEV. Along with `zpool status`, a
ZED event will be issues as `dio_verify` when a checksum
verification error occurs.
ZVOLs and dedup is not currently supported with Direct I/O.
A new dataset property `direct` has been added with the following 3
allowable values:
disabled - Accepts O_DIRECT flag, but silently ignores it and treats
the request as a buffered IO request.
standard - Follows the alignment restrictions outlined above for
write/read IO requests when the O_DIRECT flag is used.
always - Treats every write/read IO request as though it passed
O_DIRECT and will do O_DIRECT if the alignment restrictions
are met otherwise will redirect through the ARC. This
property will not allow a request to fail.
There is also a module parameter zfs_dio_enabled that can be used to
force all reads and writes through the ARC. By setting this module
parameter to 0, it mimics as if the direct dataset property is set to
disabled.
Reviewed-by: Brian Behlendorf <behlendorf@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Atkinson <batkinson@lanl.gov>
Co-authored-by: Mark Maybee <mark.maybee@delphix.com>
Co-authored-by: Matt Macy <mmacy@FreeBSD.org>
Co-authored-by: Brian Behlendorf <behlendorf@llnl.gov>
Closes #10018
This commit is contained in:
@@ -693,6 +693,14 @@ tests = ['zfs_allow_001_pos', 'zfs_allow_002_pos', 'zfs_allow_003_pos',
|
||||
'zfs_unallow_007_neg', 'zfs_unallow_008_neg']
|
||||
tags = ['functional', 'delegate']
|
||||
|
||||
[tests/functional/direct]
|
||||
tests = ['dio_aligned_block', 'dio_async_always', 'dio_async_fio_ioengines',
|
||||
'dio_compression', 'dio_dedup', 'dio_encryption', 'dio_grow_block',
|
||||
'dio_max_recordsize', 'dio_mixed', 'dio_mmap', 'dio_overwrites',
|
||||
'dio_property', 'dio_random', 'dio_recordsize', 'dio_unaligned_block',
|
||||
'dio_unaligned_filesize']
|
||||
tags = ['functional', 'direct']
|
||||
|
||||
[tests/functional/exec]
|
||||
tests = ['exec_001_pos', 'exec_002_neg']
|
||||
tags = ['functional', 'exec']
|
||||
@@ -735,7 +743,7 @@ pre =
|
||||
tags = ['functional', 'inheritance']
|
||||
|
||||
[tests/functional/io]
|
||||
tests = ['sync', 'psync', 'posixaio', 'mmap']
|
||||
tests = ['mmap', 'posixaio', 'psync', 'sync']
|
||||
tags = ['functional', 'io']
|
||||
|
||||
[tests/functional/inuse]
|
||||
|
||||
@@ -30,3 +30,7 @@ tags = ['functional', 'cli_root', 'zfs_jail']
|
||||
tests = ['pam_basic', 'pam_change_unmounted', 'pam_nounmount', 'pam_recursive',
|
||||
'pam_short_password']
|
||||
tags = ['functional', 'pam']
|
||||
|
||||
[tests/functional/direct:FreeBSD]
|
||||
tests = ['dio_write_stable_pages']
|
||||
tags = ['functional', 'direct']
|
||||
|
||||
@@ -102,6 +102,10 @@ tags = ['functional', 'compression']
|
||||
tests = ['devices_001_pos', 'devices_002_neg', 'devices_003_pos']
|
||||
tags = ['functional', 'devices']
|
||||
|
||||
[tests/functional/direct:Linux]
|
||||
tests = ['dio_write_verify']
|
||||
tags = ['functional', 'direct']
|
||||
|
||||
[tests/functional/events:Linux]
|
||||
tests = ['events_001_pos', 'events_002_pos', 'zed_rc_filter', 'zed_fd_spill',
|
||||
'zed_cksum_reported', 'zed_cksum_config', 'zed_io_config',
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
/getversion
|
||||
/largest_file
|
||||
/libzfs_input_check
|
||||
/manipulate_user_buffer
|
||||
/mkbusy
|
||||
/mkfile
|
||||
/mkfiles
|
||||
|
||||
@@ -60,6 +60,8 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/libzfs_input_check
|
||||
libzfs_core.la \
|
||||
libnvpair.la
|
||||
|
||||
scripts_zfs_tests_bin_PROGRAMS += %D%/manipulate_user_buffer
|
||||
%C%_manipulate_user_buffer_LDADD = -lpthread
|
||||
|
||||
scripts_zfs_tests_bin_PROGRAMS += %D%/mkbusy %D%/mkfile %D%/mkfiles %D%/mktree
|
||||
%C%_mkfile_LDADD = $(LTLIBINTL)
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* 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 https://opensource.org/licenses/CDDL-1.0.
|
||||
* 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) 2022 by Triad National Security, LLC.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b)) ? (a) : (b)
|
||||
#endif
|
||||
|
||||
static char *outputfile = NULL;
|
||||
static int blocksize = 131072; /* 128K */
|
||||
static int wr_err_expected = 0;
|
||||
static int numblocks = 100;
|
||||
static char *execname = NULL;
|
||||
static int print_usage = 0;
|
||||
static int randompattern = 0;
|
||||
static int ofd;
|
||||
char *buf = NULL;
|
||||
|
||||
typedef struct {
|
||||
int entire_file_written;
|
||||
} pthread_args_t;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage %s -o outputfile [-b blocksize] [-e wr_error_expected]\n"
|
||||
" [-n numblocks] [-p randpattern] [-h help]\n"
|
||||
"\n"
|
||||
"Testing whether checksum verify works correctly for O_DIRECT.\n"
|
||||
"when manipulating the contents of a userspace buffer.\n"
|
||||
"\n"
|
||||
" outputfile: File to write to.\n"
|
||||
" blocksize: Size of each block to write (must be at \n"
|
||||
" least >= 512).\n"
|
||||
" wr_err_expected: Whether pwrite() is expected to return EIO\n"
|
||||
" while manipulating the contents of the\n"
|
||||
" buffer.\n"
|
||||
" numblocks: Total number of blocksized blocks to\n"
|
||||
" write.\n"
|
||||
" randpattern: Fill data buffer with random data. Default\n"
|
||||
" behavior is to fill the buffer with the \n"
|
||||
" known data pattern (0xdeadbeef).\n"
|
||||
" help: Print usage information and exit.\n"
|
||||
"\n"
|
||||
" Required parameters:\n"
|
||||
" outputfile\n"
|
||||
"\n"
|
||||
" Default Values:\n"
|
||||
" blocksize -> 131072\n"
|
||||
" wr_err_expexted -> false\n"
|
||||
" numblocks -> 100\n"
|
||||
" randpattern -> false\n",
|
||||
execname);
|
||||
(void) exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
int errflag = 0;
|
||||
extern char *optarg;
|
||||
extern int optind, optopt;
|
||||
execname = argv[0];
|
||||
|
||||
while ((c = getopt(argc, argv, "b:ehn:o:p")) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
blocksize = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
wr_err_expected = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
print_usage = 1;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
numblocks = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
outputfile = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
randompattern = 1;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
(void) fprintf(stderr,
|
||||
"Option -%c requires an opertand\n",
|
||||
optopt);
|
||||
errflag++;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
(void) fprintf(stderr,
|
||||
"Unrecognized option: -%c\n", optopt);
|
||||
errflag++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errflag || print_usage == 1)
|
||||
(void) usage();
|
||||
|
||||
if (blocksize < 512 || outputfile == NULL || numblocks <= 0) {
|
||||
(void) fprintf(stderr,
|
||||
"Required paramater(s) missing or invalid.\n");
|
||||
(void) usage();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write blocksize * numblocks to the file using O_DIRECT.
|
||||
*/
|
||||
static void *
|
||||
write_thread(void *arg)
|
||||
{
|
||||
size_t offset = 0;
|
||||
int total_data = blocksize * numblocks;
|
||||
int left = total_data;
|
||||
ssize_t wrote = 0;
|
||||
pthread_args_t *args = (pthread_args_t *)arg;
|
||||
|
||||
while (!args->entire_file_written) {
|
||||
wrote = pwrite(ofd, buf, blocksize, offset);
|
||||
if (wrote != blocksize) {
|
||||
if (wr_err_expected)
|
||||
assert(errno == EIO);
|
||||
else
|
||||
exit(2);
|
||||
}
|
||||
|
||||
offset = ((offset + blocksize) % total_data);
|
||||
left -= blocksize;
|
||||
|
||||
if (left == 0)
|
||||
args->entire_file_written = 1;
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the buffers contents with random data.
|
||||
*/
|
||||
static void *
|
||||
manipulate_buf_thread(void *arg)
|
||||
{
|
||||
size_t rand_offset;
|
||||
char rand_char;
|
||||
pthread_args_t *args = (pthread_args_t *)arg;
|
||||
|
||||
while (!args->entire_file_written) {
|
||||
rand_offset = (rand() % blocksize);
|
||||
rand_char = (rand() % (126 - 33) + 33);
|
||||
buf[rand_offset] = rand_char;
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *datapattern = "0xdeadbeef";
|
||||
int ofd_flags = O_WRONLY | O_CREAT | O_DIRECT;
|
||||
mode_t mode = S_IRUSR | S_IWUSR;
|
||||
pthread_t write_thr;
|
||||
pthread_t manipul_thr;
|
||||
int left = blocksize;
|
||||
int offset = 0;
|
||||
int rc;
|
||||
pthread_args_t args = { 0 };
|
||||
|
||||
parse_options(argc, argv);
|
||||
|
||||
ofd = open(outputfile, ofd_flags, mode);
|
||||
if (ofd == -1) {
|
||||
(void) fprintf(stderr, "%s, %s\n", execname, outputfile);
|
||||
perror("open");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
int err = posix_memalign((void **)&buf, sysconf(_SC_PAGE_SIZE),
|
||||
blocksize);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: %s\n", execname, strerror(err));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!randompattern) {
|
||||
/* Putting known data pattern in buffer */
|
||||
while (left) {
|
||||
size_t amt = MIN(strlen(datapattern), left);
|
||||
memcpy(&buf[offset], datapattern, amt);
|
||||
offset += amt;
|
||||
left -= amt;
|
||||
}
|
||||
} else {
|
||||
/* Putting random data in buffer */
|
||||
for (int i = 0; i < blocksize; i++)
|
||||
buf[i] = rand();
|
||||
}
|
||||
|
||||
/*
|
||||
* Writing using O_DIRECT while manipulating the buffer contents until
|
||||
* the entire file is written.
|
||||
*/
|
||||
if ((rc = pthread_create(&manipul_thr, NULL, manipulate_buf_thread,
|
||||
&args))) {
|
||||
fprintf(stderr, "error: pthreads_create, manipul_thr, "
|
||||
"rc: %d\n", rc);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ((rc = pthread_create(&write_thr, NULL, write_thread, &args))) {
|
||||
fprintf(stderr, "error: pthreads_create, write_thr, "
|
||||
"rc: %d\n", rc);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
pthread_join(write_thr, NULL);
|
||||
pthread_join(manipul_thr, NULL);
|
||||
|
||||
assert(args.entire_file_written == 1);
|
||||
|
||||
(void) close(ofd);
|
||||
|
||||
free(buf);
|
||||
|
||||
return (0);
|
||||
}
|
||||
+183
-54
@@ -21,12 +21,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int alignment = 0;
|
||||
static int bsize = 0;
|
||||
static int count = 0;
|
||||
static char *ifile = NULL;
|
||||
static char *ofile = NULL;
|
||||
static off_t stride = 0;
|
||||
static off_t stride = 1;
|
||||
static off_t seek = 0;
|
||||
static int seekbytes = 0;
|
||||
static int if_o_direct = 0;
|
||||
static int of_o_direct = 0;
|
||||
static int skip = 0;
|
||||
static int skipbytes = 0;
|
||||
static int entire_file = 0;
|
||||
static const char *execname = "stride_dd";
|
||||
|
||||
static void usage(void);
|
||||
@@ -36,8 +43,10 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage: %s -i inputfile -o outputfile -b blocksize -c count \n"
|
||||
" -s stride [ -k seekblocks]\n"
|
||||
"usage: %s -i inputfile -o outputfile -b blocksize [-c count]\n"
|
||||
" [-s stride] [-k seekblocks] [-K seekbytes]\n"
|
||||
" [-a alignment] [-d if_o_direct] [-D of_o_direct]\n"
|
||||
" [-p skipblocks] [-P skipbytes] [-e entire_file]\n"
|
||||
"\n"
|
||||
"Simplified version of dd that supports the stride option.\n"
|
||||
"A stride of n means that for each block written, n - 1 blocks\n"
|
||||
@@ -45,16 +54,47 @@ usage(void)
|
||||
"means that blocks are read and written consecutively.\n"
|
||||
"All numeric parameters must be integers.\n"
|
||||
"\n"
|
||||
" inputfile: File to read from\n"
|
||||
" outputfile: File to write to\n"
|
||||
" blocksize: Size of each block to read/write\n"
|
||||
" count: Number of blocks to read/write\n"
|
||||
" stride: Read/write a block then skip (stride - 1) blocks\n"
|
||||
" seekblocks: Number of blocks to skip at start of output\n",
|
||||
" inputfile: File to read from\n"
|
||||
" outputfile: File to write to\n"
|
||||
" blocksize: Size of each block to read/write\n"
|
||||
" count: Number of blocks to read/write (Required"
|
||||
" unless -e is used)\n"
|
||||
" stride: Read/write a block then skip (stride - 1) blocks"
|
||||
"\n"
|
||||
" seekblocks: Number of blocks to skip at start of output\n"
|
||||
" seekbytes: Treat seekblocks as byte count\n"
|
||||
" alignment: Alignment passed to posix_memalign() (default"
|
||||
" PAGE_SIZE)\n"
|
||||
" if_o_direct: Use O_DIRECT with inputfile (default no O_DIRECT)"
|
||||
"\n"
|
||||
" of_o_direct: Use O_DIRECT with outputfile (default no "
|
||||
" O_DIRECT)\n"
|
||||
" skipblocks: Number of blocks to skip at start of input "
|
||||
" (default 0)\n"
|
||||
" skipbytes: Treat skipblocks as byte count\n"
|
||||
" entire_file: When used the entire inputfile will be read and"
|
||||
" count will be ignored\n",
|
||||
execname);
|
||||
(void) exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* posix_memalign() only allows for alignments which are postive, powers of two
|
||||
* and a multiple of sizeof (void *).
|
||||
*/
|
||||
static int
|
||||
invalid_alignment(int alignment)
|
||||
{
|
||||
if ((alignment < 0) || (alignment & (alignment - 1)) ||
|
||||
((alignment % sizeof (void *)))) {
|
||||
(void) fprintf(stderr,
|
||||
"Alignment must be a postive, power of two, and multiple "
|
||||
"of sizeof (void *).\n");
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[])
|
||||
{
|
||||
@@ -62,12 +102,17 @@ parse_options(int argc, char *argv[])
|
||||
int errflag = 0;
|
||||
|
||||
execname = argv[0];
|
||||
alignment = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, optopt;
|
||||
|
||||
while ((c = getopt(argc, argv, ":b:c:i:o:s:k:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "a:b:c:deDi:o:s:k:Kp:P")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
alignment = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
bsize = atoi(optarg);
|
||||
break;
|
||||
@@ -76,6 +121,18 @@ parse_options(int argc, char *argv[])
|
||||
count = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if_o_direct = 1;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
entire_file = 1;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
of_o_direct = 1;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
ifile = optarg;
|
||||
break;
|
||||
@@ -92,6 +149,18 @@ parse_options(int argc, char *argv[])
|
||||
seek = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'K':
|
||||
seekbytes = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
skip = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
skipbytes = 1;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
(void) fprintf(stderr,
|
||||
"Option -%c requires an operand\n", optopt);
|
||||
@@ -111,64 +180,59 @@ parse_options(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (bsize <= 0 || count <= 0 || stride <= 0 || ifile == NULL ||
|
||||
ofile == NULL || seek < 0) {
|
||||
if (bsize <= 0 || stride <= 0 || ifile == NULL || ofile == NULL ||
|
||||
seek < 0 || invalid_alignment(alignment) || skip < 0) {
|
||||
(void) fprintf(stderr,
|
||||
"Required parameter(s) missing or invalid.\n");
|
||||
(void) usage();
|
||||
}
|
||||
|
||||
if (count <= 0 && entire_file == 0) {
|
||||
(void) fprintf(stderr,
|
||||
"Required parameter(s) missing or invalid.\n");
|
||||
(void) usage();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
static void
|
||||
read_entire_file(int ifd, int ofd, void *buf)
|
||||
{
|
||||
int i;
|
||||
int ifd;
|
||||
int ofd;
|
||||
void *buf;
|
||||
int c;
|
||||
|
||||
parse_options(argc, argv);
|
||||
|
||||
ifd = open(ifile, O_RDONLY);
|
||||
if (ifd == -1) {
|
||||
(void) fprintf(stderr, "%s: %s: ", execname, ifile);
|
||||
perror("open");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
ofd = open(ofile, O_WRONLY | O_CREAT, 0666);
|
||||
if (ofd == -1) {
|
||||
(void) fprintf(stderr, "%s: %s: ", execname, ofile);
|
||||
perror("open");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* We use valloc because some character block devices expect a
|
||||
* page-aligned buffer.
|
||||
*/
|
||||
int err = posix_memalign(&buf, 4096, bsize);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: %s\n", execname, strerror(err));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (seek > 0) {
|
||||
if (lseek(ofd, seek * bsize, SEEK_CUR) == -1) {
|
||||
perror("output lseek");
|
||||
do {
|
||||
c = read(ifd, buf, bsize);
|
||||
if (c < 0) {
|
||||
perror("read");
|
||||
exit(2);
|
||||
} else if (c != 0) {
|
||||
c = write(ofd, buf, bsize);
|
||||
if (c < 0) {
|
||||
perror("write");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (stride > 1) {
|
||||
if (lseek(ifd, (stride - 1) * bsize, SEEK_CUR) == -1) {
|
||||
perror("input lseek");
|
||||
exit(2);
|
||||
}
|
||||
if (lseek(ofd, (stride - 1) * bsize, SEEK_CUR) == -1) {
|
||||
perror("output lseek");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
} while (c != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
read_on_count(int ifd, int ofd, void *buf)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
c = read(ifd, buf, bsize);
|
||||
if (c != bsize) {
|
||||
|
||||
perror("read");
|
||||
exit(2);
|
||||
}
|
||||
if (c != bsize) {
|
||||
if (c < 0) {
|
||||
perror("read");
|
||||
@@ -205,6 +269,71 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ifd;
|
||||
int ofd;
|
||||
int ifd_flags = O_RDONLY;
|
||||
int ofd_flags = O_WRONLY | O_CREAT;
|
||||
void *buf;
|
||||
|
||||
parse_options(argc, argv);
|
||||
|
||||
if (if_o_direct)
|
||||
ifd_flags |= O_DIRECT;
|
||||
|
||||
if (of_o_direct)
|
||||
ofd_flags |= O_DIRECT;
|
||||
|
||||
ifd = open(ifile, ifd_flags);
|
||||
if (ifd == -1) {
|
||||
(void) fprintf(stderr, "%s: %s: ", execname, ifile);
|
||||
perror("open");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
ofd = open(ofile, ofd_flags, 0666);
|
||||
if (ofd == -1) {
|
||||
(void) fprintf(stderr, "%s: %s: ", execname, ofile);
|
||||
perror("open");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* We use valloc because some character block devices expect a
|
||||
* page-aligned buffer.
|
||||
*/
|
||||
int err = posix_memalign(&buf, alignment, bsize);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: %s\n", execname, strerror(err));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (skip > 0) {
|
||||
int skipamt = skipbytes == 1 ? skip : skip * bsize;
|
||||
if (lseek(ifd, skipamt, SEEK_CUR) == -1) {
|
||||
perror("input lseek");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (seek > 0) {
|
||||
int seekamt = seekbytes == 1 ? seek : seek * bsize;
|
||||
if (lseek(ofd, seekamt, SEEK_CUR) == -1) {
|
||||
perror("output lseek");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (entire_file == 1)
|
||||
read_entire_file(ifd, ofd, buf);
|
||||
else
|
||||
read_on_count(ifd, ofd, buf);
|
||||
|
||||
free(buf);
|
||||
|
||||
(void) close(ofd);
|
||||
|
||||
@@ -200,6 +200,7 @@ export ZFSTEST_FILES='badsend
|
||||
getversion
|
||||
largest_file
|
||||
libzfs_input_check
|
||||
manipulate_user_buffer
|
||||
mkbusy
|
||||
mkfile
|
||||
mkfiles
|
||||
|
||||
@@ -3474,6 +3474,18 @@ function md5digest
|
||||
esac
|
||||
}
|
||||
|
||||
#
|
||||
# Compare the MD5 digest of two files.
|
||||
#
|
||||
function cmp_md5s {
|
||||
typeset file1=$1
|
||||
typeset file2=$2
|
||||
|
||||
typeset sum1=$(md5digest $file1)
|
||||
typeset sum2=$(md5digest $file2)
|
||||
test "$sum1" = "$sum2"
|
||||
}
|
||||
|
||||
#
|
||||
# Compute SHA256 digest for given file or stdin if no file given.
|
||||
# Note: file path must not contain spaces
|
||||
|
||||
@@ -93,6 +93,7 @@ VDEV_FILE_LOGICAL_ASHIFT vdev.file.logical_ashift vdev_file_logical_ashift
|
||||
VDEV_FILE_PHYSICAL_ASHIFT vdev.file.physical_ashift vdev_file_physical_ashift
|
||||
VDEV_MAX_AUTO_ASHIFT vdev.max_auto_ashift zfs_vdev_max_auto_ashift
|
||||
VDEV_MIN_MS_COUNT vdev.min_ms_count zfs_vdev_min_ms_count
|
||||
VDEV_DIRECT_WR_VERIFY vdev.direct_write_verify zfs_vdev_direct_write_verify
|
||||
VDEV_VALIDATE_SKIP vdev.validate_skip vdev_validate_skip
|
||||
VOL_INHIBIT_DEV UNSUPPORTED zvol_inhibit_dev
|
||||
VOL_MODE vol.mode zvol_volmode
|
||||
@@ -100,6 +101,7 @@ VOL_RECURSIVE vol.recursive UNSUPPORTED
|
||||
VOL_USE_BLK_MQ UNSUPPORTED zvol_use_blk_mq
|
||||
BCLONE_ENABLED bclone_enabled zfs_bclone_enabled
|
||||
BCLONE_WAIT_DIRTY bclone_wait_dirty zfs_bclone_wait_dirty
|
||||
DIO_ENABLED dio_enabled zfs_dio_enabled
|
||||
XATTR_COMPAT xattr_compat zfs_xattr_compat
|
||||
ZEVENT_LEN_MAX zevent.len_max zfs_zevent_len_max
|
||||
ZEVENT_RETAIN_MAX zevent.retain_max zfs_zevent_retain_max
|
||||
|
||||
@@ -265,6 +265,8 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
|
||||
functional/delegate/delegate_common.kshlib \
|
||||
functional/devices/devices.cfg \
|
||||
functional/devices/devices_common.kshlib \
|
||||
functional/direct/dio.cfg \
|
||||
functional/direct/dio.kshlib \
|
||||
functional/events/events.cfg \
|
||||
functional/events/events_common.kshlib \
|
||||
functional/fault/fault.cfg \
|
||||
@@ -1458,6 +1460,26 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/devices/devices_002_neg.ksh \
|
||||
functional/devices/devices_003_pos.ksh \
|
||||
functional/devices/setup.ksh \
|
||||
functional/direct/dio_aligned_block.ksh \
|
||||
functional/direct/dio_async_always.ksh \
|
||||
functional/direct/dio_async_fio_ioengines.ksh \
|
||||
functional/direct/dio_compression.ksh \
|
||||
functional/direct/dio_dedup.ksh \
|
||||
functional/direct/dio_encryption.ksh \
|
||||
functional/direct/dio_grow_block.ksh \
|
||||
functional/direct/dio_max_recordsize.ksh \
|
||||
functional/direct/dio_mixed.ksh \
|
||||
functional/direct/dio_mmap.ksh \
|
||||
functional/direct/dio_overwrites.ksh \
|
||||
functional/direct/dio_property.ksh \
|
||||
functional/direct/dio_random.ksh \
|
||||
functional/direct/dio_recordsize.ksh \
|
||||
functional/direct/dio_unaligned_block.ksh \
|
||||
functional/direct/dio_unaligned_filesize.ksh \
|
||||
functional/direct/dio_write_verify.ksh \
|
||||
functional/direct/dio_write_stable_pages.ksh \
|
||||
functional/direct/setup.ksh \
|
||||
functional/direct/cleanup.ksh \
|
||||
functional/dos_attributes/cleanup.ksh \
|
||||
functional/dos_attributes/read_dos_attrs_001.ksh \
|
||||
functional/dos_attributes/setup.ksh \
|
||||
|
||||
@@ -75,7 +75,7 @@ export PERF_COMPPERCENT=66
|
||||
export PERF_COMPCHUNK=0
|
||||
export BLOCKSIZE=128K
|
||||
export SYNC_TYPE=0
|
||||
export DIRECT=1
|
||||
export DIRECT=0
|
||||
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))
|
||||
|
||||
log_must set_tunable32 L2ARC_WRITE_MAX $(( $VCACHE_SZ * 2 ))
|
||||
|
||||
@@ -36,7 +36,7 @@ export PERF_COMPPERCENT=66
|
||||
export PERF_COMPCHUNK=0
|
||||
export BLOCKSIZE=128K
|
||||
export SYNC_TYPE=0
|
||||
export DIRECT=1
|
||||
export DIRECT=0
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
|
||||
@@ -37,7 +37,7 @@ export PERF_COMPPERCENT=66
|
||||
export PERF_COMPCHUNK=0
|
||||
export BLOCKSIZE=128K
|
||||
export SYNC_TYPE=0
|
||||
export DIRECT=1
|
||||
export DIRECT=0
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
|
||||
@@ -37,7 +37,7 @@ export PERF_COMPPERCENT=66
|
||||
export PERF_COMPCHUNK=0
|
||||
export BLOCKSIZE=128K
|
||||
export SYNC_TYPE=0
|
||||
export DIRECT=1
|
||||
export DIRECT=0
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
default_cleanup_noexit
|
||||
|
||||
if tunable_exists DIO_ENABLED ; then
|
||||
log_must restore_tunable DIO_ENABLED
|
||||
fi
|
||||
|
||||
log_pass
|
||||
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
DIO_VDEV1=$TEST_BASE_DIR/file1
|
||||
DIO_VDEV2=$TEST_BASE_DIR/file2
|
||||
DIO_VDEV3=$TEST_BASE_DIR/file3
|
||||
DIO_VDEVS="$DIO_VDEV1 $DIO_VDEV2 $DIO_VDEV3"
|
||||
|
||||
DIO_FILESIZE=4M
|
||||
DIO_BS=128K
|
||||
@@ -0,0 +1,331 @@
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
|
||||
function dio_cleanup
|
||||
{
|
||||
if poolexists $TESTPOOL1; then
|
||||
destroy_pool $TESTPOOL1
|
||||
fi
|
||||
|
||||
rm -f $DIO_VDEVS
|
||||
}
|
||||
|
||||
#
|
||||
# Generate an IO workload using fio and then verify the resulting data.
|
||||
#
|
||||
function dio_and_verify # mode file-size block-size directory ioengine extra-args
|
||||
{
|
||||
typeset mode=$1
|
||||
typeset size=$2
|
||||
typeset bs=$3
|
||||
typeset mntpnt=$4
|
||||
typeset ioengine=$5
|
||||
typeset extra_args=$6
|
||||
|
||||
# Invoke an fio workload via Direct I/O and verify with Direct I/O.
|
||||
log_must fio --directory=$mntpnt --name=direct-$mode \
|
||||
--rw=$mode --size=$size --bs=$bs --direct=1 --numjobs=1 \
|
||||
--verify=sha1 --ioengine=$ioengine --fallocate=none \
|
||||
--group_reporting --minimal --do_verify=1 $extra_args
|
||||
|
||||
# Now just read back the file without Direct I/O into the ARC as an
|
||||
# additional verfication step.
|
||||
log_must fio --directory=$mntpnt --name=direct-$mode \
|
||||
--rw=read --size=$size --bs=$bs --direct=0 --numjobs=1 \
|
||||
--ioengine=$ioengine --group_reporting --minimal
|
||||
|
||||
log_must rm -f "$mntpnt/direct-*"
|
||||
}
|
||||
|
||||
#
|
||||
# Get zpool status -d checksum verify failures
|
||||
#
|
||||
function get_zpool_status_chksum_verify_failures # pool_name vdev_type
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset vdev_type=$2
|
||||
|
||||
if [[ "$vdev_type" == "stripe" ]]; then
|
||||
val=$(zpool status -dp $pool | \
|
||||
awk '{s+=$6} END {print s}' )
|
||||
elif [[ "$vdev_type" == "mirror" || "$vdev_type" == "raidz" ||
|
||||
"$vdev_type" == "draid" ]]; then
|
||||
val=$(zpool status -dp $pool | \
|
||||
awk -v d="$vdev_type" '$0 ~ d {print $6}' )
|
||||
else
|
||||
log_fail "Unsupported VDEV type in \
|
||||
get_zpool_status_chksum_verify_failures(): $vdev_type"
|
||||
fi
|
||||
echo "$val"
|
||||
}
|
||||
|
||||
#
|
||||
# Get ZED dio_verify events
|
||||
#
|
||||
function get_zed_dio_verify_events # pool
|
||||
{
|
||||
typeset pool=$1
|
||||
|
||||
val=$(zpool events $pool | grep -c dio_verify)
|
||||
|
||||
echo "$val"
|
||||
}
|
||||
|
||||
#
|
||||
# Checking for checksum verify write failures with:
|
||||
# zpool status -d
|
||||
# zpool events
|
||||
# After getting that counts will clear the out the ZPool errors and events
|
||||
#
|
||||
function check_dio_write_chksum_verify_failures # pool vdev_type expect_errors
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset vdev_type=$2
|
||||
typeset expect_errors=$3
|
||||
typeset note_str="expecting none"
|
||||
|
||||
if [[ $expect_errors -ne 0 ]]; then
|
||||
note_str="expecting some"
|
||||
fi
|
||||
|
||||
log_note "Checking for Direct I/O write checksum verify errors \
|
||||
$note_str on ZPool: $pool"
|
||||
|
||||
status_failures=$(get_zpool_status_chksum_verify_failures $pool $vdev_type)
|
||||
zed_dio_verify_events=$(get_zed_dio_verify_events $pool)
|
||||
|
||||
if [[ $expect_errors -ne 0 ]]; then
|
||||
if [[ $status_failures -eq 0 ||
|
||||
$zed_dio_verify_events -eq 0 ]]; then
|
||||
zpool status -dp $pool
|
||||
zpool events $pool
|
||||
log_fail "Checksum verifies in zpool status -d \
|
||||
$status_failures. ZED dio_verify events \
|
||||
$zed_dio_verify_events. Neither should be 0."
|
||||
fi
|
||||
else
|
||||
if [[ $status_failures -ne 0 ||
|
||||
$zed_dio_verify_events -ne 0 ]]; then
|
||||
zpool status -dp $pool
|
||||
zpool events $pool
|
||||
log_fail "Checksum verifies in zpool status -d \
|
||||
$status_failures. ZED dio_verify events \
|
||||
$zed_dio_verify_events. Both should be zero."
|
||||
fi
|
||||
fi
|
||||
|
||||
log_must zpool clear $pool
|
||||
log_must zpool events -c
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Get the value of a counter from
|
||||
# Linux: /proc/spl/kstat/zfs/$pool/iostats file.
|
||||
# FreeBSD: kstat.zfs.$pool.msic.iostats.$stat
|
||||
#
|
||||
function get_iostats_stat # pool stat
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset stat=$2
|
||||
|
||||
if is_linux; then
|
||||
iostats_file=/proc/spl/kstat/zfs/$pool/iostats
|
||||
val=$(grep -m1 "$stat" $iostats_file | awk '{ print $3 }')
|
||||
else
|
||||
val=$(sysctl -n kstat.zfs.$pool.misc.iostats.$stat)
|
||||
fi
|
||||
if [[ -z "$val" ]]; then
|
||||
log_fail "Unable to read $stat counter"
|
||||
fi
|
||||
|
||||
echo "$val"
|
||||
}
|
||||
|
||||
#
|
||||
# Evict any buffered blocks by overwritting them using an O_DIRECT request.
|
||||
#
|
||||
function evict_blocks
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset file=$2
|
||||
typeset size=$3
|
||||
|
||||
log_must stride_dd -i /dev/urandom -o $file -b $size -c 1 -D
|
||||
}
|
||||
|
||||
#
|
||||
# Perform FIO Direct I/O writes to a file with the given arguments.
|
||||
# Then verify thae minimum expected number of blocks were written as
|
||||
# Direct I/O.
|
||||
#
|
||||
function verify_dio_write_count #pool bs size mnpnt
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset bs=$2
|
||||
typeset size=$3
|
||||
typeset mntpnt=$4
|
||||
typeset dio_wr_expected=$(((size / bs) -1))
|
||||
|
||||
log_note "Checking for $dio_wr_expected Direct I/O writes"
|
||||
|
||||
prev_dio_wr=$(get_iostats_stat $pool direct_write_count)
|
||||
dio_and_verify write $size $bs $mntpnt "sync"
|
||||
curr_dio_wr=$(get_iostats_stat $pool direct_write_count)
|
||||
dio_wr_actual=$((curr_dio_wr - prev_dio_wr))
|
||||
|
||||
if [[ $dio_wr_actual -lt $dio_wr_expected ]]; then
|
||||
if is_linux; then
|
||||
cat /proc/spl/kstat/zfs/$pool/iostats
|
||||
else
|
||||
sysctl kstat.zfs.$pool.misc.iostats
|
||||
fi
|
||||
log_fail "Direct writes $dio_wr_actual of $dio_wr_expected"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Perform a stride_dd write command to the file with the given arguments.
|
||||
# Then verify the minimum expected number of blocks were written as either
|
||||
# buffered IO (by the ARC), or Direct I/O to the application (dd).
|
||||
#
|
||||
function check_write # pool file bs count seek flags buf_wr dio_wr
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset file=$2
|
||||
typeset bs=$3
|
||||
typeset count=$4
|
||||
typeset seek=$5
|
||||
typeset flags=$6
|
||||
typeset buf_wr_expect=$7
|
||||
typeset dio_wr_expect=$8
|
||||
|
||||
log_note "Checking $count * $bs write(s) at offset $seek, $flags"
|
||||
|
||||
prev_buf_wr=$(get_iostats_stat $pool arc_write_count)
|
||||
prev_dio_wr=$(get_iostats_stat $pool direct_write_count)
|
||||
|
||||
log_must stride_dd -i /dev/urandom -o $file -b $bs -c $count \
|
||||
-k $seek $flags
|
||||
|
||||
curr_buf_wr=$(get_iostats_stat $pool arc_write_count)
|
||||
buf_wr_actual=$((curr_buf_wr - prev_buf_wr))
|
||||
|
||||
curr_dio_wr=$(get_iostats_stat $pool direct_write_count)
|
||||
dio_wr_actual=$((curr_dio_wr - prev_dio_wr))
|
||||
|
||||
if [[ $buf_wr_actual -lt $buf_wr_expect ]]; then
|
||||
if is_linux; then
|
||||
cat /proc/spl/kstat/zfs/$pool/iostats
|
||||
else
|
||||
sysctl kstat.zfs.$pool.misc.iostats
|
||||
fi
|
||||
log_fail "Buffered writes $buf_wr_actual of $buf_wr_expect"
|
||||
fi
|
||||
|
||||
if [[ $dio_wr_actual -lt $dio_wr_expect ]]; then
|
||||
if is_linux; then
|
||||
cat /proc/spl/kstat/zfs/$pool/iostats
|
||||
else
|
||||
sysctl kstat.zfs.$pool.misc.iostats
|
||||
fi
|
||||
log_fail "Direct writes $dio_wr_actual of $dio_wr_expect"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Perform a stride_dd read command to the file with the given arguments.
|
||||
# Then verify the minimum expected number of blocks were read as either
|
||||
# buffered IO (by the ARC), or Direct I/O to the application (dd).
|
||||
#
|
||||
function check_read # pool file bs count skip flags buf_rd dio_rd
|
||||
{
|
||||
typeset pool=$1
|
||||
typeset file=$2
|
||||
typeset bs=$3
|
||||
typeset count=$4
|
||||
typeset skip=$5
|
||||
typeset flags=$6
|
||||
typeset buf_rd_expect=$7
|
||||
typeset dio_rd_expect=$8
|
||||
|
||||
log_note "Checking $count * $bs read(s) at offset $skip, $flags"
|
||||
|
||||
prev_buf_rd=$(get_iostats_stat $pool arc_read_count)
|
||||
prev_dio_rd=$(get_iostats_stat $pool direct_read_count)
|
||||
|
||||
log_must stride_dd -i $file -o /dev/null -b $bs -c $count \
|
||||
-p $skip $flags
|
||||
|
||||
curr_buf_rd=$(get_iostats_stat $pool arc_read_count)
|
||||
buf_rd_actual=$((curr_buf_rd - prev_buf_rd))
|
||||
|
||||
curr_dio_rd=$(get_iostats_stat $pool direct_read_count)
|
||||
dio_rd_actual=$((curr_dio_rd - prev_dio_rd))
|
||||
|
||||
if [[ $buf_rd_actual -lt $buf_rd_expect ]]; then
|
||||
if is_linux; then
|
||||
cat /proc/spl/kstat/zfs/$pool/iostats
|
||||
else
|
||||
sysctl kstat.zfs.$pool.misc.iostats
|
||||
fi
|
||||
log_fail "Buffered reads $buf_rd_actual of $buf_rd_expect"
|
||||
fi
|
||||
|
||||
if [[ $dio_rd_actual -lt $dio_rd_expect ]]; then
|
||||
if is_linux; then
|
||||
cat /proc/spl/kstat/zfs/$pool/iostats
|
||||
else
|
||||
sysctl kstat.zfs.$pool.misc.iostats
|
||||
fi
|
||||
log_fail "Direct reads $dio_rd_actual of $dio_rd_expect"
|
||||
fi
|
||||
}
|
||||
|
||||
function get_file_size
|
||||
{
|
||||
typeset filename="$1"
|
||||
|
||||
if is_linux; then
|
||||
filesize=$(stat -c %s $filename)
|
||||
else
|
||||
filesize=$(stat -s $filename | awk '{print $8}' | grep -o '[0-9]\+')
|
||||
fi
|
||||
|
||||
echo $filesize
|
||||
}
|
||||
|
||||
function do_truncate_reduce
|
||||
{
|
||||
typeset filename=$1
|
||||
typeset size=$2
|
||||
|
||||
filesize=$(get_file_size $filename)
|
||||
eval "echo original filesize: $filesize"
|
||||
if is_linux; then
|
||||
truncate $filename -s $((filesize - size))
|
||||
else
|
||||
truncate -s -$size $filename
|
||||
fi
|
||||
filesize=$(get_file_size $filename)
|
||||
eval "echo new filesize after truncate: $filesize"
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify the number direct/buffered requests for (un)aligned access
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a multi-block file
|
||||
# 2. Perform various (un)aligned accesses and verify the result.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zfs set recordsize=$rs $TESTPOOL/$TESTFS
|
||||
log_must rm -f $tmp_file
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Verify the number direct/buffered requests for unaligned access"
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
|
||||
rs=$(get_prop recordsize $TESTPOOL/$TESTFS)
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
|
||||
tmp_file=$mntpnt/tmp_file
|
||||
file_size=$((rs * 8))
|
||||
|
||||
log_must stride_dd -i /dev/urandom -o $tmp_file -b $file_size -c 1
|
||||
|
||||
# N recordsize aligned writes which do not span blocks
|
||||
check_write $TESTPOOL $tmp_file $rs 1 0 "-D" 0 1
|
||||
check_write $TESTPOOL $tmp_file $rs 2 0 "-D" 0 2
|
||||
check_write $TESTPOOL $tmp_file $rs 4 0 "-D" 0 4
|
||||
check_write $TESTPOOL $tmp_file $rs 8 0 "-D" 0 8
|
||||
|
||||
# 1 recordsize aligned write which spans multiple blocks at various offsets
|
||||
check_write $TESTPOOL $tmp_file $((rs * 2)) 1 0 "-D" 0 2
|
||||
check_write $TESTPOOL $tmp_file $((rs * 2)) 1 1 "-D" 0 2
|
||||
check_write $TESTPOOL $tmp_file $((rs * 2)) 1 2 "-D" 0 2
|
||||
check_write $TESTPOOL $tmp_file $((rs * 2)) 1 3 "-D" 0 2
|
||||
check_write $TESTPOOL $tmp_file $((rs * 4)) 1 0 "-D" 0 4
|
||||
check_write $TESTPOOL $tmp_file $((rs * 4)) 1 1 "-D" 0 4
|
||||
check_write $TESTPOOL $tmp_file $((rs * 8)) 1 0 "-D" 0 8
|
||||
|
||||
# sub-blocksize unaligned writes which do not span blocks.
|
||||
check_write $TESTPOOL $tmp_file $((rs / 2)) 1 0 "-D" 1 0
|
||||
check_write $TESTPOOL $tmp_file $((rs / 2)) 1 1 "-D" 1 0
|
||||
check_write $TESTPOOL $tmp_file $((rs / 2)) 1 2 "-D" 1 0
|
||||
check_write $TESTPOOL $tmp_file $((rs / 2)) 1 3 "-D" 1 0
|
||||
|
||||
# large unaligned writes which span multiple blocks
|
||||
check_write $TESTPOOL $tmp_file $((rs * 2)) 1 $((rs / 2)) "-D -K" 2 1
|
||||
check_write $TESTPOOL $tmp_file $((rs * 4)) 2 $((rs / 4)) "-D -K" 4 6
|
||||
|
||||
# evict any cached blocks by overwriting with O_DIRECT
|
||||
evict_blocks $TESTPOOL $tmp_file $file_size
|
||||
|
||||
# recordsize aligned reads which do not span blocks
|
||||
check_read $TESTPOOL $tmp_file $rs 1 0 "-d" 0 1
|
||||
check_read $TESTPOOL $tmp_file $rs 2 0 "-d" 0 2
|
||||
check_read $TESTPOOL $tmp_file $rs 4 0 "-d" 0 4
|
||||
check_read $TESTPOOL $tmp_file $rs 8 0 "-d" 0 8
|
||||
|
||||
# 1 recordsize aligned read which spans multiple blocks at various offsets
|
||||
check_read $TESTPOOL $tmp_file $((rs * 2)) 1 0 "-d" 0 2
|
||||
check_read $TESTPOOL $tmp_file $((rs * 2)) 1 1 "-d" 0 2
|
||||
check_read $TESTPOOL $tmp_file $((rs * 2)) 1 2 "-d" 0 2
|
||||
check_read $TESTPOOL $tmp_file $((rs * 2)) 1 3 "-d" 0 2
|
||||
check_read $TESTPOOL $tmp_file $((rs * 4)) 1 0 "-d" 0 4
|
||||
check_read $TESTPOOL $tmp_file $((rs * 4)) 1 1 "-d" 0 4
|
||||
check_read $TESTPOOL $tmp_file $((rs * 8)) 1 0 "-d" 0 8
|
||||
|
||||
# sub-blocksize unaligned reads which do not span blocks.
|
||||
check_read $TESTPOOL $tmp_file $((rs / 2)) 1 0 "-d" 0 1
|
||||
check_read $TESTPOOL $tmp_file $((rs / 2)) 1 1 "-d" 0 1
|
||||
check_read $TESTPOOL $tmp_file $((rs / 2)) 1 2 "-d" 0 1
|
||||
check_read $TESTPOOL $tmp_file $((rs / 2)) 1 3 "-d" 0 1
|
||||
|
||||
# large unaligned reads which span multiple blocks
|
||||
check_read $TESTPOOL $tmp_file $((rs * 2)) 1 $((rs / 2)) "-d -P" 0 3
|
||||
check_read $TESTPOOL $tmp_file $((rs * 4)) 1 $((rs / 4)) "-d -P" 0 5
|
||||
|
||||
log_pass "Verify the number direct/buffered requests for (un)aligned access"
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# DDL 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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify small async Direct I/O requests
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Use fio to issue small read/write requests. Writes are
|
||||
# smaller than the block size and thus will be buffered,
|
||||
# reads satisfy the minimum alignment and will be direct.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zfs set direct=standard $TESTPOOL/$TESTFS
|
||||
rm $tmp_file
|
||||
}
|
||||
|
||||
log_assert "Verify direct=always mixed small async requests"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_must zfs set direct=always $TESTPOOL/$TESTFS
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
tmp_file=$mntpnt/tmp_file
|
||||
page_size=$(getconf PAGESIZE)
|
||||
file_size=1G
|
||||
runtime=10
|
||||
|
||||
log_must truncate -s $file_size $tmp_file
|
||||
|
||||
log_must fio --filename=$tmp_file --name=always-randrw \
|
||||
--rw=randwrite --bs=$page_size --size=$file_size --numjobs=1 \
|
||||
--ioengine=posixaio --fallocate=none --iodepth=4 --verify=sha1 \
|
||||
--group_reporting --minimal --runtime=$runtime --time_based
|
||||
|
||||
log_pass "Verify direct=always mixed small async requests"
|
||||
@@ -0,0 +1,106 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2022 by Triad National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/include/properties.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify FIO async engines work using Direct I/O.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Select a FIO async ioengine
|
||||
# 2. Start sequntial Direct I/O and verify with buffered I/O
|
||||
# 3. Start mixed Direct I/O and verify with buffered I/O
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must rm -f "$mntpnt/direct-*"
|
||||
}
|
||||
|
||||
function check_fio_ioengine
|
||||
{
|
||||
fio --ioengine=io_uring --parse-only > /dev/null 2>&1
|
||||
return $?
|
||||
}
|
||||
|
||||
log_assert "Verify FIO async ioengines work using Direct I/O."
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
typeset -a async_ioengine_args=("--iodepth=4" "--iodepth=4 --thread")
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
fio_async_ioengines="posixaio"
|
||||
|
||||
if is_linux; then
|
||||
fio_async_ioengines+=" libaio"
|
||||
if $(grep -q "CONFIG_IO_URING=y" /boot/config-$(uname -r)); then
|
||||
if [ -e /etc/os-release ] ; then
|
||||
source /etc/os-release
|
||||
if [ $PLATFORM_ID = "platform:el9" ] ; then
|
||||
log_note "io_uring disabled on RHEL 9 " \
|
||||
"variants: fails with " \
|
||||
"'Operation not permitted'"
|
||||
elif $(check_fio_ioengine -eq 0); then
|
||||
fio_async_ioengines+=" io_uring"
|
||||
else
|
||||
log_note "io_uring not supported by fio and " \
|
||||
"will not be tested"
|
||||
fi
|
||||
else
|
||||
if $(check_fio_ioengine); then
|
||||
fio_async_ioengines+=" io_uring"
|
||||
|
||||
else
|
||||
log_note "io_uring not supported by fio and " \
|
||||
"will not be tested"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_note "io_uring not supported by kernel will not " \
|
||||
"be tested"
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
for ioengine in $fio_async_ioengines; do
|
||||
for ioengine_args in "${async_ioengine_args[@]}"; do
|
||||
for op in "rw" "randrw" "write"; do
|
||||
log_note "Checking Direct I/O with FIO async ioengine" \
|
||||
" $ioengine with args $ioengine_args --rw=$op"
|
||||
dio_and_verify $op $DIO_FILESIZE $DIO_BS $mntpnt "$ioengine" \
|
||||
"$ioengine_args"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Verfied FIO async ioengines work using Direct I/O"
|
||||
@@ -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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/include/properties.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify compression works using Direct I/O.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Select a random compression algoritm
|
||||
# 2. Start sequential Direct I/O and verify with buffered I/O
|
||||
# 3. Start mixed Direct I/O and verify with buffered I/O
|
||||
# 4. Repeat from 2 for all compression algoritms
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must rm -f "$mntpnt/direct-*"
|
||||
log_must zfs set compression=off $TESTPOOL/$TESTFS
|
||||
}
|
||||
|
||||
log_assert "Verify compression works using Direct I/O."
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
compress_args="--buffer_compress_percentage=50"
|
||||
|
||||
for comp in "${compress_prop_vals[@]:1}"; do
|
||||
log_must zfs set compression=$comp $TESTPOOL/$TESTFS
|
||||
for op in "rw" "randrw" "write"; do
|
||||
dio_and_verify $op $DIO_FILESIZE $DIO_BS $mntpnt "sync" $compress_args
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Verfied compression works using Direct I/O"
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# DDL 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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/include/properties.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify deduplication works. Deduplication is disabled when issuing
|
||||
# Direct I/O writes.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Enable dedup
|
||||
# 2. Start sequential Direct I/O and verify with buffered I/O
|
||||
# 3. Start mixed Direct IO and verify with buffered I/O
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must rm -f "$mntpnt/direct-*"
|
||||
log_must zfs set dedup=off $TESTPOOL/$TESTFS
|
||||
}
|
||||
|
||||
log_assert "Verify deduplication works using Direct I/O."
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
dedup_args="--dedupe_percentage=50"
|
||||
|
||||
log_must zfs set dedup=on $TESTPOOL/$TESTFS
|
||||
for op in "rw" "randrw" "write"; do
|
||||
dio_and_verify $op $DIO_FILESIZE $DIO_BS $mntpnt "sync" $dedup_args
|
||||
done
|
||||
|
||||
log_pass "Verfied deduplication works using Direct I/O"
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# DDL 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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify encryption works using Direct I/O.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create multidisk pool.
|
||||
# 2. Start some mixed readwrite Direct I/O.
|
||||
# 3. Verify the results are as expected using buffered I/O.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Verify encryption works using Direct I/O."
|
||||
|
||||
log_onexit dio_cleanup
|
||||
|
||||
log_must truncate -s $MINVDEVSIZE $DIO_VDEVS
|
||||
|
||||
create_pool $TESTPOOL1 $DIO_VDEVS
|
||||
log_must eval "echo 'password' | zfs create -o encryption=on \
|
||||
-o keyformat=passphrase -o keylocation=prompt -o compression=off \
|
||||
$TESTPOOL1/$TESTFS1"
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS1)
|
||||
|
||||
for bs in "4k" "128k" "1m"; do
|
||||
for op in "rw" "randrw" "write"; do
|
||||
dio_and_verify $op $DIO_FILESIZE $bs $mntpnt "sync"
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Verified encryption works using Direct I/O"
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify the number direct/buffered requests when growing a file
|
||||
#
|
||||
# STRATEGY:
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zfs set recordsize=$rs $TESTPOOL/$TESTFS
|
||||
log_must rm -f $tmp_file
|
||||
}
|
||||
|
||||
log_assert "Verify the number direct/buffered requests when growing a file"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
|
||||
tmp_file=$mntpnt/tmp_file
|
||||
|
||||
rs=$(get_prop recordsize $TESTPOOL/$TESTFS)
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
|
||||
#
|
||||
# Verify the expected number of buffered and Direct I/O's when growing
|
||||
# the first block of a file up to the maximum recordsize.
|
||||
#
|
||||
for bs in "8192" "16384" "32768" "65536" "131072"; do
|
||||
|
||||
# When O_DIRECT is set the first write to a new file, or when the
|
||||
# block size needs to be grown, it will be done as a buffered write.
|
||||
check_write $TESTPOOL $tmp_file $bs 1 0 "-D" 1 0
|
||||
|
||||
# Overwriting the first block of an existing file with O_DIRECT will
|
||||
# be a buffered write if less than the block size.
|
||||
check_write $TESTPOOL $tmp_file 4096 1 0 "-D" 1 0
|
||||
check_write $TESTPOOL $tmp_file 4096 1 1 "-D" 1 0
|
||||
|
||||
# Overwriting the first block of an existing file with O_DIRECT will
|
||||
# be a direct write as long as the block size matches.
|
||||
check_write $TESTPOOL $tmp_file $bs 1 0 "-D" 0 1
|
||||
|
||||
# Evict any blocks which may be buffered before the read tests.
|
||||
evict_blocks $TESTPOOL $tmp_file $bs
|
||||
|
||||
# Reading the first block of an existing file with O_DIRECT will
|
||||
# be a direct read for part or all of the block size.
|
||||
check_read $TESTPOOL $tmp_file $bs 1 0 "-d" 0 1
|
||||
check_read $TESTPOOL $tmp_file 4096 1 0 "-d" 0 1
|
||||
check_read $TESTPOOL $tmp_file 4096 1 1 "-d" 0 1
|
||||
done
|
||||
|
||||
log_pass "Verify the number direct/buffered requests when growing a file"
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2022 by Triad National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify max recordsizes are supported for Direct I/O.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a pool from each vdev type with varying recordsizes.
|
||||
# 2. Start sequential Direct I/O and verify with buffered I/O.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Verify max recordsizes are supported for Direct I/O."
|
||||
|
||||
log_onexit dio_cleanup
|
||||
|
||||
log_must truncate -s $MINVDEVSIZE $DIO_VDEVS
|
||||
|
||||
for type in "" "mirror" "raidz" "draid"; do;
|
||||
for recsize in "2097152" "8388608" "16777216"; do
|
||||
create_pool $TESTPOOL1 $type $DIO_VDEVS
|
||||
log_must eval "zfs create \
|
||||
-o recordsize=$recsize -o compression=off \
|
||||
$TESTPOOL1/$TESTFS1"
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS1)
|
||||
|
||||
verify_dio_write_count $TESTPOOL1 $recsize $((4 * recsize)) \
|
||||
$mntpnt
|
||||
|
||||
destroy_pool $TESTPOOL1
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Verified max recordsizes are supported for Direct I/O."
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/include/properties.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify mixed buffered and Direct I/O are coherent.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Verify interleaved buffered and Direct I/O
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must rm -f $src_file $new_file $tmp_file
|
||||
}
|
||||
|
||||
log_assert "Verify mixed buffered and Direct I/O are coherent."
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
|
||||
src_file=$mntpnt/src_file
|
||||
new_file=$mntpnt/new_file
|
||||
tmp_file=$mntpnt/tmp_file
|
||||
page_size=$(getconf PAGESIZE)
|
||||
file_size=1048576
|
||||
|
||||
log_must stride_dd -i /dev/urandom -o $src_file -b $file_size -c 1
|
||||
|
||||
#
|
||||
# Using mixed input and output block sizes verify that buffered and
|
||||
# Direct I/O can be interleaved and the result with always be coherent.
|
||||
#
|
||||
for ibs in "512" "$page_size" "131072"; do
|
||||
for obs in "512" "$page_size" "131072"; do
|
||||
iblocks=$(($file_size / $ibs))
|
||||
oblocks=$(($file_size / $obs))
|
||||
iflags=""
|
||||
oflags=""
|
||||
|
||||
# Only allow Direct I/O when it is at least page sized.
|
||||
if [[ $ibs -ge $page_size ]]; then
|
||||
iflags="-d"
|
||||
fi
|
||||
|
||||
if [[ $obs -ge $page_size ]]; then
|
||||
oflags="-D"
|
||||
fi
|
||||
|
||||
# Verify buffered write followed by a direct read.
|
||||
log_must stride_dd -i $src_file -o $new_file -b $obs \
|
||||
-c $oblocks
|
||||
log_must stride_dd -i $new_file -o $tmp_file -b $ibs \
|
||||
-c $iblocks $iflags
|
||||
log_must cmp_md5s $new_file $tmp_file
|
||||
log_must rm -f $new_file $tmp_file
|
||||
|
||||
# Verify direct write followed by a buffered read.
|
||||
log_must stride_dd -i $src_file -o $new_file -b $obs \
|
||||
-c $oblocks $oflags
|
||||
log_must stride_dd -i $new_file -o $tmp_file -b $ibs \
|
||||
-c $iblocks
|
||||
log_must cmp_md5s $new_file $tmp_file
|
||||
log_must rm -f $new_file $tmp_file
|
||||
|
||||
# Verify direct write followed by a direct read.
|
||||
log_must stride_dd -i $src_file -o $new_file -b $obs \
|
||||
-c $oblocks $oflags
|
||||
log_must stride_dd -i $new_file -o $tmp_file -b $ibs \
|
||||
-c $iblocks $iflags
|
||||
log_must cmp_md5s $new_file $tmp_file
|
||||
log_must rm -f $new_file $tmp_file
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Verify mixed buffered and Direct I/O are coherent."
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify mixed Direct I/O and mmap I/O.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create an empty file.
|
||||
# 2. Start a background Direct I/O random read/write fio to the
|
||||
# file.
|
||||
# 3. Start a background mmap random read/write fio to the file.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zfs set recordsize=$rs $TESTPOOL/$TESTFS
|
||||
log_must rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
log_assert "Verify mixed Direct I/O and mmap I/O"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
tmp_file=$mntpnt/file
|
||||
bs=$((128 * 1024))
|
||||
blocks=64
|
||||
size=$((bs * blocks))
|
||||
runtime=60
|
||||
|
||||
rs=$(get_prop recordsize $TESTPOOL/$TESTFS)
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
|
||||
log_must stride_dd -i /dev/zero -o $tmp_file -b $bs -c $blocks
|
||||
|
||||
# Direct I/O writes
|
||||
log_must eval "fio --filename=$tmp_file --name=direct-write \
|
||||
--rw=randwrite --size=$size --bs=$bs --direct=1 --numjobs=1 \
|
||||
--ioengine=sync --fallocate=none --group_reporting --minimal \
|
||||
--runtime=$runtime --time_based --norandommap &"
|
||||
|
||||
# Direct I/O reads
|
||||
log_must eval "fio --filename=$tmp_file --name=direct-read \
|
||||
--rw=randread --size=$size --bs=$bs --direct=1 --numjobs=1 \
|
||||
--ioengine=sync --fallocate=none --group_reporting --minimal \
|
||||
--runtime=$runtime --time_based --norandommap &"
|
||||
|
||||
# mmap I/O writes
|
||||
log_must eval "fio --filename=$tmp_file --name=mmap-write \
|
||||
--rw=randwrite --size=$size --bs=$bs --numjobs=1 \
|
||||
--ioengine=mmap --fallocate=none --group_reporting --minimal \
|
||||
--runtime=$runtime --time_based --norandommap &"
|
||||
|
||||
# mmap I/O reads
|
||||
log_must eval "fio --filename=$tmp_file --name=mmap-read \
|
||||
--rw=randread --size=$size --bs=$bs --numjobs=1 \
|
||||
--ioengine=mmap --fallocate=none --group_reporting --minimal \
|
||||
--runtime=$runtime --time_based --norandommap &"
|
||||
|
||||
wait
|
||||
|
||||
log_pass "Verfied mixed Direct I/O and mmap I/O"
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2023 by Triad National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify Direct I/O overwrite.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create an empty file.
|
||||
# 2. Start a Direct I/O random write fio to the file.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zfs set recordsize=$rs $TESTPOOL/$TESTFS
|
||||
log_must rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
log_assert "Verify Direct I/O overwrites"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
tmp_file=$mntpnt/file
|
||||
bs=$((128 * 1024))
|
||||
blocks=64
|
||||
size=$((bs * blocks))
|
||||
runtime=60
|
||||
|
||||
rs=$(get_prop recordsize $TESTPOOL/$TESTFS)
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
|
||||
log_must stride_dd -i /dev/zero -o $tmp_file -b $bs -c $blocks
|
||||
|
||||
# Direct I/O overwrites
|
||||
log_must eval "fio --filename=$tmp_file --name=direct-write \
|
||||
--rw=randwrite --size=$size --bs=$bs --direct=1 --numjobs=1 \
|
||||
--ioengine=sync --fallocate=none --group_reporting --minimal \
|
||||
--runtime=$runtime --time_based --norandommap"
|
||||
|
||||
log_pass "Verfied Direct I/O overwrites"
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify the direct=always|disabled|standard property
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Verify direct=always behavior
|
||||
# 2. Verify direct=disabled behavior
|
||||
# 3. Verify direct=standard behavior
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zfs set direct=standard $TESTPOOL/$TESTFS
|
||||
log_must rm -f $tmp_file
|
||||
}
|
||||
|
||||
log_assert "Verify the direct=always|disabled|standard property"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
rs=$(get_prop recordsize $TESTPOOL/$TESTFS)
|
||||
|
||||
tmp_file=$mntpnt/tmp_file
|
||||
page_size=$(getconf PAGESIZE)
|
||||
file_size=1048576
|
||||
count=8
|
||||
|
||||
#
|
||||
# Check when "direct=always" any aligned IO is done as direct.
|
||||
# Note that the "-D" and "-d" flags are not set in the following calls to
|
||||
# stride_dd.
|
||||
#
|
||||
log_must zfs set direct=always $TESTPOOL/$TESTFS
|
||||
|
||||
log_note "Aligned writes (buffered, then all direct)"
|
||||
check_write $TESTPOOL $tmp_file $rs $count 0 "" 1 $((count - 1))
|
||||
|
||||
log_note "Aligned overwrites"
|
||||
check_write $TESTPOOL $tmp_file $rs $count 0 "" 0 $count
|
||||
|
||||
log_note "Sub-recordsize unaligned overwrites"
|
||||
check_write $TESTPOOL $tmp_file $((rs / 2)) $((2 * count)) 0 "" $((2 * count)) 0
|
||||
|
||||
log_note "Sub-page size aligned overwrites"
|
||||
check_write $TESTPOOL $tmp_file 512 $count 0 "" $count 0
|
||||
evict_blocks $TESTPOOL $tmp_file $file_size
|
||||
|
||||
log_note "Aligned reads"
|
||||
check_read $TESTPOOL $tmp_file $rs $count 0 "" 0 $count
|
||||
|
||||
log_note "Sub-recordsize unaligned reads"
|
||||
check_read $TESTPOOL $tmp_file $((rs / 2)) $((count * 2)) 0 "" 0 $((2 * count))
|
||||
|
||||
log_note "Sub-page size aligned reads (one read then ARC hits)"
|
||||
check_read $TESTPOOL $tmp_file 512 $count 0 "" 1 0
|
||||
|
||||
log_must rm -f $tmp_file
|
||||
|
||||
|
||||
#
|
||||
# Check when "direct=disabled" there are never any direct requests.
|
||||
# Note that the "-D" and "-d" flags are always set in the following calls to
|
||||
# stride_dd.
|
||||
#
|
||||
log_must zfs set direct=disabled $TESTPOOL/$TESTFS
|
||||
|
||||
log_note "Aligned writes (all buffered with an extra for create)"
|
||||
check_write $TESTPOOL $tmp_file $rs $count 0 "-D" $count 0
|
||||
|
||||
log_note "Aligned overwrites"
|
||||
check_write $TESTPOOL $tmp_file $rs $count 0 "-D" $count 0
|
||||
|
||||
log_note "Aligned reads (all ARC hits)"
|
||||
check_read $TESTPOOL $tmp_file $rs $count 0 "-d" 0 0
|
||||
|
||||
log_must rm -f $tmp_file
|
||||
|
||||
|
||||
#
|
||||
# Check when "direct=standard" only requested Direct I/O occur.
|
||||
#
|
||||
log_must zfs set direct=standard $TESTPOOL/$TESTFS
|
||||
|
||||
log_note "Aligned writes/overwrites (buffered / direct)"
|
||||
check_write $TESTPOOL $tmp_file $rs $count 0 "" $count 0
|
||||
check_write $TESTPOOL $tmp_file $rs $count 0 "-D" 0 $count
|
||||
|
||||
log_note "Aligned reads (buffered / direct)"
|
||||
evict_blocks $TESTPOOL $tmp_file $file_size
|
||||
check_read $TESTPOOL $tmp_file $rs $count 0 "" $count 0
|
||||
evict_blocks $TESTPOOL $tmp_file $file_size
|
||||
check_read $TESTPOOL $tmp_file $rs $count 0 "-d" 0 $count
|
||||
|
||||
log_pass "Verify the direct=always|disabled|standard property"
|
||||
+82
@@ -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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify mixed Direct I/O and buffered I/O. A workload of random
|
||||
# but correctly aligned direct read/writes is mixed with a
|
||||
# concurrent workload of entirely unaligned buffered read/writes.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create an empty file.
|
||||
# 2. Start a background fio randomly issuing direct read/writes.
|
||||
# 3. Start a background fio randomly issuing buffered read/writes.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must rm -f "$tmp_file"
|
||||
}
|
||||
|
||||
log_assert "Verify randomly sized mixed Direct I/O and buffered I/O"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
tmp_file=$mntpnt/file
|
||||
bs=$((1024 * 1024))
|
||||
blocks=32
|
||||
size=$((bs * blocks))
|
||||
runtime=10
|
||||
page_size=$(getconf PAGESIZE)
|
||||
|
||||
log_must stride_dd -i /dev/zero -o $tmp_file -b $bs -c $blocks
|
||||
|
||||
# Direct random read/write page-aligned IO of varying sizes with
|
||||
# occasional calls to fsync(2), mixed with...
|
||||
log_must eval "fio --filename=$tmp_file --name=direct-rwrand \
|
||||
--rw=randrw --size=$size --offset_align=$(getconf PAGESIZE) \
|
||||
--bsrange=$page_size-1m --direct=1 --fsync=32 --numjobs=2 \
|
||||
--ioengine=sync --fallocate=none --verify=sha1 \
|
||||
--group_reporting --minimal --runtime=$runtime --time_based &"
|
||||
|
||||
# Buffered random read/write entirely unaligned IO of varying sizes
|
||||
# occasional calls to fsync(2).
|
||||
log_must eval "fio --filename=$tmp_file --name=buffered-write \
|
||||
--rw=randrw --size=$size --offset_align=512 --bs_unaligned=1 \
|
||||
--bsrange=$page_size-1m --direct=0 --fsync=32 --numjobs=2 \
|
||||
--ioengine=sync --fallocate=none --verify=sha1 \
|
||||
--group_reporting --minimal --runtime=$runtime --time_based &"
|
||||
|
||||
wait
|
||||
|
||||
log_pass "Verfied randomly sized mixed Direct I/O and buffered I/O"
|
||||
@@ -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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2020 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify different recordsizes are supported for Direct I/O.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a pool from each vdev type with varying recordsizes.
|
||||
# 2. Start sequential Direct I/O and verify with buffered I/O.
|
||||
# 3. Start mixed Direct I/O and verify with buffered I/O.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Verify different recordsizes are supported for Direct I/O."
|
||||
|
||||
log_onexit dio_cleanup
|
||||
|
||||
log_must truncate -s $MINVDEVSIZE $DIO_VDEVS
|
||||
|
||||
for type in "" "mirror" "raidz" "draid"; do
|
||||
for recsize in "1024" "4096" "128k"; do
|
||||
create_pool $TESTPOOL1 $type $DIO_VDEVS
|
||||
log_must eval "zfs create \
|
||||
-o recordsize=$recsize -o compression=off \
|
||||
$TESTPOOL1/$TESTFS1"
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS1)
|
||||
|
||||
for bs in "4k" "128k"; do
|
||||
for op in "rw" "randrw" "write"; do
|
||||
dio_and_verify $op $DIO_FILESIZE $bs $mntpnt "sync"
|
||||
done
|
||||
done
|
||||
|
||||
destroy_pool $TESTPOOL1
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Verified different recordsizes are supported for Direct I/O."
|
||||
@@ -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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify failure for (un)aligned O_DIRECT
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a multi-block file
|
||||
# 2. Perform (un)aligned write/read verify the result.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zfs set recordsize=$rs $TESTPOOL/$TESTFS
|
||||
zfs set direct=standard $TESTPOOL/$TESTFS
|
||||
log_must rm -f $tmp_file
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Verify direct requests for (un)aligned access"
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
|
||||
rs=$(get_prop recordsize $TESTPOOL/$TESTFS)
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
|
||||
tmp_file=$mntpnt/tmp_file
|
||||
file_size=$((rs * 8))
|
||||
|
||||
log_must stride_dd -i /dev/urandom -o $tmp_file -b $file_size -c 1
|
||||
|
||||
log_must zfs set direct=standard $TESTPOOL/$TESTFS
|
||||
# sub-pagesize direct writes/read will always fail if direct=standard.
|
||||
log_mustnot stride_dd -i /dev/urandom -o $tmp_file -b 512 -c 8 -D
|
||||
log_mustnot stride_dd -i $tmp_file -o /dev/null -b 512 -c 8 -d
|
||||
|
||||
log_must zfs set direct=always $TESTPOOL/$TESTFS
|
||||
# sub-pagesize direct writes/read will always pass if direct=always.
|
||||
log_must stride_dd -i /dev/urandom -o $tmp_file -b 512 -c 8
|
||||
log_must stride_dd -i $tmp_file -o /dev/null -b 512 -c 8
|
||||
|
||||
log_must zfs set direct=disabled $TESTPOOL/$TESTFS
|
||||
# sub-pagesize direct writes/read will always pass if direct=disabled.
|
||||
log_must stride_dd -i /dev/urandom -o $tmp_file -b 512 -c 8 -D
|
||||
log_must stride_dd -i $tmp_file -o /dev/null -b 512 -c 8 -d
|
||||
|
||||
log_pass "Verify direct requests for (un)aligned access"
|
||||
@@ -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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2022 by Triad National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify Direct I/O reads can read an entire file that is not
|
||||
# page-aligned in length. When a file is not page-aligned in total
|
||||
# length, as much that can be read using using O_DIRECT is done so and
|
||||
# the rest is read using the ARC. O_DIRECT requires page-size alignment.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Write a file that is page-aligned (buffered)
|
||||
# 2. Truncate the file to be 512 bytes less
|
||||
# 3. Export then import the Zpool flushing out the ARC
|
||||
# 4. Read back the file using O_DIRECT
|
||||
# 5. Verify the file is read back with both Direct I/O and buffered I/O
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must rm -f "$filename"
|
||||
log_must set recordsize=$rs $TESTPOOL/$TESTFS
|
||||
}
|
||||
|
||||
log_assert "Verify Direct I/O reads can read an entire file that is not \
|
||||
page-aligned"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
|
||||
rs=$(get_prop recordsize $TESTPOOL/$TESTFS)
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
|
||||
bs=$((128 * 1024)) # bs=recordsize (128k)
|
||||
filename="$mntpnt/testfile.iso"
|
||||
|
||||
log_must stride_dd -i /dev/urandom -o $filename -b $bs -c 2
|
||||
# Truncating file so the total length is no longer page-size aligned
|
||||
log_must do_truncate_reduce $filename 512
|
||||
|
||||
# Exporting the Zpool to make sure all future reads happen from the ARC
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool import $TESTPOOL
|
||||
|
||||
# Reading the file back using Direct I/O
|
||||
prev_dio_read=$(get_iostats_stat $TESTPOOL direct_read_count)
|
||||
prev_arc_read=$(get_iostats_stat $TESTPOOL arc_read_count)
|
||||
log_must stride_dd -i $filename -o /dev/null -b $bs -e -d
|
||||
curr_dio_read=$(get_iostats_stat $TESTPOOL direct_read_count)
|
||||
curr_arc_read=$(get_iostats_stat $TESTPOOL arc_read_count)
|
||||
total_dio_read=$((curr_dio_read - prev_dio_read))
|
||||
total_arc_read=$((curr_arc_read - prev_arc_read))
|
||||
|
||||
# We should see both Direct I/O reads an ARC read to read the entire file that
|
||||
# is not page-size aligned
|
||||
if [[ $total_dio_read -lt 2 ]] || [[ $total_arc_read -lt 1 ]]; then
|
||||
log_fail "Expect 2 reads from Direct I/O and 1 from the ARC but \
|
||||
Direct I/O: $total_dio_read ARC: $total_arc_read"
|
||||
fi
|
||||
|
||||
log_pass "Verified Direct I/O read can read a none page-aligned length file"
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2022 by Triad National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify stable pages work for O_DIRECT writes.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Start a Direct I/O write workload while manipulating the user
|
||||
# buffer.
|
||||
# 2. Verify we can Read the contents of the file using buffered reads.
|
||||
# 3. Verify there is no checksum errors reported from zpool status.
|
||||
# 4. Repeat steps 1 and 2 for 3 iterations.
|
||||
# 5. Repeat 1-3 but with compression disabled.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must rm -f "$mntpnt/direct-write.iso"
|
||||
check_dio_write_chksum_verify_failures $TESTPOOL "raidz" 0
|
||||
}
|
||||
|
||||
log_assert "Verify stable pages work for Direct I/O writes."
|
||||
|
||||
if is_linux; then
|
||||
log_unsupported "Linux does not support stable pages for O_DIRECT \
|
||||
writes"
|
||||
fi
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
ITERATIONS=3
|
||||
NUMBLOCKS=300
|
||||
BS=$((128 * 1024)) #128k
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
|
||||
for compress in "on" "off";
|
||||
do
|
||||
log_must zfs set compression=$compress $TESTPOOL/$TESTFS
|
||||
|
||||
for i in $(seq 1 $ITERATIONS); do
|
||||
log_note "Verifying stable pages for Direct I/O writes \
|
||||
iteration $i of $ITERATIONS"
|
||||
|
||||
prev_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
|
||||
# Manipulate the user's buffer while running O_DIRECT write
|
||||
# workload with the buffer.
|
||||
log_must manipulate_user_buffer -o "$mntpnt/direct-write.iso" \
|
||||
-n $NUMBLOCKS -b $BS
|
||||
|
||||
# Reading back the contents of the file
|
||||
log_must stride_dd -i $mntpnt/direct-write.iso -o /dev/null \
|
||||
-b $BS -c $NUMBLOCKS
|
||||
|
||||
curr_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
total_dio_wr=$((curr_dio_wr - prev_dio_wr))
|
||||
|
||||
log_note "Making sure we have Direct I/O writes logged"
|
||||
if [[ $total_dio_wr -lt 1 ]]; then
|
||||
log_fail "No Direct I/O writes $total_dio_wr"
|
||||
fi
|
||||
|
||||
# Making sure there are no data errors for the zpool
|
||||
log_note "Making sure there are no checksum errors with the ZPool"
|
||||
log_must check_pool_status $TESTPOOL "errors" \
|
||||
"No known data errors"
|
||||
|
||||
log_must rm -f "$mntpnt/direct-write.iso"
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Verified stable pages work for Direct I/O writes."
|
||||
@@ -0,0 +1,196 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2022 by Triad National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/direct/dio.cfg
|
||||
. $STF_SUITE/tests/functional/direct/dio.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify checksum verify works for Direct I/O writes.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Set the module parameter zfs_vdev_direct_write_verify to 0.
|
||||
# 2. Check that manipulating the user buffer while Direct I/O writes are
|
||||
# taking place does not cause any panics with compression turned on.
|
||||
# 3. Start a Direct I/O write workload while manipulating the user buffer
|
||||
# without compression.
|
||||
# 4. Verify there are Direct I/O write verify failures using
|
||||
# zpool status -d and checking for zevents. We also make sure there
|
||||
# are reported data errors when reading the file back.
|
||||
# 5. Repeat steps 3 and 4 for 3 iterations.
|
||||
# 6. Set zfs_vdev_direct_write_verify set to 1 and repeat 3.
|
||||
# 7. Verify there are Direct I/O write verify failures using
|
||||
# zpool status -d and checking for zevents. We also make sure there
|
||||
# there are no reported data errors when reading the file back because
|
||||
# with us checking every Direct I/O write and on checksum validation
|
||||
# failure those writes will not be committed to a VDEV.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
# Clearing out DIO counts for Zpool
|
||||
log_must zpool clear $TESTPOOL
|
||||
# Clearing out dio_verify from event logs
|
||||
log_must zpool events -c
|
||||
log_must set_tunable32 VDEV_DIRECT_WR_VERIFY $DIO_WR_VERIFY_TUNABLE
|
||||
}
|
||||
|
||||
log_assert "Verify checksum verify works for Direct I/O writes."
|
||||
|
||||
if is_freebsd; then
|
||||
log_unsupported "FreeBSD is capable of stable pages for O_DIRECT writes"
|
||||
fi
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
ITERATIONS=3
|
||||
NUMBLOCKS=300
|
||||
BS=$((128 * 1024)) # 128k
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
|
||||
typeset DIO_WR_VERIFY_TUNABLE=$(get_tunable VDEV_DIRECT_WR_VERIFY)
|
||||
|
||||
# Get a list of vdevs in our pool
|
||||
set -A array $(get_disklist_fullpath $TESTPOOL)
|
||||
|
||||
# Get the first vdev
|
||||
firstvdev=${array[0]}
|
||||
|
||||
log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
|
||||
log_must set_tunable32 VDEV_DIRECT_WR_VERIFY 0
|
||||
|
||||
# First we will verify there are no panics while manipulating the contents of
|
||||
# the user buffer during Direct I/O writes with compression. The contents
|
||||
# will always be copied out of the ABD and there should never be any ABD ASSERT
|
||||
# failures
|
||||
log_note "Verifying no panics for Direct I/O writes with compression"
|
||||
log_must zfs set compression=on $TESTPOOL/$TESTFS
|
||||
prev_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
log_must manipulate_user_buffer -o "$mntpnt/direct-write.iso" -n $NUMBLOCKS \
|
||||
-b $BS
|
||||
curr_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
total_dio_wr=$((curr_dio_wr - prev_dio_wr))
|
||||
|
||||
log_note "Making sure we have Direct I/O writes logged"
|
||||
if [[ $total_dio_wr -lt 1 ]]; then
|
||||
log_fail "No Direct I/O writes $total_dio_wr"
|
||||
fi
|
||||
|
||||
# Clearing out DIO counts for Zpool
|
||||
log_must zpool clear $TESTPOOL
|
||||
# Clearing out dio_verify from event logs
|
||||
log_must zpool events -c
|
||||
log_must rm -f "$mntpnt/direct-write.iso"
|
||||
|
||||
# Next we will verify there are checksum errors for Direct I/O writes while
|
||||
# manipulating the contents of the user pages.
|
||||
log_must zfs set compression=off $TESTPOOL/$TESTFS
|
||||
|
||||
for i in $(seq 1 $ITERATIONS); do
|
||||
log_note "Verifying Direct I/O write checksums iteration \
|
||||
$i of $ITERATIONS with zfs_vdev_direct_write_verify=0"
|
||||
|
||||
prev_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
log_must manipulate_user_buffer -o "$mntpnt/direct-write.iso" \
|
||||
-n $NUMBLOCKS -b $BS
|
||||
|
||||
# Reading file back to verify checksum errors
|
||||
filesize=$(get_file_size "$mntpnt/direct-write.iso")
|
||||
num_blocks=$((filesize / BS))
|
||||
log_mustnot stride_dd -i "$mntpnt/direct-write.iso" -o /dev/null -b $BS \
|
||||
-c $num_blocks
|
||||
|
||||
# Getting new Direct I/O and ARC write counts.
|
||||
curr_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
total_dio_wr=$((curr_dio_wr - prev_dio_wr))
|
||||
|
||||
# Verifying there are checksum errors
|
||||
log_note "Making sure there are checksum errors for the ZPool"
|
||||
cksum=$(zpool status -P -v $TESTPOOL | awk -v v="$firstvdev" '$0 ~ v \
|
||||
{print $5}')
|
||||
if [[ $cksum -eq 0 ]]; then
|
||||
zpool status -P -v $TESTPOOL
|
||||
log_fail "No checksum failures for ZPool $TESTPOOL"
|
||||
fi
|
||||
|
||||
log_note "Making sure we have Direct I/O writes logged"
|
||||
if [[ $total_dio_wr -lt 1 ]]; then
|
||||
log_fail "No Direct I/O writes $total_dio_wr"
|
||||
fi
|
||||
log_note "Making sure we have no Direct I/O write checksum verifies \
|
||||
with ZPool"
|
||||
check_dio_write_chksum_verify_failures $TESTPOOL "raidz" 0
|
||||
|
||||
log_must rm -f "$mntpnt/direct-write.iso"
|
||||
done
|
||||
|
||||
log_must zpool status -v $TESTPOOL
|
||||
log_must zpool sync $TESTPOOL
|
||||
|
||||
|
||||
|
||||
# Finally we will verfiy that with checking every Direct I/O write we have no
|
||||
# errors at all.
|
||||
# Create the file before trying to manipulate the contents
|
||||
log_must file_write -o create -f "$mntpnt/direct-write.iso" -b $BS \
|
||||
-c $NUMBLOCKS -w
|
||||
log_must set_tunable32 VDEV_DIRECT_WR_VERIFY 1
|
||||
|
||||
for i in $(seq 1 $ITERATIONS); do
|
||||
log_note "Verifying every Direct I/O write checksums iteration $i of \
|
||||
$ITERATIONS with zfs_vdev_direct_write_verify=1"
|
||||
|
||||
prev_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
log_must manipulate_user_buffer -o "$mntpnt/direct-write.iso" \
|
||||
-n $NUMBLOCKS -b $BS -e
|
||||
|
||||
# Reading file back to verify there no are checksum errors
|
||||
filesize=$(get_file_size "$mntpnt/direct-write.iso")
|
||||
num_blocks=$((filesize / BS))
|
||||
log_must stride_dd -i "$mntpnt/direct-write.iso" -o /dev/null -b $BS \
|
||||
-c $num_blocks
|
||||
|
||||
# Getting new Direct I/O and ARC Write counts.
|
||||
curr_dio_wr=$(get_iostats_stat $TESTPOOL direct_write_count)
|
||||
total_dio_wr=$((curr_dio_wr - prev_dio_wr))
|
||||
|
||||
log_note "Making sure there are no checksum errors with the ZPool"
|
||||
log_must check_pool_status $TESTPOOL "errors" "No known data errors"
|
||||
|
||||
log_note "Making sure we have Direct I/O writes logged"
|
||||
if [[ $total_dio_wr -lt 1 ]]; then
|
||||
log_fail "No Direct I/O writes $total_dio_wr"
|
||||
fi
|
||||
|
||||
log_note "Making sure we have Direct I/O write checksum verifies with ZPool"
|
||||
check_dio_write_chksum_verify_failures "$TESTPOOL" "raidz" 1
|
||||
done
|
||||
|
||||
log_must rm -f "$mntpnt/direct-write.iso"
|
||||
|
||||
log_pass "Verified checksum verify works for Direct I/O writes."
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#!/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 https://opensource.org/licenses/CDDL-1.0.
|
||||
# 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) 2021 by Lawrence Livermore National Security, LLC.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
verify_runnable "global"
|
||||
|
||||
if tunable_exists DIO_ENABLED ; then
|
||||
log_must save_tunable DIO_ENABLED
|
||||
log_must set_tunable32 DIO_ENABLED 1
|
||||
fi
|
||||
|
||||
default_raidz_setup_noexit "$DISKS"
|
||||
log_must zfs set compression=off $TESTPOOL/$TESTFS
|
||||
log_pass
|
||||
@@ -27,5 +27,5 @@
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
verify_runnable "global"
|
||||
|
||||
default_setup "$DISKS"
|
||||
default_raidz_setup "$DISKS"
|
||||
log_must zfs set compression=on $TESTPOOL/$TESTFS
|
||||
|
||||
@@ -35,4 +35,4 @@ export PERF_COMPPERCENT=66
|
||||
export PERF_COMPCHUNK=0
|
||||
export BLOCKSIZE=128K
|
||||
export SYNC_TYPE=0
|
||||
export DIRECT=1
|
||||
export DIRECT=0
|
||||
|
||||
@@ -155,13 +155,6 @@ function cleanup_pool
|
||||
fi
|
||||
}
|
||||
|
||||
function cmp_md5s {
|
||||
typeset file1=$1
|
||||
typeset file2=$2
|
||||
|
||||
[ "$(md5digest $file1)" = "$(md5digest $file2)" ]
|
||||
}
|
||||
|
||||
#
|
||||
# Detect if the given two filesystems have same sub-datasets
|
||||
#
|
||||
|
||||
@@ -77,6 +77,14 @@ log_must zfs create $TESTPOOL/$TESTFS
|
||||
log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/sync \
|
||||
conv=fdatasync,fsync bs=1 count=1
|
||||
|
||||
#
|
||||
# Create a small file for the O_DIRECT test before freezing the pool. This
|
||||
# allows us to overwrite it after the pool is frozen and avoid the case
|
||||
# where O_DIRECT is disabled because the first block must be grown.
|
||||
#
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/direct \
|
||||
oflag=sync,direct bs=4k count=1
|
||||
|
||||
#
|
||||
# 2. Freeze TESTFS
|
||||
#
|
||||
@@ -140,6 +148,10 @@ log_must truncate -s 0 /$TESTPOOL/$TESTFS/truncated_file
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/large \
|
||||
oflag=sync bs=128k count=64
|
||||
|
||||
# TX_WRITE (O_DIRECT)
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/direct \
|
||||
oflag=sync,direct bs=4k count=1
|
||||
|
||||
# Write zeros, which compress to holes, in the middle of a file
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.1 \
|
||||
oflag=sync bs=128k count=8
|
||||
|
||||
@@ -77,7 +77,7 @@ export PERF_COMPCHUNK=0
|
||||
export RUNTIME=30
|
||||
export BLOCKSIZE=128K
|
||||
export SYNC_TYPE=0
|
||||
export DIRECT=1
|
||||
export DIRECT=0
|
||||
|
||||
# Write to the pool.
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
Reference in New Issue
Block a user