Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Direct IO support #7823

Merged
merged 1 commit into from
Aug 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions config/kernel-vfs-direct_IO.m4
Original file line number Diff line number Diff line change
@@ -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
])
1 change: 1 addition & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
52 changes: 52 additions & 0 deletions module/zfs/zpl_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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 = {
Expand Down
3 changes: 2 additions & 1 deletion scripts/commitcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/runfiles/linux.run
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
7 changes: 7 additions & 0 deletions tests/test-runner/bin/zts-report.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@
#
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
Expand Down Expand Up @@ -246,6 +252,7 @@
'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],
Expand Down
14 changes: 14 additions & 0 deletions tests/zfs-tests/include/libtest.shlib
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/zfs-tests/tests/functional/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ SUBDIRS = \
hkdf \
inheritance \
inuse \
io \
kstat \
large_files \
largest_pool \
Expand Down
12 changes: 12 additions & 0 deletions tests/zfs-tests/tests/functional/io/Makefile.am
Original file line number Diff line number Diff line change
@@ -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
31 changes: 31 additions & 0 deletions tests/zfs-tests/tests/functional/io/cleanup.ksh
Original file line number Diff line number Diff line change
@@ -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
25 changes: 25 additions & 0 deletions tests/zfs-tests/tests/functional/io/io.cfg
Original file line number Diff line number Diff line change
@@ -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"
Loading