diff --git a/cmd/zed/agents/zfs_diagnosis.c b/cmd/zed/agents/zfs_diagnosis.c index 0250682f9..685f71bb9 100644 --- a/cmd/zed/agents/zfs_diagnosis.c +++ b/cmd/zed/agents/zfs_diagnosis.c @@ -39,6 +39,15 @@ #include "zfs_agents.h" #include "fmd_api.h" +/* + * Default values for the serd engine when processing checksum or io errors. The + * semantics are N in T . + */ +#define DEFAULT_CHECKSUM_N 10 /* events */ +#define DEFAULT_CHECKSUM_T 600 /* seconds */ +#define DEFAULT_IO_N 10 /* events */ +#define DEFAULT_IO_T 600 /* seconds */ + /* * Our serd engines are named 'zfs___{checksum,io}'. This * #define reserves enough space for two 64-bit hex values plus the length of @@ -448,6 +457,8 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) zfs_case_t *zcp, *dcp; int32_t pool_state; uint64_t ena, pool_guid, vdev_guid; + uint64_t checksum_n, checksum_t; + uint64_t io_n, io_t; er_timeval_t pool_load; er_timeval_t er_when; nvlist_t *detector; @@ -784,11 +795,21 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) if (fmd_nvl_class_match(hdl, nvl, ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO))) { if (zcp->zc_data.zc_serd_io[0] == '\0') { + if (nvlist_lookup_uint64(nvl, + FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_N, + &io_n) != 0) { + io_n = DEFAULT_IO_N; + } + if (nvlist_lookup_uint64(nvl, + FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_T, + &io_t) != 0) { + io_t = DEFAULT_IO_T; + } zfs_serd_name(zcp->zc_data.zc_serd_io, pool_guid, vdev_guid, "io"); fmd_serd_create(hdl, zcp->zc_data.zc_serd_io, - fmd_prop_get_int32(hdl, "io_N"), - fmd_prop_get_int64(hdl, "io_T")); + io_n, + SEC2NSEC(io_t)); zfs_case_serialize(zcp); } if (fmd_serd_record(hdl, zcp->zc_data.zc_serd_io, ep)) @@ -813,12 +834,23 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) } if (zcp->zc_data.zc_serd_checksum[0] == '\0') { + if (nvlist_lookup_uint64(nvl, + FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_N, + &checksum_n) != 0) { + checksum_n = DEFAULT_CHECKSUM_N; + } + if (nvlist_lookup_uint64(nvl, + FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_T, + &checksum_t) != 0) { + checksum_t = DEFAULT_CHECKSUM_T; + } + zfs_serd_name(zcp->zc_data.zc_serd_checksum, pool_guid, vdev_guid, "checksum"); fmd_serd_create(hdl, zcp->zc_data.zc_serd_checksum, - fmd_prop_get_int32(hdl, "checksum_N"), - fmd_prop_get_int64(hdl, "checksum_T")); + checksum_n, + SEC2NSEC(checksum_t)); zfs_case_serialize(zcp); } if (fmd_serd_record(hdl, diff --git a/include/sys/fm/fs/zfs.h b/include/sys/fm/fs/zfs.h index 97cb14aee..b9bac7e25 100644 --- a/include/sys/fm/fs/zfs.h +++ b/include/sys/fm/fs/zfs.h @@ -78,6 +78,10 @@ extern "C" { #define FM_EREPORT_PAYLOAD_ZFS_VDEV_READ_ERRORS "vdev_read_errors" #define FM_EREPORT_PAYLOAD_ZFS_VDEV_WRITE_ERRORS "vdev_write_errors" #define FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_ERRORS "vdev_cksum_errors" +#define FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_N "vdev_cksum_n" +#define FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_T "vdev_cksum_t" +#define FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_N "vdev_io_n" +#define FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_T "vdev_io_t" #define FM_EREPORT_PAYLOAD_ZFS_VDEV_DELAYS "vdev_delays" #define FM_EREPORT_PAYLOAD_ZFS_PARENT_GUID "parent_guid" #define FM_EREPORT_PAYLOAD_ZFS_PARENT_TYPE "parent_type" diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 993222e28..da2d05216 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -356,6 +356,10 @@ typedef enum { VDEV_PROP_REMOVING, VDEV_PROP_ALLOCATING, VDEV_PROP_FAILFAST, + VDEV_PROP_CHECKSUM_N, + VDEV_PROP_CHECKSUM_T, + VDEV_PROP_IO_N, + VDEV_PROP_IO_T, VDEV_NUM_PROPS } vdev_prop_t; diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h index 3f4b78b94..73c0206ef 100644 --- a/include/sys/vdev_impl.h +++ b/include/sys/vdev_impl.h @@ -469,6 +469,14 @@ struct vdev { zfs_ratelimit_t vdev_delay_rl; zfs_ratelimit_t vdev_deadman_rl; zfs_ratelimit_t vdev_checksum_rl; + + /* + * Checksum and IO thresholds for tuning ZED + */ + uint64_t vdev_checksum_n; + uint64_t vdev_checksum_t; + uint64_t vdev_io_n; + uint64_t vdev_io_t; }; #define VDEV_PAD_SIZE (8 << 10) diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index 004930e34..16fea63f8 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -3223,7 +3223,11 @@ - + + + + + diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index aa8213eb1..b3e12bd84 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -5002,6 +5002,17 @@ zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name, (u_longlong_t)intval); } break; + case VDEV_PROP_CHECKSUM_N: + case VDEV_PROP_CHECKSUM_T: + case VDEV_PROP_IO_N: + case VDEV_PROP_IO_T: + if (intval == UINT64_MAX) { + (void) strlcpy(buf, "-", len); + } else { + (void) snprintf(buf, len, "%llu", + (u_longlong_t)intval); + } + break; case VDEV_PROP_FRAGMENTATION: if (intval == UINT64_MAX) { (void) strlcpy(buf, "-", len); diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index c31f18009..2507bfecd 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -1681,6 +1681,18 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, *ivalp = UINT64_MAX; } + /* + * Special handling for "checksum_*=none". In this case it's not + * 0 but UINT64_MAX. + */ + if ((type & ZFS_TYPE_VDEV) && isnone && + (prop == VDEV_PROP_CHECKSUM_N || + prop == VDEV_PROP_CHECKSUM_T || + prop == VDEV_PROP_IO_N || + prop == VDEV_PROP_IO_T)) { + *ivalp = UINT64_MAX; + } + /* * Special handling for setting 'refreservation' to 'auto'. Use * UINT64_MAX to tell the caller to use zfs_fix_auto_resv(). diff --git a/man/man7/vdevprops.7 b/man/man7/vdevprops.7 index af5d26f6b..6eebfa006 100644 --- a/man/man7/vdevprops.7 +++ b/man/man7/vdevprops.7 @@ -43,7 +43,8 @@ section, below. .Ss Native Properties Every vdev has a set of properties that export statistics about the vdev as well as control various behaviors. -Properties are NOT inherited from top-level vdevs. +Properties are not inherited from top-level vdevs, with the exception of +checksum_n, checksum_t, io_n, and io_t. .Pp The values of numeric properties can be specified using human-readable suffixes .Po for example, @@ -114,9 +115,19 @@ The cumulative size of all operations of each type performed by this vdev If this device is currently being removed from the pool .El .Pp -The following native properties can be used to change the behavior of a ZFS -dataset. +The following native properties can be used to change the behavior of a vdev. .Bl -tag -width "allocating" +.It Sy checksum_n , checksum_t , io_n , io_t +Tune the fault management daemon by specifying checksum/io thresholds of +errors in seconds, respectively. +These properties can be set on leaf and top-level vdevs. +When the property is set on the leaf and top-level vdev, the value of the leaf +vdev will be used. +If the property is only set on the top-level vdev, this value will be used. +The value of these properties do not persist across vdev replacement. +For this reason, it is advisable to set the property on the top-level vdev - +not on the leaf vdev itself. +The default values are 10 errors in 600 seconds. .It Sy comment A text comment up to 8192 characters long .It Sy bootsize diff --git a/module/zcommon/zpool_prop.c b/module/zcommon/zpool_prop.c index 285b97909..e99acef5a 100644 --- a/module/zcommon/zpool_prop.c +++ b/module/zcommon/zpool_prop.c @@ -410,6 +410,18 @@ vdev_prop_init(void) sfeatures); /* default numeric properties */ + zprop_register_number(VDEV_PROP_CHECKSUM_N, "checksum_n", UINT64_MAX, + PROP_DEFAULT, ZFS_TYPE_VDEV, "", "CKSUM_N", B_FALSE, + sfeatures); + zprop_register_number(VDEV_PROP_CHECKSUM_T, "checksum_t", UINT64_MAX, + PROP_DEFAULT, ZFS_TYPE_VDEV, "", "CKSUM_T", B_FALSE, + sfeatures); + zprop_register_number(VDEV_PROP_IO_N, "io_n", UINT64_MAX, + PROP_DEFAULT, ZFS_TYPE_VDEV, "", "IO_N", B_FALSE, + sfeatures); + zprop_register_number(VDEV_PROP_IO_T, "io_t", UINT64_MAX, + PROP_DEFAULT, ZFS_TYPE_VDEV, "", "IO_T", B_FALSE, + sfeatures); /* default index (boolean) properties */ zprop_register_index(VDEV_PROP_REMOVING, "removing", 0, diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 891744261..8f3e461ba 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -389,6 +389,31 @@ vdev_get_nparity(vdev_t *vd) return (nparity); } +static int +vdev_prop_get_int(vdev_t *vd, vdev_prop_t prop, uint64_t *value) +{ + spa_t *spa = vd->vdev_spa; + objset_t *mos = spa->spa_meta_objset; + uint64_t objid; + int err; + + if (vd->vdev_top_zap != 0) { + objid = vd->vdev_top_zap; + } else if (vd->vdev_leaf_zap != 0) { + objid = vd->vdev_leaf_zap; + } else { + return (EINVAL); + } + + err = zap_lookup(mos, objid, vdev_prop_to_name(prop), + sizeof (uint64_t), 1, value); + + if (err == ENOENT) + *value = vdev_prop_default_numeric(prop); + + return (err); +} + /* * Get the number of data disks for a top-level vdev. */ @@ -642,6 +667,14 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops) zfs_ratelimit_init(&vd->vdev_checksum_rl, &zfs_checksum_events_per_second, 1); + /* + * Default Thresholds for tuning ZED + */ + vd->vdev_checksum_n = vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_N); + vd->vdev_checksum_t = vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_T); + vd->vdev_io_n = vdev_prop_default_numeric(VDEV_PROP_IO_N); + vd->vdev_io_t = vdev_prop_default_numeric(VDEV_PROP_IO_T); + list_link_init(&vd->vdev_config_dirty_node); list_link_init(&vd->vdev_state_dirty_node); list_link_init(&vd->vdev_initialize_node); @@ -3597,6 +3630,39 @@ vdev_load(vdev_t *vd) } } + if (vd->vdev_top_zap != 0 || vd->vdev_leaf_zap != 0) { + uint64_t zapobj; + + if (vd->vdev_top_zap != 0) + zapobj = vd->vdev_top_zap; + else + zapobj = vd->vdev_leaf_zap; + + error = vdev_prop_get_int(vd, VDEV_PROP_CHECKSUM_N, + &vd->vdev_checksum_n); + if (error && error != ENOENT) + vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) " + "failed [error=%d]", (u_longlong_t)zapobj, error); + + error = vdev_prop_get_int(vd, VDEV_PROP_CHECKSUM_T, + &vd->vdev_checksum_t); + if (error && error != ENOENT) + vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) " + "failed [error=%d]", (u_longlong_t)zapobj, error); + + error = vdev_prop_get_int(vd, VDEV_PROP_IO_N, + &vd->vdev_io_n); + if (error && error != ENOENT) + vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) " + "failed [error=%d]", (u_longlong_t)zapobj, error); + + error = vdev_prop_get_int(vd, VDEV_PROP_IO_T, + &vd->vdev_io_t); + if (error && error != ENOENT) + vdev_dbgmsg(vd, "vdev_load: zap_lookup(zap=%llu) " + "failed [error=%d]", (u_longlong_t)zapobj, error); + } + /* * If this is a top-level vdev, initialize its metaslabs. */ @@ -5736,6 +5802,34 @@ vdev_prop_set(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl) } vd->vdev_failfast = intval & 1; break; + case VDEV_PROP_CHECKSUM_N: + if (nvpair_value_uint64(elem, &intval) != 0) { + error = EINVAL; + break; + } + vd->vdev_checksum_n = intval; + break; + case VDEV_PROP_CHECKSUM_T: + if (nvpair_value_uint64(elem, &intval) != 0) { + error = EINVAL; + break; + } + vd->vdev_checksum_t = intval; + break; + case VDEV_PROP_IO_N: + if (nvpair_value_uint64(elem, &intval) != 0) { + error = EINVAL; + break; + } + vd->vdev_io_n = intval; + break; + case VDEV_PROP_IO_T: + if (nvpair_value_uint64(elem, &intval) != 0) { + error = EINVAL; + break; + } + vd->vdev_io_t = intval; + break; default: /* Most processing is done in vdev_props_set_sync */ break; @@ -6025,28 +6119,25 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl) continue; /* Numeric Properites */ case VDEV_PROP_ALLOCATING: - src = ZPROP_SRC_LOCAL; - strval = NULL; - - err = zap_lookup(mos, objid, nvpair_name(elem), - sizeof (uint64_t), 1, &intval); - if (err == ENOENT) { - intval = - vdev_prop_default_numeric(prop); - err = 0; - } else if (err) - break; - if (intval == vdev_prop_default_numeric(prop)) - src = ZPROP_SRC_DEFAULT; - /* Leaf vdevs cannot have this property */ if (vd->vdev_mg == NULL && vd->vdev_top != NULL) { src = ZPROP_SRC_NONE; intval = ZPROP_BOOLEAN_NA; + } else { + err = vdev_prop_get_int(vd, prop, + &intval); + if (err && err != ENOENT) + break; + + if (intval == + vdev_prop_default_numeric(prop)) + src = ZPROP_SRC_DEFAULT; + else + src = ZPROP_SRC_LOCAL; } - vdev_prop_add_list(outnvl, propname, strval, + vdev_prop_add_list(outnvl, propname, NULL, intval, src); break; case VDEV_PROP_FAILFAST: @@ -6068,6 +6159,22 @@ vdev_prop_get(vdev_t *vd, nvlist_t *innvl, nvlist_t *outnvl) vdev_prop_add_list(outnvl, propname, strval, intval, src); break; + case VDEV_PROP_CHECKSUM_N: + case VDEV_PROP_CHECKSUM_T: + case VDEV_PROP_IO_N: + case VDEV_PROP_IO_T: + err = vdev_prop_get_int(vd, prop, &intval); + if (err && err != ENOENT) + break; + + if (intval == vdev_prop_default_numeric(prop)) + src = ZPROP_SRC_DEFAULT; + else + src = ZPROP_SRC_LOCAL; + + vdev_prop_add_list(outnvl, propname, NULL, + intval, src); + break; /* Text Properties */ case VDEV_PROP_COMMENT: /* Exists in the ZAP below */ diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c index fd0dc7d69..7169e49ac 100644 --- a/module/zfs/zfs_fm.c +++ b/module/zfs/zfs_fm.c @@ -200,6 +200,42 @@ recent_events_compare(const void *a, const void *b) return (0); } +/* + * workaround: vdev properties don't have inheritance + */ +static uint64_t +vdev_prop_get_inherited(vdev_t *vd, vdev_prop_t prop) +{ + uint64_t propdef, propval; + + propdef = vdev_prop_default_numeric(prop); + switch (prop) { + case VDEV_PROP_CHECKSUM_N: + propval = vd->vdev_checksum_n; + break; + case VDEV_PROP_CHECKSUM_T: + propval = vd->vdev_checksum_t; + break; + case VDEV_PROP_IO_N: + propval = vd->vdev_io_n; + break; + case VDEV_PROP_IO_T: + propval = vd->vdev_io_t; + break; + default: + propval = propdef; + break; + } + + if (propval != propdef) + return (propval); + + if (vd->vdev_parent == NULL) + return (propdef); + + return (vdev_prop_get_inherited(vd->vdev_parent, prop)); +} + static void zfs_ereport_schedule_cleaner(void); /* @@ -662,6 +698,49 @@ zfs_ereport_start(nvlist_t **ereport_out, nvlist_t **detector_out, DATA_TYPE_UINT64, zb->zb_blkid, NULL); } + /* + * Payload for tuning the zed + */ + if (vd != NULL && strcmp(subclass, FM_EREPORT_ZFS_CHECKSUM) == 0) { + uint64_t cksum_n, cksum_t; + + cksum_n = vdev_prop_get_inherited(vd, VDEV_PROP_CHECKSUM_N); + if (cksum_n != vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_N)) + fm_payload_set(ereport, + FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_N, + DATA_TYPE_UINT64, + cksum_n, + NULL); + + cksum_t = vdev_prop_get_inherited(vd, VDEV_PROP_CHECKSUM_T); + if (cksum_t != vdev_prop_default_numeric(VDEV_PROP_CHECKSUM_T)) + fm_payload_set(ereport, + FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_T, + DATA_TYPE_UINT64, + cksum_t, + NULL); + } + + if (vd != NULL && strcmp(subclass, FM_EREPORT_ZFS_IO) == 0) { + uint64_t io_n, io_t; + + io_n = vdev_prop_get_inherited(vd, VDEV_PROP_IO_N); + if (io_n != vdev_prop_default_numeric(VDEV_PROP_IO_N)) + fm_payload_set(ereport, + FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_N, + DATA_TYPE_UINT64, + io_n, + NULL); + + io_t = vdev_prop_get_inherited(vd, VDEV_PROP_IO_T); + if (io_t != vdev_prop_default_numeric(VDEV_PROP_IO_T)) + fm_payload_set(ereport, + FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_T, + DATA_TYPE_UINT64, + io_t, + NULL); + } + mutex_exit(&spa->spa_errlist_lock); *ereport_out = ereport; diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run index 23292a488..15755408b 100644 --- a/tests/runfiles/linux.run +++ b/tests/runfiles/linux.run @@ -87,7 +87,7 @@ tags = ['functional', 'devices'] [tests/functional/events:Linux] tests = ['events_001_pos', 'events_002_pos', 'zed_rc_filter', 'zed_fd_spill', - 'zed_cksum_reported'] + 'zed_cksum_reported', 'zed_cksum_config', 'zed_io_config'] tags = ['functional', 'events'] [tests/functional/fadvise:Linux] diff --git a/tests/zfs-tests/tests/Makefile.am b/tests/zfs-tests/tests/Makefile.am index 33f78e590..7d734b831 100644 --- a/tests/zfs-tests/tests/Makefile.am +++ b/tests/zfs-tests/tests/Makefile.am @@ -1367,8 +1367,10 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/events/events_001_pos.ksh \ functional/events/events_002_pos.ksh \ functional/events/setup.ksh \ + functional/events/zed_cksum_config.ksh \ functional/events/zed_cksum_reported.ksh \ functional/events/zed_fd_spill.ksh \ + functional/events/zed_io_config.ksh \ functional/events/zed_rc_filter.ksh \ functional/exec/cleanup.ksh \ functional/exec/exec_001_pos.ksh \ diff --git a/tests/zfs-tests/tests/functional/events/zed_cksum_config.ksh b/tests/zfs-tests/tests/functional/events/zed_cksum_config.ksh new file mode 100755 index 000000000..5aae3d034 --- /dev/null +++ b/tests/zfs-tests/tests/functional/events/zed_cksum_config.ksh @@ -0,0 +1,158 @@ +#!/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, Klara Inc. +# + +# DESCRIPTION: +# Verify that vdev properties, checksum_n and checksum_t, work with ZED. +# +# STRATEGY: +# 1. Create a pool with single vdev +# 2. Set checksum_n/checksum_t to non-default values +# 3. Inject checksum errors +# 4. Verify that ZED degrades vdev +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/events/events_common.kshlib + +verify_runnable "both" + +MOUNTDIR="$TEST_BASE_DIR/checksum_mount" +FILEPATH="$MOUNTDIR/checksum_file" +VDEV="$TEST_BASE_DIR/vdevfile.$$" +POOL="checksum_pool" +FILESIZE="10M" + +function cleanup +{ + log_must zed_stop + + log_must zinject -c all + if poolexists $POOL ; then + destroy_pool $POOL + fi + log_must rm -fd $VDEV $MOUNTDIR +} + +log_onexit cleanup + +log_assert "Test ZED checksum_N and checksum_T configurability" + +function do_setup +{ + log_must zpool create -f -m $MOUNTDIR $POOL $VDEV + log_must zpool events -c + log_must truncate -s 0 $ZED_DEBUG_LOG + log_must zfs set compression=off $POOL + log_must zfs set primarycache=none $POOL + log_must zfs set recordsize=512 $POOL +} + +function do_clean +{ + log_must zinject -c all + log_must zpool destroy $POOL +} + +function must_degrade +{ + log_must wait_vdev_state $POOL $VDEV "DEGRADED" 60 +} + +function mustnot_degrade +{ + log_must file_wait $ZED_DEBUG_LOG 5 + log_must wait_vdev_state $POOL $VDEV "ONLINE" 60 +} + +# Test default settings of ZED: +# checksum_n=10 +# checksum_t=600 +# fire 10 events, should degrade. +function default_degrade +{ + do_setup + + log_must mkfile $FILESIZE $FILEPATH + log_must zinject -a -t data -e checksum -T read -f 100 $FILEPATH + + blk=0 + for _ in {1..10}; do + dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null + blk=$((blk+512)) + done + + must_degrade + + do_clean +} + +# Set checksum_t=1 +# fire 10 events over 2.5 seconds, should not degrade. +function checksum_t_no_degrade +{ + do_setup + + log_must zpool set checksum_t=1 $POOL $VDEV + log_must mkfile $FILESIZE $FILEPATH + log_must zinject -a -t data -e checksum -T read -f 100 $FILEPATH + + blk=0 + for _ in {1..10}; do + dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null + blk=$((blk+512)) + sleep 0.25 + done + + mustnot_degrade + + do_clean +} + +# Set checksum_n=1 +# fire 1 event, should degrade. +function checksum_n_degrade +{ + do_setup + + log_must zpool set checksum_n=1 $POOL $VDEV + log_must mkfile $FILESIZE $FILEPATH + log_must zinject -a -t data -e checksum -T read -f 100 $FILEPATH + + dd if=$FILEPATH of=/dev/null bs=1 count=1 2>/dev/null + + must_degrade + + do_clean +} + +log_must truncate -s $MINVDEVSIZE $VDEV +log_must mkdir -p $MOUNTDIR + +log_must zed_start +default_degrade +checksum_n_degrade +checksum_t_no_degrade + +log_pass "Test ZED checksum_N and checksum_T configurability" diff --git a/tests/zfs-tests/tests/functional/events/zed_io_config.ksh b/tests/zfs-tests/tests/functional/events/zed_io_config.ksh new file mode 100755 index 000000000..637f979fe --- /dev/null +++ b/tests/zfs-tests/tests/functional/events/zed_io_config.ksh @@ -0,0 +1,150 @@ +#!/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, Klara Inc. +# + +# DESCRIPTION: +# Verify that vdev properties, io_n and io_t, work with ZED. +# +# STRATEGY: +# 1. Create a mirrored pool. +# 3. Set io_n/io_t to non-default values +# 3. Inject io errors +# 4. Verify that ZED degrades vdev + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/events/events_common.kshlib + +verify_runnable "both" + +MOUNTDIR="$TEST_BASE_DIR/io_mount" +FILEPATH="$MOUNTDIR/io_file" +VDEV="$TEST_BASE_DIR/vdevfile.$$" +VDEV1="$TEST_BASE_DIR/vdevfile1.$$" +POOL="io_pool" + +function cleanup +{ + log_must zed_stop + + log_must zinject -c all + if poolexists $POOL ; then + destroy_pool $POOL + fi + log_must rm -fd $VDEV $VDEV1 $MOUNTDIR + log_must set_tunable32 PREFETCH_DISABLE $zfsprefetch +} +log_onexit cleanup + +log_assert "Test ZED io_n and io_t configurability" + +zfsprefetch=$(get_tunable PREFETCH_DISABLE) +log_must set_tunable32 PREFETCH_DISABLE 1 + +function setup_pool +{ + log_must zpool create -f -m $MOUNTDIR $POOL mirror $VDEV $VDEV1 + log_must zpool events -c + log_must truncate -s 0 $ZED_DEBUG_LOG + log_must zfs set compression=off $POOL + log_must zfs set primarycache=none $POOL + log_must zfs set recordsize=512 $POOL +} + +function do_clean +{ + log_must zinject -c all + log_must zpool destroy $POOL +} + +# Test default ZED settings: +# io_n=10 (events) +# io_t=600 (seconds) +# fire 10 events over 2.5 seconds, should degrade. +function default_degrade +{ + setup_pool + + log_must dd if=/dev/urandom of=$FILEPATH bs=1M count=64 + log_must zinject -a -d $VDEV -e io -T read -f 100 $POOL + + blk=0 + for _ in {1..10}; do + dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null + blk=$((blk+512)) + sleep 0.25 + done + + log_must wait_vdev_state $POOL $VDEV "FAULTED" 60 + do_clean +} + +# set io_n=1 +# fire 1 event, should degrade +function io_n_degrade +{ + setup_pool + + log_must zpool set io_n=1 $POOL $VDEV + log_must dd if=/dev/urandom of=$FILEPATH bs=1M count=64 + log_must zinject -a -d $VDEV -e io -T read -f 100 $POOL + + dd if=$FILEPATH of=/dev/null bs=1 count=1 2>/dev/null + + log_must wait_vdev_state $POOL $VDEV "FAULTED" 60 + do_clean +} + +# set io_t=1 +# fire 10 events over 2.5 seconds, should not degrade +function io_t_nodegrade +{ + setup_pool + + log_must zpool set io_t=1 $POOL $VDEV + log_must dd if=/dev/urandom of=$FILEPATH bs=1M count=64 + log_must zinject -a -d $VDEV -e io -T read -f 100 $POOL + + blk=0 + for _ in {1..10}; do + dd if=$FILEPATH of=/dev/null bs=1 count=1 skip=$blk 2>/dev/null + blk=$((blk+512)) + sleep 0.25 + done + + log_must file_wait $ZED_DEBUG_LOG 30 + log_must wait_vdev_state $POOL $VDEV "ONLINE" 1 + + do_clean +} + +log_must truncate -s $MINVDEVSIZE $VDEV +log_must truncate -s $MINVDEVSIZE $VDEV1 +log_must mkdir -p $MOUNTDIR + +log_must zed_start +default_degrade +io_n_degrade +io_t_nodegrade + +log_pass "Test ZED io_n and io_t configurability"