From 12f0baf34887c6a745ad3e3f34312ee45ee62bdf Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Wed, 29 Jan 2025 07:18:09 -0700 Subject: [PATCH] Make the vfs.zfs.vdev.raidz_impl sysctl cross-platform Reviewed-by: Allan Jude Reviewed-by: Alexander Motin Signed-off-by: Alan Somers Sponsored by: ConnectWise Closes #16980 --- include/os/freebsd/spl/sys/mod_os.h | 3 +++ include/sys/vdev_impl.h | 4 +++ include/sys/vdev_raidz.h | 3 +++ module/Kbuild.in | 1 + module/os/freebsd/zfs/sysctl_os.c | 21 +++++++++++++++ module/os/linux/zfs/vdev_raidz.c | 42 +++++++++++++++++++++++++++++ module/zfs/vdev.c | 4 +++ module/zfs/vdev_raidz_math.c | 21 +++++---------- 8 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 module/os/linux/zfs/vdev_raidz.c diff --git a/include/os/freebsd/spl/sys/mod_os.h b/include/os/freebsd/spl/sys/mod_os.h index df7be6fc13f6..1479242de53b 100644 --- a/include/os/freebsd/spl/sys/mod_os.h +++ b/include/os/freebsd/spl/sys/mod_os.h @@ -94,6 +94,9 @@ #define param_set_max_auto_ashift_args(var) \ CTLTYPE_UINT, NULL, 0, param_set_max_auto_ashift, "IU" +#define param_set_raidz_impl_args(var) \ + CTLTYPE_STRING, NULL, 0, param_set_raidz_impl, "A" + #define spa_taskq_read_param_set_args(var) \ CTLTYPE_STRING, NULL, 0, spa_taskq_read_param, "A" diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h index abd66b8abc96..d45a5913dc0f 100644 --- a/include/sys/vdev_impl.h +++ b/include/sys/vdev_impl.h @@ -645,6 +645,10 @@ extern int vdev_obsolete_counts_are_precise(vdev_t *vd, boolean_t *are_precise); int vdev_checkpoint_sm_object(vdev_t *vd, uint64_t *sm_obj); void vdev_metaslab_group_create(vdev_t *vd); uint64_t vdev_best_ashift(uint64_t logical, uint64_t a, uint64_t b); +#if defined(__linux__) +int param_get_raidz_impl(char *buf, zfs_kernel_param_t *kp); +#endif +int param_set_raidz_impl(ZFS_MODULE_PARAM_ARGS); /* * Vdev ashift optimization tunables diff --git a/include/sys/vdev_raidz.h b/include/sys/vdev_raidz.h index 64f484e9aa13..ed042aedbdbc 100644 --- a/include/sys/vdev_raidz.h +++ b/include/sys/vdev_raidz.h @@ -66,6 +66,8 @@ extern const zio_vsd_ops_t vdev_raidz_vsd_ops; /* * vdev_raidz_math interface */ +/* Required, but not used, by ZFS_MODULE_PARAM_CALL */ +extern uint32_t zfs_vdev_raidz_impl; void vdev_raidz_math_init(void); void vdev_raidz_math_fini(void); const struct raidz_impl_ops *vdev_raidz_math_get_ops(void); @@ -73,6 +75,7 @@ int vdev_raidz_math_generate(struct raidz_map *, struct raidz_row *); int vdev_raidz_math_reconstruct(struct raidz_map *, struct raidz_row *, const int *, const int *, const int); int vdev_raidz_impl_set(const char *); +int vdev_raidz_impl_get(char *buffer, size_t size); typedef struct vdev_raidz_expand { uint64_t vre_vdev_id; diff --git a/module/Kbuild.in b/module/Kbuild.in index fc14d5cb535e..5190afc506f9 100644 --- a/module/Kbuild.in +++ b/module/Kbuild.in @@ -447,6 +447,7 @@ ZFS_OBJS_OS := \ trace.o \ vdev_disk.o \ vdev_file.o \ + vdev_raidz.o \ vdev_label_os.o \ zfs_acl.o \ zfs_ctldir.o \ diff --git a/module/os/freebsd/zfs/sysctl_os.c b/module/os/freebsd/zfs/sysctl_os.c index 7350b8a6d49f..bddb25a07204 100644 --- a/module/os/freebsd/zfs/sysctl_os.c +++ b/module/os/freebsd/zfs/sysctl_os.c @@ -679,6 +679,27 @@ param_set_deadman_failmode(SYSCTL_HANDLER_ARGS) return (-param_set_deadman_failmode_common(buf)); } +int +param_set_raidz_impl(SYSCTL_HANDLER_ARGS) +{ + const size_t bufsize = 128; + char *buf; + int rc; + + buf = malloc(bufsize, M_SOLARIS, M_WAITOK | M_ZERO); + if (req->newptr == NULL) + vdev_raidz_impl_get(buf, bufsize); + + rc = sysctl_handle_string(oidp, buf, bufsize, req); + if (rc || req->newptr == NULL) { + free(buf, M_SOLARIS); + return (rc); + } + rc = vdev_raidz_impl_set(buf); + free(buf, M_SOLARIS); + return (rc); +} + int param_set_slop_shift(SYSCTL_HANDLER_ARGS) { diff --git a/module/os/linux/zfs/vdev_raidz.c b/module/os/linux/zfs/vdev_raidz.c new file mode 100644 index 000000000000..0b34ca52fb90 --- /dev/null +++ b/module/os/linux/zfs/vdev_raidz.c @@ -0,0 +1,42 @@ +/* + * 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 ConnectWise */ + +#include +#include +#include +#include +#include + +int +param_get_raidz_impl(char *buf, zfs_kernel_param_t *kp) +{ + return (vdev_raidz_impl_get(buf, PAGE_SIZE)); +} + +int +param_set_raidz_impl(const char *val, zfs_kernel_param_t *kp) +{ + int error; + + error = vdev_raidz_impl_set(val); + return (error); +} diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index 5df2f77e5780..96621b2bd657 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -6580,3 +6580,7 @@ ZFS_MODULE_PARAM_CALL(zfs_vdev, zfs_vdev_, max_auto_ashift, param_set_max_auto_ashift, param_get_uint, ZMOD_RW, "Maximum ashift used when optimizing for logical -> physical sector " "size on new top-level vdevs"); + +ZFS_MODULE_PARAM_CALL(zfs_vdev, zfs_vdev_, raidz_impl, + param_set_raidz_impl, param_get_raidz_impl, ZMOD_RW, + "RAIDZ implementation"); diff --git a/module/zfs/vdev_raidz_math.c b/module/zfs/vdev_raidz_math.c index e12b96170f55..340d32b61bf8 100644 --- a/module/zfs/vdev_raidz_math.c +++ b/module/zfs/vdev_raidz_math.c @@ -81,7 +81,7 @@ static boolean_t raidz_math_initialized = B_FALSE; #define RAIDZ_IMPL_READ(i) (*(volatile uint32_t *) &(i)) -static uint32_t zfs_vdev_raidz_impl = IMPL_SCALAR; +uint32_t zfs_vdev_raidz_impl = IMPL_SCALAR; static uint32_t user_sel_impl = IMPL_FASTEST; /* Hold all supported implementations */ @@ -633,16 +633,10 @@ vdev_raidz_impl_set(const char *val) return (err); } -#if defined(_KERNEL) && defined(__linux__) - -static int -zfs_vdev_raidz_impl_set(const char *val, zfs_kernel_param_t *kp) -{ - return (vdev_raidz_impl_set(val)); -} +#if defined(_KERNEL) -static int -zfs_vdev_raidz_impl_get(char *buffer, zfs_kernel_param_t *kp) +int +vdev_raidz_impl_get(char *buffer, size_t size) { int i, cnt = 0; char *fmt; @@ -653,21 +647,18 @@ zfs_vdev_raidz_impl_get(char *buffer, zfs_kernel_param_t *kp) /* list mandatory options */ for (i = 0; i < ARRAY_SIZE(math_impl_opts) - 2; i++) { fmt = (impl == math_impl_opts[i].sel) ? "[%s] " : "%s "; - cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt, + cnt += kmem_scnprintf(buffer + cnt, size - cnt, fmt, math_impl_opts[i].name); } /* list all supported implementations */ for (i = 0; i < raidz_supp_impl_cnt; i++) { fmt = (i == impl) ? "[%s] " : "%s "; - cnt += kmem_scnprintf(buffer + cnt, PAGE_SIZE - cnt, fmt, + cnt += kmem_scnprintf(buffer + cnt, size - cnt, fmt, raidz_supp_impl[i]->name); } return (cnt); } -module_param_call(zfs_vdev_raidz_impl, zfs_vdev_raidz_impl_set, - zfs_vdev_raidz_impl_get, NULL, 0644); -MODULE_PARM_DESC(zfs_vdev_raidz_impl, "Select raidz implementation."); #endif