git: 6bf158defbcb - releng/15.0 - zfs: merge openzfs/zfs@814f9afba (zfs-2.4-release) into stable/15
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 28 Oct 2025 21:23:36 UTC
The branch releng/15.0 has been updated by cperciva:
URL: https://cgit.FreeBSD.org/src/commit/?id=6bf158defbcb2f3c948b28394388179c7e95bd8b
commit 6bf158defbcb2f3c948b28394388179c7e95bd8b
Author: Martin Matuska <mm@FreeBSD.org>
AuthorDate: 2025-10-25 08:14:36 +0000
Commit: Colin Percival <cperciva@FreeBSD.org>
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 ***