]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Direct IO support
authorBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 27 Aug 2018 17:04:21 +0000 (10:04 -0700)
committerGitHub <noreply@github.com>
Mon, 27 Aug 2018 17:04:21 +0000 (10:04 -0700)
Direct IO via the O_DIRECT flag was originally introduced in XFS by
IRIX for database workloads. Its purpose was to allow the database
to bypass the page and buffer caches to prevent unnecessary IO
operations (e.g.  readahead) while preventing contention for system
memory between the database and kernel caches.

On Illumos, there is a library function called directio(3C) that
allows user space to provide a hint to the file system that Direct IO
is useful, but the file system is free to ignore it. The semantics
are also entirely a file system decision. Those that do not
implement it return ENOTTY.

Since the semantics were never defined in any standard, O_DIRECT is
implemented such that it conforms to the behavior described in the
Linux open(2) man page as follows.

    1.  Minimize cache effects of the I/O.

    By design the ARC is already scan-resistant which helps mitigate
    the need for special O_DIRECT handling.  Data which is only
    accessed once will be the first to be evicted from the cache.
    This behavior is in consistent with Illumos and FreeBSD.

    Future performance work may wish to investigate the benefits of
    immediately evicting data from the cache which has been read or
    written with the O_DIRECT flag.  Functionally this behavior is
    very similar to applying the 'primarycache=metadata' property
    per open file.

    2. O_DIRECT _MAY_ impose restrictions on IO alignment and length.

    No additional alignment or length restrictions are imposed.

    3. O_DIRECT _MAY_ perform unbuffered IO operations directly
       between user memory and block device.

    No unbuffered IO operations are currently supported.  In order
    to support features such as transparent compression, encryption,
    and checksumming a copy must be made to transform the data.

    4. O_DIRECT _MAY_ imply O_DSYNC (XFS).

    O_DIRECT does not imply O_DSYNC for ZFS.  Callers must provide
    O_DSYNC to request synchronous semantics.

    5. O_DIRECT _MAY_ disable file locking that serializes IO
       operations.  Applications should avoid mixing O_DIRECT
       and normal IO or mmap(2) IO to the same file.  This is
       particularly true for overlapping regions.

    All I/O in ZFS is locked for correctness and this locking is not
    disabled by O_DIRECT.  However, concurrently mixing O_DIRECT,
    mmap(2), and normal I/O on the same file is not recommended.

This change is implemented by layering the aops->direct_IO operations
on the existing AIO operations.  Code already existed in ZFS on Linux
for bypassing the page cache when O_DIRECT is specified.

References:
  * http://xfs.org/docs/xfsdocs-xml-dev/XFS_User_Guide/tmp/en-US/html/ch02s09.html
  * https://blogs.oracle.com/roch/entry/zfs_and_directio
  * https://ext4.wiki.kernel.org/index.php/Clarifying_Direct_IO's_Semantics
  * https://illumos.org/man/3c/directio

Reviewed-by: Richard Elling <Richard.Elling@RichardElling.com>
Signed-off-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #224
Closes #7823

18 files changed:
config/kernel-vfs-direct_IO.m4 [new file with mode: 0644]
config/kernel.m4
configure.ac
module/zfs/zpl_file.c
scripts/commitcheck.sh
tests/runfiles/linux.run
tests/test-runner/bin/zts-report.py
tests/zfs-tests/include/libtest.shlib
tests/zfs-tests/tests/functional/Makefile.am
tests/zfs-tests/tests/functional/io/Makefile.am [new file with mode: 0644]
tests/zfs-tests/tests/functional/io/cleanup.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/io/io.cfg [new file with mode: 0644]
tests/zfs-tests/tests/functional/io/libaio.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/io/mmap.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/io/posixaio.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/io/psync.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/io/setup.ksh [new file with mode: 0755]
tests/zfs-tests/tests/functional/io/sync.ksh [new file with mode: 0755]

diff --git a/config/kernel-vfs-direct_IO.m4 b/config/kernel-vfs-direct_IO.m4
new file mode 100644 (file)
index 0000000..cc50bfb
--- /dev/null
@@ -0,0 +1,130 @@
+dnl #
+dnl # Linux 4.6.x API change
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER], [
+       AC_MSG_CHECKING([whether aops->direct_IO() uses iov_iter])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+
+               ssize_t test_direct_IO(struct kiocb *kiocb,
+                   struct iov_iter *iter) { return 0; }
+
+               static const struct address_space_operations
+                   aops __attribute__ ((unused)) = {
+                       .direct_IO = test_direct_IO,
+               };
+       ],[
+       ],[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER, 1,
+                   [aops->direct_IO() uses iov_iter without rw])
+               zfs_ac_direct_io="yes"
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+])
+
+dnl #
+dnl # Linux 4.1.x API change
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET], [
+       AC_MSG_CHECKING(
+           [whether aops->direct_IO() uses iov_iter with offset])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+
+               ssize_t test_direct_IO(struct kiocb *kiocb,
+                   struct iov_iter *iter, loff_t offset) { return 0; }
+
+               static const struct address_space_operations
+                   aops __attribute__ ((unused)) = {
+                       .direct_IO = test_direct_IO,
+               };
+       ],[
+       ],[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_OFFSET, 1,
+                   [aops->direct_IO() uses iov_iter with offset])
+               zfs_ac_direct_io="yes"
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+])
+
+dnl #
+dnl # Linux 3.16.x API change
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET], [
+       AC_MSG_CHECKING(
+           [whether aops->direct_IO() uses iov_iter with rw and offset])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+
+               ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
+                   struct iov_iter *iter, loff_t offset) { return 0; }
+
+               static const struct address_space_operations
+                   aops __attribute__ ((unused)) = {
+                   .direct_IO = test_direct_IO,
+               };
+       ],[
+       ],[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_VFS_DIRECT_IO_ITER_RW_OFFSET, 1,
+                   [aops->direct_IO() uses iov_iter with rw and offset])
+               zfs_ac_direct_io="yes"
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+])
+
+dnl #
+dnl # Ancient Linux API (predates git)
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC], [
+       AC_MSG_CHECKING([whether aops->direct_IO() uses iovec])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+
+               ssize_t test_direct_IO(int rw, struct kiocb *kiocb,
+                   const struct iovec *iov, loff_t offset,
+                   unsigned long nr_segs) { return 0; }
+
+               static const struct address_space_operations
+                   aops __attribute__ ((unused)) = {
+                   .direct_IO = test_direct_IO,
+               };
+       ],[
+       ],[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_VFS_DIRECT_IO_IOVEC, 1,
+                   [aops->direct_IO() uses iovec])
+               zfs_ac_direct_io="yes"
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_VFS_DIRECT_IO], [
+       zfs_ac_direct_io="no"
+
+       if test "$zfs_ac_direct_io" = "no"; then
+               ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER
+       fi
+
+       if test "$zfs_ac_direct_io" = "no"; then
+               ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_OFFSET
+       fi
+
+       if test "$zfs_ac_direct_io" = "no"; then
+               ZFS_AC_KERNEL_VFS_DIRECT_IO_ITER_RW_OFFSET
+       fi
+
+       if test "$zfs_ac_direct_io" = "no"; then
+               ZFS_AC_KERNEL_VFS_DIRECT_IO_IOVEC
+       fi
+
+       if test "$zfs_ac_direct_io" = "no"; then
+               AC_MSG_ERROR([no; unknown direct IO interface])
+       fi
+])
index 7ae10c1274608682bd466b9d00ffd672e6777ce0..7b92c47445254bf9fe40abbdfc7770b7ca389f15 100644 (file)
@@ -144,6 +144,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
        ZFS_AC_KERNEL_LSEEK_EXECUTE
        ZFS_AC_KERNEL_VFS_ITERATE
        ZFS_AC_KERNEL_VFS_RW_ITERATE
+       ZFS_AC_KERNEL_VFS_DIRECT_IO
        ZFS_AC_KERNEL_GENERIC_WRITE_CHECKS
        ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS
        ZFS_AC_KERNEL_FOLLOW_DOWN_ONE
index 5a308976c7688ce4e833de684f435845662b77b1..dbc063fd00933d041cf7628d22156daf20294093 100644 (file)
@@ -280,6 +280,7 @@ AC_CONFIG_FILES([
        tests/zfs-tests/tests/functional/hkdf/Makefile
        tests/zfs-tests/tests/functional/inheritance/Makefile
        tests/zfs-tests/tests/functional/inuse/Makefile
+       tests/zfs-tests/tests/functional/io/Makefile
        tests/zfs-tests/tests/functional/kstat/Makefile
        tests/zfs-tests/tests/functional/large_files/Makefile
        tests/zfs-tests/tests/functional/largest_pool/Makefile
index 91251f9e6e0fd986cf5a1d33e620d89972eded93..8d9c44b37294531d73e51f36bf2aae7f90d6055b 100644 (file)
@@ -438,6 +438,57 @@ zpl_aio_write(struct kiocb *kiocb, const struct iovec *iovp,
 }
 #endif /* HAVE_VFS_RW_ITERATE */
 
+#if defined(HAVE_VFS_RW_ITERATE)
+static ssize_t
+zpl_direct_IO_impl(int rw, struct kiocb *kiocb, struct iov_iter *iter)
+{
+       if (rw == WRITE)
+               return (zpl_iter_write(kiocb, iter));
+       else
+               return (zpl_iter_read(kiocb, iter));
+}
+#if defined(HAVE_VFS_DIRECT_IO_ITER)
+static ssize_t
+zpl_direct_IO(struct kiocb *kiocb, struct iov_iter *iter)
+{
+       return (zpl_direct_IO_impl(iov_iter_rw(iter), kiocb, iter));
+}
+#elif defined(HAVE_VFS_DIRECT_IO_ITER_OFFSET)
+static ssize_t
+zpl_direct_IO(struct kiocb *kiocb, struct iov_iter *iter, loff_t pos)
+{
+       ASSERT3S(pos, ==, kiocb->ki_pos);
+       return (zpl_direct_IO_impl(iov_iter_rw(iter), kiocb, iter));
+}
+#elif defined(HAVE_VFS_DIRECT_IO_ITER_RW_OFFSET)
+static ssize_t
+zpl_direct_IO(int rw, struct kiocb *kiocb, struct iov_iter *iter, loff_t pos)
+{
+       ASSERT3S(pos, ==, kiocb->ki_pos);
+       return (zpl_direct_IO_impl(rw, kiocb, iter));
+}
+#else
+#error "Unknown direct IO interface"
+#endif
+
+#else
+
+#if defined(HAVE_VFS_DIRECT_IO_IOVEC)
+static ssize_t
+zpl_direct_IO(int rw, struct kiocb *kiocb, const struct iovec *iovp,
+    loff_t pos, unsigned long nr_segs)
+{
+       if (rw == WRITE)
+               return (zpl_aio_write(kiocb, iovp, nr_segs, pos));
+       else
+               return (zpl_aio_read(kiocb, iovp, nr_segs, pos));
+}
+#else
+#error "Unknown direct IO interface"
+#endif
+
+#endif /* HAVE_VFS_RW_ITERATE */
+
 static loff_t
 zpl_llseek(struct file *filp, loff_t offset, int whence)
 {
@@ -929,6 +980,7 @@ const struct address_space_operations zpl_address_space_operations = {
        .readpage       = zpl_readpage,
        .writepage      = zpl_writepage,
        .writepages     = zpl_writepages,
+       .direct_IO      = zpl_direct_IO,
 };
 
 const struct file_operations zpl_file_operations = {
index 190943916340874c15ae5719791840d8fd7525f5..4d37b3a3c721eb80ac520e2fe4fa6d93000ed279 100755 (executable)
@@ -16,10 +16,11 @@ function test_url()
 }
 
 # test commit body for length
+# lines containing urls are exempt for the length limit.
 function test_commit_bodylength()
 {
     length="72"
-    body=$(git log -n 1 --pretty=%b "$REF" | grep -E -m 1 ".{$((length + 1))}")
+    body=$(git log -n 1 --pretty=%b "$REF" | grep -Ev "http(s)*://" | grep -E -m 1 ".{$((length + 1))}")
     if [ -n "$body" ]; then
         echo "error: commit message body contains line over ${length} characters"
         return 1
index 2e673c74df5096cae35df4ede336925d6906c820..a9594aeffd01290f40d74f849ee738b7c3b96fc2 100644 (file)
@@ -558,6 +558,10 @@ tests = ['inherit_001_pos']
 pre =
 tags = ['functional', 'inheritance']
 
+[tests/functional/io]
+tests = ['sync', 'psync', 'libaio', 'posixaio', 'mmap']
+tags = ['functional', 'io']
+
 [tests/functional/inuse]
 tests = ['inuse_001_pos', 'inuse_003_pos', 'inuse_004_pos',
     'inuse_005_pos', 'inuse_006_pos', 'inuse_007_pos', 'inuse_008_pos',
index 6c0a2262d2604c3d0d50a9355ee84b1553c47283..e1a9011d321be245c50c9cea53d00d3120bd8a77 100755 (executable)
@@ -120,6 +120,12 @@ rewind_reason = 'Arbitrary pool rewind is not guaranteed'
 #
 enospc_reason = 'Exact free space reporting is not guaranteed'
 
+#
+# Some tests require a minimum version of the fio benchmark utility.
+# Older distributions such as CentOS 6.x only provide fio-2.0.13.
+#
+fio_reason = 'Fio v2.3 or newer required'
+
 #
 # Some tests are not applicable to Linux or need to be updated to operate
 # in the manor required by Linux.  Any tests which are skipped for this
@@ -246,6 +252,7 @@ maybe = {
     'inuse/inuse_005_pos': ['SKIP', disk_reason],
     'inuse/inuse_008_pos': ['SKIP', disk_reason],
     'inuse/inuse_009_pos': ['SKIP', disk_reason],
+    'io/mmap': ['SKIP', fio_reason],
     'largest_pool/largest_pool_001_pos': ['FAIL', known_reason],
     'pyzfs/pyzfs_unittest': ['SKIP', python_deps_reason],
     'no_space/enospc_002_pos': ['FAIL', enospc_reason],
index 73b3978942479821c955655738fb94c5e1feba85..1fdb91bd909dab3fc44550a5ea4d17236ab28048 100644 (file)
@@ -41,6 +41,20 @@ if [ -n "$STF_PATH" ]; then
        PATH="$STF_PATH"
 fi
 
+#
+# Generic dot version comparison function
+#
+# Returns success when version $1 is greater than or equal to $2.
+#
+function compare_version_gte
+{
+       if [[ "$(printf "$1\n$2" | sort -V | tail -n1)" == "$1" ]]; then
+               return 0
+       else
+               return 1
+       fi
+}
+
 # Linux kernel version comparison function
 #
 # $1 Linux version ("4.10", "2.6.32") or blank for installed Linux version
index 5e877c1bf3abc74ad1f0055dd05b5c8ef48030d5..5cd079b988a8d2847a88c50a5335b397196905e8 100644 (file)
@@ -27,6 +27,7 @@ SUBDIRS = \
        hkdf \
        inheritance \
        inuse \
+       io \
        kstat \
        large_files \
        largest_pool \
diff --git a/tests/zfs-tests/tests/functional/io/Makefile.am b/tests/zfs-tests/tests/functional/io/Makefile.am
new file mode 100644 (file)
index 0000000..5253f08
--- /dev/null
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/io
+dist_pkgdata_SCRIPTS = \
+       setup.ksh \
+       cleanup.ksh \
+       sync.ksh \
+       psync.ksh \
+       libaio.ksh \
+       posixaio.ksh \
+       mmap.ksh
+
+dist_pkgdata_DATA = \
+       io.cfg
diff --git a/tests/zfs-tests/tests/functional/io/cleanup.ksh b/tests/zfs-tests/tests/functional/io/cleanup.ksh
new file mode 100755 (executable)
index 0000000..0031a26
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/io/io.cfg b/tests/zfs-tests/tests/functional/io/io.cfg
new file mode 100644 (file)
index 0000000..9312ad1
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+FIO_COMMON_ARGS="--numjobs=1 --bs=32k --size=32M --fallocate=none --group_reporting --verify=sha1 --minimal"
+
+FIO_READ_ARGS="--name=rw --rw=read $FIO_COMMON_ARGS"
+FIO_WRITE_ARGS="--name=rw --rw=write $FIO_COMMON_ARGS"
+FIO_RANDREAD_ARGS="--name=rw --rw=randread $FIO_COMMON_ARGS"
+FIO_RANDWRITE_ARGS="--name=rw --rw=randwrite $FIO_COMMON_ARGS"
diff --git a/tests/zfs-tests/tests/functional/io/libaio.ksh b/tests/zfs-tests/tests/functional/io/libaio.ksh
new file mode 100755 (executable)
index 0000000..c434ad9
--- /dev/null
@@ -0,0 +1,65 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+#      Verify Linux native asynchronous IO.
+#
+# STRATEGY:
+#      1. Use fio(1) in verify mode to perform write, read,
+#         random read, and random write workloads.
+#      2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+       log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify Linux native asynchronous IO"
+
+log_onexit cleanup
+
+ioengine="--ioengine=libaio"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+       log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+       log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified Linux native asynchronous IO"
diff --git a/tests/zfs-tests/tests/functional/io/mmap.ksh b/tests/zfs-tests/tests/functional/io/mmap.ksh
new file mode 100755 (executable)
index 0000000..e960078
--- /dev/null
@@ -0,0 +1,69 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+#      Verify memory mapped IO with mmap(2) and memcpy(3)
+#
+# STRATEGY:
+#      1. Use fio(1) in verify mode to perform write, read,
+#         random read, and random write workloads.
+#      2. Repeat the test with additional fio(1) options.
+#
+
+if ! compare_version_gte $(fio --version) "fio-2.3"; then
+       log_unsupported "Requires fio-2.3 or newer"
+fi
+
+verify_runnable "global"
+
+function cleanup
+{
+       log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify memory mapped IO with mmap(2) and memcpy(3)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=mmap"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+       log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+       log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified memory mapped IO with mmap(2) and memcpy(3)"
diff --git a/tests/zfs-tests/tests/functional/io/posixaio.ksh b/tests/zfs-tests/tests/functional/io/posixaio.ksh
new file mode 100755 (executable)
index 0000000..0758164
--- /dev/null
@@ -0,0 +1,65 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+#      Verify POSIX asynchronous IO with aio_read(3) and aio_write(3).
+#
+# STRATEGY:
+#      1. Use fio(1) in verify mode to perform write, read,
+#         random read, and random write workloads.
+#      2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+       log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify POSIX asynchronous IO with aio_read(3) and aio_write(3)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=posixaio"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+       log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+       log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified POSIX asynchronous IO with aio_read(3) and aio_write(3)"
diff --git a/tests/zfs-tests/tests/functional/io/psync.ksh b/tests/zfs-tests/tests/functional/io/psync.ksh
new file mode 100755 (executable)
index 0000000..efeb110
--- /dev/null
@@ -0,0 +1,65 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+#      Verify basic pread(2) and pwrite(2).
+#
+# STRATEGY:
+#      1. Use fio(1) in verify mode to perform write, read,
+#         random read, and random write workloads.
+#      2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+       log_must rm -f "/$TESTPOOL/rw*"
+}
+
+log_assert "Verify basic pread(2), pwrite(2)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=psync"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+       log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+       log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified basic pread(2), pwrite(2)"
diff --git a/tests/zfs-tests/tests/functional/io/setup.ksh b/tests/zfs-tests/tests/functional/io/setup.ksh
new file mode 100755 (executable)
index 0000000..ff72fc3
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+verify_runnable "global"
+
+default_setup "$DISKS"
+log_must zfs set compression=on $TESTPOOL/$TESTFS
diff --git a/tests/zfs-tests/tests/functional/io/sync.ksh b/tests/zfs-tests/tests/functional/io/sync.ksh
new file mode 100755 (executable)
index 0000000..83f346c
--- /dev/null
@@ -0,0 +1,65 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+#      Verify basic read(2), write(2) and lseek(2).
+#
+# STRATEGY:
+#      1. Use fio(1) in verify mode to perform write, read,
+#         random read, and random write workloads.
+#      2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+       log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify basic read(2), write(2) and lseek(2)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=sync"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in ${fio_arg[@]}; do
+       log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+       log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+       log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified basic read(2), write(2) and lseek(2)"