Skip to content

Commit 58d5620

Browse files
committed
Add vdev property to toggle adding io to vdev queue
Added vdev property to toggle queueing io to vdev queue when reading / writing from / to vdev. The intention behind this property is to improve IOPS performance when using o_direct. Signed-off-by: MigeljanImeri <ImeriMigel@gmail.com>
1 parent d8a33bc commit 58d5620

File tree

11 files changed

+140
-3
lines changed

11 files changed

+140
-3
lines changed

include/sys/fs/zfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ typedef enum {
385385
VDEV_PROP_TRIM_SUPPORT,
386386
VDEV_PROP_TRIM_ERRORS,
387387
VDEV_PROP_SLOW_IOS,
388+
VDEV_PROP_QUEUE_IO,
388389
VDEV_NUM_PROPS
389390
} vdev_prop_t;
390391

include/sys/vdev_impl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ struct vdev {
466466
uint64_t vdev_io_t;
467467
uint64_t vdev_slow_io_n;
468468
uint64_t vdev_slow_io_t;
469+
uint64_t vdev_queue_io;
469470
};
470471

471472
#define VDEV_PAD_SIZE (8 << 10)

lib/libzfs/libzfs.abi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5899,7 +5899,8 @@
58995899
<enumerator name='VDEV_PROP_TRIM_SUPPORT' value='49'/>
59005900
<enumerator name='VDEV_PROP_TRIM_ERRORS' value='50'/>
59015901
<enumerator name='VDEV_PROP_SLOW_IOS' value='51'/>
5902-
<enumerator name='VDEV_NUM_PROPS' value='52'/>
5902+
<enumerator name='VDEV_PROP_QUEUE_IO' value='52'/>
5903+
<enumerator name='VDEV_NUM_PROPS' value='53'/>
59035904
</enum-decl>
59045905
<typedef-decl name='vdev_prop_t' type-id='1573bec8' id='5aa5c90c'/>
59055906
<class-decl name='zpool_load_policy' size-in-bits='256' is-struct='yes' visibility='default' id='2f65b36f'>

man/man7/vdevprops.7

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ If this device should perform new allocations, used to disable a device
157157
when it is scheduled for later removal.
158158
See
159159
.Xr zpool-remove 8 .
160+
.It Sy queue_io
161+
Add io to the vdev queue when reading or writing to this vdev.
162+
Disabling this property can sometimes improve performance for direct IOs.
163+
It is not recommended to disable for spinning disk devices, as starvation
164+
could occur.
160165
.El
161166
.Ss User Properties
162167
In addition to the standard native properties, ZFS supports arbitrary user

module/zcommon/zpool_prop.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ vdev_prop_init(void)
470470
zprop_register_index(VDEV_PROP_TRIM_SUPPORT, "trim_support", 0,
471471
PROP_READONLY, ZFS_TYPE_VDEV, "on | off", "TRIMSUP",
472472
boolean_table, sfeatures);
473+
zprop_register_index(VDEV_PROP_QUEUE_IO, "queue_io", 1,
474+
PROP_DEFAULT, ZFS_TYPE_VDEV, "on | off", "QUEUE_IO",
475+
boolean_table, sfeatures);
473476

474477
/* default index properties */
475478
zprop_register_index(VDEV_PROP_FAILFAST, "failfast", B_TRUE,

module/zfs/vdev.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,8 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
718718
vd->vdev_slow_io_n = vdev_prop_default_numeric(VDEV_PROP_SLOW_IO_N);
719719
vd->vdev_slow_io_t = vdev_prop_default_numeric(VDEV_PROP_SLOW_IO_T);
720720

721+
vd->vdev_queue_io = vdev_prop_default_numeric(VDEV_PROP_QUEUE_IO);
722+
721723
list_link_init(&vd->vdev_config_dirty_node);
722724
list_link_init(&vd->vdev_state_dirty_node);
723725
list_link_init(&vd->vdev_initialize_node);
@@ -3860,6 +3862,12 @@ vdev_load(vdev_t *vd)
38603862
if (error && error != ENOENT)
38613863
vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
38623864
"failed [error=%d]", (u_longlong_t)zapobj, error);
3865+
3866+
error = vdev_prop_get_int(vd, VDEV_PROP_QUEUE_IO,
3867+
&vd->vdev_queue_io);
3868+
if (error && error != ENOENT)
3869+
vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) "
3870+
"failed [error=%d]", (u_longlong_t)zapobj, error);
38633871
}
38643872

38653873
/*
@@ -6095,6 +6103,15 @@ vdev_prop_set(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
60956103
}
60966104
vd->vdev_slow_io_t = intval;
60976105
break;
6106+
case VDEV_PROP_QUEUE_IO:
6107+
if (nvpair_value_uint64(elem, &intval) != 0) {
6108+
error = EINVAL;
6109+
break;
6110+
}
6111+
if (vd->vdev_ops->vdev_op_leaf) {
6112+
vd->vdev_queue_io = intval;
6113+
}
6114+
break;
60986115
default:
60996116
/* Most processing is done in vdev_props_set_sync */
61006117
break;
@@ -6458,6 +6475,7 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl)
64586475
case VDEV_PROP_IO_T:
64596476
case VDEV_PROP_SLOW_IO_N:
64606477
case VDEV_PROP_SLOW_IO_T:
6478+
case VDEV_PROP_QUEUE_IO:
64616479
err = vdev_prop_get_int(vd, prop, &intval);
64626480
if (err && err != ENOENT)
64636481
break;

module/zfs/vdev_queue.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,12 @@ vdev_queue_io(zio_t *zio)
922922
zio->io_flags |= ZIO_FLAG_DONT_QUEUE;
923923
zio->io_timestamp = gethrtime();
924924

925+
if (!zio->io_vd->vdev_queue_io &&
926+
!(zio->io_flags & ZIO_FLAG_NODATA)) {
927+
zio->io_queue_state = ZIO_QS_NONE;
928+
return (zio);
929+
}
930+
925931
mutex_enter(&vq->vq_lock);
926932
vdev_queue_io_add(vq, zio);
927933
nio = vdev_queue_io_to_issue(vq);
@@ -954,6 +960,10 @@ vdev_queue_io_done(zio_t *zio)
954960
vq->vq_io_complete_ts = now;
955961
vq->vq_io_delta_ts = zio->io_delta = now - zio->io_timestamp;
956962

963+
if (zio->io_queue_state == ZIO_QS_NONE) {
964+
return;
965+
}
966+
957967
mutex_enter(&vq->vq_lock);
958968
vdev_queue_pending_remove(vq, zio);
959969

tests/runfiles/common.run

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,8 @@ tags = ['functional', 'cli_root', 'zpool_scrub']
548548
[tests/functional/cli_root/zpool_set]
549549
tests = ['zpool_set_001_pos', 'zpool_set_002_neg', 'zpool_set_003_neg',
550550
'zpool_set_ashift', 'zpool_set_features', 'vdev_set_001_pos',
551-
'user_property_001_pos', 'user_property_002_neg',
552-
'zpool_set_clear_userprop']
551+
'user_property_001_pos', 'user_property_002_neg',
552+
'zpool_set_clear_userprop','vdev_set_queue_io']
553553
tags = ['functional', 'cli_root', 'zpool_set']
554554

555555
[tests/functional/cli_root/zpool_split]

tests/zfs-tests/tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
12451245
functional/cli_root/zpool_set/setup.ksh \
12461246
functional/cli_root/zpool/setup.ksh \
12471247
functional/cli_root/zpool_set/vdev_set_001_pos.ksh \
1248+
functional/cli_root/zpool_set/vdev_set_queue_io.ksh \
12481249
functional/cli_root/zpool_set/zpool_set_common.kshlib \
12491250
functional/cli_root/zpool_set/zpool_set_001_pos.ksh \
12501251
functional/cli_root/zpool_set/zpool_set_002_neg.ksh \

tests/zfs-tests/tests/functional/cli_root/zpool_get/vdev_get.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,5 @@ typeset -a properties=(
7676
trim_support
7777
trim_errors
7878
slow_ios
79+
queue_io
7980
)
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/bin/ksh -p
2+
# SPDX-License-Identifier: CDDL-1.0
3+
#
4+
# CDDL HEADER START
5+
#
6+
# The contents of this file are subject to the terms of the
7+
# Common Development and Distribution License (the "License").
8+
# You may not use this file except in compliance with the License.
9+
#
10+
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11+
# or https://opensource.org/licenses/CDDL-1.0.
12+
# See the License for the specific language governing permissions
13+
# and limitations under the License.
14+
#
15+
# When distributing Covered Code, include this CDDL HEADER in each
16+
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17+
# If applicable, add the following below this CDDL HEADER, with the
18+
# fields enclosed by brackets "[]" replaced with your own identifying
19+
# information: Portions Copyright [yyyy] [name of copyright owner]
20+
#
21+
# CDDL HEADER END
22+
#
23+
24+
#
25+
# Copyright (c) 2024 by Triad National Security, LLC.
26+
#
27+
28+
. $STF_SUITE/include/libtest.shlib
29+
30+
#
31+
# DESCRIPTION:
32+
# Toggling vdev queue_io property while reading from vdev should not cause panic.
33+
#
34+
# STRATEGY:
35+
# 1. Create a zpool
36+
# 2. Write a file to the pool.
37+
# 3. Start reading from file, while also toggling the queue_io property on / off.
38+
#
39+
40+
verify_runnable "global"
41+
42+
command -v fio > /dev/null || log_unsupported "fio missing"
43+
log_must save_tunable DIO_ENABLED
44+
log_must set_tunable32 DIO_ENABLED 1
45+
46+
function toggle_queue_io
47+
{
48+
zpool set queue_io=off $TESTPOOL1 $FILEDEV
49+
sleep 0.1
50+
zpool set queue_io=on $TESTPOOL1 $FILEDEV
51+
sleep 0.1
52+
}
53+
54+
function cleanup
55+
{
56+
log_must destroy_pool $TESTPOOL1
57+
rm -f $FILEDEV
58+
log_must restore_tunable DIO_ENABLED
59+
}
60+
61+
log_assert "Toggling vdev queue_io property while reading from vdev should not cause panic"
62+
log_onexit cleanup
63+
64+
# 1. Create a pool
65+
66+
FILEDEV="$TEST_BASE_DIR/filedev.$$"
67+
log_must truncate -s $(($MINVDEVSIZE * 2)) $FILEDEV
68+
log_must create_pool $TESTPOOL1 $FILEDEV
69+
70+
mntpnt=$(get_prop mountpoint $TESTPOOL1)
71+
72+
# 2. Write a file to the pool, while also toggling the queue_io property on / off.
73+
74+
log_must eval "fio --filename=$mntpnt/foobar --name=write-file \
75+
--rw=write --size=$MINVDEVSIZE --bs=128k --numjobs=1 --direct=1 \
76+
--ioengine=sync --runtime=10 &"
77+
78+
ITERATIONS=30
79+
80+
for i in $(seq $ITERATIONS); do
81+
log_must toggle_queue_io
82+
done;
83+
wait
84+
85+
# 3. Starting reading from file, while also toggling the queue_io property on / off.
86+
87+
log_must eval "fio --filename=$mntpnt/foobar --name=read-file \
88+
--rw=read --size=$MINVDEVSIZE --bs=128k --numjobs=1 --direct=1 \
89+
--ioengine=sync --time_based --runtime=10 &"
90+
91+
for i in $(seq $ITERATIONS); do
92+
log_must toggle_queue_io
93+
done;
94+
wait
95+
96+
log_pass "Toggling vdev queue_io property while reading from vdev does not cause panic"

0 commit comments

Comments
 (0)