From 4d22befde60087cbc6174122863353903df1d935 Mon Sep 17 00:00:00 2001 From: Damian Szuberski Date: Tue, 12 Apr 2022 00:51:23 +0200 Subject: [PATCH 01/84] initramfs: use `mount.zfs` instead of `mount` A followup to d7a67402a85252e163aa8a9b69e7eda499db8c61 For `mount -t zfs -o opts ds mp` command line some implementations of `mount(8)`, e. g. Busybox in Debian work as follows: ``` newfstatat(AT_FDCWD, "ds", 0x7fff826f4ab0, 0) = -1 mount("ds", "mp", "zfs", MS_SILENT, NULL) = 0 ``` The logic above skips completely `mount.zfs` and prevents us from reading filesystem properties and applying mount options. For comparison, the coreutils `mount(8)` implementation does: ``` openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_CLOEXEC) = 3 // figure out that zfs is a `nodev` filesystem and look for a helper newfstatat(AT_FDCWD, "/sbin/mount.zfs" ...) = 0 execve("/sbin/mount.zfs" ...) = 0 ``` Using `mount.zfs` in initramfs would help circumvent deficiencies of some of `mount(8)` implementations. `mount -t zfs` translates to `mount.zfs` invocation, except for cases when explicitly disabled by `-i`. Reviewed-by: Brian Behlendorf Signed-off-by: szubersk Closes #13305 (cherry picked from commit 35d81a75a8c13e011e19fd12cf553d9c5849386e) --- contrib/initramfs/scripts/zfs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/initramfs/scripts/zfs b/contrib/initramfs/scripts/zfs index 814547b6fa0c..9169adf5f5c4 100644 --- a/contrib/initramfs/scripts/zfs +++ b/contrib/initramfs/scripts/zfs @@ -326,7 +326,7 @@ mount_fs() # Need the _original_ datasets mountpoint! mountpoint=$(get_fs_value "$fs" mountpoint) - ZFS_CMD="mount -o zfsutil -t zfs" + ZFS_CMD="mount.zfs -o zfsutil" if [ "$mountpoint" = "legacy" ] || [ "$mountpoint" = "none" ]; then # Can't use the mountpoint property. Might be one of our # clones. Check the 'org.zol:mountpoint' property set in @@ -349,7 +349,7 @@ mount_fs() # If it's not a legacy filesystem, it can only be a # native one... if [ "$mountpoint" = "legacy" ]; then - ZFS_CMD="mount -t zfs" + ZFS_CMD="mount.zfs" fi fi @@ -915,7 +915,7 @@ mountroot() echo " not specified on the kernel command line." echo "" echo "Manually mount the root filesystem on $rootmnt and then exit." - echo "Hint: Try: mount -o zfsutil -t zfs ${ZFS_RPOOL-rpool}/ROOT/system $rootmnt" + echo "Hint: Try: mount.zfs -o zfsutil ${ZFS_RPOOL-rpool}/ROOT/system $rootmnt" shell fi From 8cf59e97c4fc7b70723313953ceb0f777ca3bcdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Thu, 13 Oct 2022 00:29:21 +0200 Subject: [PATCH 02/84] etc: mask zfs-load-key.service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, systemd-sysv-generator will generate a service equivalent that breaks the boot: under systemd this is covered by zfs-mount-generator We already do this for zfs-import.service, and other init scripts are suppressed automatically by the "actual" .service files Fixes: commit f04b97620059d08b37d9e80ada397e742bb2f311 ("Add init script to load keys") Reviewed-by: George Melikov Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #14010 Closes #14019 --- etc/systemd/system/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/etc/systemd/system/Makefile.am b/etc/systemd/system/Makefile.am index 5e65e1db420c..35f833de5cbc 100644 --- a/etc/systemd/system/Makefile.am +++ b/etc/systemd/system/Makefile.am @@ -22,3 +22,4 @@ SUBSTFILES += $(systemdpreset_DATA) $(systemdunit_DATA) install-data-hook: $(MKDIR_P) "$(DESTDIR)$(systemdunitdir)" ln -sf /dev/null "$(DESTDIR)$(systemdunitdir)/zfs-import.service" + ln -sf /dev/null "$(DESTDIR)$(systemdunitdir)/zfs-load-key.service" From b0bc882395ed37f60cf9612250cb99b1322cd458 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Wed, 12 Oct 2022 18:47:39 -0400 Subject: [PATCH 03/84] kcfpool_alloc() should have its argument list marked void This error occurred when building on Gentoo with debugging enabled: zfs-kmod-2.1.6/work/zfs-2.1.6/module/icp/core/kcf_sched.c:1277:14: error: a function declaration without a prototype is deprecated in all versions of C [-Werror,-Wstrict-prototypes] kcfpool_alloc() ^ void 1 error generated. This function is not present in master. Reviewed-by: Brian Behlendorf Reviewed-by: Tony Hutter Signed-off-by: Richard Yao Closes #14023 --- module/icp/core/kcf_sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/icp/core/kcf_sched.c b/module/icp/core/kcf_sched.c index 81fd15f8ea26..fa44a4dbf864 100644 --- a/module/icp/core/kcf_sched.c +++ b/module/icp/core/kcf_sched.c @@ -1274,7 +1274,7 @@ kcf_aop_done(kcf_areq_node_t *areq, int error) * Allocate the thread pool and initialize all the fields. */ static void -kcfpool_alloc() +kcfpool_alloc(void) { kcfpool = kmem_alloc(sizeof (kcf_pool_t), KM_SLEEP); From 3b935cc3ed8f83db72ea93a1310776cda44dcf66 Mon Sep 17 00:00:00 2001 From: gregory-lee-bartholomew Date: Wed, 29 Jun 2022 18:56:04 -0500 Subject: [PATCH 04/84] contrib: dracut: zfs-{rollback,snapshot}-bootfs: explicit snapname fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to a missing semicolon on the ExecStart line, it wasn't possible to specify the snapshot name on the bootfs.{rollback,snapshot} kernel parameters if the boot dataset name was obtained from the root=zfs:... kernel parameter. Reviewed-by: Ahelenia Ziemiańska Reviewed-by: Brian Behlendorf Signed-off-by: Gregory Bartholomew Closes #13585 --- contrib/dracut/90zfs/zfs-rollback-bootfs.service.in | 2 +- contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in index b4f5707516ce..a29cf3a3dd81 100644 --- a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in @@ -8,5 +8,5 @@ ConditionKernelCommandLine=bootfs.rollback [Service] Type=oneshot -ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$root@${SNAPNAME:-%v}"' +ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$root@${SNAPNAME:-%v}"' RemainAfterExit=yes diff --git a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in index 28a4edc844ad..e04be784c95c 100644 --- a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in @@ -8,5 +8,5 @@ ConditionKernelCommandLine=bootfs.snapshot [Service] Type=oneshot --ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"' +-ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"' RemainAfterExit=yes From 7795975681736c7e76bb5303b28558dff8e4a14d Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 20 Oct 2022 11:28:48 -0700 Subject: [PATCH 05/84] contrib: dracut: zfs-snapshot-bootfs: exit status fix Correct misplaced `-` is the original backport of #13769. Signed-off-by: Brian Behlendorf Issue #13769 --- contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in index e04be784c95c..9e73d1a78724 100644 --- a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in +++ b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in @@ -8,5 +8,5 @@ ConditionKernelCommandLine=bootfs.snapshot [Service] Type=oneshot --ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"' +ExecStart=-/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"' RemainAfterExit=yes From fc1c0053f9c6fd8e894c3378b489fa817f5d0330 Mon Sep 17 00:00:00 2001 From: samwyc <115969550+samwyc@users.noreply.github.com> Date: Thu, 20 Oct 2022 04:18:13 +0530 Subject: [PATCH 06/84] Fix sequential resilver drive failure race condition This patch handles the race condition on simultaneous failure of 2 drives, which misses the vdev_rebuild_reset_wanted signal in vdev_rebuild_thread. We retry to catch this inside the vdev_rebuild_complete_sync function. Reviewed-by: Brian Behlendorf Reviewed-by: Richard Yao Reviewed-by: Dipak Ghosh Reviewed-by: Akash B Signed-off-by: Samuel Wycliffe J Closes #14041 Closes #14050 --- module/zfs/vdev_rebuild.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/module/zfs/vdev_rebuild.c b/module/zfs/vdev_rebuild.c index 4d7de0c6c44c..9dfbe0cf6f30 100644 --- a/module/zfs/vdev_rebuild.c +++ b/module/zfs/vdev_rebuild.c @@ -22,6 +22,7 @@ * * Copyright (c) 2018, Intel Corporation. * Copyright (c) 2020 by Lawrence Livermore National Security, LLC. + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #include @@ -134,6 +135,7 @@ int zfs_rebuild_scrub_enabled = 1; * For vdev_rebuild_initiate_sync() and vdev_rebuild_reset_sync(). */ static void vdev_rebuild_thread(void *arg); +static void vdev_rebuild_reset_sync(void *arg, dmu_tx_t *tx); /* * Clear the per-vdev rebuild bytes value for a vdev tree. @@ -307,6 +309,17 @@ vdev_rebuild_complete_sync(void *arg, dmu_tx_t *tx) vdev_rebuild_phys_t *vrp = &vr->vr_rebuild_phys; mutex_enter(&vd->vdev_rebuild_lock); + + /* + * Handle a second device failure if it occurs after all rebuild I/O + * has completed but before this sync task has been executed. + */ + if (vd->vdev_rebuild_reset_wanted) { + mutex_exit(&vd->vdev_rebuild_lock); + vdev_rebuild_reset_sync(arg, tx); + return; + } + vrp->vrp_rebuild_state = VDEV_REBUILD_COMPLETE; vrp->vrp_end_time = gethrestime_sec(); @@ -760,7 +773,6 @@ vdev_rebuild_thread(void *arg) ASSERT(vd->vdev_rebuilding); ASSERT(spa_feature_is_active(spa, SPA_FEATURE_DEVICE_REBUILD)); ASSERT3B(vd->vdev_rebuild_cancel_wanted, ==, B_FALSE); - ASSERT3B(vd->vdev_rebuild_reset_wanted, ==, B_FALSE); vdev_rebuild_t *vr = &vd->vdev_rebuild_config; vdev_rebuild_phys_t *vrp = &vr->vr_rebuild_phys; From 4e3fecbdfd54e8fbd4b591e5a975b5a99a366bcf Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Tue, 11 Oct 2022 15:29:55 -0400 Subject: [PATCH 07/84] FreeBSD: Fix a pair of bugs in zfs_fhtovp() - Add a zfs_exit() call in an error path, otherwise a lock is leaked. - Remove the fid_gen > 1 check. That appears to be Linux-specific: zfsctl_snapdir_fid() sets fid_gen to 0 or 1 depending on whether the snapshot directory is mounted. On FreeBSD it fails, making snapshot dirs inaccessible via NFS. Reviewed-by: Alexander Motin Reviewed-by: Ryan Moeller Reviewed-by: Andriy Gapon Signed-off-by: Mark Johnston Fixes: 43dbf8817808 ("FreeBSD: vfsops: use setgen for error case") Closes #14001 Closes #13974 (cherry picked from commit ed566bf1cd0bdbf85e8c63c1c119e3d2ef5db1f6) --- module/os/freebsd/zfs/zfs_vfsops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/os/freebsd/zfs/zfs_vfsops.c b/module/os/freebsd/zfs/zfs_vfsops.c index cdd762dcbcbf..05d41d4e3b2a 100644 --- a/module/os/freebsd/zfs/zfs_vfsops.c +++ b/module/os/freebsd/zfs/zfs_vfsops.c @@ -1845,7 +1845,8 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp) return (SET_ERROR(EINVAL)); } - if (fidp->fid_len == LONG_FID_LEN && (fid_gen > 1 || setgen != 0)) { + if (fidp->fid_len == LONG_FID_LEN && setgen != 0) { + ZFS_EXIT(zfsvfs); dprintf("snapdir fid: fid_gen (%llu) and setgen (%llu)\n", (u_longlong_t)fid_gen, (u_longlong_t)setgen); return (SET_ERROR(EINVAL)); From 04f1983aab16d378be376768275856bc38be48bd Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 27 Oct 2022 01:00:58 +0300 Subject: [PATCH 08/84] FreeBSD: vn_flush_cached_data: observe vnode locking contract vm_object_page_clean() expects that the associated vnode is locked as VOP_PUTPAGES() may get called on the vnode. Reviewed-by: Ryan Moeller Signed-off-by: Andriy Gapon Closes #14079 (cherry picked from commit 41133c97949af43daadee0503a9842a8dce8f0fd) --- include/os/freebsd/spl/sys/vnode.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/os/freebsd/spl/sys/vnode.h b/include/os/freebsd/spl/sys/vnode.h index bcfc177a4751..b7ac12f3d676 100644 --- a/include/os/freebsd/spl/sys/vnode.h +++ b/include/os/freebsd/spl/sys/vnode.h @@ -95,9 +95,11 @@ vn_flush_cached_data(vnode_t *vp, boolean_t sync) if (vp->v_object->flags & OBJ_MIGHTBEDIRTY) { #endif int flags = sync ? OBJPC_SYNC : 0; + vn_lock(vp, LK_SHARED | LK_RETRY); zfs_vmobject_wlock(vp->v_object); vm_object_page_clean(vp->v_object, 0, 0, flags); zfs_vmobject_wunlock(vp->v_object); + VOP_UNLOCK(vp); } } From 7ac732b8d6f74302820785220f95779d79294c06 Mon Sep 17 00:00:00 2001 From: Akash B Date: Thu, 20 Oct 2022 05:37:51 +0530 Subject: [PATCH 09/84] Add options to zfs redundant_metadata property Currently, additional/extra copies are created for metadata in addition to the redundancy provided by the pool(mirror/raidz/draid), due to this 2 times more space is utilized per inode and this decreases the total number of inodes that can be created in the filesystem. By setting redundant_metadata to none, no additional copies of metadata are created, hence can reduce the space consumed by the additional metadata copies and increase the total number of inodes that can be created in the filesystem. Additionally, this can improve file create performance due to the reduced amount of metadata which needs to be written. Reviewed-by: Brian Behlendorf Reviewed-by: Dipak Ghosh Signed-off-by: Akash B Closes #13680 --- include/sys/dmu.h | 7 ++ include/sys/fs/zfs.h | 5 +- man/man7/zfsprops.7 | 18 +++- module/zcommon/zfs_prop.c | 5 +- module/zfs/dmu.c | 21 ++++- module/zfs/dmu_objset.c | 5 +- module/zfs/dsl_prop.c | 92 +++++++++++++++++++ tests/zfs-tests/include/properties.shlib | 3 +- .../inheritance/inherit_001_pos.ksh | 10 +- 9 files changed, 151 insertions(+), 15 deletions(-) diff --git a/include/sys/dmu.h b/include/sys/dmu.h index 070d27fde3a9..7bdd42e8bed4 100644 --- a/include/sys/dmu.h +++ b/include/sys/dmu.h @@ -27,6 +27,7 @@ * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2017, Intel Corporation. + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -142,6 +143,12 @@ typedef enum dmu_object_byteswap { #define DMU_OT_IS_DDT(ot) \ ((ot) == DMU_OT_DDT_ZAP) +#define DMU_OT_IS_CRITICAL(ot) \ + (DMU_OT_IS_METADATA(ot) && \ + (ot) != DMU_OT_DNODE && \ + (ot) != DMU_OT_DIRECTORY_CONTENTS && \ + (ot) != DMU_OT_SA) + /* Note: ztest uses DMU_OT_UINT64_OTHER as a proxy for file blocks */ #define DMU_OT_IS_FILE(ot) \ ((ot) == DMU_OT_PLAIN_FILE_CONTENTS || (ot) == DMU_OT_UINT64_OTHER) diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index df1cc060130a..f4dc2ab46536 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -29,6 +29,7 @@ * Copyright (c) 2019 Datto Inc. * Portions Copyright 2010 Robert Milkowski * Copyright (c) 2021, Colm Buckley + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #ifndef _SYS_FS_ZFS_H @@ -423,7 +424,9 @@ typedef enum { typedef enum { ZFS_REDUNDANT_METADATA_ALL, - ZFS_REDUNDANT_METADATA_MOST + ZFS_REDUNDANT_METADATA_MOST, + ZFS_REDUNDANT_METADATA_SOME, + ZFS_REDUNDANT_METADATA_NONE } zfs_redundant_metadata_type_t; typedef enum { diff --git a/man/man7/zfsprops.7 b/man/man7/zfsprops.7 index b753ec321ad0..1e2ca409f9ca 100644 --- a/man/man7/zfsprops.7 +++ b/man/man7/zfsprops.7 @@ -36,8 +36,9 @@ .\" Copyright 2018 Nexenta Systems, Inc. .\" Copyright 2019 Joyent, Inc. .\" Copyright (c) 2019, Kjeld Schouten-Lebbing +.\" Copyright (c) 2022 Hewlett Packard Enterprise Development LP. .\" -.Dd May 24, 2021 +.Dd July 21, 2022 .Dt ZFSPROPS 7 .Os . @@ -1445,7 +1446,7 @@ affects only files created afterward; existing files are unaffected. .Pp This property can also be referred to by its shortened column name, .Sy recsize . -.It Sy redundant_metadata Ns = Ns Sy all Ns | Ns Sy most +.It Sy redundant_metadata Ns = Ns Sy all Ns | Ns Sy most Ns | Ns Sy some Ns | Ns Sy none Controls what types of metadata are stored redundantly. ZFS stores an extra copy of metadata, so that if a single block is corrupted, the amount of user data lost is limited. @@ -1477,7 +1478,7 @@ When set to ZFS stores an extra copy of most types of metadata. This can improve performance of random writes, because less metadata must be written. -In practice, at worst about 100 blocks +In practice, at worst about 1000 blocks .Po of .Sy recordsize bytes each @@ -1486,6 +1487,17 @@ of user data can be lost if a single on-disk block is corrupt. The exact behavior of which metadata blocks are stored redundantly may change in future releases. .Pp +When set to +.Sy some , +ZFS stores an extra copy of only critical metadata. +This can improve file create performance since less metadata needs to be written. +If a single on-disk block is corrupt, at worst a single user file can be lost. +.Pp +When set to +.Sy none , +ZFS does not store any copies of metadata redundantly. +If a single on-disk block is corrupt, an entire dataset can be lost. +.Pp The default value is .Sy all . .It Sy refquota Ns = Ns Ar size Ns | Ns Sy none diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index 5f88bd02089d..a33eb36ac192 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -25,6 +25,7 @@ * Copyright 2016, Joyent, Inc. * Copyright (c) 2019, Klara Inc. * Copyright (c) 2019, Allan Jude + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -371,6 +372,8 @@ zfs_prop_init(void) static zprop_index_t redundant_metadata_table[] = { { "all", ZFS_REDUNDANT_METADATA_ALL }, { "most", ZFS_REDUNDANT_METADATA_MOST }, + { "some", ZFS_REDUNDANT_METADATA_SOME }, + { "none", ZFS_REDUNDANT_METADATA_NONE }, { NULL } }; @@ -387,7 +390,7 @@ zfs_prop_init(void) zprop_register_index(ZFS_PROP_REDUNDANT_METADATA, "redundant_metadata", ZFS_REDUNDANT_METADATA_ALL, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "all | most", "REDUND_MD", + "all | most | some | none", "REDUND_MD", redundant_metadata_table); zprop_register_index(ZFS_PROP_SYNC, "sync", ZFS_SYNC_STANDARD, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c index e38c9b452a28..0832fbcfdf40 100644 --- a/module/zfs/dmu.c +++ b/module/zfs/dmu.c @@ -28,6 +28,7 @@ * Copyright (c) 2019 Datto Inc. * Copyright (c) 2019, Klara Inc. * Copyright (c) 2019, Allan Jude + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #include @@ -1988,12 +1989,22 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp, zio_prop_t *zp) ZCHECKSUM_FLAG_EMBEDDED)) checksum = ZIO_CHECKSUM_FLETCHER_4; - if (os->os_redundant_metadata == ZFS_REDUNDANT_METADATA_ALL || - (os->os_redundant_metadata == - ZFS_REDUNDANT_METADATA_MOST && - (level >= zfs_redundant_metadata_most_ditto_level || - DMU_OT_IS_METADATA(type) || (wp & WP_SPILL)))) + switch (os->os_redundant_metadata) { + case ZFS_REDUNDANT_METADATA_ALL: copies++; + break; + case ZFS_REDUNDANT_METADATA_MOST: + if (level >= zfs_redundant_metadata_most_ditto_level || + DMU_OT_IS_METADATA(type) || (wp & WP_SPILL)) + copies++; + break; + case ZFS_REDUNDANT_METADATA_SOME: + if (DMU_OT_IS_CRITICAL(type)) + copies++; + break; + case ZFS_REDUNDANT_METADATA_NONE: + break; + } } else if (wp & WP_NOFILL) { ASSERT(level == 0); diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c index a8975797e8af..5ad3b2f269d6 100644 --- a/module/zfs/dmu_objset.c +++ b/module/zfs/dmu_objset.c @@ -32,6 +32,7 @@ * Copyright (c) 2018, loli10K . All rights reserved. * Copyright (c) 2019, Klara Inc. * Copyright (c) 2019, Allan Jude + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -287,7 +288,9 @@ redundant_metadata_changed_cb(void *arg, uint64_t newval) * Inheritance and range checking should have been done by now. */ ASSERT(newval == ZFS_REDUNDANT_METADATA_ALL || - newval == ZFS_REDUNDANT_METADATA_MOST); + newval == ZFS_REDUNDANT_METADATA_MOST || + newval == ZFS_REDUNDANT_METADATA_SOME || + newval == ZFS_REDUNDANT_METADATA_NONE); os->os_redundant_metadata = newval; } diff --git a/module/zfs/dsl_prop.c b/module/zfs/dsl_prop.c index 0089edf8683a..d1c3ff543661 100644 --- a/module/zfs/dsl_prop.c +++ b/module/zfs/dsl_prop.c @@ -23,6 +23,7 @@ * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 Martin Matuska. All rights reserved. * Copyright 2019 Joyent, Inc. + * Copyright (c) 2022 Hewlett Packard Enterprise Development LP. */ #include @@ -41,6 +42,7 @@ #define ZPROP_INHERIT_SUFFIX "$inherit" #define ZPROP_RECVD_SUFFIX "$recvd" +#define ZPROP_IUV_SUFFIX "$iuv" static int dodefault(zfs_prop_t prop, int intsz, int numints, void *buf) @@ -69,6 +71,16 @@ dodefault(zfs_prop_t prop, int intsz, int numints, void *buf) return (0); } +static int +dsl_prop_known_index(zfs_prop_t prop, uint64_t value) +{ + const char *str = NULL; + if (zfs_prop_get_type(prop) == PROP_TYPE_INDEX) + return (!zfs_prop_index_to_string(prop, value, &str)); + + return (-1); +} + int dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, int intsz, int numints, void *buf, char *setpoint, boolean_t snapshot) @@ -81,6 +93,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, boolean_t inheriting = B_FALSE; char *inheritstr; char *recvdstr; + char *iuvstr; ASSERT(dsl_pool_config_held(dd->dd_pool)); @@ -91,6 +104,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop)); inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); + iuvstr = kmem_asprintf("%s%s", propname, ZPROP_IUV_SUFFIX); /* * Note: dd may become NULL, therefore we shouldn't dereference it @@ -105,6 +119,18 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, inheriting = B_TRUE; } + /* Check for a iuv value. */ + err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, + iuvstr, intsz, numints, buf); + if (dsl_prop_known_index(zfs_name_to_prop(propname), + *(uint64_t *)buf) != 1) + err = ENOENT; + if (err != ENOENT) { + if (setpoint != NULL && err == 0) + dsl_dir_name(dd, setpoint); + break; + } + /* Check for a local value. */ err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, propname, intsz, numints, buf); @@ -155,6 +181,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, kmem_strfree(inheritstr); kmem_strfree(recvdstr); + kmem_strfree(iuvstr); return (err); } @@ -647,6 +674,45 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, dsl_dir_rele(dd, FTAG); } + +/* + * For newer values in zfs index type properties, we add a new key + * propname$iuv (iuv = Ignore Unknown Values) to the properties zap object + * to store the new property value and store the default value in the + * existing prop key. So that the propname$iuv key is ignored by the older zfs + * versions and the default property value from the existing prop key is + * used. + */ +static void +dsl_prop_set_iuv(objset_t *mos, uint64_t zapobj, const char *propname, + int intsz, int numints, const void *value, dmu_tx_t *tx) +{ + char *iuvstr = kmem_asprintf("%s%s", propname, ZPROP_IUV_SUFFIX); + boolean_t iuv = B_FALSE; + zfs_prop_t prop = zfs_name_to_prop(propname); + + switch (prop) { + case ZFS_PROP_REDUNDANT_METADATA: + if (*(uint64_t *)value == ZFS_REDUNDANT_METADATA_SOME || + *(uint64_t *)value == ZFS_REDUNDANT_METADATA_NONE) + iuv = B_TRUE; + break; + default: + break; + } + + if (iuv) { + VERIFY0(zap_update(mos, zapobj, iuvstr, intsz, numints, + value, tx)); + uint64_t val = zfs_prop_default_numeric(prop); + VERIFY0(zap_update(mos, zapobj, propname, intsz, numints, + &val, tx)); + } else { + zap_remove(mos, zapobj, iuvstr, tx); + } + kmem_strfree(iuvstr); +} + void dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, zprop_source_t source, int intsz, int numints, const void *value, @@ -659,6 +725,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, const char *valstr = NULL; char *inheritstr; char *recvdstr; + char *iuvstr; char *tbuf = NULL; int err; uint64_t version = spa_version(ds->ds_dir->dd_pool->dp_spa); @@ -692,6 +759,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); + iuvstr = kmem_asprintf("%s%s", propname, ZPROP_IUV_SUFFIX); switch ((int)source) { case ZPROP_SRC_NONE: @@ -709,11 +777,14 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, /* * remove propname$inherit * set propname -> value + * set propname$iuv -> new property value */ err = zap_remove(mos, zapobj, inheritstr, tx); ASSERT(err == 0 || err == ENOENT); VERIFY0(zap_update(mos, zapobj, propname, intsz, numints, value, tx)); + (void) dsl_prop_set_iuv(mos, zapobj, propname, intsz, + numints, value, tx); break; case ZPROP_SRC_INHERITED: /* @@ -723,6 +794,8 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, */ err = zap_remove(mos, zapobj, propname, tx); ASSERT(err == 0 || err == ENOENT); + err = zap_remove(mos, zapobj, iuvstr, tx); + ASSERT(err == 0 || err == ENOENT); if (version >= SPA_VERSION_RECVD_PROPS && dsl_prop_get_int_ds(ds, ZPROP_HAS_RECVD, &dummy) == 0) { dummy = 0; @@ -763,6 +836,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, kmem_strfree(inheritstr); kmem_strfree(recvdstr); + kmem_strfree(iuvstr); /* * If we are left with an empty snap zap we can destroy it. @@ -1012,6 +1086,14 @@ dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj, propname = za.za_name; source = setpoint; + + /* Skip if iuv entries are preset. */ + valstr = kmem_asprintf("%s%s", propname, + ZPROP_IUV_SUFFIX); + err = zap_contains(mos, propobj, valstr); + kmem_strfree(valstr); + if (err == 0) + continue; } else if (strcmp(suffix, ZPROP_INHERIT_SUFFIX) == 0) { /* Skip explicitly inherited entries. */ continue; @@ -1044,6 +1126,16 @@ dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj, source = ((flags & DSL_PROP_GET_INHERITING) ? setpoint : ZPROP_SOURCE_VAL_RECVD); + } else if (strcmp(suffix, ZPROP_IUV_SUFFIX) == 0) { + (void) strlcpy(buf, za.za_name, + MIN(sizeof (buf), suffix - za.za_name + 1)); + propname = buf; + source = setpoint; + prop = zfs_name_to_prop(propname); + + if (dsl_prop_known_index(prop, + za.za_first_integer) != 1) + continue; } else { /* * For backward compatibility, skip suffixes we don't diff --git a/tests/zfs-tests/include/properties.shlib b/tests/zfs-tests/include/properties.shlib index 6d467b60051d..dcf3ab7ae455 100644 --- a/tests/zfs-tests/include/properties.shlib +++ b/tests/zfs-tests/include/properties.shlib @@ -11,6 +11,7 @@ # # Copyright (c) 2012, 2016, Delphix. All rights reserved. +# Copyright (c) 2022 Hewlett Packard Enterprise Development LP. # . $STF_SUITE/include/libtest.shlib @@ -27,7 +28,7 @@ typeset -a canmount_prop_vals=('on' 'off' 'noauto') typeset -a copies_prop_vals=('1' '2' '3') typeset -a logbias_prop_vals=('latency' 'throughput') typeset -a primarycache_prop_vals=('all' 'none' 'metadata') -typeset -a redundant_metadata_prop_vals=('all' 'most') +typeset -a redundant_metadata_prop_vals=('all' 'most' 'some' 'none') typeset -a secondarycache_prop_vals=('all' 'none' 'metadata') typeset -a snapdir_prop_vals=('hidden' 'visible') typeset -a sync_prop_vals=('standard' 'always' 'disabled') diff --git a/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh index 7c5b81287736..5a5be3bd9bee 100755 --- a/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh +++ b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh @@ -26,6 +26,7 @@ # # Copyright (c) 2013, 2016 by Delphix. All rights reserved. +# Copyright (c) 2022 Hewlett Packard Enterprise Development LP. # . $STF_SUITE/include/libtest.shlib @@ -380,7 +381,8 @@ set -A prop "checksum" "" \ "sharenfs" "" \ "recordsize" "recsize" \ "snapdir" "" \ - "readonly" "" + "readonly" "" \ + "redundant_metadata" "" # # Note except for the mountpoint default value (which is handled in @@ -391,12 +393,14 @@ set -A prop "checksum" "" \ set -A def_val "on" "off" "on" \ "off" "" \ "hidden" \ - "off" + "off" \ + "all" set -A local_val "off" "on" "off" \ "on" "" \ "visible" \ - "off" + "off" \ + "none" # # Add system specific values From c8d6a91a993c6e5da47ba24d52e6f01bf3a0e01f Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Wed, 28 Sep 2022 02:38:03 +0200 Subject: [PATCH 10/84] Bring per_txg_dirty_frees_percent back to 30 The current value causes significant artificial slowdown during mass parallel file removal, which can be observed both on FreeBSD and Linux when running real workloads. Sample results from Linux doing make -j 96 clean after an allyesconfig modules build: before: 4.14s user 6.79s system 48% cpu 22.631 total after: 4.17s user 6.44s system 153% cpu 6.927 total FreeBSD results in the ticket. Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Reviewed-by: Richard Yao Reviewed-by: George Melikov Signed-off-by: Mateusz Guzik Closes #13932 Closes #13938 --- man/man4/zfs.4 | 2 +- module/zfs/dmu.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/man/man4/zfs.4 b/man/man4/zfs.4 index fcb97d716d54..b317941bbd36 100644 --- a/man/man4/zfs.4 +++ b/man/man4/zfs.4 @@ -1651,7 +1651,7 @@ prefetched during a pool traversal, like .Nm zfs Cm send or other data crawling operations. . -.It Sy zfs_per_txg_dirty_frees_percent Ns = Ns Sy 5 Ns % Pq ulong +.It Sy zfs_per_txg_dirty_frees_percent Ns = Ns Sy 30 Ns % Pq ulong Control percentage of dirtied indirect blocks from frees allowed into one TXG. After this threshold is crossed, additional frees will wait until the next TXG. .Sy 0 No disables this throttle. diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c index 0832fbcfdf40..c67a36470e33 100644 --- a/module/zfs/dmu.c +++ b/module/zfs/dmu.c @@ -71,7 +71,7 @@ int zfs_nopwrite_enabled = 1; * will wait until the next TXG. * A value of zero will disable this throttle. */ -unsigned long zfs_per_txg_dirty_frees_percent = 5; +unsigned long zfs_per_txg_dirty_frees_percent = 30; /* * Enable/disable forcing txg sync when dirty checking for holes with lseek(). From 37763ea2a67871ffce452df225b5b71733b8e2a1 Mon Sep 17 00:00:00 2001 From: Serapheim Dimitropoulos Date: Thu, 29 Sep 2022 09:39:48 -0700 Subject: [PATCH 11/84] Fix panic in dsl_process_sub_livelist for EINTR = Issue Recently we hit an assertion panic in `dsl_process_sub_livelist` while exporting the spa and interrupting `bpobj_iterate_nofree`. In that case `bpobj_iterate_nofree` stops mid-way returning an EINTR without clearing the intermediate AVL tree that keeps track of the livelist entries it has encountered so far. At that point the code has a VERIFY for the number of elements of the AVL expecting it to be zero (which is not the case for EINTR). = Fix Cleanup any intermediate state before destroying the AVL when encountering EINTR. Also added a comment documenting the scenario where the EINTR comes up. There is no need to do anything else for the calles of `dsl_process_sub_livelist` as they already handle the EINTR case. Reviewed-by: Matthew Ahrens Reviewed-by: Mark Maybee Reviewed-by: Richard Yao Signed-off-by: Serapheim Dimitropoulos Closes #13939 --- module/zfs/dsl_deadlist.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/module/zfs/dsl_deadlist.c b/module/zfs/dsl_deadlist.c index a77e381520db..7681b735ec70 100644 --- a/module/zfs/dsl_deadlist.c +++ b/module/zfs/dsl_deadlist.c @@ -1028,8 +1028,13 @@ dsl_process_sub_livelist(bpobj_t *bpobj, bplist_t *to_free, zthr_t *t, .t = t }; int err = bpobj_iterate_nofree(bpobj, dsl_livelist_iterate, &arg, size); + VERIFY(err != 0 || avl_numnodes(&avl) == 0); - VERIFY0(avl_numnodes(&avl)); + void *cookie = NULL; + livelist_entry_t *le = NULL; + while ((le = avl_destroy_nodes(&avl, &cookie)) != NULL) { + kmem_free(le, sizeof (livelist_entry_t)); + } avl_destroy(&avl); return (err); } From 820edcbf9111ece4140e806047aa54aa4b9460d9 Mon Sep 17 00:00:00 2001 From: shodanshok Date: Tue, 4 Oct 2022 20:00:02 +0200 Subject: [PATCH 12/84] Remove ambiguity on demand vs prefetch stats reported by arc_summary arc_summary currently list prefetch stats as "demand prefetch" However, a hit/miss can be due to demand or prefetch, not both. To remove any confusion, this patch removes the "Demand" word from the affected lines. Reviewed-by: Richard Yao Reviewed-by: Alexander Motin Reviewed-by: George Melikov Signed-off-by: Gionatan Danti Closes #13985 --- cmd/arc_summary/arc_summary3 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/arc_summary/arc_summary3 b/cmd/arc_summary/arc_summary3 index 7b28012ede4d..301c485b34ba 100755 --- a/cmd/arc_summary/arc_summary3 +++ b/cmd/arc_summary/arc_summary3 @@ -686,9 +686,9 @@ def section_archits(kstats_dict): print() print('Cache hits by data type:') dt_todo = (('Demand data:', arc_stats['demand_data_hits']), - ('Demand prefetch data:', arc_stats['prefetch_data_hits']), + ('Prefetch data:', arc_stats['prefetch_data_hits']), ('Demand metadata:', arc_stats['demand_metadata_hits']), - ('Demand prefetch metadata:', + ('Prefetch metadata:', arc_stats['prefetch_metadata_hits'])) for title, value in dt_todo: @@ -697,10 +697,10 @@ def section_archits(kstats_dict): print() print('Cache misses by data type:') dm_todo = (('Demand data:', arc_stats['demand_data_misses']), - ('Demand prefetch data:', + ('Prefetch data:', arc_stats['prefetch_data_misses']), ('Demand metadata:', arc_stats['demand_metadata_misses']), - ('Demand prefetch metadata:', + ('Prefetch metadata:', arc_stats['prefetch_metadata_misses'])) for title, value in dm_todo: From 25096e11800a545ff80764e51bd86dcc2a03a4bd Mon Sep 17 00:00:00 2001 From: Serapheim Dimitropoulos Date: Tue, 11 Oct 2022 12:12:04 -0700 Subject: [PATCH 13/84] zvol_wait logic may terminate prematurely Setups that have a lot of zvols may see zvol_wait terminate prematurely even though the script is still making progress. For example, we have a customer that called zvol_wait for ~7100 zvols and by the last iteration of that script it was still waiting on ~2900. Similarly another one called zvol_wait for 2200 and by the time the script terminated there were only 50 left. This patch adjusts the logic to stay within the outer loop of the script if we are making any progress whatsoever. Reviewed-by: George Wilson Reviewed-by: Pavel Zakharov Reviewed-by: Don Brady Signed-off-by: Serapheim Dimitropoulos Closes #13998 --- cmd/zvol_wait/zvol_wait | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/zvol_wait/zvol_wait b/cmd/zvol_wait/zvol_wait index f1fa42e27dc9..0b2a8a3e60c3 100755 --- a/cmd/zvol_wait/zvol_wait +++ b/cmd/zvol_wait/zvol_wait @@ -109,6 +109,13 @@ while [ "$outer_loop" -lt 20 ]; do exit 0 fi fi + + # + # zvol_count made some progress - let's stay in this loop. + # + if [ "$old_zvols_count" -gt "$zvols_count" ]; then + outer_loop=$((outer_loop - 1)) + fi done echo "Timed out waiting on zvol links" From 37d5a3e04b7baa88e41a230c1a243874c82fcb80 Mon Sep 17 00:00:00 2001 From: Serapheim Dimitropoulos Date: Tue, 11 Oct 2022 12:27:41 -0700 Subject: [PATCH 14/84] Stop ganging due to past vdev write errors = Problem While examining a customer's system we noticed unreasonable space usage from a few snapshots due to gang blocks. Under some further analysis we discovered that the pool would create gang blocks because all its disks had non-zero write error counts and they'd be skipped for normal metaslab allocations due to the following if-clause in `metaslab_alloc_dva()`: ``` /* * Avoid writing single-copy data to a failing, * non-redundant vdev, unless we've already tried all * other vdevs. */ if ((vd->vdev_stat.vs_write_errors > 0 || vd->vdev_state < VDEV_STATE_HEALTHY) && d == 0 && !try_hard && vd->vdev_children == 0) { metaslab_trace_add(zal, mg, NULL, psize, d, TRACE_VDEV_ERROR, allocator); goto next; } ``` = Proposed Solution Get rid of the predicate in the if-clause that checks the past write errors of the selected vdev. We still try to allocate from HEALTHY vdevs anyway by checking vdev_state so the past write errors doesn't seem to help us (quite the opposite - it can cause issues in long-lived pools like the one from our customer). = Testing I first created a pool with 3 vdevs: ``` $ zpool list -v volpool NAME SIZE ALLOC FREE volpool 22.5G 117M 22.4G xvdb 7.99G 40.2M 7.46G xvdc 7.99G 39.1M 7.46G xvdd 7.99G 37.8M 7.46G ``` And used `zinject` like so with each one of them: ``` $ sudo zinject -d xvdb -e io -T write -f 0.1 volpool ``` And got the vdevs to the following state: ``` $ zpool status volpool pool: volpool state: ONLINE status: One or more devices has experienced an unrecoverable error. ..... action: Determine if the device needs to be replaced, and clear the ..... config: NAME STATE READ WRITE CKSUM volpool ONLINE 0 0 0 xvdb ONLINE 0 1 0 xvdc ONLINE 0 1 0 xvdd ONLINE 0 4 0 ``` I also double-checked their write error counters with sdb: ``` sdb> spa volpool | vdev | member vdev_stat.vs_write_errors (uint64_t)0 # <---- this is the root vdev (uint64_t)2 (uint64_t)1 (uint64_t)1 ``` Then I checked that I the problem was reproduced in my VM as I the gang count was growing in zdb as I was writting more data: ``` $ sudo zdb volpool | grep gang ganged count: 1384 $ sudo zdb volpool | grep gang ganged count: 1393 $ sudo zdb volpool | grep gang ganged count: 1402 $ sudo zdb volpool | grep gang ganged count: 1414 ``` Then I updated my bits with this patch and the gang count stayed the same. Reviewed-by: Mark Maybee Reviewed-by: Matthew Ahrens Reviewed-by: Richard Yao Signed-off-by: Serapheim Dimitropoulos Closes #14003 --- module/zfs/metaslab.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c index ecc70298dc79..74796096d794 100644 --- a/module/zfs/metaslab.c +++ b/module/zfs/metaslab.c @@ -5207,12 +5207,11 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize, ASSERT(mg->mg_initialized); /* - * Avoid writing single-copy data to a failing, + * Avoid writing single-copy data to an unhealthy, * non-redundant vdev, unless we've already tried all * other vdevs. */ - if ((vd->vdev_stat.vs_write_errors > 0 || - vd->vdev_state < VDEV_STATE_HEALTHY) && + if (vd->vdev_state < VDEV_STATE_HEALTHY && d == 0 && !try_hard && vd->vdev_children == 0) { metaslab_trace_add(zal, mg, NULL, psize, d, TRACE_VDEV_ERROR, allocator); From 1bbc09e1f7b1bb2e59dcb955402dfa2e3b9050a8 Mon Sep 17 00:00:00 2001 From: George Melikov Date: Tue, 11 Oct 2022 22:59:06 +0300 Subject: [PATCH 15/84] CI: bump actions/checkout to v3 Reviewed-by: Brian Behlendorf Signed-off-by: George Melikov Closes #14018 --- .github/workflows/checkstyle.yaml | 2 +- .github/workflows/zfs-tests-functional.yml | 2 +- .github/workflows/zfs-tests-sanity.yml | 2 +- .github/workflows/zloop.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/checkstyle.yaml b/.github/workflows/checkstyle.yaml index 553d5df39796..91b8920fab3c 100644 --- a/.github/workflows/checkstyle.yaml +++ b/.github/workflows/checkstyle.yaml @@ -8,7 +8,7 @@ jobs: checkstyle: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies diff --git a/.github/workflows/zfs-tests-functional.yml b/.github/workflows/zfs-tests-functional.yml index adcbcb15681a..ac26c5345909 100644 --- a/.github/workflows/zfs-tests-functional.yml +++ b/.github/workflows/zfs-tests-functional.yml @@ -12,7 +12,7 @@ jobs: os: [18.04, 20.04] runs-on: ubuntu-${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies diff --git a/.github/workflows/zfs-tests-sanity.yml b/.github/workflows/zfs-tests-sanity.yml index c1e257dd1572..0c8828d536cd 100644 --- a/.github/workflows/zfs-tests-sanity.yml +++ b/.github/workflows/zfs-tests-sanity.yml @@ -8,7 +8,7 @@ jobs: tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies diff --git a/.github/workflows/zloop.yml b/.github/workflows/zloop.yml index cf81ad4bcafc..70b034b26540 100644 --- a/.github/workflows/zloop.yml +++ b/.github/workflows/zloop.yml @@ -10,7 +10,7 @@ jobs: env: TEST_DIR: /var/tmp/zloop steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install dependencies From 4dd9c3b08e62872580063d2a81d70f567013e77c Mon Sep 17 00:00:00 2001 From: George Melikov Date: Wed, 12 Oct 2022 09:33:38 +0300 Subject: [PATCH 16/84] CI: bump actions/upload-artifact to v3 Reviewed-by: Brian Behlendorf Signed-off-by: George Melikov Closes #14018 --- .github/workflows/checkstyle.yaml | 2 +- .github/workflows/zfs-tests-functional.yml | 2 +- .github/workflows/zfs-tests-sanity.yml | 2 +- .github/workflows/zloop.yml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/checkstyle.yaml b/.github/workflows/checkstyle.yaml index 91b8920fab3c..7b506262593f 100644 --- a/.github/workflows/checkstyle.yaml +++ b/.github/workflows/checkstyle.yaml @@ -43,7 +43,7 @@ jobs: if: failure() && steps.CheckABI.outcome == 'failure' run: | find -name *.abi | tar -cf abi_files.tar -T - - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() && steps.CheckABI.outcome == 'failure' with: name: New ABI files (use only if you're sure about interface changes) diff --git a/.github/workflows/zfs-tests-functional.yml b/.github/workflows/zfs-tests-functional.yml index ac26c5345909..26a8bf0524a8 100644 --- a/.github/workflows/zfs-tests-functional.yml +++ b/.github/workflows/zfs-tests-functional.yml @@ -75,7 +75,7 @@ jobs: sudo chmod +r $RESULTS_PATH/* # Replace ':' in dir names, actions/upload-artifact doesn't support it for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Test logs Ubuntu-${{ matrix.os }} diff --git a/.github/workflows/zfs-tests-sanity.yml b/.github/workflows/zfs-tests-sanity.yml index 0c8828d536cd..875ca4d94496 100644 --- a/.github/workflows/zfs-tests-sanity.yml +++ b/.github/workflows/zfs-tests-sanity.yml @@ -71,7 +71,7 @@ jobs: sudo chmod +r $RESULTS_PATH/* # Replace ':' in dir names, actions/upload-artifact doesn't support it for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Test logs diff --git a/.github/workflows/zloop.yml b/.github/workflows/zloop.yml index 70b034b26540..f9caa9ed4ba0 100644 --- a/.github/workflows/zloop.yml +++ b/.github/workflows/zloop.yml @@ -50,7 +50,7 @@ jobs: if: failure() run: | sudo chmod +r -R $TEST_DIR/ - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Logs @@ -58,7 +58,7 @@ jobs: /var/tmp/zloop/*/ !/var/tmp/zloop/*/vdev/ if-no-files-found: ignore - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: Pool files From 7a1b6c51d0fc79bd5184f7a4177a818cb5339468 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sat, 8 Oct 2022 21:29:54 -0400 Subject: [PATCH 17/84] Linux: Remove ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST autotools check On older kernels, the definition for `module_param_call()` typecasts function pointers to `(void *)`, which triggers -Werror, causing the check to return false when it should return true. Fixing this breaks the build process on some older kernels because they define a `__check_old_set_param()` function in their headers that checks for a non-constified `->set()`. We workaround that through the c preprocessor by defining `__check_old_set_param(set)` to `(set)`, which prevents the build failures. However, it is now apparent that all kernels that we support have adopted the GRSecurity change, so there is no need to have an explicit autotools check for it anymore. We therefore remove the autotools check, while adding the workaround to our headers for the build time non-constified `->set()` check done by older kernel headers. Reviewed-by: Brian Behlendorf Reviewed-by: Jorgen Lundman Reviewed-by: Ryan Moeller Reviewed-by: Alexander Motin Signed-off-by: Richard Yao Closes #13984 Closes #14004 --- config/kernel-mod-param.m4 | 33 ---------------------- config/kernel.m4 | 2 -- include/os/linux/kernel/linux/mod_compat.h | 14 +++++---- 3 files changed, 9 insertions(+), 40 deletions(-) delete mode 100644 config/kernel-mod-param.m4 diff --git a/config/kernel-mod-param.m4 b/config/kernel-mod-param.m4 deleted file mode 100644 index e00f19d61e7d..000000000000 --- a/config/kernel-mod-param.m4 +++ /dev/null @@ -1,33 +0,0 @@ -dnl # -dnl # Grsecurity kernel API change -dnl # constified parameters of module_param_call() methods -dnl # -AC_DEFUN([ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST], [ - ZFS_LINUX_TEST_SRC([module_param_call], [ - #include - #include - - int param_get(char *b, const struct kernel_param *kp) - { - return (0); - } - - int param_set(const char *b, const struct kernel_param *kp) - { - return (0); - } - - module_param_call(p, param_set, param_get, NULL, 0644); - ],[]) -]) - -AC_DEFUN([ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST], [ - AC_MSG_CHECKING([whether module_param_call() is hardened]) - ZFS_LINUX_TEST_RESULT([module_param_call], [ - AC_MSG_RESULT(yes) - AC_DEFINE(MODULE_PARAM_CALL_CONST, 1, - [hardened module_param_call]) - ],[ - AC_MSG_RESULT(no) - ]) -]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 41492c19d8a5..4a5e2a8dd01d 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -119,7 +119,6 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ ZFS_AC_KERNEL_SRC_FMODE_T ZFS_AC_KERNEL_SRC_KUIDGID_T ZFS_AC_KERNEL_SRC_KUID_HELPERS - ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST ZFS_AC_KERNEL_SRC_RENAME ZFS_AC_KERNEL_SRC_CURRENT_TIME ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES @@ -236,7 +235,6 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ ZFS_AC_KERNEL_FMODE_T ZFS_AC_KERNEL_KUIDGID_T ZFS_AC_KERNEL_KUID_HELPERS - ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST ZFS_AC_KERNEL_RENAME ZFS_AC_KERNEL_CURRENT_TIME ZFS_AC_KERNEL_USERNS_CAPABILITIES diff --git a/include/os/linux/kernel/linux/mod_compat.h b/include/os/linux/kernel/linux/mod_compat.h index cc42c3f7c743..642ff9826b26 100644 --- a/include/os/linux/kernel/linux/mod_compat.h +++ b/include/os/linux/kernel/linux/mod_compat.h @@ -30,12 +30,16 @@ #include #include -/* Grsecurity kernel API change */ -#ifdef MODULE_PARAM_CALL_CONST +/* + * Despite constifying struct kernel_param_ops, some older kernels define a + * `__check_old_set_param()` function in their headers that checks for a + * non-constified `->set()`. This has long been fixed in Linux mainline, but + * since we support older kernels, we workaround it by using a preprocessor + * definition to disable it. + */ +#define __check_old_set_param(_) (0) + typedef const struct kernel_param zfs_kernel_param_t; -#else -typedef struct kernel_param zfs_kernel_param_t; -#endif #define ZMOD_RW 0644 #define ZMOD_RD 0444 From df000276b8187db403f6e9d416f266684c7e6b2a Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Fri, 14 Oct 2022 20:46:47 +0200 Subject: [PATCH 18/84] zfs_domount: fix double-disown of dataset / double-free of zfsvfs_t Before this patch, in zfs_domount, if zfs_root or d_make_root fails, we leave zfsvfs != NULL. This will lead to execution of the error handling `if` statement at the `out` label, and hence to a call to dmu_objset_disown and zfsvfs_free. However, zfs_umount, which we call upon failure of zfs_root and d_make_root already does dmu_objset_disown and zfsvfs_free. I suppose this patch rather adds to the brittleness of this part of the code base, but I don't want to invest more time in this right now. To add a regression test, we'd need some kind of fault injection facility for zfs_root or d_make_root, which doesn't exist right now. And even then, I think that regression test would be too closely tied to the implementation. To repro the double-disown / double-free, do the following: 1. patch zfs_root to always return an error 2. mount a ZFS filesystem Here's the stack trace you would see then: VERIFY3(ds->ds_owner == tag) failed (0000000000000000 == ffff9142361e8000) PANIC at dsl_dataset.c:1003:dsl_dataset_disown() Showing stack for process 28332 CPU: 2 PID: 28332 Comm: zpool Tainted: G O 5.10.103-1.nutanix.el7.x86_64 #1 Call Trace: dump_stack+0x74/0x92 spl_dumpstack+0x29/0x2b [spl] spl_panic+0xd4/0xfc [spl] dsl_dataset_disown+0xe9/0x150 [zfs] dmu_objset_disown+0xd6/0x150 [zfs] zfs_domount+0x17b/0x4b0 [zfs] zpl_mount+0x174/0x220 [zfs] legacy_get_tree+0x2b/0x50 vfs_get_tree+0x2a/0xc0 path_mount+0x2fa/0xa70 do_mount+0x7c/0xa0 __x64_sys_mount+0x8b/0xe0 do_syscall_64+0x38/0x50 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Reviewed-by: Richard Yao Reviewed-by: Brian Behlendorf Reviewed-by: Ryan Moeller Co-authored-by: Christian Schwarz Signed-off-by: Christian Schwarz Closes #14025 --- module/os/linux/zfs/zfs_vfsops.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index 469b82efeeb7..f3e7fb52cd0b 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -1535,6 +1535,7 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent) error = zfs_root(zfsvfs, &root_inode); if (error) { (void) zfs_umount(sb); + zfsvfs = NULL; /* avoid double-free; first in zfs_umount */ goto out; } @@ -1542,6 +1543,7 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent) sb->s_root = d_make_root(root_inode); if (sb->s_root == NULL) { (void) zfs_umount(sb); + zfsvfs = NULL; /* avoid double-free; first in zfs_umount */ error = SET_ERROR(ENOMEM); goto out; } From 3e767e34bda1aa9e1d97a871a625558489ecaf56 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 17 Oct 2022 20:08:36 +0200 Subject: [PATCH 19/84] Linux compat: fix DECLARE_EVENT_CLASS() test when ZFS is built-in ZFS_LINUX_TRY_COMPILE_HEADER macro doesn't take CONFIG_ZFS=y into account. As a result, on several latest Linux versions, configure script marks DECLARE_EVENT_CLASS() available for non-GPL when ZFS is being built as a module, but marks it unavailable when ZFS is built-in. Follow the logic of the neighbor macros and adjust ZFS_LINUX_TRY_COMPILE_HEADER accordingly, so that it doesn't try to look for a .ko when ZFS is built-in. Reviewed-by: Brian Behlendorf Reviewed-by: Richard Yao Signed-off-by: Alexander Lobakin Closes #14006 --- config/kernel.m4 | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/config/kernel.m4 b/config/kernel.m4 index 4a5e2a8dd01d..a3806221687f 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -932,8 +932,15 @@ dnl # like ZFS_LINUX_TRY_COMPILE, except the contents conftest.h are dnl # provided via the fifth parameter dnl # AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER], [ - ZFS_LINUX_COMPILE_IFELSE( - [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]], [[ZFS_META_LICENSE]])], - [test -f build/conftest/conftest.ko], - [$3], [$4], [$5]) + AS_IF([test "x$enable_linux_builtin" = "xyes"], [ + ZFS_LINUX_COMPILE_IFELSE( + [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]], + [[ZFS_META_LICENSE]])], + [test -f build/conftest/conftest.o], [$3], [$4], [$5]) + ], [ + ZFS_LINUX_COMPILE_IFELSE( + [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]], + [[ZFS_META_LICENSE]])], + [test -f build/conftest/conftest.ko], [$3], [$4], [$5]) + ]) ]) From 7ce097c8747a403f3ddf8c2f6be4ac486b959d8a Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Wed, 26 Oct 2022 14:55:12 -0700 Subject: [PATCH 20/84] Linux 6.0 compat: META Update the META file to reflect compatibility with the 6.0 kernel. Reviewed-by: George Melikov Signed-off-by: Brian Behlendorf Closes #14091 --- META | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/META b/META index 7dd5b311d0c2..b71577f0eca4 100644 --- a/META +++ b/META @@ -6,5 +6,5 @@ Release: 1 Release-Tags: relext License: CDDL Author: OpenZFS -Linux-Maximum: 5.19 +Linux-Maximum: 6.0 Linux-Minimum: 3.10 From 212ba9bd97222613fe17bd8f0cc3e957e7f5d29b Mon Sep 17 00:00:00 2001 From: Coleman Kane Date: Tue, 18 Oct 2022 15:29:44 -0400 Subject: [PATCH 21/84] Linux 6.1 compat: change order of sys/mutex.h includes After Linux 6.1-rc1 came out, the build started failing to build a couple of the files in the linux spl code due to the mutex_init redefinition. Moving the sys/mutex.h include to a lower position within these two files appears to fix the problem. Reviewed-by: Brian Behlendorf Signed-off-by: Coleman Kane Closes #14040 --- module/os/linux/spl/spl-procfs-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/os/linux/spl/spl-procfs-list.c b/module/os/linux/spl/spl-procfs-list.c index 2cba1a3022e0..71b7f75a2a94 100644 --- a/module/os/linux/spl/spl-procfs-list.c +++ b/module/os/linux/spl/spl-procfs-list.c @@ -23,9 +23,9 @@ */ #include -#include #include #include +#include /* * A procfs_list is a wrapper around a linked list which implements the seq_file From 8929355b4cdbb2e1c98fc1d60c9f6f02d132404f Mon Sep 17 00:00:00 2001 From: vaclavskala <33496485+vaclavskala@users.noreply.github.com> Date: Fri, 28 Oct 2022 19:16:31 +0200 Subject: [PATCH 22/84] Propagate extent_bytes change to autotrim thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The autotrim thread only reads zfs_trim_extent_bytes_min and zfs_trim_extent_bytes_max variable only on thread start. We should check for parameter changes during thread execution to allow parameter changes take effect without needing to disable then restart the autotrim. Reviewed-by: Brian Behlendorf Signed-off-by: Václav Skála Closes #14077 --- module/zfs/vdev_trim.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/zfs/vdev_trim.c b/module/zfs/vdev_trim.c index 2bae33b2b532..92daed48f3d5 100644 --- a/module/zfs/vdev_trim.c +++ b/module/zfs/vdev_trim.c @@ -1188,12 +1188,11 @@ vdev_autotrim_thread(void *arg) mutex_exit(&vd->vdev_autotrim_lock); spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER); - uint64_t extent_bytes_max = zfs_trim_extent_bytes_max; - uint64_t extent_bytes_min = zfs_trim_extent_bytes_min; - while (!vdev_autotrim_should_stop(vd)) { int txgs_per_trim = MAX(zfs_trim_txg_batch, 1); boolean_t issued_trim = B_FALSE; + uint64_t extent_bytes_max = zfs_trim_extent_bytes_max; + uint64_t extent_bytes_min = zfs_trim_extent_bytes_min; /* * All of the metaslabs are divided in to groups of size From 1d2b0563f731cf74d8e6cdecad559eb5fa1a3cd7 Mon Sep 17 00:00:00 2001 From: shodanshok Date: Fri, 28 Oct 2022 19:21:54 +0200 Subject: [PATCH 23/84] Fix ARC target collapse when zfs_arc_meta_limit_percent=100 Reclaim metadata when arc_available_memory < 0 even if meta_used is not bigger than arc_meta_limit. As described in https://github.com/openzfs/zfs/issues/14054 if zfs_arc_meta_limit_percent=100 then ARC target can collapse to arc_min due to arc_purge not freeing any metadata. This patch lets arc_prune to do its work when arc_available_memory is negative even if meta_used is not bigger than arc_meta_limit, avoiding ARC target collapse. Reviewed-by: Brian Behlendorf Signed-off-by: Gionatan Danti Closes #14054 Closes #14093 --- module/zfs/arc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/zfs/arc.c b/module/zfs/arc.c index 17193ed079fe..8bf5ce09aabe 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -4460,7 +4460,7 @@ arc_evict_meta_balanced(uint64_t meta_used) * meta buffers. Requests to the upper layers will be made with * increasingly large scan sizes until the ARC is below the limit. */ - if (meta_used > arc_meta_limit) { + if (meta_used > arc_meta_limit || arc_available_memory() < 0) { if (type == ARC_BUFC_DATA) { type = ARC_BUFC_METADATA; } else { From 186e39f3362434263c9fbb36e5ee546096dcb29a Mon Sep 17 00:00:00 2001 From: Mariusz Zaborski Date: Fri, 28 Oct 2022 20:44:18 +0200 Subject: [PATCH 24/84] quota: extend quota for dataset This patch relax the quota limitation for dataset by around 3%. What this means is that user can write more data then the quota is set to. However thanks to that we can get more stable bandwidth, in case when we are overwriting data in-place, and not consuming any additional space. Reviewed-by: Brian Behlendorf Signed-off-by: Allan Jude Signed-off-by: Mariusz Zaborski Sponsored-by: Zededa Inc. Sponsored-by: Klara Inc. Closes #13839 --- module/zfs/dsl_dir.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index aca32ff9bbb9..2565af1329e3 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -1262,6 +1262,7 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, uint64_t quota; struct tempreserve *tr; int retval; + uint64_t ext_quota; uint64_t ref_rsrv; top_of_function: @@ -1337,7 +1338,16 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, * on-disk is over quota and there are no pending changes * or deferred frees (which may free up space for us). */ - if (used_on_disk + est_inflight >= quota) { + ext_quota = quota >> 5; + if (quota == UINT64_MAX) + ext_quota = 0; + + if (used_on_disk >= quota) { + /* Quota exceeded */ + mutex_exit(&dd->dd_lock); + DMU_TX_STAT_BUMP(dmu_tx_quota); + return (retval); + } else if (used_on_disk + est_inflight >= quota + ext_quota) { if (est_inflight > 0 || used_on_disk < quota) { retval = SET_ERROR(ERESTART); } else { From b27c7a1457e202435914403ddf6708cb6b53bfa0 Mon Sep 17 00:00:00 2001 From: Ryan Moeller Date: Tue, 1 Nov 2022 15:19:32 -0400 Subject: [PATCH 25/84] zil: Relax assertion in zil_parse Rather than panic debug builds when we fail to parse a whole ZIL, let's instead improve the logging of errors and continue like in a release build. Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Ryan Moeller Closes #14116 --- module/zfs/zil.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/module/zfs/zil.c b/module/zfs/zil.c index b9f177daee53..11e05e477839 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -397,8 +397,18 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func, error = zil_read_log_block(zilog, decrypt, &blk, &next_blk, lrbuf, &end); - if (error != 0) + if (error != 0) { + if (claimed) { + char name[ZFS_MAX_DATASET_NAME_LEN]; + + dmu_objset_name(zilog->zl_os, name); + + cmn_err(CE_WARN, "ZFS read log block error %d, " + "dataset %s, seq 0x%llx\n", error, name, + (u_longlong_t)blk_seq); + } break; + } for (lrp = lrbuf; lrp < end; lrp += reclen) { lr_t *lr = (lr_t *)lrp; @@ -422,10 +432,6 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func, zilog->zl_parse_blk_count = blk_count; zilog->zl_parse_lr_count = lr_count; - ASSERT(!claimed || !(zh->zh_flags & ZIL_CLAIM_LR_SEQ_VALID) || - (max_blk_seq == claim_blk_seq && max_lr_seq == claim_lr_seq) || - (decrypt && error == EIO)); - zil_bp_tree_fini(zilog); zio_buf_free(lrbuf, SPA_OLD_MAXBLOCKSIZE); From cd1f0238463ae5777a58022c422c489606221dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20F=C3=BCl=C3=B6p?= Date: Fri, 4 Nov 2022 19:07:29 +0100 Subject: [PATCH 26/84] Deny receiving into encrypted datasets if the keys are not loaded (#14139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 68ddc06b611854560fefa377437eb3c9480e084b introduced support for receiving unencrypted datasets as children of encrypted ones but unfortunately got the logic upside down. This resulted in failing to deny receives of incremental sends into encrypted datasets without their keys loaded. If receiving a filesystem, the receive was done into a newly created unencrypted child dataset of the target. In case of volumes the receive made the target volume undeletable since a dataset was created below it, which we obviously can't handle. Incremental streams with embedded blocks are affected as well. We fix the broken logic to properly deny receives in such cases. Reviewed-by: Brian Behlendorf Signed-off-by: Attila Fülöp Closes #13598 Closes #14055 Closes #14119 --- module/zfs/dmu_recv.c | 2 +- .../zfs_receive/zfs_receive_to_encrypted.ksh | 31 +++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/module/zfs/dmu_recv.c b/module/zfs/dmu_recv.c index 99eeceeb4139..98ca2b3bcec1 100644 --- a/module/zfs/dmu_recv.c +++ b/module/zfs/dmu_recv.c @@ -602,7 +602,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) * so add the DS_HOLD_FLAG_DECRYPT flag only if we are dealing * with a dataset we may encrypt. */ - if (drba->drba_dcp != NULL && + if (drba->drba_dcp == NULL || drba->drba_dcp->cp_crypt != ZIO_CRYPT_OFF) { dsflags |= DS_HOLD_FLAG_DECRYPT; } diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh index 5d76c220fc45..8bd9a6854950 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_to_encrypted.ksh @@ -25,13 +25,16 @@ # ZFS should receive to an encrypted child dataset. # # STRATEGY: -# 1. Snapshot the default dataset -# 2. Create an encrypted dataset -# 3. Attempt to receive a stream to an encrypted child -# 4. Attempt to receive a stream with properties to an encrypted child -# 5. Attempt to receive a replication stream to an encrypted child -# 6. Unmount and unload the encrypted dataset keys -# 7. Attempt to receive a snapshot stream to an encrypted child +# 1. Snapshot the default dataset +# 2. Create an encrypted dataset +# 3. Attempt to receive a stream to an encrypted child +# 4. Unload the key +# 5. Attempt to receive an incremental stream to an encrypted child (must fail) +# 6. Attempt to receive a stream with properties to an unencrypted child +# 7. Attempt to receive an incremental stream to an unencrypted child +# 8. Attempt to receive with -o encryption=off to an unencrypted child +# 9. Attempt to receive a replication stream to an unencrypted child +# 10. Attempt to receive a snapshot stream to an encrypted child (must fail) # verify_runnable "both" @@ -39,6 +42,7 @@ verify_runnable "both" function cleanup { snapexists $snap && destroy_dataset $snap -f + snapexists $snap2 && destroy_dataset $snap2 -f datasetexists $TESTPOOL/$TESTFS1 && \ destroy_dataset $TESTPOOL/$TESTFS1 -r @@ -50,15 +54,17 @@ log_assert "ZFS should receive encrypted filesystems into child dataset" typeset passphrase="password" typeset snap="$TESTPOOL/$TESTFS@snap" +typeset snap2="$TESTPOOL/$TESTFS@snap2" typeset testfile="testfile" log_must zfs snapshot $snap +log_must zfs snapshot $snap2 log_must eval "echo $passphrase | zfs create -o encryption=on" \ "-o keyformat=passphrase $TESTPOOL/$TESTFS1" log_note "Verifying ZFS will receive to an encrypted child" -log_must eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c1" +log_must eval "zfs send $snap | zfs receive -u $TESTPOOL/$TESTFS1/c1" log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c1)" != "off" # Unload the key, the following tests won't require it and we will test @@ -66,10 +72,17 @@ log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c1)" != "off" log_must zfs unmount $TESTPOOL/$TESTFS1 log_must zfs unload-key $TESTPOOL/$TESTFS1 +log_note "Verifying ZFS will not receive an incremental into an encrypted" \ + "dataset when the key is unloaded" +log_mustnot eval "zfs send -i $snap $snap2 | zfs receive $TESTPOOL/$TESTFS1/c1" + log_note "Verifying 'send -p' will receive to an unencrypted child" -log_must eval "zfs send -p $snap | zfs receive $TESTPOOL/$TESTFS1/c2" +log_must eval "zfs send -p $snap | zfs receive -u $TESTPOOL/$TESTFS1/c2" log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c2)" == "off" +log_note "Verifying 'send -i' will receive to an unencrypted child" +log_must eval "zfs send -i $snap $snap2 | zfs receive $TESTPOOL/$TESTFS1/c2" + # For completeness add the property override case. log_note "Verifying recv -o encyption=off' will receive to an unencrypted child" log_must eval "zfs send $snap | \ From ca3a675c746e3ba4da381ee4c3b218028c6dd112 Mon Sep 17 00:00:00 2001 From: Ameer Hamza <106930537+ixhamza@users.noreply.github.com> Date: Fri, 4 Nov 2022 23:33:47 +0500 Subject: [PATCH 27/84] zed: Prevent special vdev to be replaced by hot spare Special vdevs should not be replaced by a hot spare. Log vdevs already support this, extending the functionality for special vdevs. Reviewed-by: Ryan Moeller Reviewed-by: Tony Hutter Reviewed-by: Richard Yao Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Ameer Hamza Closes #14129 --- module/zfs/spa.c | 6 ++++-- .../tests/functional/fault/auto_offline_001_pos.ksh | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/module/zfs/spa.c b/module/zfs/spa.c index aa65fb658113..86447d1fdcba 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -6772,10 +6772,12 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing, return (spa_vdev_exit(spa, newrootvd, txg, error)); /* - * Spares can't replace logs + * log, dedup and special vdevs should not be replaced by spares. */ - if (oldvd->vdev_top->vdev_islog && newvd->vdev_isspare) + if ((oldvd->vdev_top->vdev_alloc_bias != VDEV_BIAS_NONE || + oldvd->vdev_top->vdev_islog) && newvd->vdev_isspare) { return (spa_vdev_exit(spa, newrootvd, txg, ENOTSUP)); + } /* * A dRAID spare can only replace a child of its parent dRAID vdev. diff --git a/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh index 86916bf906fe..d7189f298384 100755 --- a/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh +++ b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh @@ -123,6 +123,11 @@ done # the removed data device for conf in "${poolconfs[@]}" do + # special vdev can not be replaced by a hot spare + if [[ $conf = *"special mirror"* ]]; then + continue + fi + # 1. Create a pool with a spare log_must zpool create -f $TESTPOOL $conf block_device_wait ${DEV_DSKDIR}/${removedev} From 8c0684d326b5eaf37842a9fc6c98edbb8e1fdd5f Mon Sep 17 00:00:00 2001 From: Ameer Hamza <106930537+ixhamza@users.noreply.github.com> Date: Fri, 21 Oct 2022 22:46:38 +0500 Subject: [PATCH 28/84] zed: Avoid core dump if wholedisk property does not exist zed aborts and dumps core in vdev_whole_disk_from_config() if wholedisk property does not exist. make_leaf_vdev() adds the property but there may be already pools that don't have the wholedisk in the label. Reviewed-by: Ryan Moeller Reviewed-by: Alexander Motin Reviewed-by: Richard Yao Signed-off-by: Ameer Hamza Closes #14062 --- cmd/zed/agents/zfs_mod.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cmd/zed/agents/zfs_mod.c b/cmd/zed/agents/zfs_mod.c index a4e23ca1a3b0..8575d98316f9 100644 --- a/cmd/zed/agents/zfs_mod.c +++ b/cmd/zed/agents/zfs_mod.c @@ -938,14 +938,13 @@ vdev_whole_disk_from_config(zpool_handle_t *zhp, const char *vdev_path) { nvlist_t *nvl = NULL; boolean_t avail_spare, l2cache, log; - uint64_t wholedisk; + uint64_t wholedisk = 0; nvl = zpool_find_vdev(zhp, vdev_path, &avail_spare, &l2cache, &log); if (!nvl) return (0); - verify(nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_WHOLE_DISK, - &wholedisk) == 0); + (void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk); return (wholedisk); } @@ -984,7 +983,7 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data) if ((tgt = zpool_find_vdev_by_physpath(zhp, devname, &avail_spare, &l2cache, NULL)) != NULL) { char *path, fullpath[MAXPATHLEN]; - uint64_t wholedisk; + uint64_t wholedisk = 0; error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path); if (error) { @@ -992,10 +991,8 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data) return (0); } - error = nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK, + (void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk); - if (error) - wholedisk = 0; if (wholedisk) { path = strrchr(path, '/'); From 0f4ee295ba94803e5833f57481cfdbee5d1160d4 Mon Sep 17 00:00:00 2001 From: Damian Szuberski Date: Wed, 9 Nov 2022 04:16:01 +1000 Subject: [PATCH 29/84] dsl_prop_known_index(): check for invalid prop Resolve UBSAN array-index-out-of-bounds error in zprop_desc_t. Reviewed-by: Brian Behlendorf Signed-off-by: szubersk Closes #14142 Closes #14147 --- module/zcommon/zfs_prop.c | 26 ++++++++++++++++++++++++++ module/zfs/dsl_prop.c | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index a33eb36ac192..b4e8fcf1f30b 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -722,6 +722,8 @@ zfs_prop_init(void) boolean_t zfs_prop_delegatable(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); zprop_desc_t *pd = &zfs_prop_table[prop]; /* The mlslabel property is never delegatable. */ @@ -844,6 +846,8 @@ zfs_prop_valid_for_type(int prop, zfs_type_t types, boolean_t headcheck) zprop_type_t zfs_prop_get_type(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_proptype); } @@ -853,6 +857,8 @@ zfs_prop_get_type(zfs_prop_t prop) boolean_t zfs_prop_readonly(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_attr == PROP_READONLY || zfs_prop_table[prop].pd_attr == PROP_ONETIME || zfs_prop_table[prop].pd_attr == PROP_ONETIME_DEFAULT); @@ -864,6 +870,8 @@ zfs_prop_readonly(zfs_prop_t prop) boolean_t zfs_prop_visible(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_visible && zfs_prop_table[prop].pd_zfs_mod_supported); } @@ -874,6 +882,8 @@ zfs_prop_visible(zfs_prop_t prop) boolean_t zfs_prop_setonce(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_attr == PROP_ONETIME || zfs_prop_table[prop].pd_attr == PROP_ONETIME_DEFAULT); } @@ -881,12 +891,16 @@ zfs_prop_setonce(zfs_prop_t prop) const char * zfs_prop_default_string(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_strdefault); } uint64_t zfs_prop_default_numeric(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_numdefault); } @@ -897,6 +911,8 @@ zfs_prop_default_numeric(zfs_prop_t prop) const char * zfs_prop_to_name(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_name); } @@ -906,6 +922,8 @@ zfs_prop_to_name(zfs_prop_t prop) boolean_t zfs_prop_inheritable(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_attr == PROP_INHERIT || zfs_prop_table[prop].pd_attr == PROP_ONETIME); } @@ -958,6 +976,8 @@ zfs_prop_valid_keylocation(const char *str, boolean_t encrypted) const char * zfs_prop_values(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_values); } @@ -969,6 +989,8 @@ zfs_prop_values(zfs_prop_t prop) int zfs_prop_is_string(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_proptype == PROP_TYPE_STRING || zfs_prop_table[prop].pd_proptype == PROP_TYPE_INDEX); } @@ -980,6 +1002,8 @@ zfs_prop_is_string(zfs_prop_t prop) const char * zfs_prop_column_name(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_colname); } @@ -990,6 +1014,8 @@ zfs_prop_column_name(zfs_prop_t prop) boolean_t zfs_prop_align_right(zfs_prop_t prop) { + ASSERT3S(prop, >=, 0); + ASSERT3S(prop, <, ZFS_NUM_PROPS); return (zfs_prop_table[prop].pd_rightalign); } diff --git a/module/zfs/dsl_prop.c b/module/zfs/dsl_prop.c index d1c3ff543661..6cba8bd206a5 100644 --- a/module/zfs/dsl_prop.c +++ b/module/zfs/dsl_prop.c @@ -75,7 +75,8 @@ static int dsl_prop_known_index(zfs_prop_t prop, uint64_t value) { const char *str = NULL; - if (zfs_prop_get_type(prop) == PROP_TYPE_INDEX) + if (prop != ZPROP_CONT && prop != ZPROP_INVAL && + zfs_prop_get_type(prop) == PROP_TYPE_INDEX) return (!zfs_prop_index_to_string(prop, value, &str)); return (-1); From 1d9aa838ed5a11a49676678e03e6f0d50ec05d78 Mon Sep 17 00:00:00 2001 From: Ryan Moeller Date: Wed, 9 Nov 2022 21:24:06 +0000 Subject: [PATCH 30/84] libzfs recv: Check if user prop before inheritable User props trigger an assert in zfs_prop_inheritable(), we must check if the prop is a user prop first. Signed-off-by: Ryan Moeller Backported as snippit from: 63652e1 Add --enable-asan and --enable-ubsan switches --- lib/libzfs/libzfs_sendrecv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 899cc84cf912..0dbd98b2bedd 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -4013,8 +4013,8 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type, * properties: if we're asked to exclude this kind of * values we remove them from "recvprops" input nvlist. */ - if (!zfs_prop_inheritable(prop) && - !zfs_prop_user(name) && /* can be inherited too */ + if (!zfs_prop_user(name) && /* can be inherited too */ + !zfs_prop_inheritable(prop) && nvlist_exists(recvprops, name)) fnvlist_remove(recvprops, name); else From ee93cbc9d477d8ce0a6ebffe9a582dbe83144577 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Sun, 16 Oct 2022 16:53:22 +0200 Subject: [PATCH 31/84] icp: properly fix all RETs in x86_64 Asm code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 43569ee37420 ("Fix objtool: missing int3 after ret warning") addressed replacing all `ret`s in x86 asm code to a macro in the Linux kernel in order to enable SLS. That was done by copying the upstream macro definitions and fixed objtool complaints. Since then, several more mitigations were introduced, including Rethunk. It requires to have a jump to one of the thunks in order to work, so the RET macro was changed again. And, as ZFS code didn't use the mainline defition, but copied it, this is currently missing. Objtool reminds about it time to time (Clang 16, CONFIG_RETHUNK=y): fs/zfs/lua/zlua.o: warning: objtool: setjmp+0x25: 'naked' return found in RETHUNK build fs/zfs/lua/zlua.o: warning: objtool: longjmp+0x27: 'naked' return found in RETHUNK build Do it the following way: * if we're building under Linux, unconditionally include in the related files. It is available in x86 sources since even pre-2.6 times, so doesn't need any conftests; * then, if RET macro is available, it will be used directly, so that we will always have the version actual to the kernel we build; * if there's no such macro, we define it as a simple `ret`, as it was on pre-SLS times. This ensures we always have the up-to-date definition with no need to update it manually, and at the same time is safe for the whole variety of kernels ZFS module supports. Then, there's a couple more "naked" rets left in the code, they're just defined as: .byte 0xf3,0xc3 In fact, this is just: rep ret `rep ret` instead of just `ret` seems to mitigate performance issues on some old AMD processors and most likely makes no sense as of today. Anyways, address those rets, so that they will be protected with Rethunk and SLS. Include here which now always has RET definition and replace those constructs with just RET. This wipes the last couple of places with unpatched rets objtool's been complaining about. Reviewed-by: Attila Fülöp Reviewed-by: Tino Reichardt Reviewed-by: Richard Yao Reviewed-by: Brian Behlendorf Signed-off-by: Alexander Lobakin Closes #14035 --- module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S | 13 ++++++++----- module/icp/asm-x86_64/modes/ghash-x86_64.S | 9 ++++++--- module/icp/include/sys/ia32/asm_linkage.h | 9 ++++++--- module/lua/setjmp/setjmp_x86_64.S | 15 ++++++++------- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S index 70e419c2e4ab..7414b3540f34 100644 --- a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S +++ b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S @@ -47,6 +47,9 @@ #if defined(__x86_64__) && defined(HAVE_AVX) && \ defined(HAVE_AES) && defined(HAVE_PCLMULQDQ) +#define _ASM +#include + .extern gcm_avx_can_use_movbe .text @@ -363,7 +366,7 @@ _aesni_ctr32_ghash_6x: vpxor 16+8(%rsp),%xmm8,%xmm8 vpxor %xmm4,%xmm8,%xmm8 - .byte 0xf3,0xc3 + RET .cfi_endproc .size _aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x #endif /* ifdef HAVE_MOVBE */ @@ -691,7 +694,7 @@ _aesni_ctr32_ghash_no_movbe_6x: vpxor 16+8(%rsp),%xmm8,%xmm8 vpxor %xmm4,%xmm8,%xmm8 - .byte 0xf3,0xc3 + RET .cfi_endproc .size _aesni_ctr32_ghash_no_movbe_6x,.-_aesni_ctr32_ghash_no_movbe_6x @@ -810,7 +813,7 @@ aesni_gcm_decrypt: .cfi_def_cfa_register %rsp .Lgcm_dec_abort: movq %r10,%rax - .byte 0xf3,0xc3 + RET .cfi_endproc .size aesni_gcm_decrypt,.-aesni_gcm_decrypt .type _aesni_ctr32_6x,@function @@ -880,7 +883,7 @@ _aesni_ctr32_6x: vmovups %xmm14,80(%rsi) leaq 96(%rsi),%rsi - .byte 0xf3,0xc3 + RET .align 32 .Lhandle_ctr32_2: vpshufb %xmm0,%xmm1,%xmm6 @@ -1186,7 +1189,7 @@ aesni_gcm_encrypt: .cfi_def_cfa_register %rsp .Lgcm_enc_abort: movq %r10,%rax - .byte 0xf3,0xc3 + RET .cfi_endproc .size aesni_gcm_encrypt,.-aesni_gcm_encrypt diff --git a/module/icp/asm-x86_64/modes/ghash-x86_64.S b/module/icp/asm-x86_64/modes/ghash-x86_64.S index 90cc36b43a78..77a3ce185952 100644 --- a/module/icp/asm-x86_64/modes/ghash-x86_64.S +++ b/module/icp/asm-x86_64/modes/ghash-x86_64.S @@ -97,6 +97,9 @@ #if defined(__x86_64__) && defined(HAVE_AVX) && \ defined(HAVE_AES) && defined(HAVE_PCLMULQDQ) +#define _ASM +#include + .text .globl gcm_gmult_clmul @@ -149,7 +152,7 @@ gcm_gmult_clmul: pxor %xmm1,%xmm0 .byte 102,15,56,0,197 movdqu %xmm0,(%rdi) - .byte 0xf3,0xc3 + RET .cfi_endproc .size gcm_gmult_clmul,.-gcm_gmult_clmul @@ -262,7 +265,7 @@ gcm_init_htab_avx: vmovdqu %xmm5,-16(%rdi) vzeroupper - .byte 0xf3,0xc3 + RET .cfi_endproc .size gcm_init_htab_avx,.-gcm_init_htab_avx @@ -649,7 +652,7 @@ gcm_ghash_avx: vpshufb %xmm13,%xmm10,%xmm10 vmovdqu %xmm10,(%rdi) vzeroupper - .byte 0xf3,0xc3 + RET .cfi_endproc .size gcm_ghash_avx,.-gcm_ghash_avx .align 64 diff --git a/module/icp/include/sys/ia32/asm_linkage.h b/module/icp/include/sys/ia32/asm_linkage.h index 876e21e5f1b1..0717db4ab118 100644 --- a/module/icp/include/sys/ia32/asm_linkage.h +++ b/module/icp/include/sys/ia32/asm_linkage.h @@ -30,9 +30,11 @@ #include #include -#if defined(__linux__) && defined(CONFIG_SLS) -#define RET ret; int3 -#else +#if defined(_KERNEL) && defined(__linux__) +#include +#endif + +#ifndef RET #define RET ret #endif @@ -204,6 +206,7 @@ sym1 = sym2 * insert the calls to mcount for profiling. ENTRY_NP is identical, but * never calls mcount. */ +#undef ENTRY #define ENTRY(x) \ .text; \ .align ASM_ENTRY_ALIGN; \ diff --git a/module/lua/setjmp/setjmp_x86_64.S b/module/lua/setjmp/setjmp_x86_64.S index 34cf2c7dce93..47c886709c2a 100644 --- a/module/lua/setjmp/setjmp_x86_64.S +++ b/module/lua/setjmp/setjmp_x86_64.S @@ -23,7 +23,15 @@ * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ +#if defined(_KERNEL) && defined(__linux__) +#include +#endif + +#ifndef RET +#define RET ret +#endif +#undef ENTRY #define ENTRY(x) \ .text; \ .align 8; \ @@ -34,13 +42,6 @@ x: #define SET_SIZE(x) \ .size x, [.-x] - -#if defined(__linux__) && defined(CONFIG_SLS) -#define RET ret; int3 -#else -#define RET ret -#endif - /* * Setjmp and longjmp implement non-local gotos using state vectors * type label_t. From 33bc03dea7bc976307ad158bf4240c947700b3c2 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Sun, 16 Oct 2022 23:23:44 +0200 Subject: [PATCH 32/84] icp: fix rodata being marked as text in x86 Asm code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit objtool properly complains that it can't decode some of the instructions from ICP x86 Asm code. As mentioned in the Makefile, where those object files were excluded from objtool check (but they can still be visible under IBT and LTO), those are just constants, not code. In that case, they must be placed in .rodata, so they won't be marked as "allocatable, executable" (ax) in EFL headers and this effectively prevents objtool from trying to decode this data. That reveals a whole bunch of other issues in ICP Asm code, as previously objtool was bailing out after that warning message. Reviewed-by: Attila Fülöp Reviewed-by: Tino Reichardt Reviewed-by: Richard Yao Reviewed-by: Brian Behlendorf Signed-off-by: Alexander Lobakin Closes #14035 Conflicts: module/Kbuild.in --- module/icp/Makefile.in | 7 ++----- module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S | 2 ++ module/icp/asm-x86_64/modes/ghash-x86_64.S | 3 +++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/module/icp/Makefile.in b/module/icp/Makefile.in index 54b5df1a1987..ce84999ad1cf 100644 --- a/module/icp/Makefile.in +++ b/module/icp/Makefile.in @@ -60,12 +60,9 @@ $(MODULE)-$(CONFIG_X86) += algs/modes/gcm_pclmulqdq.o $(MODULE)-$(CONFIG_X86) += algs/aes/aes_impl_aesni.o $(MODULE)-$(CONFIG_X86) += algs/aes/aes_impl_x86-64.o -# Suppress objtool "can't find jump dest instruction at" warnings. They -# are caused by the constants which are defined in the text section of the -# assembly file using .byte instructions (e.g. bswap_mask). The objtool -# utility tries to interpret them as opcodes and obviously fails doing so. +# Suppress objtool "return with modified stack frame" warnings. OBJECT_FILES_NON_STANDARD_aesni-gcm-x86_64.o := y -OBJECT_FILES_NON_STANDARD_ghash-x86_64.o := y + # Suppress objtool "unsupported stack pointer realignment" warnings. We are # not using a DRAP register while aligning the stack to a 64 byte boundary. # See #6950 for the reasoning. diff --git a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S index 7414b3540f34..6da43ee00597 100644 --- a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S +++ b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S @@ -1242,6 +1242,7 @@ atomic_toggle_boolean_nv: RET .size atomic_toggle_boolean_nv,.-atomic_toggle_boolean_nv +.pushsection .rodata .align 64 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 @@ -1255,6 +1256,7 @@ atomic_toggle_boolean_nv: .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byte 65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 +.popsection /* Mark the stack non-executable. */ #if defined(__linux__) && defined(__ELF__) diff --git a/module/icp/asm-x86_64/modes/ghash-x86_64.S b/module/icp/asm-x86_64/modes/ghash-x86_64.S index 77a3ce185952..d7cdaeb368d7 100644 --- a/module/icp/asm-x86_64/modes/ghash-x86_64.S +++ b/module/icp/asm-x86_64/modes/ghash-x86_64.S @@ -655,6 +655,8 @@ gcm_ghash_avx: RET .cfi_endproc .size gcm_ghash_avx,.-gcm_ghash_avx + +.pushsection .rodata .align 64 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 @@ -708,6 +710,7 @@ gcm_ghash_avx: .byte 71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 +.popsection /* Mark the stack non-executable. */ #if defined(__linux__) && defined(__ELF__) From ab22031d79691a25d5be20244ad72e34c05d9973 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Sun, 16 Oct 2022 23:41:39 +0200 Subject: [PATCH 33/84] icp: fix all !ENDBR objtool warnings in x86 Asm code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, only Blake3 x86 Asm code has signs of being ENDBR-aware. At least, under certain conditions it includes some header file and uses some custom macro from there. Linux has its own NOENDBR since several releases ago. It's defined in the same , so currently already is provided with it. Let's unify those two into one %ENDBR macro. At first, check if it's present already. If so -- use Linux kernel version. Otherwise, try to go that second way and use %_CET_ENDBR from if available. If no, fall back to just empty definition. This fixes a couple more 'relocations to !ENDBR' across the module. And now that we always have the latest/actual ENDBR definition, use it at the entrance of the few corresponding functions that objtool still complains about. This matches the way how it's used in the upstream x86 core Asm code. Reviewed-by: Attila Fülöp Reviewed-by: Tino Reichardt Reviewed-by: Richard Yao Reviewed-by: Brian Behlendorf Signed-off-by: Alexander Lobakin Closes #14035 --- module/icp/asm-x86_64/aes/aes_amd64.S | 2 ++ module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S | 5 +++++ module/icp/asm-x86_64/modes/ghash-x86_64.S | 4 ++++ module/icp/asm-x86_64/sha2/sha256_impl.S | 1 + module/icp/asm-x86_64/sha2/sha512_impl.S | 1 + module/icp/include/sys/ia32/asm_linkage.h | 18 ++++++++++++++++++ 6 files changed, 31 insertions(+) diff --git a/module/icp/asm-x86_64/aes/aes_amd64.S b/module/icp/asm-x86_64/aes/aes_amd64.S index 931d2480609c..e631752af65e 100644 --- a/module/icp/asm-x86_64/aes/aes_amd64.S +++ b/module/icp/asm-x86_64/aes/aes_amd64.S @@ -704,6 +704,7 @@ enc_tab: ENTRY_NP(aes_encrypt_amd64) + ENDBR #ifdef GLADMAN_INTERFACE // Original interface sub $[4*8], %rsp // gnu/linux/opensolaris binary interface @@ -809,6 +810,7 @@ dec_tab: ENTRY_NP(aes_decrypt_amd64) + ENDBR #ifdef GLADMAN_INTERFACE // Original interface sub $[4*8], %rsp // gnu/linux/opensolaris binary interface diff --git a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S index 6da43ee00597..cf17b3768712 100644 --- a/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S +++ b/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S @@ -59,6 +59,7 @@ .align 32 _aesni_ctr32_ghash_6x: .cfi_startproc + ENDBR vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -375,6 +376,7 @@ _aesni_ctr32_ghash_6x: .align 32 _aesni_ctr32_ghash_no_movbe_6x: .cfi_startproc + ENDBR vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -703,6 +705,7 @@ _aesni_ctr32_ghash_no_movbe_6x: .align 32 aesni_gcm_decrypt: .cfi_startproc + ENDBR xorq %r10,%r10 cmpq $0x60,%rdx jb .Lgcm_dec_abort @@ -820,6 +823,7 @@ aesni_gcm_decrypt: .align 32 _aesni_ctr32_6x: .cfi_startproc + ENDBR vmovdqu 0-128(%rcx),%xmm4 vmovdqu 32(%r11),%xmm2 leaq -2(%rbp),%r13 // ICP uses 10,12,14 not 9,11,13 for rounds. @@ -914,6 +918,7 @@ _aesni_ctr32_6x: .align 32 aesni_gcm_encrypt: .cfi_startproc + ENDBR xorq %r10,%r10 cmpq $288,%rdx jb .Lgcm_enc_abort diff --git a/module/icp/asm-x86_64/modes/ghash-x86_64.S b/module/icp/asm-x86_64/modes/ghash-x86_64.S index d7cdaeb368d7..bf3724a23eae 100644 --- a/module/icp/asm-x86_64/modes/ghash-x86_64.S +++ b/module/icp/asm-x86_64/modes/ghash-x86_64.S @@ -107,6 +107,7 @@ .align 16 gcm_gmult_clmul: .cfi_startproc + ENDBR .L_gmult_clmul: movdqu (%rdi),%xmm0 movdqa .Lbswap_mask(%rip),%xmm5 @@ -161,6 +162,7 @@ gcm_gmult_clmul: .align 32 gcm_init_htab_avx: .cfi_startproc + ENDBR vzeroupper vmovdqu (%rsi),%xmm2 @@ -274,6 +276,7 @@ gcm_init_htab_avx: .align 32 gcm_gmult_avx: .cfi_startproc + ENDBR jmp .L_gmult_clmul .cfi_endproc .size gcm_gmult_avx,.-gcm_gmult_avx @@ -282,6 +285,7 @@ gcm_gmult_avx: .align 32 gcm_ghash_avx: .cfi_startproc + ENDBR vzeroupper vmovdqu (%rdi),%xmm10 diff --git a/module/icp/asm-x86_64/sha2/sha256_impl.S b/module/icp/asm-x86_64/sha2/sha256_impl.S index 31da7f9767df..fc0c68ba2c12 100644 --- a/module/icp/asm-x86_64/sha2/sha256_impl.S +++ b/module/icp/asm-x86_64/sha2/sha256_impl.S @@ -84,6 +84,7 @@ SHA256TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num) ENTRY_NP(SHA256TransformBlocks) .cfi_startproc + ENDBR movq %rsp, %rax .cfi_def_cfa_register %rax push %rbx diff --git a/module/icp/asm-x86_64/sha2/sha512_impl.S b/module/icp/asm-x86_64/sha2/sha512_impl.S index c2ba18538e33..ab9474a4e2bb 100644 --- a/module/icp/asm-x86_64/sha2/sha512_impl.S +++ b/module/icp/asm-x86_64/sha2/sha512_impl.S @@ -85,6 +85,7 @@ SHA512TransformBlocks(SHA2_CTX *ctx, const void *in, size_t num) ENTRY_NP(SHA512TransformBlocks) .cfi_startproc + ENDBR movq %rsp, %rax .cfi_def_cfa_register %rax push %rbx diff --git a/module/icp/include/sys/ia32/asm_linkage.h b/module/icp/include/sys/ia32/asm_linkage.h index 0717db4ab118..beb3592f3d73 100644 --- a/module/icp/include/sys/ia32/asm_linkage.h +++ b/module/icp/include/sys/ia32/asm_linkage.h @@ -34,6 +34,24 @@ #include #endif +#ifndef ENDBR +#if defined(__ELF__) && defined(__CET__) && defined(__has_include) +/* CSTYLED */ +#if __has_include() + +#include + +#ifdef _CET_ENDBR +#define ENDBR _CET_ENDBR +#endif /* _CET_ENDBR */ + +#endif /* */ +#endif /* __ELF__ && __CET__ && __has_include */ +#endif /* !ENDBR */ + +#ifndef ENDBR +#define ENDBR +#endif #ifndef RET #define RET ret #endif From 792825724b69a32b55199acc4c6a2980b656c232 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Mon, 12 Sep 2022 15:54:43 -0400 Subject: [PATCH 34/84] zpool_load_compat() should create strings of length ZFS_MAXPROPLEN Otherwise, `strlcat()` can overflow them. Coverity found this. Reviewed-by: Brian Behlendorf Reviewed-by: Neal Gompa Signed-off-by: Richard Yao Closes #13866 --- lib/libzfs/libzfs_pool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index c6884538df1d..e2912cdb91af 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -4788,8 +4788,8 @@ zpool_load_compat(const char *compat, boolean_t *features, char *report, for (uint_t i = 0; i < SPA_FEATURES; i++) features[i] = B_TRUE; - char err_badfile[1024] = ""; - char err_badtoken[1024] = ""; + char err_badfile[ZFS_MAXPROPLEN] = ""; + char err_badtoken[ZFS_MAXPROPLEN] = ""; /* * We ignore errors from the directory open() From b247d47be1834b3dcd006128d52592acbcb0f010 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 13 Sep 2022 19:59:33 -0400 Subject: [PATCH 35/84] Cleanup: Make memory barrier definitions consistent across kernels We inherited membar_consumer() and membar_producer() from OpenSolaris, but we had replaced membar_consumer() with Linux's smp_rmb() in zfs_ioctl.c. The FreeBSD SPL consequently implemented a shim for the Linux-only smp_rmb(). We reinstate membar_consumer() in platform independent code and fix the FreeBSD SPL to implement membar_consumer() in a way analogous to Linux. Reviewed-by: Konstantin Belousov Reviewed-by: Mateusz Guzik Reviewed-by: Brian Behlendorf Reviewed-by: Neal Gompa Reviewed-by: Alexander Motin Signed-off-by: Richard Yao Closes #13843 --- include/os/freebsd/linux/compiler.h | 1 - include/os/freebsd/spl/sys/atomic.h | 3 ++- include/os/linux/spl/sys/vmsystm.h | 2 ++ module/zfs/zfs_ioctl.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/os/freebsd/linux/compiler.h b/include/os/freebsd/linux/compiler.h index 20903717b58d..79f9b2d8a96a 100644 --- a/include/os/freebsd/linux/compiler.h +++ b/include/os/freebsd/linux/compiler.h @@ -83,7 +83,6 @@ #define __printf(a, b) __printflike(a, b) #define barrier() __asm__ __volatile__("": : :"memory") -#define smp_rmb() rmb() #define ___PASTE(a, b) a##b #define __PASTE(a, b) ___PASTE(a, b) diff --git a/include/os/freebsd/spl/sys/atomic.h b/include/os/freebsd/spl/sys/atomic.h index 1a68bfc4de23..01b13fc9afd7 100644 --- a/include/os/freebsd/spl/sys/atomic.h +++ b/include/os/freebsd/spl/sys/atomic.h @@ -57,7 +57,8 @@ extern uint64_t atomic_cas_64(volatile uint64_t *target, uint64_t cmp, uint64_t newval); #endif -#define membar_producer atomic_thread_fence_rel +#define membar_consumer() atomic_thread_fence_acq() +#define membar_producer() atomic_thread_fence_rel() static __inline uint32_t atomic_add_32_nv(volatile uint32_t *target, int32_t delta) diff --git a/include/os/linux/spl/sys/vmsystm.h b/include/os/linux/spl/sys/vmsystm.h index b3f121ecf0ca..fcd61e818fa3 100644 --- a/include/os/linux/spl/sys/vmsystm.h +++ b/include/os/linux/spl/sys/vmsystm.h @@ -44,7 +44,9 @@ #define zfs_totalhigh_pages totalhigh_pages #endif +#define membar_consumer() smp_rmb() #define membar_producer() smp_wmb() + #define physmem zfs_totalram_pages #define xcopyin(from, to, size) copy_from_user(to, from, size) diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 3d2492b9b908..4601ef52788a 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -7398,7 +7398,7 @@ zfsdev_get_state_impl(minor_t minor, enum zfsdev_state_type which) for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) { if (zs->zs_minor == minor) { - smp_rmb(); + membar_consumer(); switch (which) { case ZST_ONEXIT: return (zs->zs_onexit); From 3f380df778c67bf6919df088ed9635323a6b6ffb Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 13 Sep 2022 20:00:53 -0400 Subject: [PATCH 36/84] Remove incorrect free() in zfs_get_pci_slots_sys_path() Coverity found this. We attempted to free tmp, which is a pointer to a string that should be freed by the caller. Reviewed-by: Neal Gompa Reviewed-by: Tony Hutter Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13864 --- lib/libzutil/os/linux/zutil_device_path_os.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/libzutil/os/linux/zutil_device_path_os.c b/lib/libzutil/os/linux/zutil_device_path_os.c index 45a6f6f5935b..e443899bf139 100644 --- a/lib/libzutil/os/linux/zutil_device_path_os.c +++ b/lib/libzutil/os/linux/zutil_device_path_os.c @@ -265,7 +265,6 @@ zfs_get_pci_slots_sys_path(const char *dev_name) free(address2); if (asprintf(&path, "/sys/bus/pci/slots/%s", ep->d_name) == -1) { - free(tmp); continue; } break; From 1d5e569a69e3887e07560d9e6fc6e26446ccc6ca Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Thu, 15 Sep 2022 14:46:42 -0400 Subject: [PATCH 37/84] Fix use-after-free bugs in icp code These were reported by Coverity as "Read from pointer after free" bugs. Presumably, it did not report it as a use-after-free bug because it does not understand the inline assembly that implements the atomic instruction. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13881 --- module/icp/core/kcf_mech_tabs.c | 2 +- module/icp/core/kcf_prov_tabs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/icp/core/kcf_mech_tabs.c b/module/icp/core/kcf_mech_tabs.c index 2642b317d698..00a76217ff50 100644 --- a/module/icp/core/kcf_mech_tabs.c +++ b/module/icp/core/kcf_mech_tabs.c @@ -720,8 +720,8 @@ kcf_remove_mech_provider(char *mech_name, kcf_provider_desc_t *prov_desc) } /* free entry */ - KCF_PROV_REFRELE(prov_mech->pm_prov_desc); KCF_PROV_IREFRELE(prov_mech->pm_prov_desc); + KCF_PROV_REFRELE(prov_mech->pm_prov_desc); kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t)); } diff --git a/module/icp/core/kcf_prov_tabs.c b/module/icp/core/kcf_prov_tabs.c index 9d303d022517..3b0bf12e7b73 100644 --- a/module/icp/core/kcf_prov_tabs.c +++ b/module/icp/core/kcf_prov_tabs.c @@ -171,8 +171,8 @@ kcf_prov_tab_rem_provider(crypto_provider_id_t prov_id) * at that time. */ - KCF_PROV_REFRELE(prov_desc); KCF_PROV_IREFRELE(prov_desc); + KCF_PROV_REFRELE(prov_desc); return (CRYPTO_SUCCESS); } From 39a39b8ab9f3653b000294c3f2e357db68de3de2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Fri, 16 Sep 2022 22:59:25 +0200 Subject: [PATCH 38/84] =?UTF-8?q?Handle=20ECKSUM=20as=20new=20EZFS=5FCKSUM?= =?UTF-8?q?=20=E2=80=92=20"insufficient=20replicas"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a meaningful error message for ECKSUM to common error messages. Reviewed-by: Richard Yao Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #6805 Closes #13808 Closes #13898 --- include/libzfs.h | 1 + lib/libzfs/libzfs_util.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/libzfs.h b/include/libzfs.h index d55e3f2e7384..7c06ebb10486 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -150,6 +150,7 @@ typedef enum zfs_error { EZFS_NO_RESILVER_DEFER, /* pool doesn't support resilver_defer */ EZFS_EXPORT_IN_PROGRESS, /* currently exporting the pool */ EZFS_REBUILDING, /* resilvering (sequential reconstrution) */ + EZFS_CKSUM, /* insufficient replicas */ EZFS_UNKNOWN } zfs_error_t; diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 7dd38bb3d838..728b9ab92d4e 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -170,6 +170,8 @@ libzfs_error_description(libzfs_handle_t *hdl) return (dgettext(TEXT_DOMAIN, "I/O error")); case EZFS_INTR: return (dgettext(TEXT_DOMAIN, "signal received")); + case EZFS_CKSUM: + return (dgettext(TEXT_DOMAIN, "insufficient replicas")); case EZFS_ISSPARE: return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " "spare")); @@ -392,6 +394,10 @@ zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, case EINTR: zfs_verror(hdl, EZFS_INTR, fmt, ap); return (-1); + + case ECKSUM: + zfs_verror(hdl, EZFS_CKSUM, fmt, ap); + return (-1); } return (0); From 12b859c97079f6aa82aba7a63b47353c1d464d38 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 16 Sep 2022 17:02:54 -0400 Subject: [PATCH 39/84] Fix null pointer dereferences in PAM Coverity caught these. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13889 --- contrib/pam_zfs_key/pam_zfs_key.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/pam_zfs_key/pam_zfs_key.c b/contrib/pam_zfs_key/pam_zfs_key.c index 0856c7534f0d..703d0ad57f6f 100644 --- a/contrib/pam_zfs_key/pam_zfs_key.c +++ b/contrib/pam_zfs_key/pam_zfs_key.c @@ -496,7 +496,6 @@ zfs_key_config_get_dataset(zfs_key_config_t *config) if (zhp == NULL) { pam_syslog(NULL, LOG_ERR, "dataset %s not found", config->homes_prefix); - zfs_close(zhp); return (NULL); } @@ -508,6 +507,10 @@ zfs_key_config_get_dataset(zfs_key_config_t *config) return (dsname); } + if (config->homes_prefix == NULL) { + return (NULL); + } + size_t len = ZFS_MAX_DATASET_NAME_LEN; size_t total_len = strlen(config->homes_prefix) + 1 + strlen(config->username); From 9f1691a96466c737c34c969240410add1076d4f6 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Mon, 19 Sep 2022 20:30:58 -0400 Subject: [PATCH 40/84] Linux: Fix use-after-free in zfsvfs_create() Coverity reported that we pass a pointer to zfsvfs to `dmu_objset_disown()` after freeing zfsvfs in zfsvfs_create_impl() after a failure in zfsvfs_init(). We have nearly identical duplicate versions of this code for FreeBSD and Linux, but interestingly, the FreeBSD version of this code differs in such a way that it does not suffer from this bug. We remove the difference from the FreeBSD version to fix this bug. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13883 --- module/os/linux/zfs/zfs_vfsops.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index f3e7fb52cd0b..2e1b9ba5b69b 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -791,9 +791,7 @@ zfsvfs_create(const char *osname, boolean_t readonly, zfsvfs_t **zfvp) } error = zfsvfs_create_impl(zfvp, zfsvfs, os); - if (error != 0) { - dmu_objset_disown(os, B_TRUE, zfsvfs); - } + return (error); } @@ -833,6 +831,7 @@ zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os) error = zfsvfs_init(zfsvfs, os); if (error != 0) { + dmu_objset_disown(os, B_TRUE, zfsvfs); *zfvp = NULL; zfsvfs_free(zfsvfs); return (error); From c6d93d0a80d86a414d1d50b8d575b35c615dd12a Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 20 Sep 2022 17:43:03 -0400 Subject: [PATCH 41/84] FreeBSD: Fix uninitialized pointer read in spa_import_rootpool() The FreeBSD project's coverity scans found this. Reviewed-by: Brian Behlendorf Reviewed-by: Ryan Moeller Signed-off-by: Richard Yao Closes #13923 --- module/os/freebsd/zfs/spa_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/os/freebsd/zfs/spa_os.c b/module/os/freebsd/zfs/spa_os.c index d5f851a30860..a5445fa565e7 100644 --- a/module/os/freebsd/zfs/spa_os.c +++ b/module/os/freebsd/zfs/spa_os.c @@ -250,7 +250,7 @@ spa_import_rootpool(const char *name, bool checkpointrewind) mutex_exit(&spa_namespace_lock); fnvlist_free(config); cmn_err(CE_NOTE, "Can not parse the config for pool '%s'", - pname); + name); return (error); } From 1ff8f418516c5b1cbd0d4a993fa5b7150ae043c2 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 20 Sep 2022 18:20:04 -0400 Subject: [PATCH 42/84] Fix potential NULL pointer dereference in zfsdle_vdev_online() Coverity complained about this. Reviewed-by: Brian Behlendorf Reviewed-by: Chunwei Chen Signed-off-by: Richard Yao Closes #13903 --- cmd/zed/agents/zfs_mod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/zed/agents/zfs_mod.c b/cmd/zed/agents/zfs_mod.c index 8575d98316f9..d4d7a99800de 100644 --- a/cmd/zed/agents/zfs_mod.c +++ b/cmd/zed/agents/zfs_mod.c @@ -964,7 +964,7 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data) nvlist_t *tgt; int error; - char *tmp_devname, devname[MAXPATHLEN]; + char *tmp_devname, devname[MAXPATHLEN] = ""; uint64_t guid; if (nvlist_lookup_uint64(udev_nvl, ZFS_EV_VDEV_GUID, &guid) == 0) { From fbe150fe5bb58a5086040c15ab186a55b61bc8ca Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 20 Sep 2022 18:20:56 -0400 Subject: [PATCH 43/84] Call va_end() before return in zpool_standard_error_fmt() Commit ecd6cf800b63704be73fb264c3f5b6e0dafc068d by marks in OpenSolaris at Tue Jun 26 07:44:24 2007 -0700 introduced a bug where we fail to call `va_end()` before returning. The man page for va_start() says: "Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the same function." Coverity complained about this. Reviewed-by: Brian Behlendorf Reviewed-by: Chunwei Chen Signed-off-by: Richard Yao Closes #13904 --- lib/libzfs/libzfs_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 728b9ab92d4e..3adb785ddae2 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -680,7 +680,7 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case ENOSPC: case EDQUOT: zfs_verror(hdl, EZFS_NOSPC, fmt, ap); - return (-1); + break; case EAGAIN: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, From e11c4327f12df0e1f3ae9a9187a7ee553d1d6e95 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 23 Sep 2022 13:51:14 -0400 Subject: [PATCH 44/84] set_global_var_parse_kv() should pass the pointer from strdup() A comment says that the caller should free k_out, but the pointer passed via k_out is not the same pointer we received from strdup(). Instead, it is a pointer into the region we received from strdup(). The free function should always be called with the original pointer, so this is likely a bug. We solve this by calling `strdup()` a second time and then freeing the original pointer. Coverity reported this as a memory leak. Reviewed-by: Neal Gompa Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13867 --- lib/libzpool/util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c index 20cabe7c2e29..327391245a0f 100644 --- a/lib/libzpool/util.c +++ b/lib/libzpool/util.c @@ -173,12 +173,13 @@ set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out) goto err_free; } - *k_out = k; + *k_out = strdup(k); *v_out = val; + free(d); return (0); err_free: - free(k); + free(d); return (err); } From 531361114bb6c0c6b98533499b8790f7cc1747f2 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 27 Sep 2022 19:48:35 -0400 Subject: [PATCH 45/84] PAM: Fix uninitialized value read Clang's static analyzer found that config.uid is uninitialized when zfs_key_config_load() returns an error. Oddly, this was not included in the unchecked return values that Coverity found. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13957 --- contrib/pam_zfs_key/pam_zfs_key.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contrib/pam_zfs_key/pam_zfs_key.c b/contrib/pam_zfs_key/pam_zfs_key.c index 703d0ad57f6f..4b89091cdaef 100644 --- a/contrib/pam_zfs_key/pam_zfs_key.c +++ b/contrib/pam_zfs_key/pam_zfs_key.c @@ -768,7 +768,9 @@ pam_sm_close_session(pam_handle_t *pamh, int flags, return (PAM_SUCCESS); } zfs_key_config_t config; - zfs_key_config_load(pamh, &config, argc, argv); + if (zfs_key_config_load(pamh, &config, argc, argv) != 0) { + return (PAM_SESSION_ERR); + } if (config.uid < 1000) { zfs_key_config_free(&config); return (PAM_SUCCESS); From d4df36de5da013c03173e4eb90a453deff891b7a Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Thu, 29 Sep 2022 13:16:37 -0400 Subject: [PATCH 46/84] Fix unreachable code in zstreamdump 82226e4f44baa3f7c3101caaaf941927aa318e46 was intended to prevent a warning from being printed in situations where it was inappropriate, but accidentally disabled it entirely by setting featureflags in the wrong case statement. Coverity reported this as dead code. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13946 --- cmd/zstream/zstream_dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/zstream/zstream_dump.c b/cmd/zstream/zstream_dump.c index 04a4986b45d8..f0e83fb19da3 100644 --- a/cmd/zstream/zstream_dump.c +++ b/cmd/zstream/zstream_dump.c @@ -363,9 +363,6 @@ zstream_do_dump(int argc, char *argv[]) BSWAP_64(drrb->drr_fromguid); } - featureflags = - DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); - (void) printf("BEGIN record\n"); (void) printf("\thdrtype = %lld\n", DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo)); @@ -465,6 +462,9 @@ zstream_do_dump(int argc, char *argv[]) BSWAP_64(drro->drr_maxblkid); } + featureflags = + DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); + if (featureflags & DMU_BACKUP_FEATURE_RAW && drro->drr_bonuslen > drro->drr_raw_bonuslen) { (void) fprintf(stderr, From c562bbefc00f28334c2392626a27c34eab2f5b3e Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 30 Sep 2022 19:59:51 -0400 Subject: [PATCH 47/84] Fix potential NULL pointer dereference in dsl_dataset_promote_check() If the `list_head()` returns NULL, we dereference it, right before we check to see if it returned NULL. We have defined two different pointers that both point to the same thing, which are `origin_head` and `origin_ds`. Almost everything uses `origin_ds`, so we switch them to use `origin_ds`. We also promote `origin_ds` to a const pointer so that the compiler verifies that nothing modifies it. Coverity complained about this. Reviewed-by: Brian Behlendorf Reviewed-by: Neal Gompa Signed-off-by: Richard Yao Closes #13967 --- module/zfs/dsl_dataset.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index e8692c95438a..0a460213ded7 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -3307,7 +3307,6 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dataset_t *hds; struct promotenode *snap; - dsl_dataset_t *origin_ds, *origin_head; int err; uint64_t unused; uint64_t ss_mv_cnt; @@ -3327,12 +3326,11 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) } snap = list_head(&ddpa->shared_snaps); - origin_head = snap->ds; if (snap == NULL) { err = SET_ERROR(ENOENT); goto out; } - origin_ds = snap->ds; + dsl_dataset_t *const origin_ds = snap->ds; /* * Encrypted clones share a DSL Crypto Key with their origin's dsl dir. @@ -3428,10 +3426,10 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) * Check that bookmarks that are being transferred don't have * name conflicts. */ - for (dsl_bookmark_node_t *dbn = avl_first(&origin_head->ds_bookmarks); + for (dsl_bookmark_node_t *dbn = avl_first(&origin_ds->ds_bookmarks); dbn != NULL && dbn->dbn_phys.zbm_creation_txg <= dsl_dataset_phys(origin_ds)->ds_creation_txg; - dbn = AVL_NEXT(&origin_head->ds_bookmarks, dbn)) { + dbn = AVL_NEXT(&origin_ds->ds_bookmarks, dbn)) { if (strlen(dbn->dbn_name) >= max_snap_len) { err = SET_ERROR(ENAMETOOLONG); goto out; From fa74250cd379ab8564a6f4b8e6e254893de057c2 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Wed, 5 Oct 2022 20:09:24 -0400 Subject: [PATCH 48/84] PAM: Fix unchecked return value from zfs_key_config_load() 9a49c6b782443ba6e627f2261c45f082ad843094 was intended to fix this issue, but I had missed the case in pam_sm_open_session(). Clang's static analyzer had not reported it and I forgot to look for other cases. Interestingly, GCC gcc-12.1.1_p20220625's static analyzer had caught this as multiple double-free bugs, since another failure after the failure in zfs_key_config_load() will cause us to attempt to free the memory that zfs_key_config_load() was supposed to allocate, but had cleaned up upon failure. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13978 --- contrib/pam_zfs_key/pam_zfs_key.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/pam_zfs_key/pam_zfs_key.c b/contrib/pam_zfs_key/pam_zfs_key.c index 4b89091cdaef..0db119382e7b 100644 --- a/contrib/pam_zfs_key/pam_zfs_key.c +++ b/contrib/pam_zfs_key/pam_zfs_key.c @@ -714,7 +714,10 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, return (PAM_SUCCESS); } zfs_key_config_t config; - zfs_key_config_load(pamh, &config, argc, argv); + if (zfs_key_config_load(pamh, &config, argc, argv) != 0) { + return (PAM_SESSION_ERR); + } + if (config.uid < 1000) { zfs_key_config_free(&config); return (PAM_SUCCESS); From d05f247aece91500e5a1883e6fbdee66adde171f Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 11 Oct 2022 15:32:07 -0400 Subject: [PATCH 49/84] scripts/enum-extract.pl should not hard code perl path This is a portability issue. The issue had already been fixed for scripts/cstyle.pl by 2dbf1bf8296f66f24d5e404505c991bfbeec7808. scripts/enum-extract.pl was added to the repository the following year without this portability fix. Michael Bishop informed me that this broke his attempt to build ZFS 2.1.6 on NixOS, since he was building manually outside of their package manager (that usually rewrites the shebangs to NixOS' unusual paths). NixOS puts all of the paths into $PATH, so scripts that portably rely on env to find the interpreter still work. Reviewed-by: Tino Reichardt Reviewed-by: George Melikov Reviewed-by: Ryan Moeller Signed-off-by: Richard Yao Closes #14012 --- scripts/enum-extract.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/enum-extract.pl b/scripts/enum-extract.pl index 5112cc807f67..5dc2e3455145 100755 --- a/scripts/enum-extract.pl +++ b/scripts/enum-extract.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl my $usage = < Date: Fri, 14 Oct 2022 16:33:22 -0400 Subject: [PATCH 50/84] Fix potential NULL pointer dereference in lzc_ioctl() Users are allowed to pass NULL to resultp, but we unconditionally assume that they never do. When an external user does pass NULL to resultp, we dereference a NULL pointer. Clang's static analyzer complained about this. Reviewed-by: Brian Behlendorf Reviewed-by: Ryan Moeller Signed-off-by: Richard Yao Closes #14008 --- lib/libzfs_core/libzfs_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libzfs_core/libzfs_core.c b/lib/libzfs_core/libzfs_core.c index 1e6bbcd561fa..855d8cb0afb9 100644 --- a/lib/libzfs_core/libzfs_core.c +++ b/lib/libzfs_core/libzfs_core.c @@ -233,7 +233,7 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name, break; } } - if (zc.zc_nvlist_dst_filled) { + if (zc.zc_nvlist_dst_filled && resultp != NULL) { *resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst, zc.zc_nvlist_dst_size); } From 2453f9035007e69ab63e0b2268f42bbefb3c90f3 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 14 Oct 2022 16:41:56 -0400 Subject: [PATCH 51/84] Fix theoretical array overflow in lua_typename() Out of the 12 defects in lua that coverity reports, 5 of them involve `lua_typename()` and out of the dozens of defects in ZFS that lua reports, 3 of them involve `lua_typename()` due to the ZCP code. Given all of the uses of `lua_typename()` in the ZCP code, I was surprised that there were not more. It appears that only 2 were reported because only 3 called `lua_type()`, which does a defective sanity check that allows invalid types to be passed. lua/lua@d4fb848be77f4b0209acaf37a5b5e1cee741ddce addressed this in upstream lua 5.3. Unfortunately, we did not get that fix since we use lua 5.2 and we do not have assertions enabled in lua, so the upstream solution would not do anything. While we could adopt the upstream solution and enable assertions, a simpler solution is to fix the issue by making `lua_typename()` return `internal_type_error` whenever it is called with an invalid type. This avoids the array overflow and if we ever see it appear somewhere, we will know there is a problem with the lua interpreter. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13947 --- module/lua/lapi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/lua/lapi.c b/module/lua/lapi.c index 6a845c461052..75f8b2a1dd6f 100644 --- a/module/lua/lapi.c +++ b/module/lua/lapi.c @@ -251,6 +251,8 @@ LUA_API int lua_type (lua_State *L, int idx) { LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); + if (t > 8 || t < 0) + return "internal_type_error"; return ttypename(t); } From 4351d18fb0bf4e75de1d1ddecaa412ca8b1893ae Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 18 Oct 2022 15:42:14 -0400 Subject: [PATCH 52/84] ZED: Fix uninitialized value reads Coverity complained about a couple of uninitialized value reads in ZED. * zfs_deliver_dle() can pass an uninitialized string to zed_log_msg() * An uninitialized sev.sigev_signo is passed to timer_create() The former would log garbage while the latter is not a real issue, but we might as well suppress it by initializing the field to 0 for consistency's sake. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14047 --- cmd/zed/agents/fmd_api.c | 1 + cmd/zed/agents/zfs_mod.c | 1 + 2 files changed, 2 insertions(+) diff --git a/cmd/zed/agents/fmd_api.c b/cmd/zed/agents/fmd_api.c index 607b387ca3a8..f6cb7635f030 100644 --- a/cmd/zed/agents/fmd_api.c +++ b/cmd/zed/agents/fmd_api.c @@ -599,6 +599,7 @@ fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta) sev.sigev_notify_function = _timer_notify; sev.sigev_notify_attributes = NULL; sev.sigev_value.sival_ptr = ftp; + sev.sigev_signo = 0; timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid); timer_settime(ftp->ft_tid, 0, &its, NULL); diff --git a/cmd/zed/agents/zfs_mod.c b/cmd/zed/agents/zfs_mod.c index d4d7a99800de..22447100b6ab 100644 --- a/cmd/zed/agents/zfs_mod.c +++ b/cmd/zed/agents/zfs_mod.c @@ -1122,6 +1122,7 @@ zfs_deliver_dle(nvlist_t *nvl) strlcpy(name, devname, MAXPATHLEN); zfs_append_partition(name, MAXPATHLEN); } else { + sprintf(name, "unknown"); zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath"); } From 5eaad8bdb5cff5540fc551110cd06b752de86bb0 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 14 Oct 2022 22:45:13 -0400 Subject: [PATCH 53/84] Fix NULL pointer dereference in zdb Clang's static analyzer complained that we dereference a NULL pointer in dump_path() if we return 0 when there is an error. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14044 --- cmd/zdb/zdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 4e57538d2234..f424dd771f70 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -2995,7 +2995,7 @@ open_objset(const char *path, void *tag, objset_t **osp) } sa_os = *osp; - return (0); + return (err); } static void From a5f17a94d3cef918c3625aa10216485e477aee31 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 14 Oct 2022 22:46:43 -0400 Subject: [PATCH 54/84] fm_fmri_hc_create() must call va_end() before returning clang-tidy caught this. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14044 --- module/zfs/fm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/module/zfs/fm.c b/module/zfs/fm.c index 7981568b8df7..cfd1372c5b97 100644 --- a/module/zfs/fm.c +++ b/module/zfs/fm.c @@ -953,6 +953,7 @@ fm_fmri_hc_create(nvlist_t *fmri, int version, const nvlist_t *auth, } atomic_inc_64( &erpt_kstat_data.fmri_set_failed.value.ui64); + va_end(ap); return; } } From bbec0e60a8e75e9f63a6a415a86054b42ef6d675 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 14 Oct 2022 22:55:48 -0400 Subject: [PATCH 55/84] Fix NULL pointer passed to strlcpy from zap_lookup_impl() Clang's static analyzer pointed out that whenever zap_lookup_by_dnode() is called, we have the following stack where strlcpy() is passed a NULL pointer for realname from zap_lookup_by_dnode(): strlcpy() zap_lookup_impl() zap_lookup_norm_by_dnode() zap_lookup_by_dnode() Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14044 --- module/zfs/zap_micro.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module/zfs/zap_micro.c b/module/zfs/zap_micro.c index 1f32e4450522..516d46ac7f31 100644 --- a/module/zfs/zap_micro.c +++ b/module/zfs/zap_micro.c @@ -988,8 +988,10 @@ zap_lookup_impl(zap_t *zap, const char *name, } else { *(uint64_t *)buf = MZE_PHYS(zap, mze)->mze_value; - (void) strlcpy(realname, - MZE_PHYS(zap, mze)->mze_name, rn_len); + if (realname != NULL) + (void) strlcpy(realname, + MZE_PHYS(zap, mze)->mze_name, + rn_len); if (ncp) { *ncp = mzap_normalization_conflict(zap, zn, mze); From 409c99a1d3e5c47c5b61a4d471c60c5b92c887a6 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sun, 16 Oct 2022 00:19:13 -0400 Subject: [PATCH 56/84] Fix NULL pointer dereference in spa_open_common() Calling spa_open() will pass a NULL pointer to spa_open_common()'s config parameter. Under the right circumstances, we will dereference the config parameter without doing a NULL check. Clang's static analyzer found this. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14044 --- module/zfs/spa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 86447d1fdcba..c9759f35a6fb 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -5230,7 +5230,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, * If we've recovered the pool, pass back any information we * gathered while doing the load. */ - if (state == SPA_LOAD_RECOVER) { + if (state == SPA_LOAD_RECOVER && config != NULL) { fnvlist_add_nvlist(*config, ZPOOL_CONFIG_LOAD_INFO, spa->spa_load_info); } From 89c41f3979c11ee72c2129066acbbf2722036d2b Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sun, 16 Oct 2022 00:56:55 -0400 Subject: [PATCH 57/84] set_global_var() should not pass NULL pointers to dlclose() Both Coverity and Clang's static analyzer caught this. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14044 --- lib/libzpool/util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c index 327391245a0f..f4e33140b6df 100644 --- a/lib/libzpool/util.c +++ b/lib/libzpool/util.c @@ -228,13 +228,14 @@ set_global_var(char const *arg) fprintf(stderr, "Failed to open libzpool.so to set global " "variable\n"); ret = EIO; - goto out_dlclose; + goto out_free; } ret = 0; out_dlclose: dlclose(zpoolhdl); +out_free: free(varname); out_ret: return (ret); From af2e53f62c0aae6cd18c5e450977711d16b1cedb Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Mon, 17 Oct 2022 02:06:40 -0400 Subject: [PATCH 58/84] Fix possible NULL pointer dereference in sha2_mac_init() If mechanism->cm_param is NULL, passing mechanism to PROV_SHA2_GET_DIGEST_LEN() will dereference a NULL pointer. Coverity reported this. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14044 --- module/icp/io/sha2_mod.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/module/icp/io/sha2_mod.c b/module/icp/io/sha2_mod.c index d690cd0bcb05..f3125ad84528 100644 --- a/module/icp/io/sha2_mod.c +++ b/module/icp/io/sha2_mod.c @@ -823,12 +823,15 @@ sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, */ if (mechanism->cm_type % 3 == 2) { if (mechanism->cm_param == NULL || - mechanism->cm_param_len != sizeof (ulong_t)) - ret = CRYPTO_MECHANISM_PARAM_INVALID; - PROV_SHA2_GET_DIGEST_LEN(mechanism, - PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len); - if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > sha_digest_len) + mechanism->cm_param_len != sizeof (ulong_t)) { ret = CRYPTO_MECHANISM_PARAM_INVALID; + } else { + PROV_SHA2_GET_DIGEST_LEN(mechanism, + PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len); + if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > + sha_digest_len) + ret = CRYPTO_MECHANISM_PARAM_INVALID; + } } if (ret != CRYPTO_SUCCESS) { From 3830858c5cb4d209b1a05e6a3dde6b77cb88f2b3 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 18 Oct 2022 19:03:33 -0400 Subject: [PATCH 59/84] Fix memory leaks in dmu_send()/dmu_send_obj() If we encounter an EXDEV error when using the redacted snapshots feature, the memory used by dspp.fromredactsnaps is leaked. Clang's static analyzer caught this during an experiment in which I had annotated various headers in an attempt to improve the results of static analysis. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #13973 --- module/zfs/dmu_send.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/module/zfs/dmu_send.c b/module/zfs/dmu_send.c index 390afba92680..20ec4ac1739d 100644 --- a/module/zfs/dmu_send.c +++ b/module/zfs/dmu_send.c @@ -2716,6 +2716,10 @@ dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap, dspp.numfromredactsnaps = NUM_SNAPS_NOT_REDACTED; err = dmu_send_impl(&dspp); } + if (dspp.fromredactsnaps) + kmem_free(dspp.fromredactsnaps, + dspp.numfromredactsnaps * sizeof (uint64_t)); + dsl_dataset_rele(dspp.to_ds, FTAG); return (err); } @@ -2924,6 +2928,10 @@ dmu_send(const char *tosnap, const char *fromsnap, boolean_t embedok, /* dmu_send_impl will call dsl_pool_rele for us. */ err = dmu_send_impl(&dspp); } else { + if (dspp.fromredactsnaps) + kmem_free(dspp.fromredactsnaps, + dspp.numfromredactsnaps * + sizeof (uint64_t)); dsl_pool_rele(dspp.dp, FTAG); } } else { From 4c59fde1f5953b86a68bb71579b3184a93f1c9f3 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sat, 15 Oct 2022 18:27:03 -0400 Subject: [PATCH 60/84] Fix theoretical use of uninitialized values Clang's static analyzer complains about this. In get_configs(), if we have an invalid configuration that has no top level vdevs, we can read a couple of uninitialized variables. Aborting upon seeing this would break the userland tools for healthy pools, so we instead initialize the two variables to 0 to allow the userland tools to continue functioning for the pools with valid configurations. In zfs_do_wait(), if no wait activities are enabled, we read an uninitialized error variable. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14043 --- cmd/zfs/zfs_main.c | 2 +- lib/libzutil/zutil_import.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 00d5d847d05c..02b19e7163c1 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -8535,7 +8535,7 @@ static int zfs_do_wait(int argc, char **argv) { boolean_t enabled[ZFS_WAIT_NUM_ACTIVITIES]; - int error, i; + int error = 0, i; int c; /* By default, wait for all types of activity. */ diff --git a/lib/libzutil/zutil_import.c b/lib/libzutil/zutil_import.c index 1658215199f2..98f138957ba6 100644 --- a/lib/libzutil/zutil_import.c +++ b/lib/libzutil/zutil_import.c @@ -467,11 +467,9 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, uint64_t guid; uint_t children = 0; nvlist_t **child = NULL; - uint_t holes; uint64_t *hole_array, max_id; uint_t c; boolean_t isactive; - uint64_t hostid; nvlist_t *nvl; boolean_t valid_top_config = B_FALSE; @@ -479,7 +477,8 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok, goto nomem; for (pe = pl->pools; pe != NULL; pe = pe->pe_next) { - uint64_t id, max_txg = 0; + uint64_t id, max_txg = 0, hostid = 0; + uint_t holes = 0; if (nvlist_alloc(&config, NV_UNIQUE_NAME, 0) != 0) goto nomem; From 52e658edd7afbe66149da6efec467633868ca03c Mon Sep 17 00:00:00 2001 From: Pavel Snajdr Date: Thu, 5 Dec 2019 01:52:27 +0100 Subject: [PATCH 61/84] Remove zpl_revalidate: fix snapshot rollback Open files, which aren't present in the snapshot, which is being roll-backed to, need to disappear from the visible VFS image of the dataset. Kernel provides d_drop function to drop invalid entry from the dcache, but inode can be referenced by dentry multiple dentries. The introduced zpl_d_drop_aliases function walks and invalidates all aliases of an inode. Reviewed-by: Ryan Moeller Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Pavel Snajdr Closes #9600 Closes #14070 --- config/kernel-dentry-alias.m4 | 30 +++++++++++++ config/kernel.m4 | 2 + include/os/linux/kernel/linux/dcache_compat.h | 21 +++++++++ include/os/linux/zfs/sys/trace_acl.h | 6 +-- include/os/linux/zfs/sys/zpl.h | 3 +- include/sys/zfs_znode.h | 1 - module/os/linux/zfs/zfs_ctldir.c | 1 - module/os/linux/zfs/zfs_vfsops.c | 3 +- module/os/linux/zfs/zfs_znode.c | 1 - module/os/linux/zfs/zpl_inode.c | 44 ------------------- 10 files changed, 58 insertions(+), 54 deletions(-) create mode 100644 config/kernel-dentry-alias.m4 diff --git a/config/kernel-dentry-alias.m4 b/config/kernel-dentry-alias.m4 new file mode 100644 index 000000000000..f0ddb8d010b0 --- /dev/null +++ b/config/kernel-dentry-alias.m4 @@ -0,0 +1,30 @@ +dnl # +dnl # 3.18 API change +dnl # Dentry aliases are in d_u struct dentry member +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U], [ + ZFS_LINUX_TEST_SRC([dentry_alias_d_u], [ + #include + #include + #include + ], [ + struct inode *inode __attribute__ ((unused)) = NULL; + struct dentry *dentry __attribute__ ((unused)) = NULL; + hlist_for_each_entry(dentry, &inode->i_dentry, + d_u.d_alias) { + d_drop(dentry); + } + ]) +]) + +AC_DEFUN([ZFS_AC_KERNEL_DENTRY_ALIAS_D_U], [ + AC_MSG_CHECKING([whether dentry aliases are in d_u member]) + ZFS_LINUX_TEST_RESULT([dentry_alias_d_u], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_DENTRY_D_U_ALIASES, 1, + [dentry aliases are in d_u member]) + ],[ + AC_MSG_RESULT(no) + ]) +]) + diff --git a/config/kernel.m4 b/config/kernel.m4 index a3806221687f..3a059b73a570 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -93,6 +93,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ ZFS_AC_KERNEL_SRC_SETATTR_PREPARE ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED ZFS_AC_KERNEL_SRC_DENTRY + ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE ZFS_AC_KERNEL_SRC_SECURITY_INODE ZFS_AC_KERNEL_SRC_FST_MOUNT @@ -209,6 +210,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ ZFS_AC_KERNEL_SETATTR_PREPARE ZFS_AC_KERNEL_INSERT_INODE_LOCKED ZFS_AC_KERNEL_DENTRY + ZFS_AC_KERNEL_DENTRY_ALIAS_D_U ZFS_AC_KERNEL_TRUNCATE_SETSIZE ZFS_AC_KERNEL_SECURITY_INODE ZFS_AC_KERNEL_FST_MOUNT diff --git a/include/os/linux/kernel/linux/dcache_compat.h b/include/os/linux/kernel/linux/dcache_compat.h index d0588a82e9ad..e2aca1629735 100644 --- a/include/os/linux/kernel/linux/dcache_compat.h +++ b/include/os/linux/kernel/linux/dcache_compat.h @@ -61,4 +61,25 @@ d_clear_d_op(struct dentry *dentry) DCACHE_OP_REVALIDATE | DCACHE_OP_DELETE); } +/* + * Walk and invalidate all dentry aliases of an inode + * unless it's a mountpoint + */ +static inline void +zpl_d_drop_aliases(struct inode *inode) +{ + struct dentry *dentry; + spin_lock(&inode->i_lock); +#ifdef HAVE_DENTRY_D_U_ALIASES + hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { +#else + hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { +#endif + if (!IS_ROOT(dentry) && !d_mountpoint(dentry) && + (dentry->d_inode == inode)) { + d_drop(dentry); + } + } + spin_unlock(&inode->i_lock); +} #endif /* _ZFS_DCACHE_H */ diff --git a/include/os/linux/zfs/sys/trace_acl.h b/include/os/linux/zfs/sys/trace_acl.h index 4707fc6f4112..21bcefa4ea26 100644 --- a/include/os/linux/zfs/sys/trace_acl.h +++ b/include/os/linux/zfs/sys/trace_acl.h @@ -62,7 +62,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class, __field(boolean_t, z_is_sa) __field(boolean_t, z_is_mapped) __field(boolean_t, z_is_ctldir) - __field(boolean_t, z_is_stale) __field(uint32_t, i_uid) __field(uint32_t, i_gid) @@ -95,7 +94,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class, __entry->z_is_sa = zn->z_is_sa; __entry->z_is_mapped = zn->z_is_mapped; __entry->z_is_ctldir = zn->z_is_ctldir; - __entry->z_is_stale = zn->z_is_stale; __entry->i_uid = KUID_TO_SUID(ZTOI(zn)->i_uid); __entry->i_gid = KGID_TO_SGID(ZTOI(zn)->i_gid); @@ -117,7 +115,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class, "zn_prefetch %u blksz %u seq %u " "mapcnt %llu size %llu pflags %llu " "sync_cnt %u mode 0x%x is_sa %d " - "is_mapped %d is_ctldir %d is_stale %d inode { " + "is_mapped %d is_ctldir %d inode { " "uid %u gid %u ino %lu nlink %u size %lli " "blkbits %u bytes %u mode 0x%x generation %x } } " "ace { type %u flags %u access_mask %u } mask_matched %u", @@ -126,7 +124,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class, __entry->z_seq, __entry->z_mapcnt, __entry->z_size, __entry->z_pflags, __entry->z_sync_cnt, __entry->z_mode, __entry->z_is_sa, __entry->z_is_mapped, - __entry->z_is_ctldir, __entry->z_is_stale, __entry->i_uid, + __entry->z_is_ctldir, __entry->i_uid, __entry->i_gid, __entry->i_ino, __entry->i_nlink, __entry->i_size, __entry->i_blkbits, __entry->i_bytes, __entry->i_mode, __entry->i_generation, diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h index ff86e027bbe2..5f929dc32a06 100644 --- a/include/os/linux/zfs/sys/zpl.h +++ b/include/os/linux/zfs/sys/zpl.h @@ -45,7 +45,8 @@ extern const struct inode_operations zpl_inode_operations; extern const struct inode_operations zpl_dir_inode_operations; extern const struct inode_operations zpl_symlink_inode_operations; extern const struct inode_operations zpl_special_inode_operations; -extern dentry_operations_t zpl_dentry_operations; + +/* zpl_file.c */ extern const struct address_space_operations zpl_address_space_operations; extern const struct file_operations zpl_file_operations; extern const struct file_operations zpl_dir_file_operations; diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h index 1bf25a77d3a0..ca32cb49c049 100644 --- a/include/sys/zfs_znode.h +++ b/include/sys/zfs_znode.h @@ -190,7 +190,6 @@ typedef struct znode { boolean_t z_is_sa; /* are we native sa? */ boolean_t z_is_mapped; /* are we mmap'ed */ boolean_t z_is_ctldir; /* are we .zfs entry */ - boolean_t z_is_stale; /* are we stale due to rollback? */ boolean_t z_suspended; /* extra ref from a suspend? */ uint_t z_blksz; /* block size in bytes */ uint_t z_seq; /* modification sequence number */ diff --git a/module/os/linux/zfs/zfs_ctldir.c b/module/os/linux/zfs/zfs_ctldir.c index d33188f3822c..c45644a69153 100644 --- a/module/os/linux/zfs/zfs_ctldir.c +++ b/module/os/linux/zfs/zfs_ctldir.c @@ -470,7 +470,6 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id, zp->z_is_sa = B_FALSE; zp->z_is_mapped = B_FALSE; zp->z_is_ctldir = B_TRUE; - zp->z_is_stale = B_FALSE; zp->z_sa_hdl = NULL; zp->z_blksz = 0; zp->z_seq = 0; diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index 2e1b9ba5b69b..da897f120c0b 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -1500,7 +1500,6 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent) sb->s_op = &zpl_super_operations; sb->s_xattr = zpl_xattr_handlers; sb->s_export_op = &zpl_export_operations; - sb->s_d_op = &zpl_dentry_operations; /* Set features for file system. */ zfs_set_fuid_feature(zfsvfs); @@ -1859,8 +1858,8 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, dsl_dataset_t *ds) zp = list_next(&zfsvfs->z_all_znodes, zp)) { err2 = zfs_rezget(zp); if (err2) { + zpl_d_drop_aliases(ZTOI(zp)); remove_inode_hash(ZTOI(zp)); - zp->z_is_stale = B_TRUE; } /* see comment in zfs_suspend_fs() */ diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c index cd80049df142..ba2375387104 100644 --- a/module/os/linux/zfs/zfs_znode.c +++ b/module/os/linux/zfs/zfs_znode.c @@ -544,7 +544,6 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, zp->z_atime_dirty = B_FALSE; zp->z_is_mapped = B_FALSE; zp->z_is_ctldir = B_FALSE; - zp->z_is_stale = B_FALSE; zp->z_suspended = B_FALSE; zp->z_sa_hdl = NULL; zp->z_mapcnt = 0; diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c index 4f79265a0856..a0615af8de76 100644 --- a/module/os/linux/zfs/zpl_inode.c +++ b/module/os/linux/zfs/zpl_inode.c @@ -698,46 +698,6 @@ zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) return (error); } -static int -#ifdef HAVE_D_REVALIDATE_NAMEIDATA -zpl_revalidate(struct dentry *dentry, struct nameidata *nd) -{ - unsigned int flags = (nd ? nd->flags : 0); -#else -zpl_revalidate(struct dentry *dentry, unsigned int flags) -{ -#endif /* HAVE_D_REVALIDATE_NAMEIDATA */ - /* CSTYLED */ - zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; - int error; - - if (flags & LOOKUP_RCU) - return (-ECHILD); - - /* - * After a rollback negative dentries created before the rollback - * time must be invalidated. Otherwise they can obscure files which - * are only present in the rolled back dataset. - */ - if (dentry->d_inode == NULL) { - spin_lock(&dentry->d_lock); - error = time_before(dentry->d_time, zfsvfs->z_rollback_time); - spin_unlock(&dentry->d_lock); - - if (error) - return (0); - } - - /* - * The dentry may reference a stale inode if a mounted file system - * was rolled back to a point in time where the object didn't exist. - */ - if (dentry->d_inode && ITOZ(dentry->d_inode)->z_is_stale) - return (0); - - return (1); -} - const struct inode_operations zpl_inode_operations = { .setattr = zpl_setattr, .getattr = zpl_getattr, @@ -826,7 +786,3 @@ const struct inode_operations zpl_special_inode_operations = { .get_acl = zpl_get_acl, #endif /* CONFIG_FS_POSIX_ACL */ }; - -dentry_operations_t zpl_dentry_operations = { - .d_revalidate = zpl_revalidate, -}; From e9a8fb17b533089712bdd53900bcaa173b0d7334 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Thu, 27 Oct 2022 12:45:26 -0400 Subject: [PATCH 62/84] Fix too few arguments to formatting function CodeQL reported that when the VERIFY3U condition is false, we do not pass enough arguments to `spl_panic()`. This is because the format string from `snprintf()` was concatenated into the format string for `spl_panic()`, which causes us to have an unexpected format specifier. A CodeQL developer suggested fixing the macro to have a `%s` format string that takes a stringified RIGHT argument, which would fix this. However, upon inspection, the VERIFY3U check was never necessary in the first place, so we remove it in favor of just calling `snprintf()`. Lastly, it is interesting that every other static analyzer run on the codebase did not catch this, including some that made an effort to catch such things. Presumably, all of them relied on header annotations, which we have not yet done on `spl_panic()`. CodeQL apparently is able to track the flow of arguments on their way to annotated functions, which llowed it to catch this when others did not. A future patch that I have in development should annotate `spl_panic()`, so the others will catch this too. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14098 --- module/zfs/zcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/zfs/zcp.c b/module/zfs/zcp.c index f200b928bc6d..3f11445f74c8 100644 --- a/module/zfs/zcp.c +++ b/module/zfs/zcp.c @@ -277,9 +277,9 @@ zcp_table_to_nvlist(lua_State *state, int index, int depth) } break; case LUA_TNUMBER: - VERIFY3U(sizeof (buf), >, - snprintf(buf, sizeof (buf), "%lld", - (longlong_t)lua_tonumber(state, -2))); + (void) snprintf(buf, sizeof (buf), "%lld", + (longlong_t)lua_tonumber(state, -2)); + key = buf; if (saw_str_could_collide) { key_could_collide = B_TRUE; From ac01b876c91ea6dbbb75775db5603077f3490f0b Mon Sep 17 00:00:00 2001 From: Allan Jude Date: Sat, 29 Oct 2022 16:08:54 -0400 Subject: [PATCH 63/84] Avoid null pointer dereference in dsl_fs_ss_limit_check() Check for cr == NULL before dereferencing it in dsl_enforce_ds_ss_limits() to lookup the zone/jail ID. Reported-by: Coverity (CID 1210459) Reviewed-by: Richard Yao Reviewed-by: Brian Behlendorf Signed-off-by: Allan Jude Closes #14103 --- module/zfs/dsl_dir.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index 2565af1329e3..4d9bd5c7c55e 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -809,6 +809,18 @@ dsl_fs_ss_limit_check(dsl_dir_t *dd, uint64_t delta, zfs_prop_t prop, ASSERT(prop == ZFS_PROP_FILESYSTEM_LIMIT || prop == ZFS_PROP_SNAPSHOT_LIMIT); + if (prop == ZFS_PROP_SNAPSHOT_LIMIT) { + /* + * We don't enforce the limit for temporary snapshots. This is + * indicated by a NULL cred_t argument. + */ + if (cr == NULL) + return (0); + + count_prop = DD_FIELD_SNAPSHOT_COUNT; + } else { + count_prop = DD_FIELD_FILESYSTEM_COUNT; + } /* * If we're allowed to change the limit, don't enforce the limit * e.g. this can happen if a snapshot is taken by an administrative @@ -828,19 +840,6 @@ dsl_fs_ss_limit_check(dsl_dir_t *dd, uint64_t delta, zfs_prop_t prop, if (delta == 0) return (0); - if (prop == ZFS_PROP_SNAPSHOT_LIMIT) { - /* - * We don't enforce the limit for temporary snapshots. This is - * indicated by a NULL cred_t argument. - */ - if (cr == NULL) - return (0); - - count_prop = DD_FIELD_SNAPSHOT_COUNT; - } else { - count_prop = DD_FIELD_FILESYSTEM_COUNT; - } - /* * If an ancestor has been provided, stop checking the limit once we * hit that dir. We need this during rename so that we don't overcount From 256b74d0b034ff61709fca64d58f81746186eaef Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Thu, 3 Nov 2022 12:58:14 -0400 Subject: [PATCH 64/84] Address warnings about possible division by zero from clangsa * The complaint in ztest_replay_write() is only possible if something went horribly wrong. An assertion will silence this and if it goes off, we will know that something is wrong. * The complaint in spa_estimate_metaslabs_to_flush() is not impossible, but seems very unlikely. We resolve this by passing the value from the `MIN()` that does not go to infinity when the variable is zero. There was a third report from Clang's scan-build, but that was a definite false positive and disappeared when checked again through Clang's static analyzer with Z3 refution via CodeChecker. Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14124 --- cmd/ztest/ztest.c | 1 + module/zfs/spa_log_spacemap.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index a580396ebd8a..fb4297478cf1 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -2193,6 +2193,7 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap) * but not always, because we also want to verify correct * behavior when the data was not recently read into cache. */ + ASSERT(doi.doi_data_block_size); ASSERT0(offset % doi.doi_data_block_size); if (ztest_random(4) != 0) { int prefetch = ztest_random(2) ? diff --git a/module/zfs/spa_log_spacemap.c b/module/zfs/spa_log_spacemap.c index 0dfe5b8395e0..6a27f5759549 100644 --- a/module/zfs/spa_log_spacemap.c +++ b/module/zfs/spa_log_spacemap.c @@ -690,7 +690,8 @@ spa_estimate_metaslabs_to_flush(spa_t *spa) * based on the incoming rate until we exceed it. */ if (available_blocks >= 0 && available_txgs >= 0) { - uint64_t skip_txgs = MIN(available_txgs + 1, + uint64_t skip_txgs = (incoming == 0) ? + available_txgs + 1 : MIN(available_txgs + 1, (available_blocks / incoming) + 1); available_blocks -= (skip_txgs * incoming); available_txgs -= skip_txgs; From 572bd18c1f6c5856750c9c426302d690f8c528d7 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Tue, 1 Nov 2022 20:43:32 +0000 Subject: [PATCH 65/84] Make 1-bit bitfields unsigned This fixes -Wsingle-bit-bitfield-constant-conversion warning from clang-16 like: lib/libzfs/libzfs_dataset.c:4529:19: error: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Werror,-Wsingle-bit-bitfield-constant-conversion] flags.nounmount = B_TRUE; ^ ~~~~~~ Reviewed-by: Matthew Ahrens Reviewed-by: Richard Yao Signed-off-by: Brooks Davis Closes #14125 --- include/libzfs.h | 10 +++++----- lib/libzfs/libzfs_pool.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/libzfs.h b/include/libzfs.h index 7c06ebb10486..98942b41982c 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -258,10 +258,10 @@ extern int zpool_add(zpool_handle_t *, nvlist_t *); typedef struct splitflags { /* do not split, but return the config that would be split off */ - int dryrun : 1; + unsigned int dryrun : 1; /* after splitting, import the pool */ - int import : 1; + unsigned int import : 1; int name_flags; } splitflags_t; @@ -650,13 +650,13 @@ extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t); typedef struct renameflags { /* recursive rename */ - int recursive : 1; + unsigned int recursive : 1; /* don't unmount file systems */ - int nounmount : 1; + unsigned int nounmount : 1; /* force unmount file systems */ - int forceunmount : 1; + unsigned int forceunmount : 1; } renameflags_t; extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t); diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index e2912cdb91af..e43ebb15c608 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -59,8 +59,8 @@ static boolean_t zpool_vdev_is_interior(const char *name); typedef struct prop_flags { - int create:1; /* Validate property on creation */ - int import:1; /* Validate property on import */ + unsigned int create:1; /* Validate property on creation */ + unsigned int import:1; /* Validate property on import */ } prop_flags_t; /* From 5f53a444b3c1326f5b0af026763bb68e70a581ad Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Tue, 1 Nov 2022 20:45:36 +0000 Subject: [PATCH 66/84] Remove an unused variable Clang-16 detects this set-but-unused variable which is assigned and incremented, but never referenced otherwise. Reviewed-by: Matthew Ahrens Reviewed-by: Richard Yao Signed-off-by: Brooks Davis Closes #14125 --- module/zfs/zfs_fm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c index a05ff7330458..b1c3f7a6301c 100644 --- a/module/zfs/zfs_fm.c +++ b/module/zfs/zfs_fm.c @@ -253,7 +253,6 @@ void zfs_ereport_clear(spa_t *spa, vdev_t *vd) { uint64_t vdev_guid, pool_guid; - int cnt = 0; ASSERT(vd != NULL || spa != NULL); if (vd == NULL) { @@ -277,7 +276,6 @@ zfs_ereport_clear(spa_t *spa, vdev_t *vd) avl_remove(&recent_events_tree, entry); list_remove(&recent_events_list, entry); kmem_free(entry, sizeof (*entry)); - cnt++; } } From 85537f77a3574f265c5e87c3ee4b1858317530ce Mon Sep 17 00:00:00 2001 From: Serapheim Dimitropoulos Date: Thu, 3 Nov 2022 15:02:46 -0700 Subject: [PATCH 67/84] Expose zfs_vdev_open_timeout_ms as a tunable Some of our customers have been occasionally hitting zfs import failures in Linux because udevd doesn't create the by-id symbolic links in time for zpool import to use them. The main issue is that the systemd-udev-settle.service that zfs-import-cache.service and other services depend on is racy. There is also an openzfs issue filed (see https://github.com/openzfs/zfs/issues/10891) outlining the problem and potential solutions. With the proper solutions being significant in terms of complexity and the priority of the issue being low for the time being, this patch exposes `zfs_vdev_open_timeout_ms` as a tunable so people that are experiencing this issue often can increase it as a workaround. Reviewed-by: Matthew Ahrens Reviewed-by: Richard Yao Reviewed-by: Alexander Motin Reviewed-by: Don Brady Reviewed-by: Brian Behlendorf Signed-off-by: Serapheim Dimitropoulos Closes #14133 --- man/man4/zfs.4 | 7 +++++++ module/os/linux/zfs/vdev_disk.c | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/man/man4/zfs.4 b/man/man4/zfs.4 index b317941bbd36..ed8914276376 100644 --- a/man/man4/zfs.4 +++ b/man/man4/zfs.4 @@ -1222,6 +1222,13 @@ Ideally, this will be at least the sum of each queue's .Sy max_active . .No See Sx ZFS I/O SCHEDULER . . +.It Sy zfs_vdev_open_timeout_ms Ns = Ns Sy 1000 Pq uint +Timeout value to wait before determining a device is missing +during import. +This is helpful for transient missing paths due +to links being briefly removed and recreated in response to +udev events. +. .It Sy zfs_vdev_rebuild_max_active Ns = Ns Sy 3 Pq int Maximum sequential resilver I/O operations active to each device. .No See Sx ZFS I/O SCHEDULER . diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c index d19595706ca0..2f84792d89be 100644 --- a/module/os/linux/zfs/vdev_disk.c +++ b/module/os/linux/zfs/vdev_disk.c @@ -56,7 +56,7 @@ static void *zfs_vdev_holder = VDEV_HOLDER; * device is missing. The missing path may be transient since the links * can be briefly removed and recreated in response to udev events. */ -static unsigned zfs_vdev_open_timeout_ms = 1000; +static uint_t zfs_vdev_open_timeout_ms = 1000; /* * Size of the "reserved" partition, in blocks. @@ -1020,3 +1020,6 @@ param_set_max_auto_ashift(const char *buf, zfs_kernel_param_t *kp) return (0); } + +ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, open_timeout_ms, UINT, ZMOD_RW, + "Timeout before determining that a device is missing"); From 957c3776f2ac211afaba0bb89f2592b6410a7a17 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Fri, 4 Nov 2022 14:06:14 -0400 Subject: [PATCH 68/84] FreeBSD: Fix out of bounds read in zfs_ioctl_ozfs_to_legacy() There is an off by 1 error in the check. Fortunately, this function does not appear to be used in kernel space, despite being compiled as part of the kernel module. However, it is used in userspace. Callers of lzc_ioctl_fd() likely will crash if they attempt to use the unimplemented request number. This was reported by FreeBSD's coverity scan. Reported-by: Coverity (CID 1432059) Reviewed-by: Ryan Moeller Reviewed-by: Damian Szuberski Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14135 --- module/os/freebsd/zfs/zfs_ioctl_compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/os/freebsd/zfs/zfs_ioctl_compat.c b/module/os/freebsd/zfs/zfs_ioctl_compat.c index 81967bed73f9..43156f2c6366 100644 --- a/module/os/freebsd/zfs/zfs_ioctl_compat.c +++ b/module/os/freebsd/zfs/zfs_ioctl_compat.c @@ -319,7 +319,7 @@ zfs_ioctl_legacy_to_ozfs(int request) int zfs_ioctl_ozfs_to_legacy(int request) { - if (request > ZFS_IOC_LAST) + if (request >= ZFS_IOC_LAST) return (-1); if (request > ZFS_IOC_PLATFORM) { From d9de079a4b9cde7b1a958512ce8948a57324c518 Mon Sep 17 00:00:00 2001 From: shodanshok Date: Fri, 11 Nov 2022 19:41:36 +0100 Subject: [PATCH 69/84] Fix arc_p aggressive increase The original ARC paper called for an initial 50/50 MRU/MFU split and this is accounted in various places where arc_p = arc_c >> 1, with further adjustment based on ghost lists size/hit. However, in current code both arc_adapt() and arc_get_data_impl() aggressively grow arc_p until arc_c is reached, causing unneeded pressure on MFU and greatly reducing its scan-resistance until ghost list adjustments kick in. This patch restores the original behavior of initially having arc_p as 1/2 of total ARC, without preventing MRU to use up to 100% total ARC when MFU is empty. Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Gionatan Danti Closes #14137 Closes #14120 --- module/zfs/arc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/zfs/arc.c b/module/zfs/arc.c index 8bf5ce09aabe..fe66fd83d1f5 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -5166,7 +5166,7 @@ arc_adapt(int bytes, arc_state_t *state) atomic_add_64(&arc_c, (int64_t)bytes); if (arc_c > arc_c_max) arc_c = arc_c_max; - else if (state == arc_anon) + else if (state == arc_anon && arc_p < arc_c >> 1) atomic_add_64(&arc_p, (int64_t)bytes); if (arc_p > arc_c) arc_p = arc_c; @@ -5379,7 +5379,8 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag, if (aggsum_upper_bound(&arc_sums.arcstat_size) < arc_c && hdr->b_l1hdr.b_state == arc_anon && (zfs_refcount_count(&arc_anon->arcs_size) + - zfs_refcount_count(&arc_mru->arcs_size) > arc_p)) + zfs_refcount_count(&arc_mru->arcs_size) > arc_p && + arc_p < arc_c >> 1)) arc_p = MIN(arc_c, arc_p + size); } } From fa7d572a8a3298d446fc4f64a263c125c325b7c8 Mon Sep 17 00:00:00 2001 From: Rich Ercolani <214141+rincebrain@users.noreply.github.com> Date: Tue, 15 Nov 2022 17:44:12 -0500 Subject: [PATCH 70/84] Handle and detect #13709's unlock regression (#14161) In #13709, as in #11294 before it, it turns out that 63a26454 still had the same failure mode as when it was first landed as d1d47691, and fails to unlock certain datasets that formerly worked. Rather than reverting it again, let's add handling to just throw out the accounting metadata that failed to unlock when that happens, as well as a test with a pre-broken pool image to ensure that we never get bitten by this again. Fixes: #13709 Signed-off-by: Rich Ercolani Reviewed-by: Brian Behlendorf Reviewed-by: Tony Hutter --- module/zfs/dsl_crypt.c | 23 +++++++-- tests/runfiles/common.run | 2 +- .../functional/userquota/13709_reproducer.bz2 | Bin 0 -> 135829 bytes .../tests/functional/userquota/Makefile.am | 4 +- .../userquota/userspace_encrypted_13709.ksh | 45 ++++++++++++++++++ 5 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2 create mode 100755 tests/zfs-tests/tests/functional/userquota/userspace_encrypted_13709.ksh diff --git a/module/zfs/dsl_crypt.c b/module/zfs/dsl_crypt.c index 1ea184de338c..bf1f55e68ff5 100644 --- a/module/zfs/dsl_crypt.c +++ b/module/zfs/dsl_crypt.c @@ -2672,6 +2672,7 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, objset_phys_t *osp = buf; uint8_t portable_mac[ZIO_OBJSET_MAC_LEN]; uint8_t local_mac[ZIO_OBJSET_MAC_LEN]; + const uint8_t zeroed_mac[ZIO_OBJSET_MAC_LEN] = {0}; /* look up the key from the spa's keystore */ ret = spa_keystore_lookup_key(spa, dsobj, FTAG, &dck); @@ -2694,10 +2695,24 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, return (0); } - if (bcmp(portable_mac, osp->os_portable_mac, ZIO_OBJSET_MAC_LEN) != 0 || - bcmp(local_mac, osp->os_local_mac, ZIO_OBJSET_MAC_LEN) != 0) { - abd_return_buf(abd, buf, datalen); - return (SET_ERROR(ECKSUM)); + if (memcmp(portable_mac, osp->os_portable_mac, + ZIO_OBJSET_MAC_LEN) != 0 || + memcmp(local_mac, osp->os_local_mac, ZIO_OBJSET_MAC_LEN) != 0) { + /* + * If the MAC is zeroed out, we failed to decrypt it. + * This should only arise, at least on Linux, + * if we hit edge case handling for useraccounting, since we + * shouldn't get here without bailing out on error earlier + * otherwise. + * + * So if we're in that case, we can just fall through and + * special-casing noticing that it's zero will handle it + * elsewhere, since we can just regenerate it. + */ + if (memcmp(local_mac, zeroed_mac, ZIO_OBJSET_MAC_LEN) != 0) { + abd_return_buf(abd, buf, datalen); + return (SET_ERROR(ECKSUM)); + } } abd_return_buf(abd, buf, datalen); diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run index 709bd2533aa6..f8c0f90548e6 100644 --- a/tests/runfiles/common.run +++ b/tests/runfiles/common.run @@ -892,7 +892,7 @@ tests = [ 'userquota_007_pos', 'userquota_008_pos', 'userquota_009_pos', 'userquota_010_pos', 'userquota_011_pos', 'userquota_012_neg', 'userspace_001_pos', 'userspace_002_pos', 'userspace_encrypted', - 'userspace_send_encrypted'] + 'userspace_send_encrypted', 'userspace_encrypted_13709'] tags = ['functional', 'userquota'] [tests/functional/vdev_zaps] diff --git a/tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2 b/tests/zfs-tests/tests/functional/userquota/13709_reproducer.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..9c31682794616688b758dcfd3b01530b6270f4fa GIT binary patch literal 135829 zcmagFcUV(P*Ek9YNJ0@pLKP*OBoLZ0(nRz~2oOSOp*JNOkS<6Q)FUOqgeD0ggeoQU zB2q*F6#^;&R0u@@u^^%-7Q}L_=jQ!=@BQu{_dd^E`+4?Wd(E0PGka#w%qoKm2;aZg z)*t2R|0A*@Q9@pH{@?#Ucz)-v-Nb5+6im`f8f+jXQ4ir85CA68+d!8nV{h1ul!6hI ziA}^>PQ5n-j078cOCOf@Dh3E_1e?HV@&;tc_$EHP#Q;J}*KKN6CJ?NQE618B27n*1w zl@6AW)RmAVNJvRYLDCHh!4gvG)zuP`_L8;|5)yJ!g-srZCF-SE5>N?usdO<(Hyte1 zBvCCPA$b_w3{}o?2MnZI(iu|eP%%Nm)*W_OM$9D!De3=titp}{x598F(oP zhIG1wgp9aC{{eAf%I*>dXv6gX)=vWbf9Mht2GZpJViNBEMN}ljBL4&beMm@D|Cjs! zG)XQ45+cEq0Hy!$`~MpOVI)Wr(nJ66g#U+9PoT+3z#Gz~XGjh% zSc&OsMcFJMgf|7MBT4d)g_TL5#C0Ie3LB)y1k@Q4&l5|XvzZ#D&e%DWX@O_tl? zWHE7O=cl3vdzF2msO95fkJX~{78R=6%gc=y%QW{`vF zq*^?KlLPUK_iB`RA$aIoPk<^*s%Jkrp~PveIH@HOn(8^8av2Y-DYq z6o*N@g5?o-2ojrxbw&dCF1)}4Q)V_^_QzQj|JN^U!npX`})=Jev;WIxGo7UCzeBPe6x5<~ks6v<>Zst~#_`k1q{{tz*V8~SFT=YX zp7&ZlKUOcYC`&Ou6Z?gX9pg9r8XC5e)xbE|fse~*gitcFW#tu68iuQW+YRrr8}ED2 zUH)zPb98Iny6WQm+c~4y4+X0F4zCsl?VP<$J-?kYyxjlf(Az<4S+?(a3V46jmq!-M zbz8mCjj`t^cKox?=yGQpuUQbX=imMFJKviB^;4?pMn_u{=P`yQcijdII`|c>D{mC? zHq7C~&a)?WCb-xgD?7ZF+hu>akn=z72E=VF;7}g|BTAortHYe@Ftc3|wq@K|_9Pm^ zKoF#pO?wTb7tTY95uHVpOzSQ1o+A&bhM1wUNp+~8IU+=+2#gu~wKDQ0U{_q5c^UXK zX~A&$@}YZSyfjM4TchoLQElb(+~vOW17o|qX;bs6&huCl>ChRbM-eDnHU0DC+#dI# z*(W>;4fUn~4Wl~^l5~<$V%zps_)A;<)4vk^E#E!5QEquv4e}vOJzs--qzvy6htI$V zdxb4vI2$4uqK8aYZs5a7eoW^d_Wp|Q`Fp`F=llo_s^N@xv!m5n4+u2l3GGT(eKySZ zP|EvaYx_2q;y4VZ2{-VlGz?YD#HG8{1CMj9yI#PpdmB~53pcd*{4N7xzo04m%R;Mh zq{yz*t-*8EU*yUUoH_Z<_>0K=^-oAKKLieze^&E2(0 zp{{OjK@pYAgAJ2kl*9k2^TPYXT!D#?4`>|K0>!ll7sf&P2>TFYj=H6yvzdHHb# z;Pljph2%H}c^{)x-N_CL1a14{o2UH>lv45_@L@&3vm0GQ)+coHDmQ*pH}!!pdc^#7 zqQGrXkZ>Z6`tlLA74+jn@>sZEL|nn6$+I#qw&h1xSQMLNWOl@8C@RR(0kjkBSqDBQh|^3ejJu=v3t+?096fWF$WXU>7zDuWU= z^NMmkkLij!-IICdkBF7b%(ok;-z)yAot+i3uy~}k%K0k?RfDmU2�}vCyf5>ajfW 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 $FILEDEV + +log_must zpool import -d $FILEDEV $POOLNAME + +echo -e 'password\npassword\n' | log_must zfs mount -al + +# Cleanup +cleanup + +log_pass "#13709 not happening here" From 2662b8e72be466a08140065077ae5d81be00a2dc Mon Sep 17 00:00:00 2001 From: Laura Hild Date: Fri, 18 Nov 2022 14:36:19 -0500 Subject: [PATCH 71/84] Correct multipathd.target to .service https://github.com/openzfs/zfs/pull/9863 says it "orders zfs-import-cache.service and zfs-import-scan.service after multipathd.service" but the commit (79add96) actually ordered them after .target. Reviewed-by: Brian Behlendorf Signed-off-by: Laura Hild Closes #12709 Closes #14171 --- etc/systemd/system/zfs-import-cache.service.in | 2 +- etc/systemd/system/zfs-import-scan.service.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/systemd/system/zfs-import-cache.service.in b/etc/systemd/system/zfs-import-cache.service.in index 5e5c6281c9d7..e841ca5596c2 100644 --- a/etc/systemd/system/zfs-import-cache.service.in +++ b/etc/systemd/system/zfs-import-cache.service.in @@ -5,7 +5,7 @@ DefaultDependencies=no Requires=systemd-udev-settle.service After=systemd-udev-settle.service After=cryptsetup.target -After=multipathd.target +After=multipathd.service After=systemd-remount-fs.service Before=zfs-import.target ConditionFileNotEmpty=@sysconfdir@/zfs/zpool.cache diff --git a/etc/systemd/system/zfs-import-scan.service.in b/etc/systemd/system/zfs-import-scan.service.in index d3c083f7e9cf..598ef501baa6 100644 --- a/etc/systemd/system/zfs-import-scan.service.in +++ b/etc/systemd/system/zfs-import-scan.service.in @@ -5,7 +5,7 @@ DefaultDependencies=no Requires=systemd-udev-settle.service After=systemd-udev-settle.service After=cryptsetup.target -After=multipathd.target +After=multipathd.service Before=zfs-import.target ConditionFileNotEmpty=!@sysconfdir@/zfs/zpool.cache ConditionPathIsDirectory=/sys/module/zfs From ad0379bf0ef1aaa8cb1f35ec13e3ffbd8b0f1aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Wed, 12 Jan 2022 17:37:40 +0100 Subject: [PATCH 72/84] linux: libspl: zone: () -> (void) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #12968 --- lib/libspl/os/linux/zone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libspl/os/linux/zone.c b/lib/libspl/os/linux/zone.c index a71c4e0b275b..393a16ad5cdd 100644 --- a/lib/libspl/os/linux/zone.c +++ b/lib/libspl/os/linux/zone.c @@ -26,7 +26,7 @@ #include zoneid_t -getzoneid() +getzoneid(void) { return (GLOBAL_ZONEID); } From 670d66e7a070854c9f1efa54a5362af39841d2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Thu, 7 Apr 2022 04:25:05 +0200 Subject: [PATCH 73/84] tests: cmd: draid: remove unused and undocumented -v MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found with -Wunused-but-set-variable on Clang trunk Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #13304 --- tests/zfs-tests/cmd/draid/draid.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/zfs-tests/cmd/draid/draid.c b/tests/zfs-tests/cmd/draid/draid.c index 57261348b3cd..0a7c4bc965fc 100644 --- a/tests/zfs-tests/cmd/draid/draid.c +++ b/tests/zfs-tests/cmd/draid/draid.c @@ -1318,14 +1318,11 @@ static int draid_merge(int argc, char *argv[]) { char filename[MAXPATHLEN]; - int c, error, total_merged = 0, verbose = 0; + int c, error, total_merged = 0; nvlist_t *allcfgs; - while ((c = getopt(argc, argv, ":v")) != -1) { + while ((c = getopt(argc, argv, ":")) != -1) { switch (c) { - case 'v': - verbose++; - break; case ':': (void) fprintf(stderr, "missing argument for '%c' option\n", optopt); From 32f7499acf3546d7275ac0410525dae731afa11d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Thu, 7 Apr 2022 04:26:30 +0200 Subject: [PATCH 74/84] module: zfs: vdev_removal: remove unused num_indirect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found with -Wunused-but-set-variable on Clang trunk Fixes: a1d477c24c ("OpenZFS 7614, 9064 - zfs device evacuation/removal") Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #13304 --- module/zfs/vdev_removal.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/module/zfs/vdev_removal.c b/module/zfs/vdev_removal.c index 48bd20b2169f..12cc654c8d18 100644 --- a/module/zfs/vdev_removal.c +++ b/module/zfs/vdev_removal.c @@ -2056,7 +2056,6 @@ spa_vdev_remove_top_check(vdev_t *vd) * and not be raidz or draid. */ vdev_t *rvd = spa->spa_root_vdev; - int num_indirect = 0; for (uint64_t id = 0; id < rvd->vdev_children; id++) { vdev_t *cvd = rvd->vdev_child[id]; @@ -2072,8 +2071,6 @@ spa_vdev_remove_top_check(vdev_t *vd) if (cvd->vdev_ashift != 0 && cvd->vdev_alloc_bias == VDEV_BIAS_NONE) ASSERT3U(cvd->vdev_ashift, ==, spa->spa_max_ashift); - if (cvd->vdev_ops == &vdev_indirect_ops) - num_indirect++; if (!vdev_is_concrete(cvd)) continue; if (vdev_get_nparity(cvd) != 0) From 108c07c655be5228ca0adb7e4e8186d9e66cbc6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Tue, 10 May 2022 23:28:02 +0200 Subject: [PATCH 75/84] Remove final K&R definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clang trunk now warns -Wstrict-prototypes on this, and they're removed in C2x Reviewed-by: Brian Behlendorf Signed-off-by: Ahelenia Ziemiańska Closes #13447 --- cmd/zed/agents/zfs_mod.c | 4 ++-- cmd/zed/zed_disk_event.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/zed/agents/zfs_mod.c b/cmd/zed/agents/zfs_mod.c index 22447100b6ab..c53b431dc892 100644 --- a/cmd/zed/agents/zfs_mod.c +++ b/cmd/zed/agents/zfs_mod.c @@ -1212,7 +1212,7 @@ zfs_enum_pools(void *arg) * For now, each agent has its own libzfs instance */ int -zfs_slm_init() +zfs_slm_init(void) { if ((g_zfshdl = libzfs_init()) == NULL) return (-1); @@ -1238,7 +1238,7 @@ zfs_slm_init() } void -zfs_slm_fini() +zfs_slm_fini(void) { unavailpool_t *pool; pendingdev_t *device; diff --git a/cmd/zed/zed_disk_event.c b/cmd/zed/zed_disk_event.c index e31ec4cfc7e7..3c8e2fb38c15 100644 --- a/cmd/zed/zed_disk_event.c +++ b/cmd/zed/zed_disk_event.c @@ -402,7 +402,7 @@ zed_udev_monitor(void *arg) } int -zed_disk_event_init() +zed_disk_event_init(void) { int fd, fflags; @@ -438,7 +438,7 @@ zed_disk_event_init() } void -zed_disk_event_fini() +zed_disk_event_fini(void) { /* cancel monitor thread at recvmsg() */ (void) pthread_cancel(g_mon_tid); @@ -456,13 +456,13 @@ zed_disk_event_fini() #include "zed_disk_event.h" int -zed_disk_event_init() +zed_disk_event_init(void) { return (0); } void -zed_disk_event_fini() +zed_disk_event_fini(void) { } From 3d1e8080960886cf9d542e318a400a185c521806 Mon Sep 17 00:00:00 2001 From: Damian Szuberski Date: Thu, 16 Jun 2022 07:20:28 +1000 Subject: [PATCH 76/84] Fix clang 13 compilation errors ``` os/linux/zfs/zvol_os.c:1111:3: error: ignoring return value of function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result] add_disk(zv->zv_zso->zvo_disk); ^~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ zpl_xattr.c:1579:1: warning: no previous prototype for function 'zpl_posix_acl_release_impl' [-Wmissing-prototypes] ``` Reviewed-by: Brian Behlendorf Signed-off-by: szubersk Closes #13551 (cherry picked from commit 988431966639d791ac269011d136e85f3602df75) --- config/kernel-add-disk.m4 | 3 +-- module/os/linux/zfs/zpl_xattr.c | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config/kernel-add-disk.m4 b/config/kernel-add-disk.m4 index 44a8a5fd25b6..86d81ea325b9 100644 --- a/config/kernel-add-disk.m4 +++ b/config/kernel-add-disk.m4 @@ -7,8 +7,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_ADD_DISK], [ #include ], [ struct gendisk *disk = NULL; - int err = add_disk(disk); - err = err; + int error __attribute__ ((unused)) = add_disk(disk); ]) ]) diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c index e088db5d29cf..bd5d5803fb00 100644 --- a/module/os/linux/zfs/zpl_xattr.c +++ b/module/os/linux/zfs/zpl_xattr.c @@ -1414,7 +1414,9 @@ zpl_xattr_handler(const char *name) return (NULL); } -#if !defined(HAVE_POSIX_ACL_RELEASE) || defined(HAVE_POSIX_ACL_RELEASE_GPL_ONLY) +#if defined(CONFIG_FS_POSIX_ACL) && \ + (!defined(HAVE_POSIX_ACL_RELEASE) || \ + defined(HAVE_POSIX_ACL_RELEASE_GPL_ONLY)) struct acl_rel_struct { struct acl_rel_struct *next; struct posix_acl *acl; From 0e3abd29945b6d6a4f89892445f4d85bcb1d1e92 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Tue, 29 Nov 2022 12:53:33 -0500 Subject: [PATCH 77/84] Lua: Fix bad bitshift in lua_strx2number() The port of lua to OpenZFS modified lua to use int64_t for numbers instead of double. As part of this, a function for calculating exponentiation was replaced with a bit shift. Unfortunately, it did not handle negative values. Also, it only supported exponents numbers with 7 digits before before overflow. This supports exponents up to 15 digits before overflow. Clang's static analyzer reported this as "Result of operation is garbage or undefined" because the exponent was negative. Reviewed-by: Damian Szuberski Reviewed-by: Brian Behlendorf Signed-off-by: Richard Yao Closes #14204 --- module/lua/lobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/lua/lobject.c b/module/lua/lobject.c index 024d3199fe24..5d88d36c5fd7 100644 --- a/module/lua/lobject.c +++ b/module/lua/lobject.c @@ -144,7 +144,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { *endptr = cast(char *, s); /* valid up to here */ ret: if (neg) r = -r; - return (r * (1 << e)); + return ((e >= 0) ? (r * (1ULL << e)) : (r / (1ULL << -e))); } #endif From e48aaef89f3eba71da5ce6c12384348a698a5b29 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sun, 20 Nov 2022 18:04:08 -0500 Subject: [PATCH 78/84] Fix NULL pointer dereference in dbuf_prefetch_indirect_done() When ZFS is built with assertions, a prefetch is done on a redacted blkptr and `dpa->dpa_dnode` is NULL, we will have a NULL pointer dereference in `dbuf_prefetch_indirect_done()`. Both Coverity and Clang's Static Analyzer caught this. Reported-by: Coverity (CID 1524671) Reviewed-by: Brian Behlendorf Reviewed-by: Ryan Moeller Signed-off-by: Richard Yao Closes #14210 --- module/zfs/dbuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c index 7ecc2812b4e4..53f5775c9e8e 100644 --- a/module/zfs/dbuf.c +++ b/module/zfs/dbuf.c @@ -3300,10 +3300,10 @@ dbuf_prefetch_indirect_done(zio_t *zio, const zbookmark_phys_t *zb, blkptr_t *bp = ((blkptr_t *)abuf->b_data) + P2PHASE(nextblkid, 1ULL << dpa->dpa_epbs); - ASSERT(!BP_IS_REDACTED(bp) || + ASSERT(!BP_IS_REDACTED(bp) || (dpa->dpa_dnode && dsl_dataset_feature_is_active( dpa->dpa_dnode->dn_objset->os_dsl_dataset, - SPA_FEATURE_REDACTED_DATASETS)); + SPA_FEATURE_REDACTED_DATASETS))); if (BP_IS_HOLE(bp) || BP_IS_REDACTED(bp)) { dbuf_prefetch_fini(dpa, B_TRUE); } else if (dpa->dpa_curlevel == dpa->dpa_zb.zb_level) { From c4468a70c35c92b434aeb7efdccc69370b5e2dc8 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Tue, 29 Nov 2022 09:51:35 -0800 Subject: [PATCH 79/84] Don't leak packed recieved proprties When local properties (e.g., from -o and -x) are provided, don't leak the packed representation of the received properties due to variable reuse. Reviewed-by: Brian Behlendorf Signed-off-by: Brooks Davis Closes #14197 --- lib/libzfs_core/libzfs_core.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/libzfs_core/libzfs_core.c b/lib/libzfs_core/libzfs_core.c index 855d8cb0afb9..9b2050c67628 100644 --- a/lib/libzfs_core/libzfs_core.c +++ b/lib/libzfs_core/libzfs_core.c @@ -890,7 +890,8 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops, fnvlist_free(outnvl); } else { zfs_cmd_t zc = {"\0"}; - char *packed = NULL; + char *rp_packed = NULL; + char *lp_packed = NULL; size_t size; ASSERT3S(g_refcount, >, 0); @@ -899,14 +900,14 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops, (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); if (recvdprops != NULL) { - packed = fnvlist_pack(recvdprops, &size); - zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed; + rp_packed = fnvlist_pack(recvdprops, &size); + zc.zc_nvlist_src = (uint64_t)(uintptr_t)rp_packed; zc.zc_nvlist_src_size = size; } if (localprops != NULL) { - packed = fnvlist_pack(localprops, &size); - zc.zc_nvlist_conf = (uint64_t)(uintptr_t)packed; + lp_packed = fnvlist_pack(localprops, &size); + zc.zc_nvlist_conf = (uint64_t)(uintptr_t)lp_packed; zc.zc_nvlist_conf_size = size; } @@ -941,8 +942,10 @@ recv_impl(const char *snapname, nvlist_t *recvdprops, nvlist_t *localprops, zc.zc_nvlist_dst_size, errors, KM_SLEEP)); } - if (packed != NULL) - fnvlist_pack_free(packed, size); + if (rp_packed != NULL) + fnvlist_pack_free(rp_packed, size); + if (lp_packed != NULL) + fnvlist_pack_free(lp_packed, size); free((void *)(uintptr_t)zc.zc_nvlist_dst); } From 2c50512ad2c6a53964be82420b819406bae69a89 Mon Sep 17 00:00:00 2001 From: Damian Szuberski Date: Thu, 17 Nov 2022 03:27:53 +1000 Subject: [PATCH 80/84] Make autodetection disable pyzfs for kernel/srpm configurations Reviewed-by: Brian Behlendorf Reviewed-by: Richard Yao Signed-off-by: szubersk Closes #13394 Closes #14178 --- config/always-pyzfs.m4 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/config/always-pyzfs.m4 b/config/always-pyzfs.m4 index 00e5d0e2cbbd..efea49f5f025 100644 --- a/config/always-pyzfs.m4 +++ b/config/always-pyzfs.m4 @@ -46,6 +46,16 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [ ]) AC_SUBST(DEFINE_PYZFS) + dnl # + dnl # Autodetection disables pyzfs if kernel or srpm config + dnl # + AS_IF([test "x$enable_pyzfs" = xcheck], [ + AS_IF([test "x$ZFS_CONFIG" = xkernel -o "x$ZFS_CONFIG" = xsrpm ], [ + enable_pyzfs=no + AC_MSG_NOTICE([Disabling pyzfs for kernel/srpm config]) + ]) + ]) + dnl # dnl # Python "packaging" (or, failing that, "distlib") module is required to build and install pyzfs dnl # From c8d2ab05e1e6bf21185723fabdebbe5bb3374381 Mon Sep 17 00:00:00 2001 From: George Amanakis Date: Fri, 18 Nov 2022 20:38:37 +0100 Subject: [PATCH 81/84] Fix setting the large_block feature after receiving a snapshot We are not allowed to dirty a filesystem when done receiving a snapshot. In this case the flag SPA_FEATURE_LARGE_BLOCKS will not be set on that filesystem since the filesystem is not on dp_dirty_datasets, and a subsequent encrypted raw send will fail. Fix this by checking in dsl_dataset_snapshot_sync_impl() if the feature needs to be activated and do so if appropriate. Reviewed-by: Brian Behlendorf Signed-off-by: George Amanakis Closes #13699 Closes #13782 --- module/zfs/dsl_dataset.c | 15 ++++ tests/runfiles/common.run | 2 +- .../tests/functional/rsend/Makefile.am | 1 + .../rsend/send_raw_large_blocks.ksh | 78 +++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100755 tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh diff --git a/module/zfs/dsl_dataset.c b/module/zfs/dsl_dataset.c index 0a460213ded7..71d876caed9e 100644 --- a/module/zfs/dsl_dataset.c +++ b/module/zfs/dsl_dataset.c @@ -1747,6 +1747,21 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname, } } + /* + * We are not allowed to dirty a filesystem when done receiving + * a snapshot. In this case the flag SPA_FEATURE_LARGE_BLOCKS will + * not be set and a subsequent encrypted raw send will fail. Hence + * activate this feature if needed here. + */ + for (spa_feature_t f = 0; f < SPA_FEATURES; f++) { + if (zfeature_active(f, ds->ds_feature_activation[f]) && + !(zfeature_active(f, ds->ds_feature[f]))) { + dsl_dataset_activate_feature(dsobj, f, + ds->ds_feature_activation[f], tx); + ds->ds_feature[f] = ds->ds_feature_activation[f]; + } + } + ASSERT3U(ds->ds_prev != 0, ==, dsl_dataset_phys(ds)->ds_prev_snap_obj != 0); if (ds->ds_prev) { diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run index f8c0f90548e6..bd3d4d58e788 100644 --- a/tests/runfiles/common.run +++ b/tests/runfiles/common.run @@ -828,7 +828,7 @@ tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos', 'send_realloc_encrypted_files', 'send_spill_block', 'send_holds', 'send_hole_birth', 'send_mixed_raw', 'send-wR_encrypted_zvol', 'send_partial_dataset', 'send_invalid', 'send_doall', - 'send_raw_spill_block', 'send_raw_ashift'] + 'send_raw_spill_block', 'send_raw_ashift', 'send_raw_large_blocks'] tags = ['functional', 'rsend'] [tests/functional/scrub_mirror] diff --git a/tests/zfs-tests/tests/functional/rsend/Makefile.am b/tests/zfs-tests/tests/functional/rsend/Makefile.am index b8eb54f64c3e..6bc243f32a3c 100644 --- a/tests/zfs-tests/tests/functional/rsend/Makefile.am +++ b/tests/zfs-tests/tests/functional/rsend/Makefile.am @@ -50,6 +50,7 @@ dist_pkgdata_SCRIPTS = \ send_realloc_encrypted_files.ksh \ send_spill_block.ksh \ send_raw_spill_block.ksh \ + send_raw_large_blocks.ksh \ send_raw_ashift.ksh \ send_holds.ksh \ send_hole_birth.ksh \ diff --git a/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh b/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh new file mode 100755 index 000000000000..39e93a7df3c2 --- /dev/null +++ b/tests/zfs-tests/tests/functional/rsend/send_raw_large_blocks.ksh @@ -0,0 +1,78 @@ +#!/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, George Amanakis. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/rsend/rsend.kshlib + +# +# Description: +# Receiving a snapshot with large blocks and raw sending it succeeds. +# +# Strategy: +# 1) Create a set of files each containing some file data in an +# encrypted filesystem with recordsize=1m. +# 2) Snapshot and send with large_blocks enabled to a new filesystem. +# 3) Raw send to a file. If the large_blocks feature is not activated +# in the filesystem created in (2) the raw send will fail. +# + +verify_runnable "both" + +log_assert "Receiving and raw sending a snapshot with large blocks succeeds" + +backup=$TEST_BASE_DIR/backup +raw_backup=$TEST_BASE_DIR/raw_backup + +function cleanup +{ + log_must rm -f $backup $raw_backup $ibackup $unc_backup + destroy_pool pool_lb/fs + log_must rm -f $TESTDIR/vdev_a +} + +log_onexit cleanup + +typeset passphrase="password" +typeset file="/pool_lb/fs/$TESTFILE0" + +# Create pool +truncate -s $MINVDEVSIZE $TESTDIR/vdev_a +log_must zpool create -f -o feature@large_blocks=enabled pool_lb $TESTDIR/vdev_a + +log_must eval "echo $passphrase > /pool_lb/pwd" + +log_must zfs create -o recordsize=1m pool_lb/fs +log_must dd if=/dev/urandom of=$file bs=1024 count=1024 +log_must zfs snapshot pool_lb/fs@snap1 + +log_must eval "zfs send -L pool_lb/fs@snap1 > $backup" +log_must eval "zfs recv -o encryption=aes-256-ccm -o keyformat=passphrase \ + -o keylocation=file:///pool_lb/pwd -o primarycache=none \ + -o recordsize=1m pool_lb/testfs5 < $backup" + +log_must eval "zfs send --raw pool_lb/testfs5@snap1 > $raw_backup" + +log_pass "Receiving and raw sending a snapshot with large blocks succeeds" From 7819b12f2cf2f77f8c4cfc7d11328fab7b5feb32 Mon Sep 17 00:00:00 2001 From: Tony Hutter Date: Thu, 1 Dec 2022 10:21:12 -0800 Subject: [PATCH 82/84] zfs-2.1.7: Use ubuntu-20.04 for zloop and sanity builders The zfs-2.1.7 branch is still using the older 'python-dev' package names rather than the newer 'python3-dev' packages that are required for 'ubuntu-latest'. Use 'ubuntu-20.04' instead of 'ubuntu-latest' to get around this. Signed-off-by: Tony Hutter --- .github/workflows/zfs-tests-sanity.yml | 2 +- .github/workflows/zloop.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/zfs-tests-sanity.yml b/.github/workflows/zfs-tests-sanity.yml index 875ca4d94496..c56355623002 100644 --- a/.github/workflows/zfs-tests-sanity.yml +++ b/.github/workflows/zfs-tests-sanity.yml @@ -6,7 +6,7 @@ on: jobs: tests: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/zloop.yml b/.github/workflows/zloop.yml index f9caa9ed4ba0..1c42491ee912 100644 --- a/.github/workflows/zloop.yml +++ b/.github/workflows/zloop.yml @@ -6,7 +6,7 @@ on: jobs: tests: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: TEST_DIR: /var/tmp/zloop steps: From 21bd7661334cd865d17934bebbcaf8d3356279ee Mon Sep 17 00:00:00 2001 From: Tony Hutter Date: Wed, 30 Nov 2022 13:09:04 -0800 Subject: [PATCH 83/84] Tag zfs-2.1.7 META file and changelog updated. Signed-off-by: Tony Hutter --- META | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/META b/META index b71577f0eca4..7879ff1d0abf 100644 --- a/META +++ b/META @@ -1,7 +1,7 @@ Meta: 1 Name: zfs Branch: 1.0 -Version: 2.1.6 +Version: 2.1.7 Release: 1 Release-Tags: relext License: CDDL From 45765ab6260cc50cef349ae2ba1a4f35c902d29f Mon Sep 17 00:00:00 2001 From: Ryan Moeller Date: Tue, 6 Dec 2022 19:10:29 +0000 Subject: [PATCH 84/84] Bump changelog for zfs-2.1.7 Signed-off-by: Ryan Moeller --- contrib/truenas/changelog | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contrib/truenas/changelog b/contrib/truenas/changelog index a426dbae76eb..79177c41f390 100644 --- a/contrib/truenas/changelog +++ b/contrib/truenas/changelog @@ -1,3 +1,17 @@ +openzfs (2.1.7-0) unstable; urgency=medium + + * Merge tag zfs-2.1.7 + * Expose libzutil error info in libpc_handle_t + * Build packages with debug symbols + * Add support for overlayfs for docker + * Optimize microzaps + * zed: Avoid core dump if wholedisk property does not exist + * zed: post a udev change event from spa_vdev_attach() + * SCALE: ignore wholedisk + * Skip trivial permission checks on xattrs for POSIX ACL type + + -- Ryan Moeller Wed, 07 Dec 2022 16:00:00 -0500 + openzfs (2.1.6-0) unstable; urgency=medium * Merge tag zfs-2.1.6