Skip to content

Commit

Permalink
ZTS: test for STATX_DIOALIGN
Browse files Browse the repository at this point in the history
Uses the statx helper to test the results of the STATX_DIOALIGN request
as we manipulate DIO enable, dataset recordsize and file size and
structure.

Sponsored-by: https://despairlabs.com/sponsor/
Signed-off-by: Rob Norris <[email protected]>
  • Loading branch information
robn committed Jan 22, 2025
1 parent 981b1e0 commit 3775cf2
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 2 deletions.
2 changes: 1 addition & 1 deletion tests/runfiles/common.run
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ tests = ['sparse_001_pos']
tags = ['functional', 'sparse']

[tests/functional/stat]
tests = ['stat_001_pos']
tests = ['stat_001_pos', 'statx_dioalign']
tags = ['functional', 'stat']

[tests/functional/suid]
Expand Down
9 changes: 8 additions & 1 deletion tests/test-runner/bin/zts-report.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ idmap_reason = 'Idmapped mount needs kernel 5.12+'
#
cfr_reason = 'Kernel copy_file_range support required'

#
# Some statx fields are not supported by all kernels
#
statx_reason = 'Needed statx(2) field not supported on this kernel'

if sys.platform.startswith('freebsd'):
cfr_cross_reason = 'copy_file_range(2) cross-filesystem needs FreeBSD 14+'
else:
Expand Down Expand Up @@ -293,7 +298,8 @@ if sys.platform.startswith('freebsd'):
'block_cloning/block_cloning_cross_enc_dataset':
['SKIP', cfr_cross_reason],
'block_cloning/block_cloning_copyfilerange_cross_dataset':
['SKIP', cfr_cross_reason]
['SKIP', cfr_cross_reason],
'stat/statx_dioalign': ['SKIP', 'na_reason'],
})
elif sys.platform.startswith('linux'):
maybe.update({
Expand Down Expand Up @@ -361,6 +367,7 @@ elif sys.platform.startswith('linux'):
'mmp/mmp_active_import': ['FAIL', known_reason],
'mmp/mmp_exported_import': ['FAIL', known_reason],
'mmp/mmp_inactive_import': ['FAIL', known_reason],
'stat/statx_dioalign': ['SKIP', 'statx_reason'],
})


Expand Down
1 change: 1 addition & 0 deletions tests/zfs-tests/tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2050,6 +2050,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/stat/cleanup.ksh \
functional/stat/setup.ksh \
functional/stat/stat_001_pos.ksh \
functional/stat/statx_dioalign.ksh \
functional/suid/cleanup.ksh \
functional/suid/setup.ksh \
functional/suid/suid_write_to_none.ksh \
Expand Down
144 changes: 144 additions & 0 deletions tests/zfs-tests/tests/functional/stat/statx_dioalign.ksh
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/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) 2025, Rob Norris <[email protected]>
#

#
# Uses the statx helper to test the results of the STATX_DIOALIGN request as we
# manipulate DIO enable, dataset recordsize and file size and structure.
#

. $STF_SUITE/include/libtest.shlib

verify_runnable "both"

if ! is_linux ; then
log_unsupported "statx(2) only available on Linux"
fi

if [[ $(linux_version) -lt $(linux_version "6.1") ]] ; then
log_unsupported "STATX_DIOALIGN not available before Linux 6.1"
fi

CLAIM="STATX_DIOALIGN returns useful values when Direct IO is available."

TESTDS=${TESTPOOL}/${TESTFS}
TESTFILE=${TESTDIR}/${TESTFILE0}

log_must save_tunable DIO_ENABLED
typeset recordsize_saved=$(get_prop recordsize $TESTDS)
typeset direct_saved=$(get_prop direct $TESTDS)

function cleanup
{
rm -f ${TESTFILE}
zfs set recordsize=$recordsize_saved $TESTDS
zfs set direct=$direct_saved $TESTDS
restore_tunable DIO_ENABLED
}
log_onexit cleanup

# assert_dioalign <file> <memalign> <ioalign>
function assert_dioalign
{
typeset file=$1
typeset -i memalign=$2
typeset -i ioalign=$3

typeset -a v=($(statx dioalign $file | cut -f2- -d' '))
log_note "statx dioalign returned: $file: mem=${v[0]} io=${v[1]}"
log_must [ ${v[0]} -eq $memalign -a ${v[1]} -eq $ioalign ]
}

log_assert $CLAIM

# Compute the expected IO size. Testing this properly means changing the
# ashift, which means recreating the pool, which is slightly fiddly here, so
# I have not bothered.
typeset -i PAGE_SIZE=$(getconf PAGE_SIZE)
typeset -i IO_SIZE=$(( 1 << $(zpool get -H -o value ashift $TESTPOOL) ))
if [[ $IO_SIZE -lt $PAGE_SIZE ]] ; then
IO_SIZE=$PAGE_SIZE
fi

# Set recordsize and make a recordsized file for the general tests.
log_must zfs set recordsize=128K $TESTDS
log_must dd if=/dev/urandom of=$TESTFILE bs=128k count=1
log_must zpool sync

# when DIO is disabled via tunable, result should always be zero, no matter
# what the value of the direct= property.
log_must set_tunable32 DIO_ENABLED 0

for d in disabled standard always ; do
log_must zfs set direct=$d $TESTDS
assert_dioalign $TESTFILE 0 0
done

# when DIO is enabled via tunable, behaviour is dependent on the direct=
# property.
log_must set_tunable32 DIO_ENABLED 1

# when DIO is disabled via property, result should be zero.
log_must zfs set direct=disabled $TESTDS
assert_dioalign $TESTFILE 0 0

# when DIO is enabled, the result should be mem=recordsize, io=pagesize
for d in standard always ; do
log_must zfs set direct=$d $TESTDS
assert_dioalign $TESTFILE 131072 $IO_SIZE
done

# setting the recordsize smaller than the blocksize on an existing file
# will use the file's blocksize
log_must zfs set recordsize=32K $TESTDS
for d in standard always ; do
log_must zfs set direct=$d $TESTDS
assert_dioalign $TESTFILE 131072 $IO_SIZE
done

# setting the recordsize larger than the blocksize on an existing file with
# only one block will use the dataset's recordsize, ie the size that the block
# could grow to
log_must zfs set recordsize=256K $TESTDS
for d in standard always ; do
log_must zfs set direct=$d $TESTDS
assert_dioalign $TESTFILE 262144 $IO_SIZE
done

# extending a file into the second block fixes its blocksize, so result should
# be its blocksize, regardless of how the recordsize changes
log_must zfs set recordsize=128K $TESTDS
log_must dd if=/dev/urandom of=$TESTFILE bs=128k count=1 seek=1
log_must zpool sync

for rs in 64K 128K 256K 512K ; do
log_must zfs set recordsize=$rs $TESTDS
for d in standard always ; do
log_must zfs set direct=$d $TESTDS
assert_dioalign $TESTFILE 131072 $IO_SIZE
done
done

log_pass $CLAIM

0 comments on commit 3775cf2

Please sign in to comment.