The branch releng/15.0 has been updated by cperciva:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=6bf158defbcb2f3c948b28394388179c7e95bd8b

commit 6bf158defbcb2f3c948b28394388179c7e95bd8b
Author:     Martin Matuska <[email protected]>
AuthorDate: 2025-10-25 08:14:36 +0000
Commit:     Colin Percival <[email protected]>
CommitDate: 2025-10-28 21:22:49 +0000

    zfs: merge openzfs/zfs@814f9afba (zfs-2.4-release) into stable/15
    
    OpenZFS 2.4.0 rc3
    
    Notable upstream pull request merges:
     #17750 964dfc317 FreeBSD: Correct _PC_MIN_HOLE_SIZE
     #17793 b9d1e28a7 ddt prune: Add SCL_ZIO deadlock workaround
     #17799 1585a10a8 Make mount/share errors non-fatal for zfs create/clone
     #17801 073b34b3e Fix display of default xattr to show 'sa'
     #17803 e09c86cb1 zvol: verify IO type is supported
     #17807 -multiple zpool iostat: fix regressions in "all pools" mode
                      after #17786
     #17826 b9356f06e Explicit set ashift for non-leaf vdevs
     #17830 f0bff230f Suppress some ashift warnings
     #17833 c1f55bff8 Fix the type of the raidz_outlier_check_interval_ms
                      parameter
     #17836 799bda73e Fix return value for setting zvol threading
     #17834 f0c76f8a7 libzpool/cmn_err: remove suppression, add stop option,
                      cleanup
     #17843 1956417b5 mmap_seek: print error code and text on failure
     #17847 7987d4deb Update device removal documentation
     #17851 6f6e1c90a FreeBSD: zfs_getpages: Don't zero freshly allocated pages
    
    Approved by:    re (cperciva)
    Obtained from:  OpenZFS
    OpenZFS commit: 814f9afba7d6714bd63f18ac808955b61d37f9f0
    OpenZFS tag:    zfs-2.4.0-rc3
    
    (cherry picked from commit ce7e1f86a1810038f142c5c68b787c47252b39c5)
---
 .../.github/ISSUE_TEMPLATE/feature_request.md      |   2 +-
 .../.github/workflows/scripts/qemu-2-start.sh      |  11 +-
 sys/contrib/openzfs/.github/workflows/zfs-qemu.yml |   2 +-
 sys/contrib/openzfs/META                           |   2 +-
 sys/contrib/openzfs/cmd/zdb/zdb.c                  | 191 +++++++++++++++++++--
 sys/contrib/openzfs/cmd/zfs/zfs_main.c             |  10 +-
 sys/contrib/openzfs/cmd/zinject/zinject.c          |  81 +++++++--
 sys/contrib/openzfs/cmd/zpool/zpool_iter.c         |  19 +-
 sys/contrib/openzfs/cmd/zpool/zpool_main.c         |   1 +
 sys/contrib/openzfs/cmd/zpool/zpool_vdev.c         |  64 +++----
 .../config/kernel-block-device-operations.m4       |  34 ++++
 sys/contrib/openzfs/config/kernel-drop-inode.m4    |  24 +++
 sys/contrib/openzfs/config/kernel-namespace.m4     |  31 ++++
 .../openzfs/config/kernel-userns-capabilities.m4   |  79 ---------
 sys/contrib/openzfs/config/kernel-writeback.m4     |  58 +++++++
 sys/contrib/openzfs/config/kernel-writepage_t.m4   |  26 ---
 sys/contrib/openzfs/config/kernel.m4               |   8 +-
 sys/contrib/openzfs/contrib/intel_qat/readme.md    |   2 +-
 sys/contrib/openzfs/etc/init.d/README.md           |   2 +-
 sys/contrib/openzfs/include/libzfs.h               |   2 +
 .../include/os/linux/kernel/linux/vfs_compat.h     |   7 +
 sys/contrib/openzfs/include/sys/spa.h              |   2 +-
 sys/contrib/openzfs/include/sys/zfs_ioctl.h        |   1 +
 sys/contrib/openzfs/include/sys/zio.h              |   1 +
 sys/contrib/openzfs/lib/libspl/include/sys/uio.h   |   1 +
 sys/contrib/openzfs/lib/libuutil/libuutil.abi      | 105 +----------
 sys/contrib/openzfs/lib/libzfs/libzfs.abi          | 172 ++++---------------
 sys/contrib/openzfs/lib/libzfs/libzfs_config.c     |  17 ++
 sys/contrib/openzfs/lib/libzfs/libzfs_status.c     |  78 +++++----
 .../openzfs/lib/libzfs_core/libzfs_core.abi        | 105 +----------
 sys/contrib/openzfs/lib/libzpool/kernel.c          |  79 +++++++--
 sys/contrib/openzfs/man/man8/zdb.8                 |  14 ++
 sys/contrib/openzfs/man/man8/zinject.8             |  14 ++
 sys/contrib/openzfs/man/man8/zpool-remove.8        |   4 +-
 .../openzfs/module/icp/algs/sha2/sha2_generic.c    |  41 +++--
 .../openzfs/module/os/freebsd/zfs/zfs_ctldir.c     |   3 +-
 .../openzfs/module/os/freebsd/zfs/zfs_vnops_os.c   |  31 +++-
 sys/contrib/openzfs/module/os/linux/spl/spl-zone.c |  19 +-
 sys/contrib/openzfs/module/os/linux/zfs/abd_os.c   |   9 +
 sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c  |   2 +-
 .../openzfs/module/os/linux/zfs/zfs_vnops_os.c     |   5 +-
 sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c |  74 ++++++++
 .../openzfs/module/os/linux/zfs/zpl_super.c        |   4 +-
 sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c  | 109 ++++++++----
 sys/contrib/openzfs/module/zcommon/zfs_prop.c      |   2 +-
 sys/contrib/openzfs/module/zfs/arc.c               |  17 +-
 sys/contrib/openzfs/module/zfs/mmp.c               |   2 +-
 sys/contrib/openzfs/module/zfs/spa_misc.c          |   8 +-
 sys/contrib/openzfs/module/zfs/vdev_removal.c      |  80 ++++++---
 sys/contrib/openzfs/module/zfs/zio.c               |  35 +++-
 sys/contrib/openzfs/module/zfs/zio_inject.c        |  38 ++++
 sys/contrib/openzfs/module/zfs/zvol.c              |   2 +-
 sys/contrib/openzfs/tests/runfiles/common.run      |   3 +-
 sys/contrib/openzfs/tests/runfiles/sanity.run      |   2 +-
 .../openzfs/tests/zfs-tests/cmd/mmap_seek.c        |  35 ++--
 .../openzfs/tests/zfs-tests/tests/Makefile.am      |   1 +
 .../cli_root/zpool_reopen/zpool_reopen_004_pos.ksh |   2 +
 .../functional/delegate/delegate_common.kshlib     |   6 +-
 .../tests/functional/xattr/xattr_014_pos.ksh       |  53 ++++++
 .../functional/zvol/zvol_misc/zvol_misc_trim.ksh   |   7 +
 60 files changed, 1133 insertions(+), 706 deletions(-)

diff --git a/sys/contrib/openzfs/.github/ISSUE_TEMPLATE/feature_request.md 
b/sys/contrib/openzfs/.github/ISSUE_TEMPLATE/feature_request.md
index 9b50a4a3d96e..f3d4316f6f67 100644
--- a/sys/contrib/openzfs/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/sys/contrib/openzfs/.github/ISSUE_TEMPLATE/feature_request.md
@@ -14,7 +14,7 @@ Please check our issue tracker before opening a new feature 
request.
 Filling out the following template will help other contributors better 
understand your proposed feature.
 -->
 
-### Describe the feature would like to see added to OpenZFS
+### Describe the feature you would like to see added to OpenZFS
 
 <!--
 Provide a clear and concise description of the feature.
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh 
b/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh
index 1c608348ffcd..422b3e9df388 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh
@@ -121,7 +121,14 @@ case "$OS" in
     KSRC="$FREEBSD_SNAP/../amd64/$FreeBSD/src.txz"
     ;;
   freebsd15-0c)
-    FreeBSD="15.0-ALPHA3"
+    FreeBSD="15.0-ALPHA4"
+    OSNAME="FreeBSD $FreeBSD"
+    OSv="freebsd14.0"
+    
URLxz="$FREEBSD_SNAP/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI-ufs.raw.xz"
+    KSRC="$FREEBSD_SNAP/../amd64/$FreeBSD/src.txz"
+    ;;
+  freebsd16-0c)
+    FreeBSD="16.0-CURRENT"
     OSNAME="FreeBSD $FreeBSD"
     OSv="freebsd14.0"
     
URLxz="$FREEBSD_SNAP/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI-ufs.raw.xz"
@@ -287,7 +294,7 @@ else
   while pidof /usr/bin/qemu-system-x86_64 >/dev/null; do
     ssh 2>/dev/null root@vm0 "uname -a" && break
   done
-  ssh root@vm0 "pkg install -y bash ca_root_nss git qemu-guest-agent python3 
py311-cloud-init"
+  ssh root@vm0 "env IGNORE_OSVERSION=yes pkg install -y bash ca_root_nss git 
qemu-guest-agent python3 py311-cloud-init"
   ssh root@vm0 "chsh -s $BASH root"
   ssh root@vm0 'sysrc qemu_guest_agent_enable="YES"'
   ssh root@vm0 'sysrc cloudinit_enable="YES"'
diff --git a/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml 
b/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml
index 64277dcca236..f1b189062bb7 100644
--- a/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml
+++ b/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml
@@ -68,7 +68,7 @@ jobs:
         # FreeBSD variants of 2025-06:
         # FreeBSD Release: freebsd13-5r, freebsd14-2r, freebsd14-3r
         # FreeBSD Stable:  freebsd13-5s, freebsd14-3s
-        # FreeBSD Current: freebsd15-0c
+        # FreeBSD Current: freebsd15-0c, freebsd16-0c
         os: ${{ fromJson(needs.test-config.outputs.test_os) }}
     runs-on: ubuntu-24.04
     steps:
diff --git a/sys/contrib/openzfs/META b/sys/contrib/openzfs/META
index ddb64774e4c0..2bfa51841cc4 100644
--- a/sys/contrib/openzfs/META
+++ b/sys/contrib/openzfs/META
@@ -2,7 +2,7 @@ Meta:          1
 Name:          zfs
 Branch:        1.0
 Version:       2.4.0
-Release:       rc2
+Release:       rc3
 Release-Tags:  relext
 License:       CDDL
 Author:        OpenZFS
diff --git a/sys/contrib/openzfs/cmd/zdb/zdb.c 
b/sys/contrib/openzfs/cmd/zdb/zdb.c
index 70a4ed46f263..2560ad045db3 100644
--- a/sys/contrib/openzfs/cmd/zdb/zdb.c
+++ b/sys/contrib/openzfs/cmd/zdb/zdb.c
@@ -106,11 +106,15 @@ extern boolean_t spa_mode_readable_spacemaps;
 extern uint_t zfs_reconstruct_indirect_combinations_max;
 extern uint_t zfs_btree_verify_intensity;
 
+enum {
+       ARG_ALLOCATED = 256,
+       ARG_BLOCK_BIN_MODE,
+       ARG_BLOCK_CLASSES,
+};
+
 static const char cmdname[] = "zdb";
 uint8_t dump_opt[512];
 
-#define        ALLOCATED_OPT   256
-
 typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
 
 static uint64_t *zopt_metaslab = NULL;
@@ -131,6 +135,20 @@ static objset_t *os;
 static boolean_t kernel_init_done;
 static boolean_t corruption_found = B_FALSE;
 
+static enum {
+       BIN_AUTO = 0,
+       BIN_PSIZE,
+       BIN_LSIZE,
+       BIN_ASIZE,
+} block_bin_mode = BIN_AUTO;
+
+static enum {
+       CLASS_NORMAL = 1 << 1,
+       CLASS_SPECIAL = 1 << 2,
+       CLASS_DEDUP = 1 << 3,
+       CLASS_OTHER = 1 << 4,
+} block_classes = 0;
+
 static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *,
     boolean_t);
 static void mos_obj_refd(uint64_t);
@@ -749,6 +767,12 @@ usage(void)
        (void) fprintf(stderr, "    Options to control amount of output:\n");
        (void) fprintf(stderr, "        -b --block-stats             "
            "block statistics\n");
+       (void) fprintf(stderr, "           --bin=(lsize|psize|asize) "
+           "bin blocks based on this size in all three columns\n");
+       (void) fprintf(stderr,
+           "           --class=(normal|special|dedup|other)[,...]\n"
+           "                                     only consider blocks from "
+           "these allocation classes\n");
        (void) fprintf(stderr, "        -B --backup                  "
            "backup stream\n");
        (void) fprintf(stderr, "        -c --checksum                "
@@ -1694,7 +1718,7 @@ dump_metaslab(metaslab_t *msp)
            (u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
            (u_longlong_t)space_map_object(sm), freebuf);
 
-       if (dump_opt[ALLOCATED_OPT] ||
+       if (dump_opt[ARG_ALLOCATED] ||
            (dump_opt['m'] > 2 && !dump_opt['L'])) {
                mutex_enter(&msp->ms_lock);
                VERIFY0(metaslab_load(msp));
@@ -1705,7 +1729,7 @@ dump_metaslab(metaslab_t *msp)
                dump_metaslab_stats(msp);
        }
 
-       if (dump_opt[ALLOCATED_OPT]) {
+       if (dump_opt[ARG_ALLOCATED]) {
                uint64_t off = msp->ms_start;
                zfs_range_tree_walk(msp->ms_allocatable, dump_allocated,
                    &off);
@@ -1726,7 +1750,7 @@ dump_metaslab(metaslab_t *msp)
                    SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
        }
 
-       if (dump_opt[ALLOCATED_OPT] ||
+       if (dump_opt[ARG_ALLOCATED] ||
            (dump_opt['m'] > 2 && !dump_opt['L'])) {
                metaslab_unload(msp);
                mutex_exit(&msp->ms_lock);
@@ -5814,6 +5838,34 @@ dump_size_histograms(zdb_cb_t *zcb)
 
 
        (void) printf("\nBlock Size Histogram\n");
+       switch (block_bin_mode) {
+       case BIN_PSIZE:
+               printf("(note: all categories are binned by %s)\n", "psize");
+               break;
+       case BIN_LSIZE:
+               printf("(note: all categories are binned by %s)\n", "lsize");
+               break;
+       case BIN_ASIZE:
+               printf("(note: all categories are binned by %s)\n", "asize");
+               break;
+       default:
+               printf("(note: all categories are binned separately)\n");
+               break;
+       }
+       if (block_classes != 0) {
+               char buf[256] = "";
+               if (block_classes & CLASS_NORMAL)
+                       strlcat(buf, "\"normal\", ", sizeof (buf));
+               if (block_classes & CLASS_SPECIAL)
+                       strlcat(buf, "\"special\", ", sizeof (buf));
+               if (block_classes & CLASS_DEDUP)
+                       strlcat(buf, "\"dedup\", ", sizeof (buf));
+               if (block_classes & CLASS_OTHER)
+                       strlcat(buf, "\"other\", ", sizeof (buf));
+               buf[strlen(buf)-2] = '\0';
+               printf("(note: only blocks in these classes are counted: %s)\n",
+                   buf);
+       }
        /*
         * Print the first line titles
         */
@@ -6162,29 +6214,85 @@ skipped:
                    [BPE_GET_PSIZE(bp)]++;
                return;
        }
+
+       if (block_classes != 0) {
+               spa_config_enter(zcb->zcb_spa, SCL_CONFIG, FTAG, RW_READER);
+
+               uint64_t vdev = DVA_GET_VDEV(&bp->blk_dva[0]);
+               uint64_t offset = DVA_GET_OFFSET(&bp->blk_dva[0]);
+               vdev_t *vd = vdev_lookup_top(zcb->zcb_spa, vdev);
+               ASSERT(vd != NULL);
+               metaslab_t *ms = vd->vdev_ms[offset >> vd->vdev_ms_shift];
+               ASSERT(ms != NULL);
+               metaslab_group_t *mg = ms->ms_group;
+               ASSERT(mg != NULL);
+               metaslab_class_t *mc = mg->mg_class;
+               ASSERT(mc != NULL);
+
+               spa_config_exit(zcb->zcb_spa, SCL_CONFIG, FTAG);
+
+               int class;
+               if (mc == spa_normal_class(zcb->zcb_spa)) {
+                       class = CLASS_NORMAL;
+               } else if (mc == spa_special_class(zcb->zcb_spa)) {
+                       class = CLASS_SPECIAL;
+               } else if (mc == spa_dedup_class(zcb->zcb_spa)) {
+                       class = CLASS_DEDUP;
+               } else {
+                       class = CLASS_OTHER;
+               }
+
+               if (!(block_classes & class)) {
+                       goto hist_skipped;
+               }
+       }
+
        /*
         * The binning histogram bins by powers of two up to
         * SPA_MAXBLOCKSIZE rather than creating bins for
         * every possible blocksize found in the pool.
         */
-       int bin = highbit64(BP_GET_PSIZE(bp)) - 1;
+       int bin;
+
+       /*
+        * Binning strategy: each bin includes blocks up to and including
+        * the given size (excluding blocks that fit into the previous bin).
+        * This way, the "4K" bin includes blocks within the (2K; 4K] range.
+        */
+#define        BIN(size) (highbit64((size) - 1))
+
+       switch (block_bin_mode) {
+       case BIN_PSIZE: bin = BIN(BP_GET_PSIZE(bp)); break;
+       case BIN_LSIZE: bin = BIN(BP_GET_LSIZE(bp)); break;
+       case BIN_ASIZE: bin = BIN(BP_GET_ASIZE(bp)); break;
+       case BIN_AUTO: break;
+       default: PANIC("bad block_bin_mode"); abort();
+       }
+
+       if (block_bin_mode == BIN_AUTO)
+               bin = BIN(BP_GET_PSIZE(bp));
 
        zcb->zcb_psize_count[bin]++;
        zcb->zcb_psize_len[bin] += BP_GET_PSIZE(bp);
        zcb->zcb_psize_total += BP_GET_PSIZE(bp);
 
-       bin = highbit64(BP_GET_LSIZE(bp)) - 1;
+       if (block_bin_mode == BIN_AUTO)
+               bin = BIN(BP_GET_LSIZE(bp));
 
        zcb->zcb_lsize_count[bin]++;
        zcb->zcb_lsize_len[bin] += BP_GET_LSIZE(bp);
        zcb->zcb_lsize_total += BP_GET_LSIZE(bp);
 
-       bin = highbit64(BP_GET_ASIZE(bp)) - 1;
+       if (block_bin_mode == BIN_AUTO)
+               bin = BIN(BP_GET_ASIZE(bp));
 
        zcb->zcb_asize_count[bin]++;
        zcb->zcb_asize_len[bin] += BP_GET_ASIZE(bp);
        zcb->zcb_asize_total += BP_GET_ASIZE(bp);
 
+#undef BIN
+
+hist_skipped:
        if (!do_claim)
                return;
 
@@ -9426,7 +9534,11 @@ main(int argc, char **argv)
                {"livelist",            no_argument,            NULL, 'y'},
                {"zstd-headers",        no_argument,            NULL, 'Z'},
                {"allocated-map",       no_argument,            NULL,
-                   ALLOCATED_OPT},
+                   ARG_ALLOCATED},
+               {"bin",                 required_argument,      NULL,
+                   ARG_BLOCK_BIN_MODE},
+               {"class",               required_argument,      NULL,
+                   ARG_BLOCK_CLASSES},
                {0, 0, 0, 0}
        };
 
@@ -9457,7 +9569,7 @@ main(int argc, char **argv)
                case 'u':
                case 'y':
                case 'Z':
-               case ALLOCATED_OPT:
+               case ARG_ALLOCATED:
                        dump_opt[c]++;
                        dump_all = 0;
                        break;
@@ -9540,6 +9652,59 @@ main(int argc, char **argv)
                case 'x':
                        vn_dumpdir = optarg;
                        break;
+               case ARG_BLOCK_BIN_MODE:
+                       if (strcmp(optarg, "lsize") == 0) {
+                               block_bin_mode = BIN_LSIZE;
+                       } else if (strcmp(optarg, "psize") == 0) {
+                               block_bin_mode = BIN_PSIZE;
+                       } else if (strcmp(optarg, "asize") == 0) {
+                               block_bin_mode = BIN_ASIZE;
+                       } else {
+                               (void) fprintf(stderr,
+                                   "--bin=\"%s\" must be one of \"lsize\", "
+                                   "\"psize\" or \"asize\"\n", optarg);
+                               usage();
+                       }
+                       break;
+
+               case ARG_BLOCK_CLASSES: {
+                       char *buf = strdup(optarg), *tok = buf, *next,
+                           *save = NULL;
+
+                       while ((next = strtok_r(tok, ",", &save)) != NULL) {
+                               tok = NULL;
+
+                               if (strcmp(next, "normal") == 0) {
+                                       block_classes |= CLASS_NORMAL;
+                               } else if (strcmp(next, "special") == 0) {
+                                       block_classes |= CLASS_SPECIAL;
+                               } else if (strcmp(next, "dedup") == 0) {
+                                       block_classes |= CLASS_DEDUP;
+                               } else if (strcmp(next, "other") == 0) {
+                                       block_classes |= CLASS_OTHER;
+                               } else {
+                                       (void) fprintf(stderr,
+                                           "--class=\"%s\" must be a "
+                                           "comma-separated list of either "
+                                           "\"normal\", \"special\", "
+                                           "\"asize\" or \"other\"; "
+                                           "got \"%s\"\n",
+                                           optarg, next);
+                                       usage();
+                               }
+                       }
+
+                       if (block_classes == 0) {
+                               (void) fprintf(stderr,
+                                   "--class= must be a comma-separated "
+                                   "list of either \"normal\", \"special\", "
+                                   "\"asize\" or \"other\"; got empty\n");
+                               usage();
+                       }
+
+                       free(buf);
+                       break;
+               }
                default:
                        usage();
                        break;
@@ -9582,6 +9747,9 @@ main(int argc, char **argv)
         */
        spa_mode_readable_spacemaps = B_TRUE;
 
+       libspl_set_assert_ok((dump_opt['A'] == 1) || (dump_opt['A'] > 2));
+       zfs_recover = (dump_opt['A'] > 1);
+
        if (dump_all)
                verbose = MAX(verbose, 1);
 
@@ -9592,9 +9760,6 @@ main(int argc, char **argv)
                        dump_opt[c] += verbose;
        }
 
-       libspl_set_assert_ok((dump_opt['A'] == 1) || (dump_opt['A'] > 2));
-       zfs_recover = (dump_opt['A'] > 1);
-
        argc -= optind;
        argv += optind;
        if (argc < 2 && dump_opt['R'])
diff --git a/sys/contrib/openzfs/cmd/zfs/zfs_main.c 
b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
index b66440c8f9f8..ccdd5ffef8e6 100644
--- a/sys/contrib/openzfs/cmd/zfs/zfs_main.c
+++ b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
@@ -914,7 +914,11 @@ zfs_do_clone(int argc, char **argv)
                        log_history = B_FALSE;
                }
 
-               ret = zfs_mount_and_share(g_zfs, argv[1], ZFS_TYPE_DATASET);
+               /*
+                * Dataset cloned successfully, mount/share failures are
+                * non-fatal.
+                */
+               (void) zfs_mount_and_share(g_zfs, argv[1], ZFS_TYPE_DATASET);
        }
 
        zfs_close(zhp);
@@ -1333,7 +1337,9 @@ zfs_do_create(int argc, char **argv)
                goto error;
        }
 
-       ret = zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
+       /* Dataset created successfully, mount/share failures are non-fatal */
+       ret = 0;
+       (void) zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
 error:
        nvlist_free(props);
        return (ret);
diff --git a/sys/contrib/openzfs/cmd/zinject/zinject.c 
b/sys/contrib/openzfs/cmd/zinject/zinject.c
index 113797c878b9..c2f646f2567d 100644
--- a/sys/contrib/openzfs/cmd/zinject/zinject.c
+++ b/sys/contrib/openzfs/cmd/zinject/zinject.c
@@ -107,6 +107,8 @@
  *     zinject
  *     zinject <-a | -u pool>
  *     zinject -c <id|all>
+ *     zinject -E <delay> [-a] [-m] [-f freq] [-l level] [-r range]
+ *         [-T iotype] [-t type object | -b bookmark pool]
  *     zinject [-q] <-t type> [-f freq] [-u] [-a] [-m] [-e errno] [-l level]
  *         [-r range] <object>
  *     zinject [-f freq] [-a] [-m] [-u] -b objset:object:level:start:end pool
@@ -132,14 +134,18 @@
  * The '-f' flag controls the frequency of errors injected, expressed as a
  * real number percentage between 0.0001 and 100.  The default is 100.
  *
- * The this form is responsible for actually injecting the handler into the
+ * The <object> form is responsible for actually injecting the handler into the
  * framework.  It takes the arguments described above, translates them to the
  * internal tuple using libzpool, and then issues an ioctl() to register the
  * handler.
  *
- * The final form can target a specific bookmark, regardless of whether a
+ * The '-b' option can target a specific bookmark, regardless of whether a
  * human-readable interface has been designed.  It allows developers to specify
  * a particular block by number.
+ *
+ * The '-E' option injects pipeline ready stage delays for the given object or
+ * bookmark. The delay is specified in milliseconds, and it supports I/O type
+ * and range filters.
  */
 
 #include <errno.h>
@@ -346,6 +352,13 @@ usage(void)
            "\t\tsuch that the operation takes a minimum of supplied seconds\n"
            "\t\tto complete.\n"
            "\n"
+           "\tzinject -E <delay> [-a] [-m] [-f freq] [-l level] [-r range]\n"
+           "\t\t[-T iotype] [-t type object | -b bookmark pool]\n"
+           "\n"
+           "\t\tInject pipeline ready stage delays for the given object path\n"
+           "\t\t(data or dnode) or raw bookmark. The delay is specified in\n"
+           "\t\tmilliseconds.\n"
+           "\n"
            "\tzinject -I [-s <seconds> | -g <txgs>] pool\n"
            "\t\tCause the pool to stop writing blocks yet not\n"
            "\t\treport errors for a duration.  Simulates buggy hardware\n"
@@ -724,12 +737,15 @@ register_handler(const char *pool, int flags, 
zinject_record_t *record,
        if (quiet) {
                (void) printf("%llu\n", (u_longlong_t)zc.zc_guid);
        } else {
+               boolean_t show_object = B_FALSE;
+               boolean_t show_iotype = B_FALSE;
                (void) printf("Added handler %llu with the following "
                    "properties:\n", (u_longlong_t)zc.zc_guid);
                (void) printf("  pool: %s\n", pool);
                if (record->zi_guid) {
                        (void) printf("  vdev: %llx\n",
                            (u_longlong_t)record->zi_guid);
+                       show_iotype = B_TRUE;
                } else if (record->zi_func[0] != '\0') {
                        (void) printf("  panic function: %s\n",
                            record->zi_func);
@@ -742,7 +758,18 @@ register_handler(const char *pool, int flags, 
zinject_record_t *record,
                } else if (record->zi_timer > 0) {
                        (void) printf(" timer: %lld ms\n",
                            (u_longlong_t)NSEC2MSEC(record->zi_timer));
+                       if (record->zi_cmd == ZINJECT_DELAY_READY) {
+                               show_object = B_TRUE;
+                               show_iotype = B_TRUE;
+                       }
                } else {
+                       show_object = B_TRUE;
+               }
+               if (show_iotype) {
+                       (void) printf("iotype: %s\n",
+                           iotype_to_str(record->zi_iotype));
+               }
+               if (show_object) {
                        (void) printf("objset: %llu\n",
                            (u_longlong_t)record->zi_objset);
                        (void) printf("object: %llu\n",
@@ -910,6 +937,7 @@ main(int argc, char **argv)
        int ret;
        int flags = 0;
        uint32_t dvas = 0;
+       hrtime_t ready_delay = -1;
 
        if ((g_zfs = libzfs_init()) == NULL) {
                (void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
@@ -940,7 +968,7 @@ main(int argc, char **argv)
        }
 
        while ((c = getopt(argc, argv,
-           ":aA:b:C:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:P:")) != -1) {
+           ":aA:b:C:d:D:E:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:P:")) != -1) {
                switch (c) {
                case 'a':
                        flags |= ZINJECT_FLUSH_ARC;
@@ -1113,6 +1141,18 @@ main(int argc, char **argv)
                case 'u':
                        flags |= ZINJECT_UNLOAD_SPA;
                        break;
+               case 'E':
+                       ready_delay = MSEC2NSEC(strtol(optarg, &end, 10));
+                       if (ready_delay <= 0 || *end != '\0') {
+                               (void) fprintf(stderr, "invalid delay '%s': "
+                                   "must be a positive duration\n", optarg);
+                               usage();
+                               libzfs_fini(g_zfs);
+                               return (1);
+                       }
+                       record.zi_cmd = ZINJECT_DELAY_READY;
+                       record.zi_timer = ready_delay;
+                       break;
                case 'L':
                        if ((label = name_to_type(optarg)) == TYPE_INVAL &&
                            !LABEL_TYPE(type)) {
@@ -1150,7 +1190,7 @@ main(int argc, char **argv)
                 */
                if (raw != NULL || range != NULL || type != TYPE_INVAL ||
                    level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED ||
-                   record.zi_freq > 0 || dvas != 0) {
+                   record.zi_freq > 0 || dvas != 0 || ready_delay >= 0) {
                        (void) fprintf(stderr, "cancel (-c) incompatible with "
                            "any other options\n");
                        usage();
@@ -1186,7 +1226,7 @@ main(int argc, char **argv)
                 */
                if (raw != NULL || range != NULL || type != TYPE_INVAL ||
                    level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED ||
-                   dvas != 0) {
+                   dvas != 0 || ready_delay >= 0) {
                        (void) fprintf(stderr, "device (-d) incompatible with "
                            "data error injection\n");
                        usage();
@@ -1276,13 +1316,23 @@ main(int argc, char **argv)
                        return (1);
                }
 
-               record.zi_cmd = ZINJECT_DATA_FAULT;
+               if (record.zi_cmd == ZINJECT_UNINITIALIZED) {
+                       record.zi_cmd = ZINJECT_DATA_FAULT;
+                       if (!error)
+                               error = EIO;
+               } else if (error != 0) {
+                       (void) fprintf(stderr, "error type -e incompatible "
+                           "with delay injection\n");
+                       libzfs_fini(g_zfs);
+                       return (1);
+               } else {
+                       record.zi_iotype = io_type;
+               }
+
                if (translate_raw(raw, &record) != 0) {
                        libzfs_fini(g_zfs);
                        return (1);
                }
-               if (!error)
-                       error = EIO;
        } else if (record.zi_cmd == ZINJECT_PANIC) {
                if (raw != NULL || range != NULL || type != TYPE_INVAL ||
                    level != 0 || device != NULL || record.zi_freq > 0 ||
@@ -1410,6 +1460,13 @@ main(int argc, char **argv)
                        record.zi_dvas = dvas;
                }
 
+               if (record.zi_cmd != ZINJECT_UNINITIALIZED && error != 0) {
+                       (void) fprintf(stderr, "error type -e incompatible "
+                           "with delay injection\n");
+                       libzfs_fini(g_zfs);
+                       return (1);
+               }
+
                if (error == EACCES) {
                        if (type != TYPE_DATA) {
                                (void) fprintf(stderr, "decryption errors "
@@ -1425,8 +1482,12 @@ main(int argc, char **argv)
                         * not found.
                         */
                        error = ECKSUM;
-               } else {
+               } else if (record.zi_cmd == ZINJECT_UNINITIALIZED) {
                        record.zi_cmd = ZINJECT_DATA_FAULT;
+                       if (!error)
+                               error = EIO;
+               } else {
+                       record.zi_iotype = io_type;
                }
 
                if (translate_record(type, argv[0], range, level, &record, pool,
@@ -1434,8 +1495,6 @@ main(int argc, char **argv)
                        libzfs_fini(g_zfs);
                        return (1);
                }
-               if (!error)
-                       error = EIO;
        }
 
        /*
diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_iter.c 
b/sys/contrib/openzfs/cmd/zpool/zpool_iter.c
index 16d4fe5eb1c6..fef602736705 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_iter.c
+++ b/sys/contrib/openzfs/cmd/zpool/zpool_iter.c
@@ -103,6 +103,7 @@ add_pool(zpool_handle_t *zhp, zpool_list_t *zlp)
                new->zn_last_refresh = zlp->zl_last_refresh;
                uu_avl_insert(zlp->zl_avl, new, idx);
        } else {
+               zpool_refresh_stats_from_handle(node->zn_handle, zhp);
                node->zn_last_refresh = zlp->zl_last_refresh;
                zpool_close(zhp);
                free(new);
@@ -203,31 +204,23 @@ pool_list_refresh(zpool_list_t *zlp)
                return (navail);
        }
 
-       /*
-        * Search for any new pools and add them to the list. zpool_iter()
-        * will call zpool_refresh_stats() as part of its work, so this has
-        * the side effect of updating all active handles.
-        */
+       /* Search for any new pools and add them to the list. */
        (void) zpool_iter(g_zfs, add_pool_cb, zlp);
 
-       /*
-        * Walk the list for any that weren't refreshed, and update and remove
-        * them. It's not enough to just skip available ones, as zpool_iter()
-        * won't update them, so they'll still appear active in our list.
-        */
+       /* Walk the list of existing pools, and update or remove them. */
        zpool_node_t *node, *next;
        for (node = uu_avl_first(zlp->zl_avl); node != NULL; node = next) {
                next = uu_avl_next(zlp->zl_avl, node);
 
                /*
-                * Skip any that were refreshed and are online; they're already
-                * handled.
+                * Skip any that were refreshed and are online; they were added
+                * by zpool_iter() and are already up to date.
                 */
                if (node->zn_last_refresh == zlp->zl_last_refresh &&
                    zpool_get_state(node->zn_handle) != POOL_STATE_UNAVAIL)
                        continue;
 
-               /* Do the refresh ourselves, just in case. */
+               /* Refresh and remove if necessary. */
                boolean_t missing;
                zpool_refresh_stats(node->zn_handle, &missing);
                if (missing) {
diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_main.c 
b/sys/contrib/openzfs/cmd/zpool/zpool_main.c
index 286336cf2730..1feec55c0e8b 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_main.c
+++ b/sys/contrib/openzfs/cmd/zpool/zpool_main.c
@@ -6677,6 +6677,7 @@ zpool_do_iostat(int argc, char **argv)
                        if (skip) {
                                (void) fflush(stdout);
                                (void) fsleep(interval);
+                               last_npools = npools;
                                continue;
                        }
 
diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c 
b/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c
index 088c0108e911..222b5524669e 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c
+++ b/sys/contrib/openzfs/cmd/zpool/zpool_vdev.c
@@ -270,14 +270,13 @@ is_spare(nvlist_t *config, const char *path)
  *     draid*          Virtual dRAID spare
  */
 static nvlist_t *
-make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
+make_leaf_vdev(const char *arg, boolean_t is_primary, uint64_t ashift)
 {
        char path[MAXPATHLEN];
        struct stat64 statbuf;
        nvlist_t *vdev = NULL;
        const char *type = NULL;
        boolean_t wholedisk = B_FALSE;
-       uint64_t ashift = 0;
        int err;
 
        /*
@@ -381,31 +380,6 @@ make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t 
is_primary)
                verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
                    (uint64_t)wholedisk) == 0);
 
-       /*
-        * Override defaults if custom properties are provided.
-        */
-       if (props != NULL) {
-               const char *value = NULL;
-
-               if (nvlist_lookup_string(props,
-                   zpool_prop_to_name(ZPOOL_PROP_ASHIFT), &value) == 0) {
-                       if (zfs_nicestrtonum(NULL, value, &ashift) != 0) {
-                               (void) fprintf(stderr,
-                                   gettext("ashift must be a number.\n"));
-                               return (NULL);
-                       }
-                       if (ashift != 0 &&
-                           (ashift < ASHIFT_MIN || ashift > ASHIFT_MAX)) {
-                               (void) fprintf(stderr,
-                                   gettext("invalid 'ashift=%" PRIu64 "' "
-                                   "property: only values between %" PRId32 " "
-                                   "and %" PRId32 " are allowed.\n"),
-                                   ashift, ASHIFT_MIN, ASHIFT_MAX);
-                               return (NULL);
-                       }
-               }
-       }
-
        /*
         * If the device is known to incorrectly report its physical sector
         * size explicitly provide the known correct value.
@@ -1513,6 +1487,29 @@ construct_spec(nvlist_t *props, int argc, char **argv)
        const char *type, *fulltype;
        boolean_t is_log, is_special, is_dedup, is_spare;
        boolean_t seen_logs;
+       uint64_t ashift = 0;
+
+       if (props != NULL) {
+               const char *value = NULL;
+
+               if (nvlist_lookup_string(props,
+                   zpool_prop_to_name(ZPOOL_PROP_ASHIFT), &value) == 0) {
+                       if (zfs_nicestrtonum(NULL, value, &ashift) != 0) {
+                               (void) fprintf(stderr,
+                                   gettext("ashift must be a number.\n"));
+                               return (NULL);
+                       }
+                       if (ashift != 0 &&
+                           (ashift < ASHIFT_MIN || ashift > ASHIFT_MAX)) {
+                               (void) fprintf(stderr,
+                                   gettext("invalid 'ashift=%" PRIu64 "' "
+                                   "property: only values between %" PRId32 " "
+                                   "and %" PRId32 " are allowed.\n"),
+                                   ashift, ASHIFT_MIN, ASHIFT_MAX);
+                               return (NULL);
+                       }
+               }
+       }
 
        top = NULL;
        toplevels = 0;
@@ -1618,9 +1615,9 @@ construct_spec(nvlist_t *props, int argc, char **argv)
                                    children * sizeof (nvlist_t *));
                                if (child == NULL)
                                        zpool_no_memory();
-                               if ((nv = make_leaf_vdev(props, argv[c],
+                               if ((nv = make_leaf_vdev(argv[c],
                                    !(is_log || is_special || is_dedup ||
-                                   is_spare))) == NULL) {
+                                   is_spare), ashift)) == NULL) {
                                        for (c = 0; c < children - 1; c++)
                                                nvlist_free(child[c]);
                                        free(child);
@@ -1684,6 +1681,10 @@ construct_spec(nvlist_t *props, int argc, char **argv)
                                            ZPOOL_CONFIG_ALLOCATION_BIAS,
                                            VDEV_ALLOC_BIAS_DEDUP) == 0);
                                }
+                               if (ashift > 0) {
+                                       fnvlist_add_uint64(nv,
+                                           ZPOOL_CONFIG_ASHIFT, ashift);
+                               }
                                if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
                                        verify(nvlist_add_uint64(nv,
                                            ZPOOL_CONFIG_NPARITY,
@@ -1711,8 +1712,9 @@ construct_spec(nvlist_t *props, int argc, char **argv)
                         * We have a device.  Pass off to make_leaf_vdev() to
                         * construct the appropriate nvlist describing the vdev.
                         */
-                       if ((nv = make_leaf_vdev(props, argv[0], !(is_log ||
-                           is_special || is_dedup || is_spare))) == NULL)
+                       if ((nv = make_leaf_vdev(argv[0], !(is_log ||
+                           is_special || is_dedup || is_spare),
+                           ashift)) == NULL)
                                goto spec_out;
 
                        verify(nvlist_add_uint64(nv,
diff --git a/sys/contrib/openzfs/config/kernel-block-device-operations.m4 
b/sys/contrib/openzfs/config/kernel-block-device-operations.m4
index 4ff20b9c413d..1905340a9c7d 100644
--- a/sys/contrib/openzfs/config/kernel-block-device-operations.m4
+++ b/sys/contrib/openzfs/config/kernel-block-device-operations.m4
@@ -119,15 +119,49 @@ 
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK], [
        ])
 ])
 
+dnl #
+dnl # 6.18 API change
+dnl # block_device_operation->getgeo takes struct gendisk* as first arg
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
+       ZFS_LINUX_TEST_SRC([block_device_operations_getgeo_gendisk], [
+               #include <linux/blkdev.h>
+
+               static int blk_getgeo(struct gendisk *disk, struct hd_geometry 
*geo)
+               {
+                       (void) disk, (void) geo;
+                       return (0);
+               }
+
+               static const struct block_device_operations
+                   bops __attribute__ ((unused)) = {
+                       .getgeo = blk_getgeo,
+               };
+       ], [], [])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
+       AC_MSG_CHECKING([whether bops->getgeo() takes gendisk as first arg])
+       ZFS_LINUX_TEST_RESULT([block_device_operations_getgeo_gendisk], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE([HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [1],
+                       [Define if getgeo() in block_device_operations takes 
struct gendisk * as its first arg])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
 AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
        ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
        ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
        ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
        ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
+       ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
 ])
 
 AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS], [
        ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
        ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
        ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
+       ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
 ])
diff --git a/sys/contrib/openzfs/config/kernel-drop-inode.m4 
b/sys/contrib/openzfs/config/kernel-drop-inode.m4
new file mode 100644
index 000000000000..6f2b12cadc02
--- /dev/null
+++ b/sys/contrib/openzfs/config/kernel-drop-inode.m4
@@ -0,0 +1,24 @@
+dnl #
+dnl # 6.18 API change
+dnl # - generic_drop_inode() renamed to inode_generic_drop()
+dnl # - generic_delete_inode() renamed to inode_just_drop()
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GENERIC_DROP], [
+       ZFS_LINUX_TEST_SRC([inode_generic_drop], [
+               #include <linux/fs.h>
+       ],[
+               struct inode *ip = NULL;
+               inode_generic_drop(ip);
+       ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_INODE_GENERIC_DROP], [
+       AC_MSG_CHECKING([whether inode_generic_drop() exists])
+       ZFS_LINUX_TEST_RESULT([inode_generic_drop], [
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_GENERIC_DROP, 1,
+                       [inode_generic_drop() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
diff --git a/sys/contrib/openzfs/config/kernel-namespace.m4 
b/sys/contrib/openzfs/config/kernel-namespace.m4
new file mode 100644
index 000000000000..9b0b12e4eab4
--- /dev/null
+++ b/sys/contrib/openzfs/config/kernel-namespace.m4
@@ -0,0 +1,31 @@
+dnl #
+dnl # 6.18 API change
+dnl # ns->ops->type was moved to ns->ns.ns_type (struct ns_common)
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_NS_COMMON_TYPE], [
+       ZFS_LINUX_TEST_SRC([ns_common_type], [
+               #include <linux/user_namespace.h>
+       ],[
+               struct user_namespace ns;
+               ns.ns.ns_type = 0;
*** 2486 LINES SKIPPED ***

Reply via email to