From 03e9caaec006134b3db9d02ac40fe9369ee78b03 Mon Sep 17 00:00:00 2001 From: Rich Ercolani <214141+rincebrain@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:35:22 -0500 Subject: [PATCH] Add a tunable to disable BRT support. Copy the disable parameter that FreeBSD implemented, and extend it to work on Linux as well, until we're sure this is stable. Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Rich Ercolani Closes #15529 --- include/os/freebsd/zfs/sys/zfs_vfsops_os.h | 1 + include/os/linux/zfs/sys/zfs_vfsops_os.h | 2 ++ man/man4/zfs.4 | 5 +++++ module/os/freebsd/zfs/zfs_vfsops.c | 4 ++++ module/os/freebsd/zfs/zfs_vnops_os.c | 5 +++++ module/os/linux/zfs/zfs_vnops_os.c | 4 ++++ module/os/linux/zfs/zpl_file_range.c | 5 +++++ tests/zfs-tests/include/libtest.shlib | 15 +++++++++++++++ tests/zfs-tests/include/tunables.cfg | 1 + .../tests/functional/block_cloning/cleanup.ksh | 4 ++++ .../tests/functional/block_cloning/setup.ksh | 5 +++++ 11 files changed, 51 insertions(+) diff --git a/include/os/freebsd/zfs/sys/zfs_vfsops_os.h b/include/os/freebsd/zfs/sys/zfs_vfsops_os.h index 7f0f24325d59..e7ebcccbe0ce 100644 --- a/include/os/freebsd/zfs/sys/zfs_vfsops_os.h +++ b/include/os/freebsd/zfs/sys/zfs_vfsops_os.h @@ -285,6 +285,7 @@ typedef struct zfid_long { #define LONG_FID_LEN (sizeof (zfid_long_t) - sizeof (uint16_t)) extern int zfs_super_owner; +extern int zfs_bclone_enabled; extern void zfs_init(void); extern void zfs_fini(void); diff --git a/include/os/linux/zfs/sys/zfs_vfsops_os.h b/include/os/linux/zfs/sys/zfs_vfsops_os.h index b4d5db21f5e5..220466550258 100644 --- a/include/os/linux/zfs/sys/zfs_vfsops_os.h +++ b/include/os/linux/zfs/sys/zfs_vfsops_os.h @@ -45,6 +45,8 @@ extern "C" { typedef struct zfsvfs zfsvfs_t; struct znode; +extern int zfs_bclone_enabled; + /* * This structure emulates the vfs_t from other platforms. It's purpose * is to facilitate the handling of mount options and minimize structural diff --git a/man/man4/zfs.4 b/man/man4/zfs.4 index 4a0441ed9469..5daf27e9d536 100644 --- a/man/man4/zfs.4 +++ b/man/man4/zfs.4 @@ -1154,6 +1154,11 @@ Selecting any option other than results in vector instructions from the respective CPU instruction set being used. . +.It Sy zfs_bclone_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int +Enable the experimental block cloning feature. +If this setting is 0, then even if feature@block_cloning is enabled, +attempts to clone blocks will act as though the feature is disabled. +. .It Sy zfs_blake3_impl Ns = Ns Sy fastest Pq string Select a BLAKE3 implementation. .Pp diff --git a/module/os/freebsd/zfs/zfs_vfsops.c b/module/os/freebsd/zfs/zfs_vfsops.c index a972c720dfdb..f2d5391037c4 100644 --- a/module/os/freebsd/zfs/zfs_vfsops.c +++ b/module/os/freebsd/zfs/zfs_vfsops.c @@ -89,6 +89,10 @@ int zfs_debug_level; SYSCTL_INT(_vfs_zfs, OID_AUTO, debug, CTLFLAG_RWTUN, &zfs_debug_level, 0, "Debug level"); +int zfs_bclone_enabled = 1; +SYSCTL_INT(_vfs_zfs, OID_AUTO, bclone_enabled, CTLFLAG_RWTUN, + &zfs_bclone_enabled, 0, "Enable block cloning"); + struct zfs_jailparam { int mount_snapshot; }; diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c index c37f543cea02..107cd69c756c 100644 --- a/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/module/os/freebsd/zfs/zfs_vnops_os.c @@ -6250,6 +6250,11 @@ zfs_freebsd_copy_file_range(struct vop_copy_file_range_args *ap) int error; uint64_t len = *ap->a_lenp; + if (!zfs_bclone_enabled) { + mp = NULL; + goto bad_write_fallback; + } + /* * TODO: If offset/length is not aligned to recordsize, use * vn_generic_copy_file_range() on this fragment. diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c index 1ae8023adc32..e990f7055f8a 100644 --- a/module/os/linux/zfs/zfs_vnops_os.c +++ b/module/os/linux/zfs/zfs_vnops_os.c @@ -4249,4 +4249,8 @@ EXPORT_SYMBOL(zfs_map); module_param(zfs_delete_blocks, ulong, 0644); MODULE_PARM_DESC(zfs_delete_blocks, "Delete files larger than N blocks async"); +/* CSTYLED */ +module_param(zfs_bclone_enabled, uint, 0644); +MODULE_PARM_DESC(zfs_bclone_enabled, "Enable block cloning"); + #endif diff --git a/module/os/linux/zfs/zpl_file_range.c b/module/os/linux/zfs/zpl_file_range.c index c47fe99dacff..73476ff40ebf 100644 --- a/module/os/linux/zfs/zpl_file_range.c +++ b/module/os/linux/zfs/zpl_file_range.c @@ -31,6 +31,8 @@ #include #include +int zfs_bclone_enabled = 1; + /* * Clone part of a file via block cloning. * @@ -50,6 +52,9 @@ __zpl_clone_file_range(struct file *src_file, loff_t src_off, fstrans_cookie_t cookie; int err; + if (!zfs_bclone_enabled) + return (-EOPNOTSUPP); + if (!spa_feature_is_enabled( dmu_objset_spa(ITOZSB(dst_i)->z_os), SPA_FEATURE_BLOCK_CLONING)) return (-EOPNOTSUPP); diff --git a/tests/zfs-tests/include/libtest.shlib b/tests/zfs-tests/include/libtest.shlib index 844caa17d8ed..d5d7bb6c8360 100644 --- a/tests/zfs-tests/include/libtest.shlib +++ b/tests/zfs-tests/include/libtest.shlib @@ -3334,6 +3334,21 @@ function set_tunable_impl esac } +function save_tunable +{ + [[ ! -d $TEST_BASE_DIR ]] && return 1 + [[ -e $TEST_BASE_DIR/tunable-$1 ]] && return 2 + echo "$(get_tunable """$1""")" > "$TEST_BASE_DIR"/tunable-"$1" +} + +function restore_tunable +{ + [[ ! -e $TEST_BASE_DIR/tunable-$1 ]] && return 1 + val="$(cat $TEST_BASE_DIR/tunable-"""$1""")" + set_tunable64 "$1" "$val" + rm $TEST_BASE_DIR/tunable-$1 +} + # # Get a global system tunable # diff --git a/tests/zfs-tests/include/tunables.cfg b/tests/zfs-tests/include/tunables.cfg index fb861f1a285c..e4e380aa7fd5 100644 --- a/tests/zfs-tests/include/tunables.cfg +++ b/tests/zfs-tests/include/tunables.cfg @@ -93,6 +93,7 @@ VOL_INHIBIT_DEV UNSUPPORTED zvol_inhibit_dev VOL_MODE vol.mode zvol_volmode VOL_RECURSIVE vol.recursive UNSUPPORTED VOL_USE_BLK_MQ UNSUPPORTED zvol_use_blk_mq +BCLONE_ENABLED zfs_bclone_enabled zfs_bclone_enabled XATTR_COMPAT xattr_compat zfs_xattr_compat ZEVENT_LEN_MAX zevent.len_max zfs_zevent_len_max ZEVENT_RETAIN_MAX zevent.retain_max zfs_zevent_retain_max diff --git a/tests/zfs-tests/tests/functional/block_cloning/cleanup.ksh b/tests/zfs-tests/tests/functional/block_cloning/cleanup.ksh index 7ac13adb6325..b985445a5d12 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/cleanup.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/cleanup.ksh @@ -31,4 +31,8 @@ verify_runnable "global" default_cleanup_noexit +if tunable_exists BCLONE_ENABLED ; then + log_must restore_tunable BCLONE_ENABLED +fi + log_pass diff --git a/tests/zfs-tests/tests/functional/block_cloning/setup.ksh b/tests/zfs-tests/tests/functional/block_cloning/setup.ksh index 512f5a0644df..58441bf8f3ad 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/setup.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/setup.ksh @@ -33,4 +33,9 @@ fi verify_runnable "global" +if tunable_exists BCLONE_ENABLED ; then + log_must save_tunable BCLONE_ENABLED + log_must set_tunable32 BCLONE_ENABLED 1 +fi + log_pass