diff --git a/cmd/zed/zed.d/Makefile.am b/cmd/zed/zed.d/Makefile.am index c65b43fb02..812558cf6d 100644 --- a/cmd/zed/zed.d/Makefile.am +++ b/cmd/zed/zed.d/Makefile.am @@ -16,6 +16,7 @@ dist_zedexec_SCRIPTS = \ %D%/scrub_finish-notify.sh \ %D%/statechange-led.sh \ %D%/statechange-notify.sh \ + %D%/statechange-slot_off.sh \ %D%/trim_finish-notify.sh \ %D%/vdev_attach-led.sh \ %D%/vdev_clear-led.sh @@ -35,6 +36,7 @@ zedconfdefaults = \ scrub_finish-notify.sh \ statechange-led.sh \ statechange-notify.sh \ + statechange-slot_off.sh \ vdev_attach-led.sh \ vdev_clear-led.sh diff --git a/cmd/zed/zed.d/statechange-slot_off.sh b/cmd/zed/zed.d/statechange-slot_off.sh index d6f3c94a41..150012abe7 100755 --- a/cmd/zed/zed.d/statechange-slot_off.sh +++ b/cmd/zed/zed.d/statechange-slot_off.sh @@ -1,4 +1,5 @@ #!/bin/sh +# shellcheck disable=SC3014,SC2154,SC2086,SC2034 # # Turn off disk's enclosure slot if it becomes FAULTED. # @@ -43,15 +44,17 @@ if [ ! -f "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" ] ; then exit 4 fi -echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" - -# Wait for sysfs for report that the slot is off. It can take ~400ms on some -# enclosures. +# Turn off the slot and wait for sysfs to report that the slot is off. +# It can take ~400ms on some enclosures and multiple retries may be needed. for i in $(seq 1 20) ; do - if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then - break - fi - sleep 0.1 + echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" + + for j in $(seq 1 5) ; do + if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then + break 2 + fi + sleep 0.1 + done done if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" != "off" ] ; then diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 10a3b5b14f..6d0dae8d8b 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -3143,6 +3143,7 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, nvlist_t *props, int flags) { int ret = 0; + int ms_status = 0; zpool_handle_t *zhp; const char *name; uint64_t version; @@ -3232,10 +3233,15 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, ret = 1; if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && - !(flags & ZFS_IMPORT_ONLY) && - zpool_enable_datasets(zhp, mntopts, 0) != 0) { - zpool_close(zhp); - return (1); + !(flags & ZFS_IMPORT_ONLY)) { + ms_status = zpool_enable_datasets(zhp, mntopts, 0); + if (ms_status == EZFS_SHAREFAILED) { + (void) fprintf(stderr, gettext("Import was " + "successful, but unable to share some datasets")); + } else if (ms_status == EZFS_MOUNTFAILED) { + (void) fprintf(stderr, gettext("Import was " + "successful, but unable to mount some datasets")); + } } zpool_close(zhp); @@ -6755,6 +6761,7 @@ zpool_do_split(int argc, char **argv) char *mntopts = NULL; splitflags_t flags; int c, ret = 0; + int ms_status = 0; boolean_t loadkeys = B_FALSE; zpool_handle_t *zhp; nvlist_t *config, *props = NULL; @@ -6891,13 +6898,18 @@ zpool_do_split(int argc, char **argv) ret = 1; } - if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && - zpool_enable_datasets(zhp, mntopts, 0) != 0) { - ret = 1; - (void) fprintf(stderr, gettext("Split was successful, but " - "the datasets could not all be mounted\n")); - (void) fprintf(stderr, gettext("Try doing '%s' with a " - "different altroot\n"), "zpool import"); + if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) { + ms_status = zpool_enable_datasets(zhp, mntopts, 0); + if (ms_status == EZFS_SHAREFAILED) { + (void) fprintf(stderr, gettext("Split was successful, " + "datasets are mounted but sharing of some datasets " + "has failed\n")); + } else if (ms_status == EZFS_MOUNTFAILED) { + (void) fprintf(stderr, gettext("Split was successful" + ", but some datasets could not be mounted\n")); + (void) fprintf(stderr, gettext("Try doing '%s' with a " + "different altroot\n"), "zpool import"); + } } zpool_close(zhp); nvlist_free(config); diff --git a/contrib/debian/openzfs-zfsutils.install b/contrib/debian/openzfs-zfsutils.install index 0f58508f00..301d8f67b3 100644 --- a/contrib/debian/openzfs-zfsutils.install +++ b/contrib/debian/openzfs-zfsutils.install @@ -60,7 +60,6 @@ usr/share/man/man8/zfs-get.8 usr/share/man/man8/zfs-groupspace.8 usr/share/man/man8/zfs-hold.8 usr/share/man/man8/zfs-inherit.8 -usr/share/man/man8/zfs-jail.8 usr/share/man/man8/zfs-list.8 usr/share/man/man8/zfs-load-key.8 usr/share/man/man8/zfs-mount-generator.8 @@ -80,7 +79,6 @@ usr/share/man/man8/zfs-set.8 usr/share/man/man8/zfs-share.8 usr/share/man/man8/zfs-snapshot.8 usr/share/man/man8/zfs-unallow.8 -usr/share/man/man8/zfs-unjail.8 usr/share/man/man8/zfs-unload-key.8 usr/share/man/man8/zfs-unmount.8 usr/share/man/man8/zfs-unzone.8 diff --git a/include/libzfs.h b/include/libzfs.h index a7037e3e62..fa05b7921b 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -156,6 +156,7 @@ typedef enum zfs_error { EZFS_NOT_USER_NAMESPACE, /* a file is not a user namespace */ EZFS_CKSUM, /* insufficient replicas */ EZFS_RESUME_EXISTS, /* Resume on existing dataset without force */ + EZFS_SHAREFAILED, /* filesystem share failed */ EZFS_UNKNOWN } zfs_error_t; diff --git a/include/os/linux/kernel/linux/simd_x86.h b/include/os/linux/kernel/linux/simd_x86.h index c324d3aca8..4e99c2d1c2 100644 --- a/include/os/linux/kernel/linux/simd_x86.h +++ b/include/os/linux/kernel/linux/simd_x86.h @@ -126,6 +126,15 @@ extern void kfpu_end(void); #error "Toolchain needs to support the XSAVE assembler instruction" #endif +#ifndef XFEATURE_MASK_XTILE +/* + * For kernels where this doesn't exist yet, we still don't want to break + * by save/restoring this broken nonsense. + * See issue #14989 or Intel errata SPR4 for why + */ +#define XFEATURE_MASK_XTILE 0x60000 +#endif + #include #include @@ -294,18 +303,18 @@ kfpu_begin(void) uint8_t *state = zfs_kfpu_fpregs[smp_processor_id()]; #if defined(HAVE_XSAVES) if (static_cpu_has(X86_FEATURE_XSAVES)) { - kfpu_do_xsave("xsaves", state, ~0); + kfpu_do_xsave("xsaves", state, ~XFEATURE_MASK_XTILE); return; } #endif #if defined(HAVE_XSAVEOPT) if (static_cpu_has(X86_FEATURE_XSAVEOPT)) { - kfpu_do_xsave("xsaveopt", state, ~0); + kfpu_do_xsave("xsaveopt", state, ~XFEATURE_MASK_XTILE); return; } #endif if (static_cpu_has(X86_FEATURE_XSAVE)) { - kfpu_do_xsave("xsave", state, ~0); + kfpu_do_xsave("xsave", state, ~XFEATURE_MASK_XTILE); } else if (static_cpu_has(X86_FEATURE_FXSR)) { kfpu_save_fxsr(state); } else { @@ -355,12 +364,12 @@ kfpu_end(void) uint8_t *state = zfs_kfpu_fpregs[smp_processor_id()]; #if defined(HAVE_XSAVES) if (static_cpu_has(X86_FEATURE_XSAVES)) { - kfpu_do_xrstor("xrstors", state, ~0); + kfpu_do_xrstor("xrstors", state, ~XFEATURE_MASK_XTILE); goto out; } #endif if (static_cpu_has(X86_FEATURE_XSAVE)) { - kfpu_do_xrstor("xrstor", state, ~0); + kfpu_do_xrstor("xrstor", state, ~XFEATURE_MASK_XTILE); } else if (static_cpu_has(X86_FEATURE_FXSR)) { kfpu_restore_fxsr(state); } else { diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index 5d1fe651c9..b38ad88096 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -1300,7 +1300,7 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags) zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used, zfs_mount_one, &ms, B_TRUE); if (ms.ms_mntstatus != 0) - ret = ms.ms_mntstatus; + ret = EZFS_MOUNTFAILED; /* * Share all filesystems that need to be shared. This needs to be @@ -1311,7 +1311,7 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags) zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used, zfs_share_one, &ms, B_FALSE); if (ms.ms_mntstatus != 0) - ret = ms.ms_mntstatus; + ret = EZFS_SHAREFAILED; else zfs_commit_shares(NULL); diff --git a/man/Makefile.am b/man/Makefile.am index 2973520324..36c1aede10 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -38,7 +38,6 @@ dist_man_MANS = \ %D%/man8/zfs-groupspace.8 \ %D%/man8/zfs-hold.8 \ %D%/man8/zfs-inherit.8 \ - %D%/man8/zfs-jail.8 \ %D%/man8/zfs-list.8 \ %D%/man8/zfs-load-key.8 \ %D%/man8/zfs-mount.8 \ @@ -57,14 +56,11 @@ dist_man_MANS = \ %D%/man8/zfs-share.8 \ %D%/man8/zfs-snapshot.8 \ %D%/man8/zfs-unallow.8 \ - %D%/man8/zfs-unjail.8 \ %D%/man8/zfs-unload-key.8 \ %D%/man8/zfs-unmount.8 \ - %D%/man8/zfs-unzone.8 \ %D%/man8/zfs-upgrade.8 \ %D%/man8/zfs-userspace.8 \ %D%/man8/zfs-wait.8 \ - %D%/man8/zfs-zone.8 \ %D%/man8/zfs_ids_to_path.8 \ %D%/man8/zgenhostid.8 \ %D%/man8/zinject.8 \ @@ -104,6 +100,18 @@ dist_man_MANS = \ %D%/man8/zstreamdump.8 \ %D%/man8/zpool_influxdb.8 +if BUILD_FREEBSD +dist_man_MANS += \ + %D%/man8/zfs-jail.8 \ + %D%/man8/zfs-unjail.8 +endif + +if BUILD_LINUX +dist_man_MANS += \ + %D%/man8/zfs-unzone.8 \ + %D%/man8/zfs-zone.8 +endif + nodist_man_MANS = \ %D%/man8/zed.8 \ %D%/man8/zfs-mount-generator.8 diff --git a/man/man7/zfsprops.7 b/man/man7/zfsprops.7 index b219d752e0..b0e73c1c2a 100644 --- a/man/man7/zfsprops.7 +++ b/man/man7/zfsprops.7 @@ -38,7 +38,7 @@ .\" Copyright (c) 2019, Kjeld Schouten-Lebbing .\" Copyright (c) 2022 Hewlett Packard Enterprise Development LP. .\" -.Dd April 18, 2023 +.Dd August 8, 2023 .Dt ZFSPROPS 7 .Os . @@ -1911,13 +1911,15 @@ See for more information. Jails are a .Fx -feature and are not relevant on other platforms. -The default value is -.Sy off . -.It Sy zoned Ns = Ns Sy on Ns | Ns Sy off +feature and this property is not available on other platforms. +.It Sy zoned Ns = Ns Sy off Ns | Ns Sy on Controls whether the dataset is managed from a non-global zone or namespace. -The default value is -.Sy off . +See +.Xr zfs-zone 8 +for more information. +Zoning is a +Linux +feature and this property is not available on other platforms. .El .Pp The following three properties cannot be changed after the file system is diff --git a/man/man8/zpool.8 b/man/man8/zpool.8 index e8eadffa6f..4c4020bdd8 100644 --- a/man/man8/zpool.8 +++ b/man/man8/zpool.8 @@ -110,9 +110,10 @@ Removes ZFS label information from the specified .It Xo .Xr zpool-attach 8 Ns / Ns Xr zpool-detach 8 .Xc -Increases or decreases redundancy by -.Cm attach Ns ing or -.Cm detach Ns ing a device on an existing vdev (virtual device). +Converts a non-redundant disk into a mirror, or increases +the redundancy level of an existing mirror +.Cm ( attach Ns ), or performs the inverse operation ( +.Cm detach Ns ). .It Xo .Xr zpool-add 8 Ns / Ns Xr zpool-remove 8 .Xc @@ -233,16 +234,16 @@ Invalid command line options were specified. .El . .Sh EXAMPLES -.\" Examples 1, 2, 3, 4, 11, 12 are shared with zpool-create.8. -.\" Examples 5, 13 are shared with zpool-add.8. -.\" Examples 6, 15 are shared with zpool-list.8. -.\" Examples 7 are shared with zpool-destroy.8. -.\" Examples 8 are shared with zpool-export.8. -.\" Examples 9 are shared with zpool-import.8. -.\" Examples 10 are shared with zpool-upgrade.8. -.\" Examples 14 are shared with zpool-remove.8. -.\" Examples 16 are shared with zpool-status.8. -.\" Examples 13, 16 are also shared with zpool-iostat.8. +.\" Examples 1, 2, 3, 4, 12, 13 are shared with zpool-create.8. +.\" Examples 6, 14 are shared with zpool-add.8. +.\" Examples 7, 16 are shared with zpool-list.8. +.\" Examples 8 are shared with zpool-destroy.8. +.\" Examples 9 are shared with zpool-export.8. +.\" Examples 10 are shared with zpool-import.8. +.\" Examples 11 are shared with zpool-upgrade.8. +.\" Examples 15 are shared with zpool-remove.8. +.\" Examples 17 are shared with zpool-status.8. +.\" Examples 14, 17 are also shared with zpool-iostat.8. .\" Make sure to update them omnidirectionally .Ss Example 1 : No Creating a RAID-Z Storage Pool The following command creates a pool with a single raidz root vdev that @@ -264,14 +265,21 @@ While not recommended, a pool based on files can be useful for experimental purposes. .Dl # Nm zpool Cm create Ar tank Pa /path/to/file/a /path/to/file/b . -.Ss Example 5 : No Adding a Mirror to a ZFS Storage Pool +.Ss Example 5 : No Making a non-mirrored ZFS Storage Pool mirrored +The following command converts an existing single device +.Ar sda +into a mirror by attaching a second device to it, +.Ar sdb . +.Dl # Nm zpool Cm attach Ar tank Pa sda sdb +. +.Ss Example 6 : No Adding a Mirror to a ZFS Storage Pool The following command adds two mirrored disks to the pool .Ar tank , assuming the pool is already made up of two-way mirrors. The additional space is immediately available to any datasets within the pool. .Dl # Nm zpool Cm add Ar tank Sy mirror Pa sda sdb . -.Ss Example 6 : No Listing Available ZFS Storage Pools +.Ss Example 7 : No Listing Available ZFS Storage Pools The following command lists all available pools on the system. In this case, the pool .Ar zion @@ -285,19 +293,19 @@ tank 61.5G 20.0G 41.5G - 48% 32% 1.00x ONLINE - zion - - - - - - - FAULTED - .Ed . -.Ss Example 7 : No Destroying a ZFS Storage Pool +.Ss Example 8 : No Destroying a ZFS Storage Pool The following command destroys the pool .Ar tank and any datasets contained within: .Dl # Nm zpool Cm destroy Fl f Ar tank . -.Ss Example 8 : No Exporting a ZFS Storage Pool +.Ss Example 9 : No Exporting a ZFS Storage Pool The following command exports the devices in pool .Ar tank so that they can be relocated or later imported: .Dl # Nm zpool Cm export Ar tank . -.Ss Example 9 : No Importing a ZFS Storage Pool +.Ss Example 10 : No Importing a ZFS Storage Pool The following command displays available pools, and then imports the pool .Ar tank for use on the system. @@ -318,7 +326,7 @@ config: .No # Nm zpool Cm import Ar tank .Ed . -.Ss Example 10 : No Upgrading All ZFS Storage Pools to the Current Version +.Ss Example 11 : No Upgrading All ZFS Storage Pools to the Current Version The following command upgrades all ZFS Storage pools to the current version of the software: .Bd -literal -compact -offset Ds @@ -326,7 +334,7 @@ the software: This system is currently running ZFS version 2. .Ed . -.Ss Example 11 : No Managing Hot Spares +.Ss Example 12 : No Managing Hot Spares The following command creates a new pool with an available hot spare: .Dl # Nm zpool Cm create Ar tank Sy mirror Pa sda sdb Sy spare Pa sdc .Pp @@ -341,12 +349,12 @@ The hot spare can be permanently removed from the pool using the following command: .Dl # Nm zpool Cm remove Ar tank Pa sdc . -.Ss Example 12 : No Creating a ZFS Pool with Mirrored Separate Intent Logs +.Ss Example 13 : No Creating a ZFS Pool with Mirrored Separate Intent Logs The following command creates a ZFS storage pool consisting of two, two-way mirrors and mirrored log devices: .Dl # Nm zpool Cm create Ar pool Sy mirror Pa sda sdb Sy mirror Pa sdc sdd Sy log mirror Pa sde sdf . -.Ss Example 13 : No Adding Cache Devices to a ZFS Pool +.Ss Example 14 : No Adding Cache Devices to a ZFS Pool The following command adds two disks for use as cache devices to a ZFS storage pool: .Dl # Nm zpool Cm add Ar pool Sy cache Pa sdc sdd @@ -359,7 +367,7 @@ Capacity and reads can be monitored using the subcommand as follows: .Dl # Nm zpool Cm iostat Fl v Ar pool 5 . -.Ss Example 14 : No Removing a Mirrored top-level (Log or Data) Device +.Ss Example 15 : No Removing a Mirrored top-level (Log or Data) Device The following commands remove the mirrored log device .Sy mirror-2 and mirrored top-level data device @@ -394,7 +402,7 @@ The command to remove the mirrored data .Ar mirror-1 No is : .Dl # Nm zpool Cm remove Ar tank mirror-1 . -.Ss Example 15 : No Displaying expanded space on a device +.Ss Example 16 : No Displaying expanded space on a device The following command displays the detailed information for the pool .Ar data . This pool is comprised of a single raidz vdev where one of its devices @@ -411,7 +419,7 @@ data 23.9G 14.6G 9.30G - 48% 61% 1.00x ONLINE - sdc - - - - - .Ed . -.Ss Example 16 : No Adding output columns +.Ss Example 17 : No Adding output columns Additional columns can be added to the .Nm zpool Cm status No and Nm zpool Cm iostat No output with Fl c . .Bd -literal -compact -offset Ds diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c index b7453578a7..f2831a0e8a 100644 --- a/module/zfs/dbuf.c +++ b/module/zfs/dbuf.c @@ -2701,7 +2701,7 @@ dmu_buf_will_clone(dmu_buf_t *db_fake, dmu_tx_t *tx) */ mutex_enter(&db->db_mtx); VERIFY(!dbuf_undirty(db, tx)); - ASSERT0(dbuf_find_dirty_eq(db, tx->tx_txg)); + ASSERT3P(dbuf_find_dirty_eq(db, tx->tx_txg), ==, NULL); if (db->db_buf != NULL) { arc_buf_destroy(db->db_buf, db); db->db_buf = NULL; diff --git a/module/zfs/zil.c b/module/zfs/zil.c index f2d279e36a..b30676b42d 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -814,17 +814,17 @@ static void zil_free_lwb(zilog_t *zilog, lwb_t *lwb) { ASSERT(MUTEX_HELD(&zilog->zl_lock)); - ASSERT(!MUTEX_HELD(&lwb->lwb_vdev_lock)); - VERIFY(list_is_empty(&lwb->lwb_waiters)); - VERIFY(list_is_empty(&lwb->lwb_itxs)); - ASSERT(avl_is_empty(&lwb->lwb_vdev_tree)); + ASSERT(lwb->lwb_state == LWB_STATE_NEW || + lwb->lwb_state == LWB_STATE_FLUSH_DONE); ASSERT3P(lwb->lwb_child_zio, ==, NULL); ASSERT3P(lwb->lwb_write_zio, ==, NULL); ASSERT3P(lwb->lwb_root_zio, ==, NULL); ASSERT3U(lwb->lwb_alloc_txg, <=, spa_syncing_txg(zilog->zl_spa)); ASSERT3U(lwb->lwb_max_txg, <=, spa_syncing_txg(zilog->zl_spa)); - ASSERT(lwb->lwb_state == LWB_STATE_NEW || - lwb->lwb_state == LWB_STATE_FLUSH_DONE); + VERIFY(list_is_empty(&lwb->lwb_itxs)); + VERIFY(list_is_empty(&lwb->lwb_waiters)); + ASSERT(avl_is_empty(&lwb->lwb_vdev_tree)); + ASSERT(!MUTEX_HELD(&lwb->lwb_vdev_lock)); /* * Clear the zilog's field to indicate this lwb is no longer @@ -1329,6 +1329,9 @@ zil_lwb_add_block(lwb_t *lwb, const blkptr_t *bp) int ndvas = BP_GET_NDVAS(bp); int i; + ASSERT3S(lwb->lwb_state, !=, LWB_STATE_WRITE_DONE); + ASSERT3S(lwb->lwb_state, !=, LWB_STATE_FLUSH_DONE); + if (zil_nocacheflush) return; @@ -1408,15 +1411,9 @@ zil_lwb_flush_vdevs_done(zio_t *zio) zilog_t *zilog = lwb->lwb_zilog; zil_commit_waiter_t *zcw; itx_t *itx; - uint64_t txg; - list_t itxs, waiters; spa_config_exit(zilog->zl_spa, SCL_STATE, lwb); - list_create(&itxs, sizeof (itx_t), offsetof(itx_t, itx_node)); - list_create(&waiters, sizeof (zil_commit_waiter_t), - offsetof(zil_commit_waiter_t, zcw_node)); - hrtime_t t = gethrtime() - lwb->lwb_issued_timestamp; mutex_enter(&zilog->zl_lock); @@ -1425,6 +1422,9 @@ zil_lwb_flush_vdevs_done(zio_t *zio) lwb->lwb_root_zio = NULL; + ASSERT3S(lwb->lwb_state, ==, LWB_STATE_WRITE_DONE); + lwb->lwb_state = LWB_STATE_FLUSH_DONE; + if (zilog->zl_last_lwb_opened == lwb) { /* * Remember the highest committed log sequence number @@ -1435,22 +1435,13 @@ zil_lwb_flush_vdevs_done(zio_t *zio) zilog->zl_commit_lr_seq = zilog->zl_lr_seq; } - list_move_tail(&itxs, &lwb->lwb_itxs); - list_move_tail(&waiters, &lwb->lwb_waiters); - txg = lwb->lwb_issued_txg; - - ASSERT3S(lwb->lwb_state, ==, LWB_STATE_WRITE_DONE); - lwb->lwb_state = LWB_STATE_FLUSH_DONE; - - mutex_exit(&zilog->zl_lock); - - while ((itx = list_remove_head(&itxs)) != NULL) + while ((itx = list_remove_head(&lwb->lwb_itxs)) != NULL) zil_itx_destroy(itx); - list_destroy(&itxs); - while ((zcw = list_remove_head(&waiters)) != NULL) { + while ((zcw = list_remove_head(&lwb->lwb_waiters)) != NULL) { mutex_enter(&zcw->zcw_lock); + ASSERT3P(zcw->zcw_lwb, ==, lwb); zcw->zcw_lwb = NULL; /* * We expect any ZIO errors from child ZIOs to have been @@ -1475,7 +1466,11 @@ zil_lwb_flush_vdevs_done(zio_t *zio) mutex_exit(&zcw->zcw_lock); } - list_destroy(&waiters); + + uint64_t txg = lwb->lwb_issued_txg; + + /* Once we drop the lock, lwb may be freed by zil_sync(). */ + mutex_exit(&zilog->zl_lock); mutex_enter(&zilog->zl_lwb_io_lock); ASSERT3U(zilog->zl_lwb_inflight[txg & TXG_MASK], >, 0); @@ -1929,10 +1924,10 @@ next_lwb: BP_GET_LSIZE(&lwb->lwb_blk)); } lwb->lwb_issued_timestamp = gethrtime(); - zio_nowait(lwb->lwb_root_zio); - zio_nowait(lwb->lwb_write_zio); if (lwb->lwb_child_zio) zio_nowait(lwb->lwb_child_zio); + zio_nowait(lwb->lwb_write_zio); + zio_nowait(lwb->lwb_root_zio); /* * If nlwb was ready when we gave it the block pointer, diff --git a/module/zfs/zio.c b/module/zfs/zio.c index 7458b416c2..3b3b40fa73 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -1775,8 +1775,9 @@ zio_write_compress(zio_t *zio) compress = ZIO_COMPRESS_OFF; /* Make sure someone doesn't change their mind on overwrites */ - ASSERT(BP_IS_EMBEDDED(bp) || MIN(zp->zp_copies + BP_IS_GANG(bp), - spa_max_replication(spa)) == BP_GET_NDVAS(bp)); + ASSERT(BP_IS_EMBEDDED(bp) || BP_IS_GANG(bp) || + MIN(zp->zp_copies, spa_max_replication(spa)) + == BP_GET_NDVAS(bp)); } /* If it's a compressed write that is not raw, compress the buffer. */ diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib b/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib index 9998e5a87b..8e16366b4c 100644 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib @@ -34,13 +34,21 @@ function have_same_content log_must [ "$hash1" = "$hash2" ] } -function unique_blocks +# +# get_same_blocks dataset1 path/to/file1 dataset2 path/to/file2 +# +# Returns a space-separated list of the indexes (starting at 0) of the L0 +# blocks that are shared between both files (by first DVA and checksum). +# Assumes that the two files have the same content, use have_same_content to +# confirm that. +# +function get_same_blocks { typeset zdbout=${TMPDIR:-$TEST_BASE_DIR}/zdbout.$$ zdb -vvvvv $1 -O $2 | \ - awk '/ L0 / { print ++l " " $3 " " $7 }' > $zdbout.a + awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.a zdb -vvvvv $3 -O $4 | \ - awk '/ L0 / { print ++l " " $3 " " $7 }' > $zdbout.b + awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.b echo $(sort $zdbout.a $zdbout.b | uniq -d | cut -f1 -d' ') } diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh index 9adcbfcd88..43ea47b0ef 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange.ksh @@ -54,7 +54,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) -log_must [ "$blocks" = "1 2 3 4" ] +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) +log_must [ "$blocks" = "0 1 2 3" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh index 07e089e89c..74e6b04903 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh @@ -58,8 +58,8 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/$TESTFS1/file1 /$TESTPOOL/$TESTFS2/file2 -typeset blocks=$(unique_blocks \ +typeset blocks=$(get_same_blocks \ $TESTPOOL/$TESTFS1 file1 $TESTPOOL/$TESTFS2 file2) -log_must [ "$blocks" = "1 2 3 4" ] +log_must [ "$blocks" = "0 1 2 3" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh index 87f99eb5c0..9a96eacd60 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback.ksh @@ -58,8 +58,8 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone -typeset blocks=$(unique_blocks $TESTPOOL file $TESTPOOL clone) -log_must [ "$blocks" = "1 2 3 4" ] +typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone) +log_must [ "$blocks" = "0 1 2 3" ] log_note "Copying within a block with copy_file_range" @@ -69,8 +69,8 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone -typeset blocks=$(unique_blocks $TESTPOOL file $TESTPOOL clone) -log_must [ "$blocks" = "2 3 4" ] +typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone) +log_must [ "$blocks" = "1 2 3" ] log_note "Copying across a block with copy_file_range" @@ -80,7 +80,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone -typeset blocks=$(unique_blocks $TESTPOOL file $TESTPOOL clone) -log_must [ "$blocks" = "2" ] +typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone) +log_must [ "$blocks" = "1" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh index 3451f887af..a10545bc07 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh @@ -59,7 +59,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone -typeset blocks=$(unique_blocks $TESTPOOL file $TESTPOOL clone) +typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone) log_must [ "$blocks" = "" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh index ecac62b203..a5da0a0bd3 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_partial.ksh @@ -54,7 +54,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) log_must [ "$blocks" = "" ] log_must clonefile -f /$TESTPOOL/file1 /$TESTPOOL/file2 131072 131072 262144 @@ -62,7 +62,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) -log_must [ "$blocks" = "2 3" ] +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) +log_must [ "$blocks" = "1 2" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh index 30b155a140..d21b625113 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_disabled_copyfilerange.ksh @@ -54,7 +54,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) log_must [ "$blocks" = "" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh index d13a392298..3f227fb68e 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlone.ksh @@ -50,7 +50,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) -log_must [ "$blocks" = "1 2 3 4" ] +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) +log_must [ "$blocks" = "0 1 2 3" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh index 6556050c43..cefc4336ae 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange.ksh @@ -50,7 +50,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) -log_must [ "$blocks" = "1 2 3 4" ] +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) +log_must [ "$blocks" = "0 1 2 3" ] log_pass $claim diff --git a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh index 37a3511a26..067f55aaa6 100755 --- a/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh +++ b/tests/zfs-tests/tests/functional/block_cloning/block_cloning_ficlonerange_partial.ksh @@ -50,7 +50,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) log_must [ "$blocks" = "" ] log_must clonefile -r /$TESTPOOL/file1 /$TESTPOOL/file2 131072 131072 262144 @@ -58,7 +58,7 @@ log_must sync_pool $TESTPOOL log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2 -typeset blocks=$(unique_blocks $TESTPOOL file1 $TESTPOOL file2) -log_must [ "$blocks" = "2 3" ] +typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2) +log_must [ "$blocks" = "1 2" ] log_pass $claim