diff options
| author | Martin Matuska <mm@FreeBSD.org> | 2026-03-19 20:25:34 +0000 |
|---|---|---|
| committer | Martin Matuska <mm@FreeBSD.org> | 2026-03-19 20:25:34 +0000 |
| commit | 80aae8a3f8aa70712930664572be9e6885dc0be7 (patch) | |
| tree | 0eb99ca0cd6644259dcc434ec95c88253d216258 | |
| parent | 56dddebc55494fdf75eeb914cc9e345d0d762f8c (diff) | |
| parent | 3ee08abd2fcef3123188e9ad61a9cd80b9b7831c (diff) | |
zfs: merge openzfs/zfs@3ee08abd2
Notable upstream pull request merges:
#17000 -multiple cmd/zfs: support creating parents with canmount=no
#17926 b481a8bbb Make zpool status dedup table support raw bytes -p output
#18238 -multiple Report space metrics per allocation class
#18240 5dad9459d Add --no-preserve-encryption flag
#18257 1eace5906 libzfs: use mount_setattr for selective remount including
legacy mounts
#18259 1e2c94a04 More consistent use of TREE_* macros in AVL comparators
#18262 c58b8b7dc Fix check for .cfi_negate_ra_state on aarch64
#18264 f109c7bb9 Add the --file-layout (-f) option to zdb(8)
#18268 304de7f19 libzfs: handle EDOM error in zpool_create
#18275 753f1e1e2 zstream: add a drop_record subcommand
#18276 0f90a797d Fix vdev_rebuild_range() tx commit
#18277 1e1d64d66 Fix log vdev removal issues
#18278 06b0abfe6 Fix the send --exclude option to work with encryption
#18281 e73ada771 libzpool: lift zfs_file ops out to separate source file
#18284 d97945776 zstream: consolidate shared code
#18285 -multiple Separate SIMD compile checks for userspace and kernel
#18288 c5905b2cb Implement lzc_send_progress
#18289 -multiple L2ARC: Add depth cap and write budget fairness for
persistent markers
#18290 d45c8d648 FreeBSD: Improve dmesg kernel message prefix
#18294 b403040c4 draid: fix data corruption after disk clear
#18296 -multiple libzfs: mnttab cleanup
#18300 d35951b18 zpool clear: remove undocumented rewind flags
#18301 ae7fcd5f9 fix libzfs diff mem leak in an error path
#18303 65165df12 zilstat: add man page
#18314 7f65e04ab libzfs: scrub: only include start and end nv pairs if
needed for scrub
#18315 -multiple Sync ZVOLs block cloning conditions with file systems
#18330 f80338fac zarcsummary: add man page
#18337 f259a47c7 zpool-iostat.8: clarify first report shows per-second
averages
Obtained from: OpenZFS
OpenZFS commit: 3ee08abd2fcef3123188e9ad61a9cd80b9b7831c
180 files changed, 5809 insertions, 2666 deletions
diff --git a/cddl/lib/libicp/Makefile b/cddl/lib/libicp/Makefile index 15846e67a14b..28e60d687bb7 100644 --- a/cddl/lib/libicp/Makefile +++ b/cddl/lib/libicp/Makefile @@ -104,6 +104,7 @@ CFLAGS+= -I${SRCTOP}/sys CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include CFLAGS+= -I${ZFSTOP}/module/icp/include CFLAGS+= -I${ZFSTOP}/lib/libzpool/include +CFLAGS+= -include ${ZFSTOP}/include/sys/simd_config.h CFLAGS+= -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h CFLAGS+= -DHAVE_ISSETUGID CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h diff --git a/cddl/lib/libicp_rescue/Makefile b/cddl/lib/libicp_rescue/Makefile index 8dc8c396774c..337bf0b145fa 100644 --- a/cddl/lib/libicp_rescue/Makefile +++ b/cddl/lib/libicp_rescue/Makefile @@ -102,6 +102,7 @@ CFLAGS+= -I${SRCTOP}/sys CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include CFLAGS+= -I${ZFSTOP}/module/icp/include CFLAGS+= -I${ZFSTOP}/lib/libzpool/include +CFLAGS+= -include ${ZFSTOP}/include/sys/simd_config.h CFLAGS+= -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h CFLAGS+= -DHAVE_ISSETUGID -UHAVE_AVX -DRESCUE CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h diff --git a/cddl/lib/libspl/Makefile b/cddl/lib/libspl/Makefile index b0f47172e52d..a8935a86be16 100644 --- a/cddl/lib/libspl/Makefile +++ b/cddl/lib/libspl/Makefile @@ -42,7 +42,7 @@ SRCS += \ tunables.c \ os/freebsd/getexecname.c \ os/freebsd/gethostid.c \ - os/freebsd/getmntany.c \ + os/freebsd/getextmntent.c \ os/freebsd/mnttab.c .endif diff --git a/cddl/lib/libzdb/Makefile b/cddl/lib/libzdb/Makefile index f5a6a42d7aad..194521680e9c 100644 --- a/cddl/lib/libzdb/Makefile +++ b/cddl/lib/libzdb/Makefile @@ -20,6 +20,7 @@ CFLAGS+= -I${ZFSTOP}/lib/libzpool/include CFLAGS+= -I${ZFSTOP}/include/os/freebsd/zfs CFLAGS+= -I${SRCTOP}/sys CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include +CFLAGS+= -include ${ZFSTOP}/include/sys/simd_config.h CFLAGS+= -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h CFLAGS+= -I${ZFSTOP}/lib/libzutil CFLAGS+= -DHAVE_ISSETUGID -DIN_BASE diff --git a/cddl/lib/libzfs/Makefile b/cddl/lib/libzfs/Makefile index 8f364d2c2bb1..d28424a353e5 100644 --- a/cddl/lib/libzfs/Makefile +++ b/cddl/lib/libzfs/Makefile @@ -35,6 +35,7 @@ USER_C = \ libzfs_diff.c \ libzfs_import.c \ libzfs_iter.c \ + libzfs_mnttab.c \ libzfs_mount.c \ libzfs_pool.c \ libzfs_sendrecv.c \ @@ -94,6 +95,7 @@ CFLAGS+= -I${SRCTOP}/sys/contrib/ck/include CFLAGS+= -I${SRCTOP}/sys CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include CFLAGS+= -I${ZFSTOP}/module/icp/include +CFLAGS+= -include ${ZFSTOP}/include/sys/simd_config.h CFLAGS+= -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h CFLAGS+= -DHAVE_ISSETUGID CFLAGS+= -DHAVE_EXECVPE diff --git a/cddl/lib/libzpool/Makefile b/cddl/lib/libzpool/Makefile index 74a5f6ccb438..9361d352f7c0 100644 --- a/cddl/lib/libzpool/Makefile +++ b/cddl/lib/libzpool/Makefile @@ -176,6 +176,7 @@ KERNEL_C = \ zfs_chksum.c \ zfs_crrd.c \ zfs_debug_common.c \ + zfs_file_os.c \ zfs_fm.c \ zfs_fuid.c \ zfs_impl.c \ @@ -265,6 +266,7 @@ CFLAGS+= \ -I${SRCTOP}/cddl/compat/opensolaris/include \ -I${ZFSTOP}/module/icp/include \ -I${SRCTOP}/compat/linuxkpi/common/include/linux \ + -include ${ZFSTOP}/include/sys/simd_config.h \ -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h \ -DHAVE_ISSETUGID \ -include ${SRCTOP}/sys/modules/zfs/zfs_config.h \ diff --git a/cddl/usr.bin/zstream/Makefile b/cddl/usr.bin/zstream/Makefile index f0a11383045c..b8c17df1aea6 100644 --- a/cddl/usr.bin/zstream/Makefile +++ b/cddl/usr.bin/zstream/Makefile @@ -9,10 +9,12 @@ INCS= zstream.h SRCS= \ zstream.c \ zstream_decompress.c \ + zstream_drop_record.c \ zstream_dump.c \ zstream_recompress.c \ zstream_redup.c \ - zstream_token.c + zstream_token.c \ + zstream_util.c SYMLINKS= zstream ${BINDIR}/zstreamdump @@ -27,6 +29,7 @@ CFLAGS+= \ -I${SRCTOP}/sys \ -I${SRCTOP}/cddl/compat/opensolaris/include \ -I${ZFSTOP}/module/icp/include \ + -include ${ZFSTOP}/include/sys/simd_config.h \ -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h \ -DHAVE_ISSETUGID \ -include ${SRCTOP}/sys/modules/zfs/zfs_config.h diff --git a/cddl/usr.bin/ztest/Makefile b/cddl/usr.bin/ztest/Makefile index 71b8c1705c4f..83c7b0eee13a 100644 --- a/cddl/usr.bin/ztest/Makefile +++ b/cddl/usr.bin/ztest/Makefile @@ -16,6 +16,7 @@ CFLAGS+= \ -I${ZFSTOP}/lib/libzpool/include \ -I${SRCTOP}/cddl/compat/opensolaris/include \ -I${ZFSTOP}/module/icp/include \ + -include ${ZFSTOP}/include/sys/simd_config.h \ -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h \ -DHAVE_ISSETUGID \ -include ${SRCTOP}/sys/modules/zfs/zfs_config.h diff --git a/cddl/usr.sbin/zdb/Makefile b/cddl/usr.sbin/zdb/Makefile index fa49271dc760..8bf07cb4c06a 100644 --- a/cddl/usr.sbin/zdb/Makefile +++ b/cddl/usr.sbin/zdb/Makefile @@ -18,6 +18,7 @@ CFLAGS+= \ -I${ZFSTOP}/lib/libspl/include/os/freebsd/spl \ -I${ZFSTOP}/lib/libzpool/include \ -I${SRCTOP}/sys \ + -include ${ZFSTOP}/include/sys/simd_config.h \ -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h \ -DHAVE_ISSETUGID diff --git a/cddl/usr.sbin/zhack/Makefile b/cddl/usr.sbin/zhack/Makefile index a238da39a243..f6225e7f5d99 100644 --- a/cddl/usr.sbin/zhack/Makefile +++ b/cddl/usr.sbin/zhack/Makefile @@ -17,6 +17,7 @@ CFLAGS+= -I${ZFSTOP}/lib/libzpool/include CFLAGS+= -I${SRCTOP}/sys CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include CFLAGS+= -I${ZFSTOP}/module/icp/include +CFLAGS+= -include ${ZFSTOP}/include/sys/simd_config.h CFLAGS+= -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h CFLAGS+= -DHAVE_ISSETUGID CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h diff --git a/stand/libsa/zfs/Makefile.inc b/stand/libsa/zfs/Makefile.inc index fe13eeea872d..3df6779559c9 100644 --- a/stand/libsa/zfs/Makefile.inc +++ b/stand/libsa/zfs/Makefile.inc @@ -43,7 +43,9 @@ ZFS_EARLY= -I${SAZFSSRC}/spl \ # from FreeBSD. # .for i in ${ZFS_SRC} ${ZSTD_SRC} -CFLAGS.$i+= -include ${ZFSOSINC}/spl/sys/ccompile.h -Wformat -Wall -I${ZFSTOP}/include \ +CFLAGS.$i+= -include ${ZFSTOP}/include/sys/simd_config.h \ + -include ${ZFSOSINC}/spl/sys/ccompile.h \ + -Wformat -Wall -I${ZFSTOP}/include \ -DNEED_SOLARIS_BOOLEAN .endfor diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index d4b29aac5e63..871cd1c0705a 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -205,6 +205,7 @@ CDDL_C= ${CC} -c ${CDDL_CFLAGS} ${WERROR} ${.IMPSRC} # Special flags for managing the compat compiles for ZFS ZFS_CFLAGS+= -I$S/contrib/openzfs/module/icp/include \ + -include $S/contrib/openzfs/include/sys/simd_config.h \ ${CDDL_CFLAGS} -DBUILDING_ZFS -DHAVE_UIO_ZEROCOPY \ -DWITH_NETDUMP -D__KERNEL__ -D_SYS_CONDVAR_H_ -DSMP diff --git a/sys/contrib/openzfs/README.md b/sys/contrib/openzfs/README.md index a39b88fedd12..fa348a243839 100644 --- a/sys/contrib/openzfs/README.md +++ b/sys/contrib/openzfs/README.md @@ -30,6 +30,42 @@ We have a [Code of Conduct](./CODE_OF_CONDUCT.md). OpenZFS is released under a CDDL license. For more details see the NOTICE, LICENSE and COPYRIGHT files; `UCRL-CODE-235197` -# Supported Kernels - * The `META` file contains the officially recognized supported Linux kernel versions. - * Supported FreeBSD versions are any supported branches and releases starting from 13.0-RELEASE. +# Supported Kernels and Distributions + +## Linux + +Given the wide variety of Linux environments, we prioritize development and testing on stable, supported kernels and distributions. + +### Kernel ([kernel.org](https://kernel.org)) + +All **longterm** kernels from [kernel.org](https://kernel.org) are supported. **stable** kernels are usually supported in the next OpenZFS release. + +**Supported longterm kernels**: **6.18**, **6.12**, **6.6**, **6.1**, **5.15**, **5.10**. + +### Red Hat Enterprise Linux (RHEL) + +All RHEL (and compatible systems: AlmaLinux OS, Rocky Linux, etc) on the **full** or **maintenance** support tracks are supported. + +**Supported RHEL releases**: **8.10**, **9.7**, **10.1**. + +### Ubuntu + +All Ubuntu **LTS** releases are supported. + +**Supported Ubuntu releases**: **24.04 “Noble”**, **22.04 “Jammy”**. + +### Debian + +All Debian **stable** and **LTS** releases are supported. + +**Supported Debian releases**: **13 “Trixie”**, **12 “Bookworm”**, **11 “Bullseye”**. + +### Other Distributions + +Generally, if a distribution is following an LTS kernel, it should work well with OpenZFS. + +## FreeBSD + +All FreeBSD releases receiving [security support](https://www.freebsd.org/security/#sup) are supported by OpenZFS. + +**Supported FreeBSD releases**: **15.0**, **14.4**, **13.5**. diff --git a/sys/contrib/openzfs/cmd/zdb/zdb.c b/sys/contrib/openzfs/cmd/zdb/zdb.c index 13217fd1c348..68c9696a8aaf 100644 --- a/sys/contrib/openzfs/cmd/zdb/zdb.c +++ b/sys/contrib/openzfs/cmd/zdb/zdb.c @@ -87,6 +87,8 @@ #include <sys/brt.h> #include <sys/brt_impl.h> #include <zfs_comutil.h> +#include <sys/vdev_raidz.h> +#include <sys/vdev_raidz_impl.h> #include <sys/zstd/zstd.h> #include <sys/backtrace.h> @@ -743,11 +745,13 @@ usage(void) "\t%s -r [-K <key>] -O <dataset> <object-id> <destination>\n" "\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n" "\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n" + "\t%s -f [-H] [-e [-V] [-p <path> ...]] [-U <cache>]\n" + "\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]]\n" "\t%s -E [-A] word0:word1:...:word15\n" "\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] " "<poolname>\n\n", cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, - cmdname, cmdname, cmdname, cmdname, cmdname, cmdname); + cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname); (void) fprintf(stderr, " Dataset name must include at least one " "separator character '/' or '@'\n"); @@ -786,6 +790,8 @@ usage(void) "dataset(s)\n"); (void) fprintf(stderr, " -D --dedup-stats " "dedup statistics\n"); + (void) fprintf(stderr, " -f --file-layout " + "display a file's layout across raidz disks\n"); (void) fprintf(stderr, " -E --embedded-block-pointer=INTEGER\n" " decode and display block " "from an embedded block pointer\n"); @@ -818,6 +824,7 @@ usage(void) (void) fprintf(stderr, " -y --livelist " "perform livelist and metaslab validation on any livelists being " "deleted\n\n"); + (void) fprintf(stderr, " Below options are intended for use " "with other options:\n"); (void) fprintf(stderr, " -A --ignore-assertions " @@ -830,6 +837,8 @@ usage(void) "groups\n"); (void) fprintf(stderr, " -G --dump-debug-msg " "dump zfs_dbgmsg buffer before exiting\n"); + (void) fprintf(stderr, " -H --scripting-mode " + "dump output in a format that is scripting friendly\n"); (void) fprintf(stderr, " -I --inflight=INTEGER " "specify the maximum number of checksumming I/Os " "[default is 200]\n"); @@ -2135,7 +2144,8 @@ dump_ddt_object(ddt_t *ddt, ddt_type_t type, ddt_class_t class) (void) printf("%s: object=%llu\n", name, (u_longlong_t)ddt->ddt_object[type][class]); - zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class]); + zpool_dump_ddt(NULL, &ddt->ddt_histogram[type][class], + dump_opt['P'] > 0); if (dump_opt['D'] < 4) return; @@ -2212,7 +2222,7 @@ dump_all_ddts(spa_t *spa) if (dump_opt['D'] > 1) { (void) printf("DDT histogram (aggregated over all DDTs):\n"); ddt_get_dedup_histogram(spa, &ddh_total); - zpool_dump_ddt(&dds_total, &ddh_total); + zpool_dump_ddt(&dds_total, &ddh_total, dump_opt['P'] > 0); } dump_dedup_ratio(&dds_total); @@ -2645,6 +2655,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp, if (bp_freed) (void) snprintf(blkbuf + strlen(blkbuf), buflen - strlen(blkbuf), " %s", "FREE"); + (void) snprintf(blkbuf + strlen(blkbuf), buflen - strlen(blkbuf), " cksum=%016llx:%016llx:%016llx:%016llx", @@ -2655,6 +2666,74 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp, } } +static void +inverse_text(boolean_t on) +{ + if (isatty(STDOUT_FILENO)) { + if (on) + fputs("\x1b[7m", stdout); + else + fputs("\x1b[m", stdout); + } +} + +static void +print_file_layout_line(int line, int first_disk, int last_disk, int ashift, + raidz_row_t *rr) +{ + if (first_disk != 0) { + /* Account for empty columns */ + for (int c = 0; c < first_disk; c++) { + (void) printf("%s%s", (c == 0) ? " │ " : " ", + line == 0 ? "` ` ` ` ` " : " ` ` ` ` `"); + } + } + + /* + * Check if we need to account for out of order disks in raidz1. + * Here flip means the disks in first two column were exchanged. + */ + boolean_t flip = rr->rr_firstdatacol == 1 && + (rr->rr_offset & (1ULL << 20)); + + for (int c = 0; c < rr->rr_cols; c++) { + raidz_col_t *rc = &rr->rr_col[c]; + char colname[8]; + boolean_t pcol = flip ? (c == 1) : (c < rr->rr_firstdatacol); + + if (rc->rc_devidx > last_disk) + continue; + + (void) snprintf(colname, sizeof (colname), "%c%d", + pcol ? 'P' : 'D', (flip && c < 2) ? 0 : + pcol ? c : c - rr->rr_firstdatacol); + + (void) printf("%s", (rc->rc_devidx == 0) ? " │ " : " "); + if (pcol) + inverse_text(B_TRUE); + if (line == 0) { + (void) printf("%3s %5d", colname, + (int)(rc->rc_size >> ashift)); + } else { + (void) printf("%10llx", + (u_longlong_t)((rc->rc_offset + + VDEV_LABEL_START_SIZE) >> ashift)); + } + if (pcol) + inverse_text(B_FALSE); + if (rc->rc_devidx == last_disk) { + /* empty columns */ + for (int c = last_disk + 1; c < rr->rr_cols; c++) { + (void) printf(" %s", + line == 0 ? "` ` ` ` ` " : " ` ` ` ` `"); + } + break; + } + } + (void) printf(" │\n"); +} + + static u_longlong_t print_indirect(spa_t *spa, blkptr_t *bp, const zbookmark_phys_t *zb, const dnode_phys_t *dnp) @@ -2701,17 +2780,133 @@ print_indirect(spa_t *spa, blkptr_t *bp, const zbookmark_phys_t *zb, return (offset); } +static void +print_file_layout_raidz(vdev_t *vd, blkptr_t *bp, uint64_t file_offset, + boolean_t last) +{ + /* + * RAIDZ file data layout + * + * Use vdev_raidz_map_alloc() to get the actual layout + */ + const dva_t *dva = bp->blk_dva; + zio_t zio = {0}; + zio.io_size = P2ROUNDUP_TYPED(BP_GET_PSIZE(bp), + 1ULL << vd->vdev_ashift, uint64_t); + zio.io_offset = DVA_GET_OFFSET(&dva[0]); + zio.io_type = ZIO_TYPE_READ; + zio.io_abd = abd_alloc_for_io(zio.io_size, B_FALSE); + + vdev_raidz_t *vdrz = vd->vdev_tsd; + raidz_map_t *rm = vdev_raidz_map_alloc(&zio, vd->vdev_ashift, + vd->vdev_children, vdrz->vd_nparity); + raidz_row_t *rr = rm->rm_row[0]; + + /* + * Account for out of order disks in raidz1. + * For now just reverse them back and adjust for it later. + */ + if (rr->rr_firstdatacol == 1 && (zio.io_offset & (1ULL << 20))) { + uint64_t devidx = rr->rr_col[0].rc_devidx; + rr->rr_col[0].rc_devidx = rr->rr_col[1].rc_devidx; + rr->rr_col[1].rc_devidx = devidx; + } + + if (!dump_opt['H']) { + int last_disk = vd->vdev_children - 1; + int first_disk = rr->rr_col[0].rc_devidx; + + (void) printf("%12llx", (u_longlong_t)file_offset); + print_file_layout_line(0, first_disk, last_disk, + vd->vdev_ashift, rr); + (void) printf("%*c", 12, ' '); + print_file_layout_line(1, first_disk, last_disk, + vd->vdev_ashift, rr); + /* Check for split row */ + if (first_disk != 0) { + (void) printf("%*c", 12, ' '); + print_file_layout_line(0, 0, first_disk - 1, + vd->vdev_ashift, rr); + (void) printf("%*c", 12, ' '); + print_file_layout_line(1, 0, first_disk - 1, + vd->vdev_ashift, rr); + } + /* seperate rows with a line */ + (void) printf("%*c", 12, ' '); + for (int c = 0; c < vd->vdev_children; c++) { + (void) printf("%s%10s", (c == 0) ? + (last ? " └─" : " ├─") : "──", + "──────────"); + } + (void) printf("─%s\n", last ? "┘" : "┤"); + } else { + static uint64_t next_offset = 0; + + if (next_offset != file_offset) { + (void) printf("skip hole\t-\t%llx\n", + (u_longlong_t)((file_offset - next_offset) >> + vd->vdev_ashift)); + } + next_offset = file_offset + BP_GET_LSIZE(bp); + + for (int c = 0; c < rr->rr_cols; c++) { + raidz_col_t *rc = &rr->rr_col[c]; + char *path = vd->vdev_child[rc->rc_devidx]->vdev_path; + // c < rr->rr_firstdatacol + if (rc->rc_size == 0) + continue; + (void) printf("%s\t%llu\t%d\n", + zfs_basename(path), + (u_longlong_t)(rc->rc_offset + + VDEV_LABEL_START_SIZE)/512, + (int)rc->rc_size/512); + } + } +} + +static void +print_file_layout(spa_t *spa, blkptr_t *bp, const zbookmark_phys_t *zb, + const dnode_phys_t *dnp) +{ + if (!BP_IS_EMBEDDED(bp)) { + ASSERT3U(BP_GET_TYPE(bp), ==, dnp->dn_type); + ASSERT3U(BP_GET_LEVEL(bp), ==, zb->zb_level); + } + ASSERT(zb->zb_level >= 0); + + if (BP_IS_HOLE(bp)) + return; + + if (BP_IS_EMBEDDED(bp)) + return; + + const dva_t *dva = bp->blk_dva; + vdev_t *vd = spa->spa_root_vdev->vdev_child[DVA_GET_VDEV(&dva[0])]; + uint64_t file_offset = blkid2offset(dnp, bp, zb); + + if (strcmp("raidz", vd->vdev_ops->vdev_op_type) == 0) { + boolean_t last = (file_offset + BP_GET_LSIZE(bp)) >= + (dnp->dn_used & ~0x03ffULL); + print_file_layout_raidz(vd, bp, file_offset, last); + } +} + static int visit_indirect(spa_t *spa, const dnode_phys_t *dnp, blkptr_t *bp, const zbookmark_phys_t *zb) { - u_longlong_t offset; + u_longlong_t offset = 0; int err = 0; if (BP_GET_BIRTH(bp) == 0) return (0); - offset = print_indirect(spa, bp, zb, dnp); + if (dump_opt['f']) { + if (BP_GET_LEVEL(bp) == 0) + print_file_layout(spa, bp, zb, dnp); + } else { + print_indirect(spa, bp, zb, dnp); + } if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) { arc_flags_t flags = ARC_FLAG_WAIT; @@ -2763,6 +2958,63 @@ dump_indirect(dnode_t *dn) zbookmark_phys_t czb; (void) printf("Indirect blocks:\n"); + SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset), + dn->dn_object, dnp->dn_nlevels - 1, 0); + for (int j = 0; j < dnp->dn_nblkptr; j++) { + czb.zb_blkid = j; + (void) visit_indirect(dmu_objset_spa(dn->dn_objset), dnp, + &dnp->dn_blkptr[j], &czb); + } + + (void) printf("\n"); +} + +static int +dump_indirect_layout(dnode_t *dn) +{ + dnode_phys_t *dnp = dn->dn_phys; + zbookmark_phys_t czb; + + spa_t *spa = dmu_objset_spa(dn->dn_objset); + int ashift = spa->spa_root_vdev->vdev_child[0]->vdev_ashift; + int children = spa->spa_root_vdev->vdev_child[0]->vdev_children; + + if (strcmp(spa->spa_root_vdev->vdev_child[0]->vdev_ops->vdev_op_type, + "raidz") != 0) { + (void) fprintf(stderr, "file layout only supports raidz\n"); + return (ENOTSUP); + } + + /* + * Start layout with a header + */ + if (dump_opt['H']) { + (void) printf("DISK\t\tLBA\t\tCOUNT\n"); + } else { + char diskhdr[16]; + + (void) printf("%12s: %d\n", "block size", dn->dn_datablksz); + (void) printf("%12s: %s%d\n", "vdev_type", + spa->spa_root_vdev->vdev_child[0]->vdev_ops->vdev_op_type, + (int)vdev_get_nparity(spa->spa_root_vdev->vdev_child[0])); + (void) printf("%12s: %d\n", "sector size", 1 << ashift); + (void) printf("%12s: %d\n\n", "child disks", children); + + (void) printf("%*c ", 12, ' '); + + for (int c = 0; c < children; c++) { + (void) snprintf(diskhdr, sizeof (diskhdr), + "V%d:DISK-%d", 0, c); + (void) printf(" %10s ", diskhdr); + } + (void) printf("\n"); + + (void) printf("%12s", "FILE OFFSET"); + for (int c = 0; c < children; c++) + (void) printf("%s%10s", (c == 0) ? " ┌─" : "──", + "──────────"); + (void) printf("─┐\n"); + } SET_BOOKMARK(&czb, dmu_objset_id(dn->dn_objset), dn->dn_object, dnp->dn_nlevels - 1, 0); @@ -2773,6 +3025,7 @@ dump_indirect(dnode_t *dn) } (void) printf("\n"); + return (0); } static void @@ -3033,7 +3286,6 @@ dump_full_bpobj(bpobj_t *bpo, const char *name, int indent) if (dump_opt['d'] < 5) return; - if (indent == 0) { (void) bpobj_iterate_nofree(bpo, dump_bpobj_cb, NULL, NULL); (void) printf("\n"); @@ -4161,7 +4413,6 @@ dump_object(objset_t *os, uint64_t object, int verbosity, start = end; } } - out: if (db != NULL) dmu_buf_rele(db, FTAG); @@ -4170,6 +4421,60 @@ out: } static void +dump_object_file_layout(objset_t *os, uint64_t object, int verbosity) +{ + (void) verbosity; + dmu_buf_t *db = NULL; + dmu_object_info_t doi; + dnode_t *dn; + boolean_t dnode_held = B_FALSE; + int error; + + char osname[ZFS_MAX_DATASET_NAME_LEN]; + dmu_objset_name(os, osname); + (void) printf("%12s: '%s'\n", "objset", osname); + (void) printf("%12s: %d\n", "object", (int)object); + + if (object == 0) { + dn = DMU_META_DNODE(os); + dmu_object_info_from_dnode(dn, &doi); + } else { + /* + * Encrypted datasets will have sensitive bonus buffers + * encrypted. Therefore we cannot hold the bonus buffer and + * must hold the dnode itself instead. + */ + error = dmu_object_info(os, object, &doi); + if (error) + fatal("dmu_object_info() failed, errno %u", error); + + if (!key_loaded && os->os_encrypted && + DMU_OT_IS_ENCRYPTED(doi.doi_bonus_type)) { + error = dnode_hold(os, object, FTAG, &dn); + if (error) + fatal("dnode_hold() failed, errno %u", error); + dnode_held = B_TRUE; + } else { + error = dmu_bonus_hold(os, object, FTAG, &db); + if (error) + fatal("dmu_bonus_hold(%llu) failed, errno %u", + object, error); + dn = DB_DNODE((dmu_buf_impl_t *)db); + } + } + + error = dump_indirect_layout(dn); + + if (db != NULL) + dmu_buf_rele(db, FTAG); + if (dnode_held) + dnode_rele(dn, FTAG); + + if (error) + zdb_exit(1); +} + +static void count_dir_mos_objects(dsl_dir_t *dd) { mos_obj_refd(dd->dd_object); @@ -4357,7 +4662,7 @@ dump_objset(objset_t *os) zdb_nicenum(refdbytes, numbuf, sizeof (numbuf)); - if (verbosity >= 4) { + if (verbosity >= 4 || dump_opt['d']) { (void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp "); (void) snprintf_blkptr(blkbuf + strlen(blkbuf), sizeof (blkbuf) - strlen(blkbuf), os->os_rootbp); @@ -4380,21 +4685,21 @@ dump_objset(objset_t *os) flags = zopt_object_ranges[i].zor_flags; object = obj_start; - if (object == 0 || obj_start == obj_end) - dump_object(os, object, verbosity, &print_header, NULL, - flags); - else + if (object == 0 || obj_start == obj_end) { + dump_object(os, object, verbosity, + &print_header, NULL, flags); + } else { object--; + } while ((dmu_object_next(os, &object, B_FALSE, 0) == 0) && object <= obj_end) { - dump_object(os, object, verbosity, &print_header, NULL, - flags); + dump_object(os, object, verbosity, + &print_header, NULL, flags); } } if (zopt_object_args > 0) { - (void) printf("\n"); return; } @@ -4478,6 +4783,32 @@ dump_objset(objset_t *os) } static void +dump_file_data_layout(objset_t *os) +{ + uint64_t object; + int verbosity = dump_opt['d']; + unsigned i; + uint64_t obj_start; + uint64_t obj_end; + + for (i = 0; i < zopt_object_args; i++) { + obj_start = zopt_object_ranges[i].zor_obj_start; + obj_end = zopt_object_ranges[i].zor_obj_end; + + object = obj_start; + if (object == 0 || obj_start == obj_end) + dump_object_file_layout(os, object, verbosity); + else + object--; + + while ((dmu_object_next(os, &object, B_FALSE, 0) == 0) && + object <= obj_end) { + dump_object_file_layout(os, object, verbosity); + } + } +} + +static void dump_uberblock(uberblock_t *ub, const char *header, const char *footer) { time_t timestamp = ub->ub_timestamp; @@ -5708,7 +6039,6 @@ dump_one_objset(const char *dsname, void *arg) !dmu_objset_is_snapshot(os)) { global_feature_count[SPA_FEATURE_LIVELIST]++; } - dump_objset(os); close_objset(os, FTAG); fuid_table_destroy(); @@ -7789,7 +8119,7 @@ dump_simulated_ddt(spa_t *spa) (void) printf("Simulated DDT histogram:\n"); - zpool_dump_ddt(&dds_total, &ddh_total); + zpool_dump_ddt(&dds_total, &ddh_total, dump_opt['P'] > 0); dump_dedup_ratio(&dds_total); } @@ -9528,9 +9858,11 @@ main(int argc, char **argv) {"dedup-stats", no_argument, NULL, 'D'}, {"exported", no_argument, NULL, 'e'}, {"embedded-block-pointer", no_argument, NULL, 'E'}, + {"file-layout", no_argument, NULL, 'f'}, {"automatic-rewind", no_argument, NULL, 'F'}, {"dump-debug-msg", no_argument, NULL, 'G'}, {"history", no_argument, NULL, 'h'}, + {"scripting-mode", no_argument, NULL, 'H'}, {"intent-logs", no_argument, NULL, 'i'}, {"inflight", required_argument, NULL, 'I'}, {"checkpointed-state", no_argument, NULL, 'k'}, @@ -9570,7 +9902,7 @@ main(int argc, char **argv) }; while ((c = getopt_long(argc, argv, - "AbBcCdDeEFGhiI:kK:lLmMNo:Op:PqrRsSt:TuU:vVx:XYyZ", + "AbBcCdDeEfFGhHiI:kK:lLmMNo:Op:PqrRsSt:TuU:vVx:XYyZ", long_options, NULL)) != -1) { switch (c) { case 'b': @@ -9580,6 +9912,7 @@ main(int argc, char **argv) case 'd': case 'D': case 'E': + case 'f': case 'G': case 'h': case 'i': @@ -9603,6 +9936,7 @@ main(int argc, char **argv) case 'A': case 'e': case 'F': + case 'H': case 'k': case 'L': case 'P': @@ -9742,6 +10076,10 @@ main(int argc, char **argv) (void) fprintf(stderr, "-p option requires use of -e\n"); usage(); } + if (dump_opt['H'] && !dump_opt['f']) { + (void) fprintf(stderr, "-H option requires use of -f\n"); + usage(); + } #if defined(_LP64) /* * ZDB does not typically re-read blocks; therefore limit the ARC @@ -9781,7 +10119,7 @@ main(int argc, char **argv) verbose = MAX(verbose, 1); for (c = 0; c < 256; c++) { - if (dump_all && strchr("ABeEFkKlLNOPrRSXy", c) == NULL) + if (dump_all && strchr("ABeEfFkKlLNOPrRSXy", c) == NULL) dump_opt[c] = 1; if (dump_opt[c]) dump_opt[c] += verbose; @@ -10153,7 +10491,7 @@ retry_lookup: flagbits['z'] = ZOR_FLAG_ZAP; flagbits['A'] = ZOR_FLAG_ALL_TYPES; - if (argc > 0 && dump_opt['d']) { + if (argc > 0 && (dump_opt['d'] || dump_opt['f'])) { zopt_object_args = argc; zopt_object_ranges = calloc(zopt_object_args, sizeof (zopt_object_range_t)); @@ -10179,7 +10517,10 @@ retry_lookup: strerror(errno)); } } - if (dump_opt['B']) { + + if (dump_opt['f'] && os != NULL) { + dump_file_data_layout(os); + } else if (dump_opt['B']) { dump_backup(target, objset_id, argc > 0 ? argv[0] : NULL); } else if (os != NULL) { diff --git a/sys/contrib/openzfs/cmd/zed/zed_exec.c b/sys/contrib/openzfs/cmd/zed/zed_exec.c index a14af4f20a85..08d03daddd49 100644 --- a/sys/contrib/openzfs/cmd/zed/zed_exec.c +++ b/sys/contrib/openzfs/cmd/zed/zed_exec.c @@ -45,21 +45,10 @@ struct launched_process_node { static int _launched_process_node_compare(const void *x1, const void *x2) { - pid_t p1; - pid_t p2; + const struct launched_process_node *node1 = x1; + const struct launched_process_node *node2 = x2; - assert(x1 != NULL); - assert(x2 != NULL); - - p1 = ((const struct launched_process_node *) x1)->pid; - p2 = ((const struct launched_process_node *) x2)->pid; - - if (p1 < p2) - return (-1); - else if (p1 == p2) - return (0); - else - return (1); + return (TREE_CMP(node1->pid, node2->pid)); } static pthread_t _reap_children_tid = (pthread_t)-1; diff --git a/sys/contrib/openzfs/cmd/zed/zed_strings.c b/sys/contrib/openzfs/cmd/zed/zed_strings.c index 2e5ed1d83d67..a161db1ae5cc 100644 --- a/sys/contrib/openzfs/cmd/zed/zed_strings.c +++ b/sys/contrib/openzfs/cmd/zed/zed_strings.c @@ -42,26 +42,10 @@ typedef struct zed_strings_node zed_strings_node_t; static int _zed_strings_node_compare(const void *x1, const void *x2) { - const char *s1; - const char *s2; - int rv; + const zed_strings_node_t *n1 = x1; + const zed_strings_node_t *n2 = x2; - assert(x1 != NULL); - assert(x2 != NULL); - - s1 = ((const zed_strings_node_t *) x1)->key; - assert(s1 != NULL); - s2 = ((const zed_strings_node_t *) x2)->key; - assert(s2 != NULL); - rv = strcmp(s1, s2); - - if (rv < 0) - return (-1); - - if (rv > 0) - return (1); - - return (0); + return (TREE_ISIGN(strcmp(n1->key, n2->key))); } /* diff --git a/sys/contrib/openzfs/cmd/zfs/zfs_iter.c b/sys/contrib/openzfs/cmd/zfs/zfs_iter.c index 15d5e1633e6e..bbb6cc55dbd7 100644 --- a/sys/contrib/openzfs/cmd/zfs/zfs_iter.c +++ b/sys/contrib/openzfs/cmd/zfs/zfs_iter.c @@ -413,14 +413,12 @@ zfs_sort(const void *larg, const void *rarg) if (lstr) ret = TREE_ISIGN(strcmp(lstr, rstr)); - else if (lnum < rnum) - ret = -1; - else if (lnum > rnum) - ret = 1; + else + ret = TREE_CMP(lnum, rnum); if (ret != 0) { if (psc->sc_reverse == B_TRUE) - ret = (ret < 0) ? 1 : -1; + ret = -ret; return (ret); } } diff --git a/sys/contrib/openzfs/cmd/zfs/zfs_main.c b/sys/contrib/openzfs/cmd/zfs/zfs_main.c index 3941ff58ba47..48e563181fda 100644 --- a/sys/contrib/openzfs/cmd/zfs/zfs_main.c +++ b/sys/contrib/openzfs/cmd/zfs/zfs_main.c @@ -292,12 +292,13 @@ get_usage(zfs_help_t idx) { switch (idx) { case HELP_CLONE: - return (gettext("\tclone [-pu] [-o property=value] ... " + return (gettext("\tclone [-p[p]u] [-o property=value] ... " "<snapshot> <filesystem|volume>\n")); case HELP_CREATE: - return (gettext("\tcreate [-Pnpuv] [-o property=value] ... " + return (gettext("\tcreate [-Pnp[p]uv] [-o property=value] ... " "<filesystem>\n" - "\tcreate [-Pnpsv] [-b blocksize] [-o property=value] ... " + "\tcreate [-Pnp[p]sv] [-b blocksize] " + "[-o property=value] ... " "-V <size> <volume>\n")); case HELP_DESTROY: return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n" @@ -338,16 +339,17 @@ get_usage(zfs_help_t idx) case HELP_RENAME: return (gettext("\trename [-f] <filesystem|volume|snapshot> " "<filesystem|volume|snapshot>\n" - "\trename -p [-f] <filesystem|volume> <filesystem|volume>\n" + "\trename -p[p] [-f] <filesystem|volume> " + "<filesystem|volume>\n" "\trename -u [-f] <filesystem> <filesystem>\n" "\trename -r <snapshot> <snapshot>\n")); case HELP_ROLLBACK: return (gettext("\trollback [-rRf] <snapshot>\n")); case HELP_SEND: - return (gettext("\tsend [-DLPbcehnpsVvw] " + return (gettext("\tsend [-DLPbcehnpsUVvw] " "[-i|-I snapshot]\n" "\t [-R [-X dataset[,dataset]...]] <snapshot>\n" - "\tsend [-DnVvPLecw] [-i snapshot|bookmark] " + "\tsend [-DnVvPLecwU] [-i snapshot|bookmark] " "<filesystem|volume|snapshot>\n" "\tsend [-DnPpVvLec] [-i bookmark|snapshot] " "--redact <bookmark> <snapshot>\n" @@ -766,6 +768,26 @@ finish_progress(const char *done) pt_header = NULL; } +static void +makeprops_parents(nvlist_t **ptr, boolean_t parents_nomount) +{ + nvlist_t *props = NULL; + + if (parents_nomount) { + if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) + nomem(); + + if (nvlist_add_string(props, + zfs_prop_to_name(ZFS_PROP_CANMOUNT), + "off") != 0) { + nvlist_free(props); + nomem(); + } + } + + *ptr = props; +} + static int zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type) { @@ -826,6 +848,7 @@ zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type) * the clone exists. * * The '-p' flag creates all the non-existing ancestors of the target first. + * If repeated twice, the ancestors are created with `canmount=off`. * * The '-u' flag prevents the newly created file system from being mounted. */ @@ -834,8 +857,10 @@ zfs_do_clone(int argc, char **argv) { zfs_handle_t *zhp = NULL; boolean_t parents = B_FALSE; + boolean_t parents_nomount = B_FALSE; boolean_t nomount = B_FALSE; nvlist_t *props; + nvlist_t *props_parents = NULL; int ret = 1; int c; @@ -852,7 +877,10 @@ zfs_do_clone(int argc, char **argv) } break; case 'p': - parents = B_TRUE; + if (!parents) + parents = B_TRUE; + else + parents_nomount = B_TRUE; break; case 'u': nomount = B_TRUE; @@ -900,9 +928,11 @@ zfs_do_clone(int argc, char **argv) ret = 0; goto error; } - if (zfs_create_ancestors(g_zfs, argv[1]) != 0) { + + makeprops_parents(&props_parents, parents_nomount); + if (zfs_create_ancestors_props(g_zfs, argv[1], + props_parents) != 0) goto error; - } } /* pass to libzfs */ @@ -930,11 +960,13 @@ error: zfs_close(zhp); error_open: nvlist_free(props); + nvlist_free(props_parents); return (!!ret); usage: ASSERT0P(zhp); nvlist_free(props); + nvlist_free(props_parents); usage(B_FALSE); return (-1); } @@ -1068,6 +1100,7 @@ default_volblocksize(zpool_handle_t *zhp, nvlist_t *props) * SPA_VERSION_REFRESERVATION, we set a refreservation instead. * * The '-p' flag creates all the non-existing ancestors of the target first. + * If repeated twice, the ancestors are created with `canmount=off`. * * The '-n' flag is no-op (dry run) mode. This will perform a user-space sanity * check of arguments and properties, but does not check for permissions, @@ -1090,12 +1123,14 @@ zfs_do_create(int argc, char **argv) boolean_t noreserve = B_FALSE; boolean_t bflag = B_FALSE; boolean_t parents = B_FALSE; + boolean_t parents_nomount = B_FALSE; boolean_t dryrun = B_FALSE; boolean_t nomount = B_FALSE; boolean_t verbose = B_FALSE; boolean_t parseable = B_FALSE; int ret = 1; nvlist_t *props; + nvlist_t *props_parents = NULL; uint64_t intval; const char *strval; @@ -1124,7 +1159,10 @@ zfs_do_create(int argc, char **argv) parseable = B_TRUE; break; case 'p': - parents = B_TRUE; + if (!parents) + parents = B_TRUE; + else + parents_nomount = B_TRUE; break; case 'b': bflag = B_TRUE; @@ -1274,6 +1312,8 @@ zfs_do_create(int argc, char **argv) } if (parents && zfs_name_valid(argv[0], type)) { + makeprops_parents(&props_parents, parents_nomount); + /* * Now create the ancestors of target dataset. If the target * already exists and '-p' option was used we should not @@ -1289,7 +1329,8 @@ zfs_do_create(int argc, char **argv) "create ancestors of %s\n", argv[0]); } if (!dryrun) { - if (zfs_create_ancestors(g_zfs, argv[0]) != 0) { + if (zfs_create_ancestors_props(g_zfs, argv[0], + props_parents) != 0) { goto error; } } @@ -1348,9 +1389,11 @@ zfs_do_create(int argc, char **argv) (void) zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET); error: nvlist_free(props); + nvlist_free(props_parents); return (ret); badusage: nvlist_free(props); + nvlist_free(props_parents); usage(B_FALSE); return (2); } @@ -2905,15 +2948,13 @@ us_compare(const void *larg, const void *rarg) uint64_t rv64 = 0; zfs_prop_t prop = sortcol->sc_prop; const char *propname = NULL; - boolean_t reverse = sortcol->sc_reverse; switch (prop) { case ZFS_PROP_TYPE: propname = "type"; (void) nvlist_lookup_uint32(lnvl, propname, &lv32); (void) nvlist_lookup_uint32(rnvl, propname, &rv32); - if (rv32 != lv32) - rc = (rv32 < lv32) ? 1 : -1; + rc = TREE_CMP(lv32, rv32); break; case ZFS_PROP_NAME: propname = "name"; @@ -2923,8 +2964,7 @@ compare_nums: &lv64); (void) nvlist_lookup_uint64(rnvl, propname, &rv64); - if (rv64 != lv64) - rc = (rv64 < lv64) ? 1 : -1; + rc = TREE_CMP(lv64, rv64); } else { if ((nvlist_lookup_string(lnvl, propname, &lvstr) == ENOENT) || @@ -2932,7 +2972,7 @@ compare_nums: &rvstr) == ENOENT)) { goto compare_nums; } - rc = strcmp(lvstr, rvstr); + rc = TREE_ISIGN(strcmp(lvstr, rvstr)); } break; case ZFS_PROP_USED: @@ -2945,8 +2985,7 @@ compare_nums: propname = "quota"; (void) nvlist_lookup_uint64(lnvl, propname, &lv64); (void) nvlist_lookup_uint64(rnvl, propname, &rv64); - if (rv64 != lv64) - rc = (rv64 < lv64) ? 1 : -1; + rc = TREE_CMP(lv64, rv64); break; default: @@ -2954,10 +2993,9 @@ compare_nums: } if (rc != 0) { - if (rc < 0) - return (reverse ? 1 : -1); - else - return (reverse ? -1 : 1); + if (sortcol->sc_reverse) + return (-rc); + return (rc); } } @@ -2967,9 +3005,8 @@ compare_nums: * translation where we can have duplicate type/name combinations). */ if (nvlist_lookup_boolean_value(lnvl, "smbentity", &lvb) == 0 && - nvlist_lookup_boolean_value(rnvl, "smbentity", &rvb) == 0 && - lvb != rvb) - return (lvb < rvb ? -1 : 1); + nvlist_lookup_boolean_value(rnvl, "smbentity", &rvb) == 0) + return (TREE_CMP(lvb, rvb)); return (0); } @@ -4045,6 +4082,8 @@ found3:; * Renames the given dataset to another of the same type. * * The '-p' flag creates all the non-existing ancestors of the target first. + * If repeated twice, the ancestors are created with `canmount=off`. + * * The '-u' flag prevents file systems from being remounted during rename. */ static int @@ -4056,12 +4095,17 @@ zfs_do_rename(int argc, char **argv) int ret = 1; int types; boolean_t parents = B_FALSE; + boolean_t parents_nomount = B_FALSE; + nvlist_t *props_parents = NULL; /* check options */ while ((c = getopt(argc, argv, "pruf")) != -1) { switch (c) { case 'p': - parents = B_TRUE; + if (parents) + parents_nomount = B_TRUE; + else + parents = B_TRUE; break; case 'r': flags.recursive = B_TRUE; @@ -4128,9 +4172,13 @@ zfs_do_rename(int argc, char **argv) goto error_open; /* If we were asked and the name looks good, try to create ancestors. */ - if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp)) && - zfs_create_ancestors(g_zfs, argv[1]) != 0) { - goto error; + if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp))) { + + makeprops_parents(&props_parents, parents_nomount); + if (zfs_create_ancestors_props(g_zfs, argv[1], + props_parents) != 0) { + goto error; + } } ret = (zfs_rename(zhp, argv[1], flags) != 0); @@ -4138,6 +4186,7 @@ zfs_do_rename(int argc, char **argv) error: zfs_close(zhp); error_open: + nvlist_free(props_parents); return (ret); } @@ -4759,11 +4808,12 @@ zfs_do_send(int argc, char **argv) {"holds", no_argument, NULL, 'h'}, {"saved", no_argument, NULL, 'S'}, {"exclude", required_argument, NULL, 'X'}, + {"no-preserve-encryption", no_argument, NULL, 'U'}, {0, 0, 0, 0} }; /* check options */ - while ((c = getopt_long(argc, argv, ":i:I:RsDpVvnPLeht:cwbd:SX:", + while ((c = getopt_long(argc, argv, ":i:I:RsDpVvnPLeht:cwbd:SX:U", long_options, NULL)) != -1) { switch (c) { case 'X': @@ -4849,6 +4899,9 @@ zfs_do_send(int argc, char **argv) case 'S': flags.saved = B_TRUE; break; + case 'U': + flags.no_preserve_encryption = B_TRUE; + break; case ':': /* * If a parameter was not passed, optopt contains the @@ -5497,11 +5550,11 @@ who_perm_compare(const void *larg, const void *rarg) zfs_deleg_who_type_t rtype = r->who_perm.who_type; int lweight = who_type2weight(ltype); int rweight = who_type2weight(rtype); - int res = lweight - rweight; + int res = TREE_CMP(lweight, rweight); if (res == 0) - res = strncmp(l->who_perm.who_name, r->who_perm.who_name, - ZFS_MAX_DELEG_NAME-1); - return (TREE_ISIGN(res)); + res = TREE_ISIGN(strncmp(l->who_perm.who_name, + r->who_perm.who_name, ZFS_MAX_DELEG_NAME-1)); + return (res); } static int @@ -7641,15 +7694,11 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual) zfs_handle_t *zhp; int ret = 0; struct stat64 statbuf; - struct extmnttab entry; + struct mnttab entry; const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount"; ino_t path_inode; char *zfs_mntpnt, *entry_mntpnt; - /* - * Search for the given (major,minor) pair in the mount table. - */ - if (getextmntent(path, &entry, &statbuf) != 0) { if (op == OP_SHARE) { (void) fprintf(stderr, gettext("cannot %s '%s': not " @@ -9373,7 +9422,6 @@ main(int argc, char **argv) /* * Run the appropriate command. */ - libzfs_mnttab_cache(g_zfs, B_TRUE); if (find_command_idx(cmdname, &i) == 0) { current_command = &command_table[i]; ret = command_table[i].func(argc - 1, newargv + 1); diff --git a/sys/contrib/openzfs/cmd/zinject/translate.c b/sys/contrib/openzfs/cmd/zinject/translate.c index 898edd9edbd7..cd157b5928f6 100644 --- a/sys/contrib/openzfs/cmd/zinject/translate.c +++ b/sys/contrib/openzfs/cmd/zinject/translate.c @@ -85,7 +85,7 @@ static int parse_pathname(const char *inpath, char *dataset, char *relpath, struct stat64 *statbuf) { - struct extmnttab mp; + struct mnttab mp; const char *rel; char fullpath[MAXPATHLEN]; diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_main.c b/sys/contrib/openzfs/cmd/zpool/zpool_main.c index 265d7488dd8a..eb76a21352ab 100644 --- a/sys/contrib/openzfs/cmd/zpool/zpool_main.c +++ b/sys/contrib/openzfs/cmd/zpool/zpool_main.c @@ -458,7 +458,7 @@ get_usage(zpool_help_t idx) return (gettext("\tattach [-fsw] [-o property=value] " "<pool> <vdev> <new-device>\n")); case HELP_CLEAR: - return (gettext("\tclear [[--power]|[-nF]] <pool> [device]\n")); + return (gettext("\tclear [--power] <pool> [device]\n")); case HELP_CREATE: return (gettext("\tcreate [-fnd] [-o property=value] ... \n" "\t [-O file-system-property=value] ... \n" @@ -6960,7 +6960,19 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str, switch (prop) { case ZPOOL_PROP_SIZE: + case ZPOOL_PROP_NORMAL_SIZE: + case ZPOOL_PROP_SPECIAL_SIZE: + case ZPOOL_PROP_DEDUP_SIZE: + case ZPOOL_PROP_LOG_SIZE: + case ZPOOL_PROP_ELOG_SIZE: + case ZPOOL_PROP_SELOG_SIZE: case ZPOOL_PROP_EXPANDSZ: + case ZPOOL_PROP_NORMAL_EXPANDSZ: + case ZPOOL_PROP_SPECIAL_EXPANDSZ: + case ZPOOL_PROP_DEDUP_EXPANDSZ: + case ZPOOL_PROP_LOG_EXPANDSZ: + case ZPOOL_PROP_ELOG_EXPANDSZ: + case ZPOOL_PROP_SELOG_EXPANDSZ: case ZPOOL_PROP_CHECKPOINT: case ZPOOL_PROP_DEDUPRATIO: case ZPOOL_PROP_DEDUPCACHED: @@ -6971,6 +6983,12 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str, format); break; case ZPOOL_PROP_FRAGMENTATION: + case ZPOOL_PROP_NORMAL_FRAGMENTATION: + case ZPOOL_PROP_SPECIAL_FRAGMENTATION: + case ZPOOL_PROP_DEDUP_FRAGMENTATION: + case ZPOOL_PROP_LOG_FRAGMENTATION: + case ZPOOL_PROP_ELOG_FRAGMENTATION: + case ZPOOL_PROP_SELOG_FRAGMENTATION: if (value == ZFS_FRAG_INVALID) { (void) strlcpy(propval, "-", sizeof (propval)); } else if (format == ZFS_NICENUM_RAW) { @@ -6982,6 +7000,12 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str, } break; case ZPOOL_PROP_CAPACITY: + case ZPOOL_PROP_NORMAL_CAPACITY: + case ZPOOL_PROP_SPECIAL_CAPACITY: + case ZPOOL_PROP_DEDUP_CAPACITY: + case ZPOOL_PROP_LOG_CAPACITY: + case ZPOOL_PROP_ELOG_CAPACITY: + case ZPOOL_PROP_SELOG_CAPACITY: /* capacity value is in parts-per-10,000 (aka permyriad) */ if (format == ZFS_NICENUM_RAW) (void) snprintf(propval, sizeof (propval), "%llu", @@ -8227,7 +8251,7 @@ zpool_do_offline(int argc, char **argv) } /* - * zpool clear [-nF]|[--power] <pool> [device] + * zpool clear [--power] <pool> [device] * * Clear all errors associated with a pool or a particular device. */ @@ -8236,11 +8260,7 @@ zpool_do_clear(int argc, char **argv) { int c; int ret = 0; - boolean_t dryrun = B_FALSE; - boolean_t do_rewind = B_FALSE; - boolean_t xtreme_rewind = B_FALSE; boolean_t is_power_on = B_FALSE; - uint32_t rewind_policy = ZPOOL_NO_REWIND; nvlist_t *policy = NULL; zpool_handle_t *zhp; char *pool, *device; @@ -8251,18 +8271,9 @@ zpool_do_clear(int argc, char **argv) }; /* check options */ - while ((c = getopt_long(argc, argv, "FnX", long_options, + while ((c = getopt_long(argc, argv, "", long_options, NULL)) != -1) { switch (c) { - case 'F': - do_rewind = B_TRUE; - break; - case 'n': - dryrun = B_TRUE; - break; - case 'X': - xtreme_rewind = B_TRUE; - break; case ZPOOL_OPTION_POWER: is_power_on = B_TRUE; break; @@ -8289,24 +8300,8 @@ zpool_do_clear(int argc, char **argv) usage(B_FALSE); } - if ((dryrun || xtreme_rewind) && !do_rewind) { - (void) fprintf(stderr, - gettext("-n or -X only meaningful with -F\n")); - usage(B_FALSE); - } - if (dryrun) - rewind_policy = ZPOOL_TRY_REWIND; - else if (do_rewind) - rewind_policy = ZPOOL_DO_REWIND; - if (xtreme_rewind) - rewind_policy |= ZPOOL_EXTREME_REWIND; - - /* In future, further rewind policy choices can be passed along here */ - if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || - nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, - rewind_policy) != 0) { + if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0) return (1); - } pool = argv[0]; device = argc == 2 ? argv[1] : NULL; @@ -10500,7 +10495,7 @@ print_dedup_stats(zpool_handle_t *zhp, nvlist_t *config, boolean_t literal) (uint64_t **)&dds, &c) == 0); verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, (uint64_t **)&ddh, &c) == 0); - zpool_dump_ddt(dds, ddh); + zpool_dump_ddt(dds, ddh, literal); } #define ST_SIZE 4096 diff --git a/sys/contrib/openzfs/cmd/zstream/Makefile.am b/sys/contrib/openzfs/cmd/zstream/Makefile.am index 1ccf67a6ce89..6c629ff5aa59 100644 --- a/sys/contrib/openzfs/cmd/zstream/Makefile.am +++ b/sys/contrib/openzfs/cmd/zstream/Makefile.am @@ -8,10 +8,13 @@ zstream_SOURCES = \ %D%/zstream.c \ %D%/zstream.h \ %D%/zstream_decompress.c \ + %D%/zstream_drop_record.c \ %D%/zstream_dump.c \ %D%/zstream_recompress.c \ %D%/zstream_redup.c \ - %D%/zstream_token.c + %D%/zstream_token.c \ + %D%/zstream_util.c \ + %D%/zstream_util.h zstream_LDADD = \ libzfs.la \ diff --git a/sys/contrib/openzfs/cmd/zstream/zstream.c b/sys/contrib/openzfs/cmd/zstream/zstream.c index d3417c69c49a..f1a2fa757402 100644 --- a/sys/contrib/openzfs/cmd/zstream/zstream.c +++ b/sys/contrib/openzfs/cmd/zstream/zstream.c @@ -43,6 +43,8 @@ zstream_usage(void) "\n" "\tzstream decompress [-v] [OBJECT,OFFSET[,TYPE]] ...\n" "\n" + "\tzstream drop_record [-v] [OBJECT,OFFSET] ...\n" + "\n" "\tzstream recompress [ -l level] TYPE\n" "\n" "\tzstream token resume_token\n" @@ -68,6 +70,8 @@ main(int argc, char *argv[]) return (zstream_do_dump(argc - 1, argv + 1)); } else if (strcmp(subcommand, "decompress") == 0) { return (zstream_do_decompress(argc - 1, argv + 1)); + } else if (strcmp(subcommand, "drop_record") == 0) { + return (zstream_do_drop_record(argc - 1, argv + 1)); } else if (strcmp(subcommand, "recompress") == 0) { return (zstream_do_recompress(argc - 1, argv + 1)); } else if (strcmp(subcommand, "token") == 0) { diff --git a/sys/contrib/openzfs/cmd/zstream/zstream.h b/sys/contrib/openzfs/cmd/zstream/zstream.h index 889b6e753e63..ba4c7456d27e 100644 --- a/sys/contrib/openzfs/cmd/zstream/zstream.h +++ b/sys/contrib/openzfs/cmd/zstream/zstream.h @@ -25,12 +25,10 @@ extern "C" { #endif -extern void *safe_calloc(size_t n); -extern int sfread(void *buf, size_t size, FILE *fp); -extern void *safe_malloc(size_t size); extern int zstream_do_redup(int, char *[]); extern int zstream_do_dump(int, char *[]); extern int zstream_do_decompress(int argc, char *argv[]); +extern int zstream_do_drop_record(int argc, char *argv[]); extern int zstream_do_recompress(int argc, char *argv[]); extern int zstream_do_token(int, char *[]); extern void zstream_usage(void); diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_decompress.c b/sys/contrib/openzfs/cmd/zstream/zstream_decompress.c index 40bb1ece881c..a9dbe30798d8 100644 --- a/sys/contrib/openzfs/cmd/zstream/zstream_decompress.c +++ b/sys/contrib/openzfs/cmd/zstream/zstream_decompress.c @@ -37,31 +37,7 @@ #include <sys/zstd/zstd.h> #include "zfs_fletcher.h" #include "zstream.h" - -static int -dump_record(dmu_replay_record_t *drr, void *payload, int payload_len, - zio_cksum_t *zc, int outfd) -{ - assert(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum) - == sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); - fletcher_4_incremental_native(drr, - offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); - if (drr->drr_type != DRR_BEGIN) { - assert(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. - drr_checksum.drr_checksum)); - drr->drr_u.drr_checksum.drr_checksum = *zc; - } - fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, - sizeof (zio_cksum_t), zc); - if (write(outfd, drr, sizeof (*drr)) == -1) - return (errno); - if (payload_len != 0) { - fletcher_4_incremental_native(payload, payload_len, zc); - if (write(outfd, payload, payload_len) == -1) - return (errno); - } - return (0); -} +#include "zstream_util.h" int zstream_do_decompress(int argc, char *argv[]) diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_drop_record.c b/sys/contrib/openzfs/cmd/zstream/zstream_drop_record.c new file mode 100644 index 000000000000..b6895bd52cc0 --- /dev/null +++ b/sys/contrib/openzfs/cmd/zstream/zstream_drop_record.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2026 ConnectWise. All rights reserved. + * Use is subject to license terms. + */ + +#include <err.h> +#include <search.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/zfs_ioctl.h> +#include <sys/zio_checksum.h> +#include <sys/zstd/zstd.h> +#include "zfs_fletcher.h" +#include "zstream.h" +#include "zstream_util.h" + +int +zstream_do_drop_record(int argc, char *argv[]) +{ + const int KEYSIZE = 64; + int bufsz = SPA_MAXBLOCKSIZE; + char *buf = safe_malloc(bufsz); + dmu_replay_record_t thedrr; + dmu_replay_record_t *drr = &thedrr; + zio_cksum_t stream_cksum; + int c; + boolean_t verbose = B_FALSE; + + while ((c = getopt(argc, argv, "v")) != -1) { + switch (c) { + case 'v': + verbose = B_TRUE; + break; + case '?': + (void) fprintf(stderr, "invalid option '%c'\n", + optopt); + zstream_usage(); + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 0) + zstream_usage(); + + if (hcreate(argc) == 0) + errx(1, "hcreate"); + for (int i = 0; i < argc; i++) { + uint64_t object, offset; + char *obj_str; + char *offset_str; + char *key; + char *end; + + obj_str = strsep(&argv[i], ","); + if (argv[i] == NULL) { + zstream_usage(); + exit(2); + } + errno = 0; + object = strtoull(obj_str, &end, 0); + if (errno || *end != '\0') + errx(1, "invalid value for object"); + offset_str = strsep(&argv[i], ","); + offset = strtoull(offset_str, &end, 0); + if (errno || *end != '\0') + errx(1, "invalid value for offset"); + + if (asprintf(&key, "%llu,%llu", (u_longlong_t)object, + (u_longlong_t)offset) < 0) { + err(1, "asprintf"); + } + ENTRY e = {.key = key}; + ENTRY *p; + + p = hsearch(e, ENTER); + if (p == NULL) + errx(1, "hsearch"); + p->data = (void*)(intptr_t)B_TRUE; + } + + if (isatty(STDIN_FILENO)) { + (void) fprintf(stderr, + "Error: The send stream is a binary format " + "and can not be read from a\n" + "terminal. Standard input must be redirected.\n"); + exit(1); + } + + fletcher_4_init(); + int begin = 0; + boolean_t seen = B_FALSE; + while (sfread(drr, sizeof (*drr), stdin) != 0) { + struct drr_write *drrw; + uint64_t payload_size = 0; + + /* + * We need to regenerate the checksum. + */ + if (drr->drr_type != DRR_BEGIN) { + memset(&drr->drr_u.drr_checksum.drr_checksum, 0, + sizeof (drr->drr_u.drr_checksum.drr_checksum)); + } + + switch (drr->drr_type) { + case DRR_BEGIN: + { + ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0); + VERIFY0(begin++); + seen = B_TRUE; + + uint32_t sz = drr->drr_payloadlen; + + VERIFY3U(sz, <=, 1U << 28); + + if (sz != 0) { + if (sz > bufsz) { + buf = realloc(buf, sz); + if (buf == NULL) + err(1, "realloc"); + bufsz = sz; + } + (void) sfread(buf, sz, stdin); + } + payload_size = sz; + break; + } + case DRR_END: + { + struct drr_end *drre = &drr->drr_u.drr_end; + /* + * We would prefer to just check --begin == 0, but + * replication streams have an end of stream END + * record, so we must avoid tripping it. + */ + VERIFY3B(seen, ==, B_TRUE); + begin--; + /* + * Use the recalculated checksum, unless this is + * the END record of a stream package, which has + * no checksum. + */ + if (!ZIO_CHECKSUM_IS_ZERO(&drre->drr_checksum)) + drre->drr_checksum = stream_cksum; + break; + } + + case DRR_OBJECT: + { + struct drr_object *drro = &drr->drr_u.drr_object; + VERIFY3S(begin, ==, 1); + + if (drro->drr_bonuslen > 0) { + payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro); + (void) sfread(buf, payload_size, stdin); + } + break; + } + + case DRR_SPILL: + { + struct drr_spill *drrs = &drr->drr_u.drr_spill; + VERIFY3S(begin, ==, 1); + payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs); + (void) sfread(buf, payload_size, stdin); + break; + } + + case DRR_WRITE_BYREF: + VERIFY3S(begin, ==, 1); + fprintf(stderr, + "Deduplicated streams are not supported\n"); + exit(1); + break; + + case DRR_WRITE: + { + VERIFY3S(begin, ==, 1); + drrw = &thedrr.drr_u.drr_write; + payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw); + ENTRY *p; + char key[KEYSIZE]; + + snprintf(key, KEYSIZE, "%llu,%llu", + (u_longlong_t)drrw->drr_object, + (u_longlong_t)drrw->drr_offset); + ENTRY e = {.key = key}; + + (void) sfread(buf, payload_size, stdin); + p = hsearch(e, FIND); + if (p == NULL) { + /* + * Dump the contents of the block unaltered + */ + } else { + /* + * Read and discard the block + */ + if (verbose) + fprintf(stderr, + "Dropping WRITE record for object " + "%llu offset %llu\n", + (u_longlong_t)drrw->drr_object, + (u_longlong_t)drrw->drr_offset); + continue; + } + break; + } + + case DRR_WRITE_EMBEDDED: + { + ENTRY *p; + char key[KEYSIZE]; + + VERIFY3S(begin, ==, 1); + struct drr_write_embedded *drrwe = + &drr->drr_u.drr_write_embedded; + payload_size = + P2ROUNDUP((uint64_t)drrwe->drr_psize, 8); + + snprintf(key, KEYSIZE, "%llu,%llu", + (u_longlong_t)drrwe->drr_object, + (u_longlong_t)drrwe->drr_offset); + ENTRY e = {.key = key}; + + (void) sfread(buf, payload_size, stdin); + p = hsearch(e, FIND); + if (p == NULL) { + /* + * Dump the contents of the block unaltered + */ + } else { + /* + * Read and discard the block + */ + if (verbose) + fprintf(stderr, + "Dropping WRITE_EMBEDDED record for" + " object %llu offset %llu\n", + (u_longlong_t)drrwe->drr_object, + (u_longlong_t)drrwe->drr_offset); + continue; + } + break; + } + + case DRR_FREEOBJECTS: + case DRR_FREE: + case DRR_OBJECT_RANGE: + VERIFY3S(begin, ==, 1); + break; + + default: + (void) fprintf(stderr, "INVALID record type 0x%x\n", + drr->drr_type); + /* should never happen, so assert */ + assert(B_FALSE); + } + + if (feof(stdout)) { + fprintf(stderr, "Error: unexpected end-of-file\n"); + exit(1); + } + if (ferror(stdout)) { + fprintf(stderr, "Error while reading file: %s\n", + strerror(errno)); + exit(1); + } + + /* + * We need to recalculate the checksum, and it needs to be + * initially zero to do that. BEGIN records don't have + * a checksum. + */ + if (drr->drr_type != DRR_BEGIN) { + memset(&drr->drr_u.drr_checksum.drr_checksum, 0, + sizeof (drr->drr_u.drr_checksum.drr_checksum)); + } + if (dump_record(drr, buf, payload_size, + &stream_cksum, STDOUT_FILENO) != 0) + break; + if (drr->drr_type == DRR_END) { + /* + * Typically the END record is either the last + * thing in the stream, or it is followed + * by a BEGIN record (which also zeros the checksum). + * However, a stream package ends with two END + * records. The last END record's checksum starts + * from zero. + */ + ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0); + } + } + free(buf); + fletcher_4_fini(); + hdestroy(); + + return (0); +} diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_dump.c b/sys/contrib/openzfs/cmd/zstream/zstream_dump.c index 78949d4d0666..6ccc57204c8e 100644 --- a/sys/contrib/openzfs/cmd/zstream/zstream_dump.c +++ b/sys/contrib/openzfs/cmd/zstream/zstream_dump.c @@ -44,6 +44,7 @@ #include <sys/zio.h> #include <zfs_fletcher.h> #include "zstream.h" +#include "zstream_util.h" /* * If dump mode is enabled, the number of bytes to print per line @@ -60,18 +61,6 @@ static FILE *send_stream = 0; static boolean_t do_byteswap = B_FALSE; static boolean_t do_cksum = B_TRUE; -void * -safe_malloc(size_t size) -{ - void *rv = malloc(size); - if (rv == NULL) { - (void) fprintf(stderr, "ERROR; failed to allocate %zu bytes\n", - size); - abort(); - } - return (rv); -} - /* * ssread - send stream read. * diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_recompress.c b/sys/contrib/openzfs/cmd/zstream/zstream_recompress.c index 174265eceb09..5092b534a8f3 100644 --- a/sys/contrib/openzfs/cmd/zstream/zstream_recompress.c +++ b/sys/contrib/openzfs/cmd/zstream/zstream_recompress.c @@ -37,31 +37,7 @@ #include <sys/zstd/zstd.h> #include "zfs_fletcher.h" #include "zstream.h" - -static int -dump_record(dmu_replay_record_t *drr, void *payload, int payload_len, - zio_cksum_t *zc, int outfd) -{ - assert(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum) - == sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); - fletcher_4_incremental_native(drr, - offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); - if (drr->drr_type != DRR_BEGIN) { - assert(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. - drr_checksum.drr_checksum)); - drr->drr_u.drr_checksum.drr_checksum = *zc; - } - fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, - sizeof (zio_cksum_t), zc); - if (write(outfd, drr, sizeof (*drr)) == -1) - return (errno); - if (payload_len != 0) { - fletcher_4_incremental_native(payload, payload_len, zc); - if (write(outfd, payload, payload_len) == -1) - return (errno); - } - return (0); -} +#include "zstream_util.h" int zstream_do_recompress(int argc, char *argv[]) diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_redup.c b/sys/contrib/openzfs/cmd/zstream/zstream_redup.c index c1cb6d4d3ad7..59bccd7b15ad 100644 --- a/sys/contrib/openzfs/cmd/zstream/zstream_redup.c +++ b/sys/contrib/openzfs/cmd/zstream/zstream_redup.c @@ -37,6 +37,7 @@ #include <sys/zio_checksum.h> #include "zfs_fletcher.h" #include "zstream.h" +#include "zstream_util.h" #define MAX_RDT_PHYSMEM_PERCENT 20 @@ -57,34 +58,6 @@ typedef struct redup_table { int numhashbits; } redup_table_t; -void * -safe_calloc(size_t n) -{ - void *rv = calloc(1, n); - if (rv == NULL) { - fprintf(stderr, - "Error: could not allocate %u bytes of memory\n", - (int)n); - exit(1); - } - return (rv); -} - -/* - * Safe version of fread(), exits on error. - */ -int -sfread(void *buf, size_t size, FILE *fp) -{ - int rv = fread(buf, size, 1, fp); - if (rv == 0 && ferror(fp)) { - (void) fprintf(stderr, "Error while reading file: %s\n", - strerror(errno)); - exit(1); - } - return (rv); -} - /* * Safe version of pread(), exits on error. */ @@ -104,31 +77,6 @@ spread(int fd, void *buf, size_t count, off_t offset) } } -static int -dump_record(dmu_replay_record_t *drr, void *payload, int payload_len, - zio_cksum_t *zc, int outfd) -{ - assert(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum) - == sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); - fletcher_4_incremental_native(drr, - offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); - if (drr->drr_type != DRR_BEGIN) { - assert(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. - drr_checksum.drr_checksum)); - drr->drr_u.drr_checksum.drr_checksum = *zc; - } - fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, - sizeof (zio_cksum_t), zc); - if (write(outfd, drr, sizeof (*drr)) == -1) - return (errno); - if (payload_len != 0) { - fletcher_4_incremental_native(payload, payload_len, zc); - if (write(outfd, payload, payload_len) == -1) - return (errno); - } - return (0); -} - static void rdt_insert(redup_table_t *rdt, uint64_t guid, uint64_t object, uint64_t offset, uint64_t stream_offset) diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_util.c b/sys/contrib/openzfs/cmd/zstream/zstream_util.c new file mode 100644 index 000000000000..b44175284bbd --- /dev/null +++ b/sys/contrib/openzfs/cmd/zstream/zstream_util.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>. + * All rights reserved + * Copyright (c) 2013 Steven Hartland. All rights reserved. + * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> + * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved. + * Copyright (c) 2019 Datto Inc. + * Copyright (c) 2024, Klara, Inc. + */ + +#include <sys/debug.h> +#include <stddef.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <zfs_fletcher.h> +#include "zstream_util.h" + +/* + * From libzfs_sendrecv.c + */ +int +dump_record(dmu_replay_record_t *drr, void *payload, size_t payload_len, + zio_cksum_t *zc, int outfd) +{ + ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), + ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t)); + fletcher_4_incremental_native(drr, + offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc); + if (drr->drr_type != DRR_BEGIN) { + ASSERT(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u. + drr_checksum.drr_checksum)); + drr->drr_u.drr_checksum.drr_checksum = *zc; + } + fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum, + sizeof (zio_cksum_t), zc); + if (write(outfd, drr, sizeof (*drr)) == -1) + return (errno); + if (payload_len != 0) { + fletcher_4_incremental_native(payload, payload_len, zc); + if (write(outfd, payload, payload_len) == -1) + return (errno); + } + return (0); +} + +void * +safe_malloc(size_t size) +{ + void *rv = malloc(size); + if (rv == NULL) { + (void) fprintf(stderr, "Error: failed to allocate %zu bytes\n", + size); + exit(1); + } + return (rv); +} + +void * +safe_calloc(size_t size) +{ + void *rv = calloc(1, size); + if (rv == NULL) { + (void) fprintf(stderr, + "Error: failed to allocate %zu bytes\n", size); + exit(1); + } + return (rv); +} + +/* + * Safe version of fread(), exits on error. + */ +int +sfread(void *buf, size_t size, FILE *fp) +{ + int rv = fread(buf, size, 1, fp); + if (rv == 0 && ferror(fp)) { + (void) fprintf(stderr, "Error while reading file: %s\n", + strerror(errno)); + exit(1); + } + return (rv); +} diff --git a/sys/contrib/openzfs/cmd/zstream/zstream_util.h b/sys/contrib/openzfs/cmd/zstream/zstream_util.h new file mode 100644 index 000000000000..50600fdd1811 --- /dev/null +++ b/sys/contrib/openzfs/cmd/zstream/zstream_util.h @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2026 by Garth Snyder. All rights reserved. + */ + +#ifndef _ZSTREAM_UTIL_H +#define _ZSTREAM_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> +#include <sys/zfs_ioctl.h> +#include <sys/zio_checksum.h> + +/* + * The safe_ versions of the functions below terminate the process if the + * operation doesn't succeed instead of returning an error. + */ +extern void * +safe_malloc(size_t size); + +extern void * +safe_calloc(size_t n); + +extern int +sfread(void *buf, size_t size, FILE *fp); + +/* + * 1) Update checksum with the record header up to drr_checksum. + * 2) Update checksum field in the record header. + * 3) Update checksum with the checksum field in the record header. + * 4) Update checksum with the contents of the payload. + * 5) Write header and payload to fd. + */ +extern int +dump_record(dmu_replay_record_t *drr, void *payload, size_t payload_len, + zio_cksum_t *zc, int outfd); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZSTREAM_UTIL_H */ diff --git a/sys/contrib/openzfs/config/Rules.am b/sys/contrib/openzfs/config/Rules.am index f8626f3687f4..5117929cac56 100644 --- a/sys/contrib/openzfs/config/Rules.am +++ b/sys/contrib/openzfs/config/Rules.am @@ -7,6 +7,7 @@ PHONY = AM_CPPFLAGS = \ -include $(top_builddir)/zfs_config.h \ + -include $(top_srcdir)/include/sys/simd_config.h \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/lib/libspl/include \ diff --git a/sys/contrib/openzfs/config/kernel-fs-context.m4 b/sys/contrib/openzfs/config/kernel-fs-context.m4 index 13e1f5ffc55e..317ddc21273d 100644 --- a/sys/contrib/openzfs/config/kernel-fs-context.m4 +++ b/sys/contrib/openzfs/config/kernel-fs-context.m4 @@ -29,5 +29,8 @@ AC_DEFUN([ZFS_AC_KERNEL_FS_CONTEXT], [ AC_DEFINE(HAVE_FS_CONTEXT, 1, [fs_context exists]) ],[ AC_MSG_RESULT(no) + AC_MSG_ERROR([ + *** This kernel does not have `struct fs_context`. OpenZFS cannot be compiled. + ]) ]) ]) diff --git a/sys/contrib/openzfs/config/kernel.m4 b/sys/contrib/openzfs/config/kernel.m4 index 45a215d22774..3389c5359834 100644 --- a/sys/contrib/openzfs/config/kernel.m4 +++ b/sys/contrib/openzfs/config/kernel.m4 @@ -37,6 +37,7 @@ dnl # only once the compilation can be done in parallel significantly dnl # speeding up the process. dnl # AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ + ZFS_AC_KERNEL_SRC_SIMD ZFS_AC_KERNEL_SRC_TYPES ZFS_AC_KERNEL_SRC_OBJTOOL ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE @@ -161,6 +162,7 @@ dnl # dnl # Check results of kernel interface tests. dnl # AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ + ZFS_AC_KERNEL_SIMD ZFS_AC_KERNEL_TYPES ZFS_AC_KERNEL_ACCESS_OK_TYPE ZFS_AC_KERNEL_OBJTOOL @@ -450,13 +452,6 @@ AC_DEFUN([ZFS_AC_KERNEL], [ AC_MSG_RESULT([$kernsrcver]) - AX_COMPARE_VERSION([$kernsrcver], [ge], [$ZFS_META_KVER_MIN], [], [ - AC_MSG_ERROR([ - *** Cannot build against kernel version $kernsrcver. - *** The minimum supported kernel version is $ZFS_META_KVER_MIN. - ]) - ]) - AC_ARG_ENABLE([linux-experimental], AS_HELP_STRING([--enable-linux-experimental], [Allow building against some unsupported kernel versions])) @@ -898,7 +893,7 @@ AC_DEFUN([ZFS_LINUX_TEST_ERROR], [ *** incompatible modifications. *** *** ZFS Version: $ZFS_META_ALIAS - *** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX + *** Highest compatible kernel version: $ZFS_META_KVER_MAX ]) ]) @@ -1069,7 +1064,7 @@ AC_DEFUN([ZFS_LINUX_REQUIRE_API], [ *** APIs. *** *** ZFS Version: $ZFS_META_ALIAS - *** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX + *** Highest compatible kernel version: $ZFS_META_KVER_MAX ]) ], [ AC_MSG_RESULT(no) diff --git a/sys/contrib/openzfs/config/toolchain-cfi.m4 b/sys/contrib/openzfs/config/toolchain-cfi.m4 new file mode 100644 index 000000000000..f1ad2b23934d --- /dev/null +++ b/sys/contrib/openzfs/config/toolchain-cfi.m4 @@ -0,0 +1,33 @@ +dnl # SPDX-License-Identifier: CDDL-1.0 +dnl # +dnl # Check whether assembler supports .cfi_negate_ra_state on AArch64. +dnl # + +AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_CFI_PSEUDO_OP], [ + case "$host_cpu" in + aarch64*) + AC_CACHE_CHECK([whether assembler supports .cfi_negate_ra_state], + [zfs_cv_as_cfi_pseudo_op], [ + cat > conftest.S <<_ACEOF + .text +conftest: + .cfi_startproc + .cfi_negate_ra_state + ret + .cfi_endproc +_ACEOF + if AC_TRY_COMMAND([$CC -c $CFLAGS $CPPFLAGS conftest.S -o conftest.o]) >/dev/null 2>&1; then + zfs_cv_as_cfi_pseudo_op=yes + else + zfs_cv_as_cfi_pseudo_op=no + fi + rm -f conftest.S conftest.o + ]) + + AS_IF([test "x$zfs_cv_as_cfi_pseudo_op" = xyes], [ + AC_DEFINE([HAVE_AS_CFI_PSEUDO_OP], 1, + [Define if your assembler supports .cfi_negate_ra_state.]) + ]) + ;; + esac +]) diff --git a/sys/contrib/openzfs/config/toolchain-simd.m4 b/sys/contrib/openzfs/config/toolchain-simd.m4 index d8197157f755..1d20370f87f6 100644 --- a/sys/contrib/openzfs/config/toolchain-simd.m4 +++ b/sys/contrib/openzfs/config/toolchain-simd.m4 @@ -2,579 +2,87 @@ dnl # SPDX-License-Identifier: CDDL-1.0 dnl # dnl # Checks if host toolchain supports SIMD instructions dnl # -AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_SIMD], [ - case "$host_cpu" in - amd64 | x86_64 | x86 | i686) - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE2 - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE3 - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSSE3 - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE4_1 - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE4_2 - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX2 - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512F - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512CD - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512DQ - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512BW - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512IFMA - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512VBMI - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512PF - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512ER - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512VL - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AES - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_PCLMULQDQ - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_MOVBE - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_VAES - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_VPCLMULQDQ - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SHA512EXT - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVE - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVEOPT - ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVES - ;; - esac -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE], [ - AC_MSG_CHECKING([whether host toolchain supports SSE]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - int main() - { - __asm__ __volatile__("xorps %xmm0, %xmm1"); - return (0); - } - ]])], [ - AC_DEFINE([HAVE_SSE], 1, [Define if host toolchain supports SSE]) - AC_MSG_RESULT([yes]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE2 -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE2], [ - AC_MSG_CHECKING([whether host toolchain supports SSE2]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - int main() - { - __asm__ __volatile__("pxor %xmm0, %xmm1"); - return (0); - } - ]])], [ - AC_DEFINE([HAVE_SSE2], 1, [Define if host toolchain supports SSE2]) - AC_MSG_RESULT([yes]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE3 -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE3], [ - AC_MSG_CHECKING([whether host toolchain supports SSE3]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - int main() - { - char v[16]; - __asm__ __volatile__("lddqu %0,%%xmm0" :: "m"(v[0])); - return (0); - } - ]])], [ - AC_DEFINE([HAVE_SSE3], 1, [Define if host toolchain supports SSE3]) - AC_MSG_RESULT([yes]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSSE3 -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSSE3], [ - AC_MSG_CHECKING([whether host toolchain supports SSSE3]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - int main() - { - __asm__ __volatile__("pshufb %xmm0,%xmm1"); - return (0); - } - ]])], [ - AC_DEFINE([HAVE_SSSE3], 1, [Define if host toolchain supports SSSE3]) - AC_MSG_RESULT([yes]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE4_1 -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE4_1], [ - AC_MSG_CHECKING([whether host toolchain supports SSE4.1]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - int main() - { - __asm__ __volatile__("pmaxsb %xmm0,%xmm1"); - return (0); - } - ]])], [ - AC_DEFINE([HAVE_SSE4_1], 1, [Define if host toolchain supports SSE4.1]) - AC_MSG_RESULT([yes]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE4_2 -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SSE4_2], [ - AC_MSG_CHECKING([whether host toolchain supports SSE4.2]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - int main() - { - __asm__ __volatile__("pcmpgtq %xmm0, %xmm1"); - return (0); - } - ]])], [ - AC_DEFINE([HAVE_SSE4_2], 1, [Define if host toolchain supports SSE4.2]) - AC_MSG_RESULT([yes]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX], [ - AC_MSG_CHECKING([whether host toolchain supports AVX]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - int main() - { - char v[32]; - __asm__ __volatile__("vmovdqa %0,%%ymm0" :: "m"(v[0])); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX], 1, [Define if host toolchain supports AVX]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX2 -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX2], [ - AC_MSG_CHECKING([whether host toolchain supports AVX2]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vpshufb %ymm0,%ymm1,%ymm2"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX2], 1, [Define if host toolchain supports AVX2]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512F -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512F], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512F]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vpandd %zmm0,%zmm1,%zmm2"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512F], 1, [Define if host toolchain supports AVX512F]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512CD -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512CD], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512CD]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vplzcntd %zmm0,%zmm1"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512CD], 1, [Define if host toolchain supports AVX512CD]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512DQ -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512DQ], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512DQ]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vandpd %zmm0,%zmm1,%zmm2"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512DQ], 1, [Define if host toolchain supports AVX512DQ]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512BW -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512BW], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512BW]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vpshufb %zmm0,%zmm1,%zmm2"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512BW], 1, [Define if host toolchain supports AVX512BW]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512IFMA -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512IFMA], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512IFMA]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vpmadd52luq %zmm0,%zmm1,%zmm2"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512IFMA], 1, [Define if host toolchain supports AVX512IFMA]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512VBMI -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512VBMI], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512VBMI]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vpermb %zmm0,%zmm1,%zmm2"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512VBMI], 1, [Define if host toolchain supports AVX512VBMI]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512PF -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512PF], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512PF]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vgatherpf0dps (%rsi,%zmm0,4){%k1}"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512PF], 1, [Define if host toolchain supports AVX512PF]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512ER -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512ER], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512ER]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vexp2pd %zmm0,%zmm1"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512ER], 1, [Define if host toolchain supports AVX512ER]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512VL -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AVX512VL], [ - AC_MSG_CHECKING([whether host toolchain supports AVX512VL]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vpabsq %zmm0,%zmm1"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AVX512VL], 1, [Define if host toolchain supports AVX512VL]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AES -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AES], [ - AC_MSG_CHECKING([whether host toolchain supports AES]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("aesenc %xmm0, %xmm1"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_AES], 1, [Define if host toolchain supports AES]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_PCLMULQDQ -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_PCLMULQDQ], [ - AC_MSG_CHECKING([whether host toolchain supports PCLMULQDQ]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("pclmulqdq %0, %%xmm0, %%xmm1" :: "i"(0)); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_PCLMULQDQ], 1, [Define if host toolchain supports PCLMULQDQ]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_MOVBE -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_MOVBE], [ - AC_MSG_CHECKING([whether host toolchain supports MOVBE]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("movbe 0(%eax), %eax"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_MOVBE], 1, [Define if host toolchain supports MOVBE]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_VAES -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_VAES], [ - AC_MSG_CHECKING([whether host toolchain supports VAES]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vaesenc %ymm0, %ymm1, %ymm0"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_VAES], 1, [Define if host toolchain supports VAES]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_VPCLMULQDQ -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_VPCLMULQDQ], [ - AC_MSG_CHECKING([whether host toolchain supports VPCLMULQDQ]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vpclmulqdq %0, %%ymm4, %%ymm3, %%ymm5" :: "i"(0)); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_VPCLMULQDQ], 1, [Define if host toolchain supports VPCLMULQDQ]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SHA512EXT -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_SHA512EXT], [ - AC_MSG_CHECKING([whether host toolchain supports SHA512]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - __asm__ __volatile__("vsha512msg2 %ymm5, %ymm6"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_SHA512EXT], 1, [Define if host toolchain supports SHA512]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVE -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVE], [ - AC_MSG_CHECKING([whether host toolchain supports XSAVE]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - char b[4096] __attribute__ ((aligned (64))); - __asm__ __volatile__("xsave %[b]\n" : : [b] "m" (*b) : "memory"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_XSAVE], 1, [Define if host toolchain supports XSAVE]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVEOPT -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVEOPT], [ - AC_MSG_CHECKING([whether host toolchain supports XSAVEOPT]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - char b[4096] __attribute__ ((aligned (64))); - __asm__ __volatile__("xsaveopt %[b]\n" : : [b] "m" (*b) : "memory"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_XSAVEOPT], 1, [Define if host toolchain supports XSAVEOPT]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVES -dnl # -AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVES], [ - AC_MSG_CHECKING([whether host toolchain supports XSAVES]) - - AC_LINK_IFELSE([AC_LANG_SOURCE([ - [ - int main() - { - char b[4096] __attribute__ ((aligned (64))); - __asm__ __volatile__("xsaves %[b]\n" : : [b] "m" (*b) : "memory"); - return (0); - } - ]])], [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_XSAVES], 1, [Define if host toolchain supports XSAVES]) - ], [ - AC_MSG_RESULT([no]) - ]) -]) +dnl # Each invocation of ZFS_AC_TOOLCHAIN_SIMD_CHECK(name, asmsrc) creates +dnl # two sets of macros: +dnl # - ZFS_AC_TOOLCHAIN_SIMD_<name> +dnl # - ZFS_AC_KERNEL_SRC_SIMD_<name> & ZFS_AC_KERNEL_SIMD_<name> +dnl # +dnl # These try to compile the given <asmsrc> in a __asm__ directive, using +dnl # either the host or the kernel toolchains. Successful checks set +dnl # HAVE_TOOLCHAIN_<name> or HAVE_KERNEL_<name>, respectively. +dnl # +AC_DEFUN([ZFS_AC_SIMD_CHECK], [ + AC_DEFUN([ZFS_AC_TOOLCHAIN_SIMD_]m4_quote($1), [ + AC_MSG_CHECKING([whether host toolchain supports $1]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ + int main () { + __asm__ __volatile__($2); + return (0); + } + ]])], [ + AC_DEFINE([HAVE_TOOLCHAIN_$1], 1, + [Define if host toolchain supports $1]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + ]) + + AC_DEFUN([ZFS_AC_KERNEL_SRC_SIMD_]m4_quote($1), [ + ZFS_LINUX_TEST_SRC( + [simd_]m4_quote(m4_translit([$1], [A-Z], [a-z])), [], [ + __asm__ __volatile__($2); + ]) + ]) + AC_DEFUN([ZFS_AC_KERNEL_SIMD_]m4_quote($1), [ + AC_MSG_CHECKING([whether kernel toolchain supports $1]) + ZFS_LINUX_TEST_RESULT( + [simd_]m4_quote(m4_translit([$1], [A-Z], [a-z])), [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_KERNEL_$1], 1, + [Define if kernel toolchain supports $1]) + ], [ + AC_MSG_RESULT([no]) + ]) + ]) + + dnl Stash the names of the new functions so we can execute them later. + m4_pushdef([_zfs_ac_toolchain_simd_checks], + [ZFS_AC_TOOLCHAIN_SIMD_]m4_quote($1)) + m4_pushdef([_zfs_ac_kernel_src_simd_checks], + [ZFS_AC_KERNEL_SRC_SIMD_]m4_quote($1)) + m4_pushdef([_zfs_ac_kernel_simd_checks], + [ZFS_AC_KERNEL_SIMD_]m4_quote($1)) +]) + +dnl # Invoke the macros created by ZFS_AC_TOOLCHAIN_SIMD_CHECK. +AC_DEFUN([ZFS_AC_TOOLCHAIN_SIMD], [ + m4_stack_foreach([_zfs_ac_toolchain_simd_checks], [m4_indir]) +]) +AC_DEFUN([ZFS_AC_KERNEL_SRC_SIMD], [ + m4_stack_foreach([_zfs_ac_kernel_src_simd_checks], [m4_indir]) +]) +AC_DEFUN([ZFS_AC_KERNEL_SIMD], [ + m4_stack_foreach([_zfs_ac_kernel_simd_checks], [m4_indir]) +]) + +dnl # Instruction sets to test +ZFS_AC_SIMD_CHECK([SSE2], ["pxor %xmm0, %xmm1"]) +ZFS_AC_SIMD_CHECK([SSSE3], ["pshufb %xmm0, %xmm1"]) +ZFS_AC_SIMD_CHECK([SSE4_1], ["pmaxsb %xmm0, %xmm1"]) +ZFS_AC_SIMD_CHECK([AVX], ["vmovdqa %ymm0, %ymm1"]) +ZFS_AC_SIMD_CHECK([AVX2], ["vpshufb %ymm0, %ymm1, %ymm2"]) +ZFS_AC_SIMD_CHECK([AVX512F], ["vpandd %zmm0, %zmm1, %zmm2"]) +ZFS_AC_SIMD_CHECK([AVX512BW], ["vpshufb %zmm0, %zmm1, %zmm2"]) +ZFS_AC_SIMD_CHECK([AVX512VL], ["vpabsq %zmm0,%zmm1"]) +ZFS_AC_SIMD_CHECK([AES], ["aesenc %xmm0, %xmm1"]) +ZFS_AC_SIMD_CHECK([PCLMULQDQ], ["pclmulqdq %0, %%xmm0, %%xmm1" :: "i"(0)]) +ZFS_AC_SIMD_CHECK([MOVBE], ["movbe 0(%eax), %eax"]) +ZFS_AC_SIMD_CHECK([VAES], ["vaesenc %ymm0, %ymm1, %ymm0"]) +ZFS_AC_SIMD_CHECK([VPCLMULQDQ], ["vpclmulqdq %0, %%ymm4, %%ymm3, %%ymm5" :: "i"(0)]) +ZFS_AC_SIMD_CHECK([SHA512EXT], ["vsha512msg2 %ymm5, %ymm6"]) +ZFS_AC_SIMD_CHECK([XSAVE], ["xsave 0"]) +ZFS_AC_SIMD_CHECK([XSAVEOPT], ["xsaveopt 0"]) +ZFS_AC_SIMD_CHECK([XSAVES], ["xsaves 0"]) diff --git a/sys/contrib/openzfs/config/user-mount-setattr.m4 b/sys/contrib/openzfs/config/user-mount-setattr.m4 new file mode 100644 index 000000000000..efcfd66b2e9a --- /dev/null +++ b/sys/contrib/openzfs/config/user-mount-setattr.m4 @@ -0,0 +1,27 @@ +dnl # SPDX-License-Identifier: CDDL-1.0 +dnl # +dnl # Check for mount_setattr() and struct mount_attr availability +dnl # +AC_DEFUN([ZFS_AC_CONFIG_USER_MOUNT_SETATTR], [ + AC_CHECK_FUNC([mount_setattr], [ + AC_MSG_CHECKING([for struct mount_attr]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + #include <sys/mount.h> + ]], [[ + struct mount_attr attr = { + .attr_set = MOUNT_ATTR_RDONLY, + .attr_clr = MOUNT_ATTR_NOEXEC, + }; + (void) attr; + ]]) + ], [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_MOUNT_SETATTR], [1], + [mount_setattr() and struct mount_attr + are available]) + ], [ + AC_MSG_RESULT([no]) + ]) + ]) +]) diff --git a/sys/contrib/openzfs/config/user-statx.m4 b/sys/contrib/openzfs/config/user-statx.m4 index b2441631c824..d359f48b8579 100644 --- a/sys/contrib/openzfs/config/user-statx.m4 +++ b/sys/contrib/openzfs/config/user-statx.m4 @@ -15,6 +15,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER_STATX], [ AC_MSG_CHECKING([for STATX_MNT_ID]) AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ + #define _GNU_SOURCE #include <sys/stat.h> ]], [[ struct statx stx; diff --git a/sys/contrib/openzfs/config/user.m4 b/sys/contrib/openzfs/config/user.m4 index ffd22c75a06f..c7a489d5ae4b 100644 --- a/sys/contrib/openzfs/config/user.m4 +++ b/sys/contrib/openzfs/config/user.m4 @@ -20,6 +20,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [ ZFS_AC_CONFIG_USER_LIBUUID ZFS_AC_CONFIG_USER_LIBBLKID ZFS_AC_CONFIG_USER_STATX + ZFS_AC_CONFIG_USER_MOUNT_SETATTR ]) ZFS_AC_CONFIG_USER_LIBTIRPC ZFS_AC_CONFIG_USER_LIBCRYPTO diff --git a/sys/contrib/openzfs/config/zfs-build.m4 b/sys/contrib/openzfs/config/zfs-build.m4 index ccec87b7befd..1e1485c4cf46 100644 --- a/sys/contrib/openzfs/config/zfs-build.m4 +++ b/sys/contrib/openzfs/config/zfs-build.m4 @@ -265,7 +265,8 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [ ZFS_AC_CONFIG_ALWAYS_KERNEL_CC_NO_IPA_SRA ZFS_AC_CONFIG_ALWAYS_CC_ASAN ZFS_AC_CONFIG_ALWAYS_CC_UBSAN - ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_SIMD + ZFS_AC_TOOLCHAIN_SIMD + ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_CFI_PSEUDO_OP ZFS_AC_CONFIG_ALWAYS_SYSTEM ZFS_AC_CONFIG_ALWAYS_ARCH ZFS_AC_CONFIG_CHECK_ARCH_VAR diff --git a/sys/contrib/openzfs/contrib/debian/openzfs-zfsutils.install b/sys/contrib/openzfs/contrib/debian/openzfs-zfsutils.install index 6810108f2c5d..5e7cdb98571c 100644 --- a/sys/contrib/openzfs/contrib/debian/openzfs-zfsutils.install +++ b/sys/contrib/openzfs/contrib/debian/openzfs-zfsutils.install @@ -42,8 +42,10 @@ usr/bin/dbufstat usr/sbin usr/bin/zilstat usr/share/zfs/compatibility.d/ usr/share/bash-completion/completions +usr/share/man/man1/zarcsummary.1 usr/share/man/man1/zarcstat.1 usr/share/man/man1/zhack.1 +usr/share/man/man1/zilstat.1 usr/share/man/man1/zvol_wait.1 usr/share/man/man5/ usr/share/man/man8/fsck.zfs.8 diff --git a/sys/contrib/openzfs/include/Makefile.am b/sys/contrib/openzfs/include/Makefile.am index ccca7cb594e6..a084247e03c7 100644 --- a/sys/contrib/openzfs/include/Makefile.am +++ b/sys/contrib/openzfs/include/Makefile.am @@ -82,6 +82,7 @@ COMMON_H = \ sys/sa.h \ sys/sa_impl.h \ sys/sha2.h \ + sys/simd_config.h \ sys/skein.h \ sys/spa.h \ sys/spa_checkpoint.h \ diff --git a/sys/contrib/openzfs/include/libzfs.h b/sys/contrib/openzfs/include/libzfs.h index 0ff3948e117b..a9a31c90ae74 100644 --- a/sys/contrib/openzfs/include/libzfs.h +++ b/sys/contrib/openzfs/include/libzfs.h @@ -766,6 +766,8 @@ _LIBZFS_H void libzfs_add_handle(get_all_cb_t *, zfs_handle_t *); _LIBZFS_H int zfs_create(libzfs_handle_t *, const char *, zfs_type_t, nvlist_t *); _LIBZFS_H int zfs_create_ancestors(libzfs_handle_t *, const char *); +_LIBZFS_H int zfs_create_ancestors_props(libzfs_handle_t *, const char *, + nvlist_t *); _LIBZFS_H int zfs_destroy(zfs_handle_t *, boolean_t); _LIBZFS_H int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t); _LIBZFS_H int zfs_destroy_snaps_nvl(libzfs_handle_t *, nvlist_t *, boolean_t); @@ -844,6 +846,9 @@ typedef struct sendflags { /* stream represents a partially received dataset */ boolean_t saved; + + /* allow sending datasets with props, without preserving encryption */ + boolean_t no_preserve_encryption; } sendflags_t; typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *); diff --git a/sys/contrib/openzfs/include/libzfs_core.h b/sys/contrib/openzfs/include/libzfs_core.h index 231beaa69290..deb810230b48 100644 --- a/sys/contrib/openzfs/include/libzfs_core.h +++ b/sys/contrib/openzfs/include/libzfs_core.h @@ -125,7 +125,7 @@ _LIBZFS_CORE_H int lzc_send_space(const char *, const char *, _LIBZFS_CORE_H int lzc_send_space_resume_redacted(const char *, const char *, enum lzc_send_flags, uint64_t, uint64_t, uint64_t, const char *, int, uint64_t *); -_LIBZFS_CORE_H uint64_t lzc_send_progress(int); +_LIBZFS_CORE_H int lzc_send_progress(const char *, int, uint64_t *, uint64_t *); _LIBZFS_CORE_H boolean_t lzc_exists(const char *); diff --git a/sys/contrib/openzfs/include/libzutil.h b/sys/contrib/openzfs/include/libzutil.h index 59599b0f63f4..2061a845409a 100644 --- a/sys/contrib/openzfs/include/libzutil.h +++ b/sys/contrib/openzfs/include/libzutil.h @@ -167,7 +167,8 @@ _LIBZUTIL_H void zfs_niceraw(uint64_t, char *, size_t); #define nicenum(num, buf, size) zfs_nicenum(num, buf, size) #define NN_NUMBUF_SZ (6) -_LIBZUTIL_H void zpool_dump_ddt(const ddt_stat_t *, const ddt_histogram_t *); +_LIBZUTIL_H void zpool_dump_ddt(const ddt_stat_t *, const ddt_histogram_t *, + boolean_t parsable); _LIBZUTIL_H int zpool_history_unpack(char *, uint64_t, uint64_t *, nvlist_t ***, uint_t *); _LIBZUTIL_H void fsleep(float sec); diff --git a/sys/contrib/openzfs/include/os/linux/kernel/linux/simd_x86.h b/sys/contrib/openzfs/include/os/linux/kernel/linux/simd_x86.h index be1d14df9461..42a0affb2ca9 100644 --- a/sys/contrib/openzfs/include/os/linux/kernel/linux/simd_x86.h +++ b/sys/contrib/openzfs/include/os/linux/kernel/linux/simd_x86.h @@ -315,19 +315,19 @@ kfpu_begin(void) * FPU state to be correctly preserved and restored. */ uint8_t *state = zfs_kfpu_fpregs[smp_processor_id()]; -#if defined(HAVE_XSAVES) +#if HAVE_SIMD(XSAVES) if (static_cpu_has(X86_FEATURE_XSAVES)) { kfpu_do_xsave("xsaves", state, ~XFEATURE_MASK_XTILE); return; } #endif -#if defined(HAVE_XSAVEOPT) +#if HAVE_SIMD(XSAVEOPT) if (static_cpu_has(X86_FEATURE_XSAVEOPT)) { kfpu_do_xsave("xsaveopt", state, ~XFEATURE_MASK_XTILE); return; } #endif -#if defined(HAVE_XSAVE) +#if HAVE_SIMD(XSAVE) if (static_cpu_has(X86_FEATURE_XSAVE)) { kfpu_do_xsave("xsave", state, ~XFEATURE_MASK_XTILE); return; @@ -380,13 +380,13 @@ static inline void kfpu_end(void) { uint8_t *state = zfs_kfpu_fpregs[smp_processor_id()]; -#if defined(HAVE_XSAVES) +#if HAVE_SIMD(XSAVES) if (static_cpu_has(X86_FEATURE_XSAVES)) { kfpu_do_xrstor("xrstors", state, ~XFEATURE_MASK_XTILE); goto out; } #endif -#if defined(HAVE_XSAVE) +#if HAVE_SIMD(XSAVE) if (static_cpu_has(X86_FEATURE_XSAVE)) { kfpu_do_xrstor("xrstor", state, ~XFEATURE_MASK_XTILE); goto out; @@ -440,15 +440,9 @@ zfs_xgetbv(uint32_t index) static inline boolean_t __simd_state_enabled(const uint64_t state) { - boolean_t has_osxsave; uint64_t xcr0; -#if defined(X86_FEATURE_OSXSAVE) - has_osxsave = !!boot_cpu_has(X86_FEATURE_OSXSAVE); -#else - has_osxsave = B_FALSE; -#endif - if (!has_osxsave) + if (!boot_cpu_has(X86_FEATURE_OSXSAVE)) return (B_FALSE); xcr0 = zfs_xgetbv(0); @@ -539,11 +533,7 @@ zfs_avx2_available(void) static inline boolean_t zfs_bmi1_available(void) { -#if defined(X86_FEATURE_BMI1) return (!!boot_cpu_has(X86_FEATURE_BMI1)); -#else - return (B_FALSE); -#endif } /* @@ -552,11 +542,7 @@ zfs_bmi1_available(void) static inline boolean_t zfs_bmi2_available(void) { -#if defined(X86_FEATURE_BMI2) return (!!boot_cpu_has(X86_FEATURE_BMI2)); -#else - return (B_FALSE); -#endif } /* @@ -565,11 +551,7 @@ zfs_bmi2_available(void) static inline boolean_t zfs_aes_available(void) { -#if defined(X86_FEATURE_AES) return (!!boot_cpu_has(X86_FEATURE_AES)); -#else - return (B_FALSE); -#endif } /* @@ -578,11 +560,7 @@ zfs_aes_available(void) static inline boolean_t zfs_pclmulqdq_available(void) { -#if defined(X86_FEATURE_PCLMULQDQ) return (!!boot_cpu_has(X86_FEATURE_PCLMULQDQ)); -#else - return (B_FALSE); -#endif } /* @@ -591,11 +569,7 @@ zfs_pclmulqdq_available(void) static inline boolean_t zfs_movbe_available(void) { -#if defined(X86_FEATURE_MOVBE) return (!!boot_cpu_has(X86_FEATURE_MOVBE)); -#else - return (B_FALSE); -#endif } /* @@ -604,11 +578,7 @@ zfs_movbe_available(void) static inline boolean_t zfs_vaes_available(void) { -#if defined(X86_FEATURE_VAES) return (!!boot_cpu_has(X86_FEATURE_VAES)); -#else - return (B_FALSE); -#endif } /* @@ -617,15 +587,12 @@ zfs_vaes_available(void) static inline boolean_t zfs_vpclmulqdq_available(void) { -#if defined(X86_FEATURE_VPCLMULQDQ) return (!!boot_cpu_has(X86_FEATURE_VPCLMULQDQ)); -#else - return (B_FALSE); -#endif } /* * Check if SHA512 instructions are available + * Kernel added X86_FEATURE_SHA512 in 6.13 (torvalds/linux@a0423af92cb3) */ static inline boolean_t zfs_sha512ext_available(void) @@ -643,11 +610,7 @@ zfs_sha512ext_available(void) static inline boolean_t zfs_shani_available(void) { -#if defined(X86_FEATURE_SHA_NI) return (!!boot_cpu_has(X86_FEATURE_SHA_NI)); -#else - return (B_FALSE); -#endif } /* @@ -662,7 +625,7 @@ zfs_shani_available(void) * AVX512DQ Double-word and Quadword Instructions * AVX512VL Vector Length Extensions * - * AVX512IFMA Integer Fused Multiply Add (Not supported by kernel 4.4) + * AVX512IFMA Integer Fused Multiply Add * AVX512VBMI Vector Byte Manipulation Instructions */ @@ -672,12 +635,7 @@ zfs_shani_available(void) static inline boolean_t zfs_avx512f_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512F) - has_avx512 = !!boot_cpu_has(X86_FEATURE_AVX512F); -#endif - return (has_avx512 && __zmm_enabled()); + return (boot_cpu_has(X86_FEATURE_AVX512F) && __zmm_enabled()); } /* @@ -686,13 +644,7 @@ zfs_avx512f_available(void) static inline boolean_t zfs_avx512cd_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512CD) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512CD); -#endif - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && boot_cpu_has(X86_FEATURE_AVX512F)); } /* @@ -701,13 +653,7 @@ zfs_avx512cd_available(void) static inline boolean_t zfs_avx512er_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512ER) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512ER); -#endif - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && boot_cpu_has(X86_FEATURE_AVX512ER)); } /* @@ -716,13 +662,7 @@ zfs_avx512er_available(void) static inline boolean_t zfs_avx512pf_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512PF) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512PF); -#endif - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && boot_cpu_has(X86_FEATURE_AVX512PF)); } /* @@ -731,14 +671,7 @@ zfs_avx512pf_available(void) static inline boolean_t zfs_avx512bw_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512BW) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512BW); -#endif - - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && boot_cpu_has(X86_FEATURE_AVX512BW)); } /* @@ -747,13 +680,7 @@ zfs_avx512bw_available(void) static inline boolean_t zfs_avx512dq_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512DQ) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512DQ); -#endif - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && boot_cpu_has(X86_FEATURE_AVX512DQ)); } /* @@ -762,13 +689,7 @@ zfs_avx512dq_available(void) static inline boolean_t zfs_avx512vl_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512VL) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512VL); -#endif - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && boot_cpu_has(X86_FEATURE_AVX512VL)); } /* @@ -777,13 +698,8 @@ zfs_avx512vl_available(void) static inline boolean_t zfs_avx512ifma_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512IFMA) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512IFMA); -#endif - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && + boot_cpu_has(X86_FEATURE_AVX512IFMA)); } /* @@ -792,13 +708,8 @@ zfs_avx512ifma_available(void) static inline boolean_t zfs_avx512vbmi_available(void) { - boolean_t has_avx512 = B_FALSE; - -#if defined(X86_FEATURE_AVX512VBMI) - has_avx512 = boot_cpu_has(X86_FEATURE_AVX512F) && - boot_cpu_has(X86_FEATURE_AVX512VBMI); -#endif - return (has_avx512 && __zmm_enabled()); + return (zfs_avx512f_available() && + boot_cpu_has(X86_FEATURE_AVX512VBMI)); } #endif /* defined(__x86) */ diff --git a/sys/contrib/openzfs/include/sys/arc_impl.h b/sys/contrib/openzfs/include/sys/arc_impl.h index 1c400c513e21..dbe712e2e739 100644 --- a/sys/contrib/openzfs/include/sys/arc_impl.h +++ b/sys/contrib/openzfs/include/sys/arc_impl.h @@ -46,6 +46,10 @@ extern "C" { * and each of the states has two types: data and metadata. */ #define L2ARC_FEED_TYPES 4 +#define L2ARC_MFU_META 0 +#define L2ARC_MRU_META 1 +#define L2ARC_MFU_DATA 2 +#define L2ARC_MRU_DATA 3 /* * L2ARC state and statistics for persistent marker management. @@ -56,10 +60,19 @@ typedef struct l2arc_info { uint64_t l2arc_total_capacity; /* total L2ARC capacity */ uint64_t l2arc_smallest_capacity; /* smallest device capacity */ /* - * Per-device thread coordination for sublist processing + * Per-device thread coordination for sublist processing. + * reset: flags sublist marker for lazy reset to tail. */ boolean_t *l2arc_sublist_busy[L2ARC_FEED_TYPES]; - kmutex_t l2arc_sublist_lock; /* protects busy flags */ + boolean_t *l2arc_sublist_reset[L2ARC_FEED_TYPES]; + kmutex_t l2arc_sublist_lock; /* protects busy/reset flags */ + /* + * Cumulative bytes scanned per pass since marker reset. + * Limits how far persistent markers advance from tail + * before resetting, based on % of state size. + */ + uint64_t l2arc_ext_scanned[L2ARC_FEED_TYPES]; + int l2arc_next_sublist[L2ARC_FEED_TYPES]; /* round-robin */ } l2arc_info_t; /* @@ -456,6 +469,12 @@ typedef struct l2arc_dev { boolean_t l2ad_thread_exit; /* signal thread exit */ kmutex_t l2ad_feed_thr_lock; /* thread sleep/wake */ kcondvar_t l2ad_feed_cv; /* thread wakeup cv */ + /* + * Consecutive cycles where metadata filled write budget + * while data passes got nothing written. Used to detect + * monopolization and skip metadata to give data a chance. + */ + uint64_t l2ad_meta_cycles; } l2arc_dev_t; /* diff --git a/sys/contrib/openzfs/include/sys/fs/zfs.h b/sys/contrib/openzfs/include/sys/fs/zfs.h index de2149641d21..ba79a674e73f 100644 --- a/sys/contrib/openzfs/include/sys/fs/zfs.h +++ b/sys/contrib/openzfs/include/sys/fs/zfs.h @@ -275,9 +275,90 @@ typedef enum { ZPOOL_PROP_LAST_SCRUBBED_TXG, ZPOOL_PROP_DEDUPUSED, ZPOOL_PROP_DEDUPSAVED, + ZPOOL_PROP_AVAILABLE, + ZPOOL_PROP_USABLE, + ZPOOL_PROP_USED, + ZPOOL_PROP_NORMAL_SIZE, + ZPOOL_PROP_NORMAL_CAPACITY, + ZPOOL_PROP_NORMAL_FREE, + ZPOOL_PROP_NORMAL_ALLOCATED, + ZPOOL_PROP_NORMAL_AVAILABLE, + ZPOOL_PROP_NORMAL_USABLE, + ZPOOL_PROP_NORMAL_USED, + ZPOOL_PROP_NORMAL_EXPANDSZ, + ZPOOL_PROP_NORMAL_FRAGMENTATION, + ZPOOL_PROP_SPECIAL_SIZE, + ZPOOL_PROP_SPECIAL_CAPACITY, + ZPOOL_PROP_SPECIAL_FREE, + ZPOOL_PROP_SPECIAL_ALLOCATED, + ZPOOL_PROP_SPECIAL_AVAILABLE, + ZPOOL_PROP_SPECIAL_USABLE, + ZPOOL_PROP_SPECIAL_USED, + ZPOOL_PROP_SPECIAL_EXPANDSZ, + ZPOOL_PROP_SPECIAL_FRAGMENTATION, + ZPOOL_PROP_DEDUP_SIZE, + ZPOOL_PROP_DEDUP_CAPACITY, + ZPOOL_PROP_DEDUP_FREE, + ZPOOL_PROP_DEDUP_ALLOCATED, + ZPOOL_PROP_DEDUP_AVAILABLE, + ZPOOL_PROP_DEDUP_USABLE, + ZPOOL_PROP_DEDUP_USED, + ZPOOL_PROP_DEDUP_EXPANDSZ, + ZPOOL_PROP_DEDUP_FRAGMENTATION, + ZPOOL_PROP_LOG_SIZE, + ZPOOL_PROP_LOG_CAPACITY, + ZPOOL_PROP_LOG_FREE, + ZPOOL_PROP_LOG_ALLOCATED, + ZPOOL_PROP_LOG_AVAILABLE, + ZPOOL_PROP_LOG_USABLE, + ZPOOL_PROP_LOG_USED, + ZPOOL_PROP_LOG_EXPANDSZ, + ZPOOL_PROP_LOG_FRAGMENTATION, + ZPOOL_PROP_ELOG_SIZE, + ZPOOL_PROP_ELOG_CAPACITY, + ZPOOL_PROP_ELOG_FREE, + ZPOOL_PROP_ELOG_ALLOCATED, + ZPOOL_PROP_ELOG_AVAILABLE, + ZPOOL_PROP_ELOG_USABLE, + ZPOOL_PROP_ELOG_USED, + ZPOOL_PROP_ELOG_EXPANDSZ, + ZPOOL_PROP_ELOG_FRAGMENTATION, + ZPOOL_PROP_SELOG_SIZE, + ZPOOL_PROP_SELOG_CAPACITY, + ZPOOL_PROP_SELOG_FREE, + ZPOOL_PROP_SELOG_ALLOCATED, + ZPOOL_PROP_SELOG_AVAILABLE, + ZPOOL_PROP_SELOG_USABLE, + ZPOOL_PROP_SELOG_USED, + ZPOOL_PROP_SELOG_EXPANDSZ, + ZPOOL_PROP_SELOG_FRAGMENTATION, ZPOOL_NUM_PROPS } zpool_prop_t; +/* Offsets for metaslab class properties. */ +typedef enum { + ZPOOL_MC_PROP_SIZE, + ZPOOL_MC_PROP_CAPACITY, + ZPOOL_MC_PROP_FREE, + ZPOOL_MC_PROP_ALLOCATED, + ZPOOL_MC_PROP_AVAILABLE, + ZPOOL_MC_PROP_USABLE, + ZPOOL_MC_PROP_USED, + ZPOOL_MC_PROP_EXPANDSZ, + ZPOOL_MC_PROP_FRAGMENTATION, + ZPOOL_NUM_MC_PROPS +} zpool_mc_prop_t; + +/* Offsets for metaslab class property groups. */ +typedef enum { + ZPOOL_MC_PROPS_NORMAL = ZPOOL_PROP_NORMAL_SIZE, + ZPOOL_MC_PROPS_SPECIAL = ZPOOL_PROP_SPECIAL_SIZE, + ZPOOL_MC_PROPS_DEDUP = ZPOOL_PROP_DEDUP_SIZE, + ZPOOL_MC_PROPS_LOG = ZPOOL_PROP_LOG_SIZE, + ZPOOL_MC_PROPS_ELOG = ZPOOL_PROP_ELOG_SIZE, + ZPOOL_MC_PROPS_SELOG = ZPOOL_PROP_SELOG_SIZE, +} zpool_mc_props_t; + /* Small enough to not hog a whole line of printout in zpool(8). */ #define ZPROP_MAX_COMMENT 32 #define ZPROP_BOOLEAN_NA 2 diff --git a/sys/contrib/openzfs/include/sys/simd_config.h b/sys/contrib/openzfs/include/sys/simd_config.h new file mode 100644 index 000000000000..fe4fe38a0e29 --- /dev/null +++ b/sys/contrib/openzfs/include/sys/simd_config.h @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2026, TrueNAS. + */ + +#ifndef _SYS_SIMD_CONFIG_H +#define _SYS_SIMD_CONFIG_H + +/* + * Goal: a HAVE_SIMD(x) macro that expands to either 1 or 0 depending on + * the availabilty of that extension on the wanted toolchain. + * + * We need to allow the following: + * - #define HAVE_TOOLCHAIN_AVX 1 (zfs_config.h, detected by configure) + * - #undef HAVE_TOOLCHAIN_AVX (zfs_config.h, probed but not detected) + * - -DHAVE_TOOLCHAIN_AVX (Makefile.bsd) + * + * For completeness, we also allow disabling by defined HAVE_TOOLCHAIN_AVX=0. + * + * The "obvious" implementation of this would be a macro that includes + * defined(...) in its expansion, but unfortunately that is not portable, and + * can produce compiler warnings (see -Wexpansion-to-defined). So we need to + * build our own version. + */ + +/* + * 1. Expand incoming token to its defined value, if anything: + * eg HAVE_SIMD(AVX) + * -> _zfs_deftrue(HAVE_TOOLCHAIN_AVX) + * or -> __zfs_deftrue() (HAVE_TOOLCHAIN_AVX defined) + * or -> __zfs_deftrue(1) (HAVE_TOOLCHAIN_AVX = 1) + * -> __zfs_deftrue(0) (HAVE_TOOLCHAIN_AVX = 0) + * or -> __zfs_deftrue(HAVE_TOOLCHAIN_AVX) (HAVE_TOOLCHAIN_AVX undef) + */ +#define _zfs_deftrue(x) __zfs_deftrue(x) + +/* + * 2. Replace know values with a token that we control: + * __zfs_deftrue() + * -> ___zfs_deftrue(___zfs_deftrue_arg_) + * __zfs_deftrue(1) + * -> ___zfs_deftrue(___zfs_deftrue_arg_1) + * __zfs_deftrue(0) + * -> ___zfs_deftrue(___zfs_deftrue_arg_0) + * __zfs_deftrue(HAVE_TOOLCHAIN_AVX) + * -> ___zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX) + */ +#define __zfs_deftrue(v) ___zfs_deftrue(___zfs_deftrue_arg_##v) + +/* + * 3. Expand the incoming token into positional parameters for the next call: + * ___zfs_deftrue(___zfs_deftrue_arg_0) + * -> ____zfs_deftrue(0, 0, 0) + * ___zfs_deftrue(___zfs_deftrue_arg_1) + * -> ____zfs_deftrue(0, 1, 0) + * ___zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX) + * -> ____zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX, 0) + */ +#define ___zfs_deftrue_arg_ 0, 1 +#define ___zfs_deftrue_arg_1 0, 1 +#define ___zfs_deftrue_arg_0 0, 0 +#define ___zfs_deftrue(t, ...) ____zfs_deftrue(t, 0) + +/* + * 4. Emit the second argument, either the original value or the default 0. + * ____zfs_deftrue(0, 0, 0) -> 0 + * ____zfs_deftrue(0, 1, 0) -> 1 + * ____zfs_deftrue(___zfs_deftrue_arg_HAVE_TOOLCHAIN_AVX, 0) -> 0 + */ +#define ____zfs_deftrue(_n, v, ...) v + +/* + * The Linux kernel requires a specific toolchain. Everything else uses the + * regular compiler toolchain. + */ +#if defined(_KERNEL) && defined(__linux__) +#define HAVE_SIMD(ext) _zfs_deftrue(HAVE_KERNEL_##ext) +#else +#define HAVE_SIMD(ext) _zfs_deftrue(HAVE_TOOLCHAIN_##ext) +#endif + +#endif diff --git a/sys/contrib/openzfs/include/sys/spa.h b/sys/contrib/openzfs/include/sys/spa.h index 1a84844c522a..0de8a1867a12 100644 --- a/sys/contrib/openzfs/include/sys/spa.h +++ b/sys/contrib/openzfs/include/sys/spa.h @@ -1082,6 +1082,7 @@ extern uint64_t spa_guid(spa_t *spa); extern uint64_t spa_load_guid(spa_t *spa); extern uint64_t spa_last_synced_txg(spa_t *spa); extern uint64_t spa_first_txg(spa_t *spa); +extern uint64_t spa_open_txg(spa_t *spa); extern uint64_t spa_syncing_txg(spa_t *spa); extern uint64_t spa_final_dirty_txg(spa_t *spa); extern uint64_t spa_version(spa_t *spa); diff --git a/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h b/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h index 8c8dcfb077f6..55885dbd706f 100644 --- a/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h +++ b/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h @@ -172,19 +172,19 @@ typedef struct reflow_node { extern const raidz_impl_ops_t vdev_raidz_scalar_impl; extern boolean_t raidz_will_scalar_work(void); -#if defined(__x86_64) && defined(HAVE_SSE2) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(SSE2) /* only x86_64 for now */ extern const raidz_impl_ops_t vdev_raidz_sse2_impl; #endif -#if defined(__x86_64) && defined(HAVE_SSSE3) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(SSSE3) /* only x86_64 for now */ extern const raidz_impl_ops_t vdev_raidz_ssse3_impl; #endif -#if defined(__x86_64) && defined(HAVE_AVX2) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(AVX2) /* only x86_64 for now */ extern const raidz_impl_ops_t vdev_raidz_avx2_impl; #endif -#if defined(__x86_64) && defined(HAVE_AVX512F) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(AVX512F) /* only x86_64 for now */ extern const raidz_impl_ops_t vdev_raidz_avx512f_impl; #endif -#if defined(__x86_64) && defined(HAVE_AVX512BW) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(AVX512BW) /* only x86_64 for now */ extern const raidz_impl_ops_t vdev_raidz_avx512bw_impl; #endif #if defined(__aarch64__) diff --git a/sys/contrib/openzfs/include/sys/vdev_rebuild.h b/sys/contrib/openzfs/include/sys/vdev_rebuild.h index 51e669c2c50d..b787b1d5d993 100644 --- a/sys/contrib/openzfs/include/sys/vdev_rebuild.h +++ b/sys/contrib/openzfs/include/sys/vdev_rebuild.h @@ -91,6 +91,7 @@ boolean_t vdev_rebuild_active(vdev_t *); int vdev_rebuild_load(vdev_t *); void vdev_rebuild(vdev_t *, uint64_t); +void vdev_rebuild_txgs(vdev_t *, uint64_t *, uint64_t *); void vdev_rebuild_stop_wait(vdev_t *); void vdev_rebuild_stop_all(spa_t *); void vdev_rebuild_restart(spa_t *); diff --git a/sys/contrib/openzfs/include/zfs_fletcher.h b/sys/contrib/openzfs/include/zfs_fletcher.h index f3a620a7c7e2..d450f7f5e8a7 100644 --- a/sys/contrib/openzfs/include/zfs_fletcher.h +++ b/sys/contrib/openzfs/include/zfs_fletcher.h @@ -97,13 +97,13 @@ typedef union fletcher_4_ctx { zio_cksum_t scalar; zfs_fletcher_superscalar_t superscalar[4]; -#if defined(HAVE_SSE2) || (defined(HAVE_SSE2) && defined(HAVE_SSSE3)) +#if HAVE_SIMD(SSE2) || (HAVE_SIMD(SSE2) && HAVE_SIMD(SSSE3)) zfs_fletcher_sse_t sse[4]; #endif -#if defined(HAVE_AVX) && defined(HAVE_AVX2) +#if HAVE_SIMD(AVX) && HAVE_SIMD(AVX2) zfs_fletcher_avx_t avx[4]; #endif -#if defined(__x86_64) && defined(HAVE_AVX512F) +#if defined(__x86_64) && HAVE_SIMD(AVX512F) zfs_fletcher_avx512_t avx512[4]; #endif #if defined(__aarch64__) @@ -134,23 +134,23 @@ typedef struct fletcher_4_func { _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_superscalar_ops; _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_superscalar4_ops; -#if defined(HAVE_SSE2) +#if HAVE_SIMD(SSE2) _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_sse2_ops; #endif -#if defined(HAVE_SSE2) && defined(HAVE_SSSE3) +#if HAVE_SIMD(SSE2) && HAVE_SIMD(SSSE3) _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_ssse3_ops; #endif -#if defined(HAVE_AVX) && defined(HAVE_AVX2) +#if HAVE_SIMD(AVX) && HAVE_SIMD(AVX2) _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_avx2_ops; #endif -#if defined(__x86_64) && defined(HAVE_AVX512F) +#if defined(__x86_64) && HAVE_SIMD(AVX512F) _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_avx512f_ops; #endif -#if defined(__x86_64) && defined(HAVE_AVX512BW) +#if defined(__x86_64) && HAVE_SIMD(AVX512BW) _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_avx512bw_ops; #endif diff --git a/sys/contrib/openzfs/lib/libspl/Makefile.am b/sys/contrib/openzfs/lib/libspl/Makefile.am index 00445427f983..8b50c65c0e60 100644 --- a/sys/contrib/openzfs/lib/libspl/Makefile.am +++ b/sys/contrib/openzfs/lib/libspl/Makefile.am @@ -44,7 +44,7 @@ if BUILD_LINUX libspl_la_SOURCES += \ %D%/os/linux/getexecname.c \ %D%/os/linux/gethostid.c \ - %D%/os/linux/getmntany.c \ + %D%/os/linux/mnttab.c \ %D%/os/linux/zone.c endif @@ -52,7 +52,7 @@ if BUILD_FREEBSD libspl_la_SOURCES += \ %D%/os/freebsd/getexecname.c \ %D%/os/freebsd/gethostid.c \ - %D%/os/freebsd/getmntany.c \ + %D%/os/freebsd/getextmntent.c \ %D%/os/freebsd/mnttab.c \ %D%/os/freebsd/zone.c endif diff --git a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/mnttab.h b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/mnttab.h index e520bf5ef3bb..ac65b7df5ddf 100644 --- a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/mnttab.h +++ b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/mnttab.h @@ -57,27 +57,11 @@ struct mnttab { char *mnt_mntopts; }; -/* - * NOTE: fields in extmnttab should match struct mnttab till new fields - * are encountered, this allows hasmntopt to work properly when its arg is - * a pointer to an extmnttab struct cast to a mnttab struct pointer. - */ - -struct extmnttab { - char *mnt_special; - char *mnt_mountp; - char *mnt_fstype; - char *mnt_mntopts; - uint_t mnt_major; - uint_t mnt_minor; -}; - struct stat64; struct statfs; -extern int getmntany(FILE *fp, struct mnttab *mp, struct mnttab *mpref); extern int _sol_getmntent(FILE *fp, struct mnttab *mp); -extern int getextmntent(const char *path, struct extmnttab *entry, +extern int getextmntent(const char *path, struct mnttab *entry, struct stat64 *statbuf); extern void statfs2mnttab(struct statfs *sfs, struct mnttab *mp); extern char *hasmntopt(struct mnttab *mnt, const char *opt); diff --git a/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/mnttab.h b/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/mnttab.h index c1b7f3b389c0..f6a65636d606 100644 --- a/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/mnttab.h +++ b/sys/contrib/openzfs/lib/libspl/include/os/linux/sys/mnttab.h @@ -54,26 +54,10 @@ struct mnttab { char *mnt_mntopts; }; -/* - * NOTE: fields in extmnttab should match struct mnttab till new fields - * are encountered, this allows hasmntopt to work properly when its arg is - * a pointer to an extmnttab struct cast to a mnttab struct pointer. - */ - -struct extmnttab { - char *mnt_special; - char *mnt_mountp; - char *mnt_fstype; - char *mnt_mntopts; - uint_t mnt_major; - uint_t mnt_minor; -}; - struct statfs; -extern int getmntany(FILE *fp, struct mnttab *mp, struct mnttab *mpref); extern int _sol_getmntent(FILE *fp, struct mnttab *mp); -extern int getextmntent(const char *path, struct extmnttab *mp, +extern int getextmntent(const char *path, struct mnttab *mp, struct stat64 *statbuf); static inline char *_sol_hasmntopt(struct mnttab *mnt, const char *opt) { diff --git a/sys/contrib/openzfs/lib/libspl/os/freebsd/getmntany.c b/sys/contrib/openzfs/lib/libspl/os/freebsd/getextmntent.c index baff124b4a40..07b886123153 100644 --- a/sys/contrib/openzfs/lib/libspl/os/freebsd/getmntany.c +++ b/sys/contrib/openzfs/lib/libspl/os/freebsd/getextmntent.c @@ -40,7 +40,7 @@ #include <libzutil.h> int -getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) +getextmntent(const char *path, struct mnttab *entry, struct stat64 *statbuf) { struct statfs sfs; @@ -60,6 +60,6 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) zfs_strerror(errno)); return (-1); } - statfs2mnttab(&sfs, (struct mnttab *)entry); + statfs2mnttab(&sfs, entry); return (0); } diff --git a/sys/contrib/openzfs/lib/libspl/os/freebsd/mnttab.c b/sys/contrib/openzfs/lib/libspl/os/freebsd/mnttab.c index 5287da132966..db7caba9fce2 100644 --- a/sys/contrib/openzfs/lib/libspl/os/freebsd/mnttab.c +++ b/sys/contrib/openzfs/lib/libspl/os/freebsd/mnttab.c @@ -26,8 +26,7 @@ */ /* - * This file implements Solaris compatible getmntany() and hasmntopt() - * functions. + * This file implements Solaris compatible hasmntopt() functions. */ #include <sys/param.h> @@ -177,38 +176,6 @@ fail: } int -getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp) -{ - int i, error; - - error = statfs_init(); - if (error != 0) - return (error); - - (void) pthread_rwlock_rdlock(&gsfs_lock); - - for (i = 0; i < allfs; i++) { - if (mrefp->mnt_special != NULL && - strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) { - continue; - } - if (mrefp->mnt_mountp != NULL && - strcmp(mrefp->mnt_mountp, gsfs[i].f_mntonname) != 0) { - continue; - } - if (mrefp->mnt_fstype != NULL && - strcmp(mrefp->mnt_fstype, gsfs[i].f_fstypename) != 0) { - continue; - } - statfs2mnttab(&gsfs[i], mgetp); - (void) pthread_rwlock_unlock(&gsfs_lock); - return (0); - } - (void) pthread_rwlock_unlock(&gsfs_lock); - return (-1); -} - -int getmntent(FILE *fp, struct mnttab *mp) { int error, nfs; diff --git a/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c b/sys/contrib/openzfs/lib/libspl/os/linux/mnttab.c index ee1cdf59b9e5..25fa132ac6fc 100644 --- a/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c +++ b/sys/contrib/openzfs/lib/libspl/os/linux/mnttab.c @@ -45,23 +45,6 @@ static __thread char buf[BUFSIZE]; -#define DIFF(xx) ( \ - (mrefp->xx != NULL) && \ - (mgetp->xx == NULL || strcmp(mrefp->xx, mgetp->xx) != 0)) - -int -getmntany(FILE *fp, struct mnttab *mgetp, struct mnttab *mrefp) -{ - int ret; - - while ( - ((ret = _sol_getmntent(fp, mgetp)) == 0) && ( - DIFF(mnt_special) || DIFF(mnt_mountp) || - DIFF(mnt_fstype) || DIFF(mnt_mntopts))) { } - - return (ret); -} - int _sol_getmntent(FILE *fp, struct mnttab *mgetp) { @@ -85,7 +68,7 @@ _sol_getmntent(FILE *fp, struct mnttab *mgetp) } static int -getextmntent_impl(FILE *fp, struct extmnttab *mp, uint64_t *mnt_id) +getextmntent_impl(FILE *fp, struct mnttab *mp, uint64_t *mnt_id, dev_t *dev) { int ret; struct stat64 st; @@ -101,19 +84,17 @@ getextmntent_impl(FILE *fp, struct extmnttab *mp, uint64_t *mnt_id) *mnt_id = stx.stx_mnt_id; #endif if (stat64(mp->mnt_mountp, &st) != 0) { - mp->mnt_major = 0; - mp->mnt_minor = 0; + *dev = 0; return (ret); } - mp->mnt_major = major(st.st_dev); - mp->mnt_minor = minor(st.st_dev); + *dev = st.st_dev; } return (ret); } int -getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) +getextmntent(const char *path, struct mnttab *entry, struct stat64 *statbuf) { struct stat64 st; FILE *fp; @@ -121,6 +102,7 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) boolean_t have_mnt_id = B_FALSE; uint64_t target_mnt_id = 0; uint64_t entry_mnt_id; + dev_t dev; #ifdef HAVE_STATX_MNT_ID struct statx stx; #endif @@ -160,12 +142,11 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) */ match = 0; - while (getextmntent_impl(fp, entry, &entry_mnt_id) == 0) { + while (getextmntent_impl(fp, entry, &entry_mnt_id, &dev) == 0) { if (have_mnt_id) { match = (entry_mnt_id == target_mnt_id); } else { - match = makedev(entry->mnt_major, entry->mnt_minor) == - statbuf->st_dev; + match = (dev == statbuf->st_dev); } if (match) break; @@ -178,11 +159,8 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf) return (-1); } - if (stat64(entry->mnt_mountp, &st) != 0) { - entry->mnt_major = 0; - entry->mnt_minor = 0; + if (stat64(entry->mnt_mountp, &st) != 0) return (-1); - } return (0); } diff --git a/sys/contrib/openzfs/lib/libzdb/libzdb.c b/sys/contrib/openzfs/lib/libzdb/libzdb.c index cca1327b1b03..c7766766fc7b 100644 --- a/sys/contrib/openzfs/lib/libzdb/libzdb.c +++ b/sys/contrib/openzfs/lib/libzdb/libzdb.c @@ -68,35 +68,23 @@ livelist_compare(const void *larg, const void *rarg) { const blkptr_t *l = larg; const blkptr_t *r = rarg; + int cmp = 0; /* Sort them according to dva[0] */ - uint64_t l_dva0_vdev, r_dva0_vdev; - l_dva0_vdev = DVA_GET_VDEV(&l->blk_dva[0]); - r_dva0_vdev = DVA_GET_VDEV(&r->blk_dva[0]); - if (l_dva0_vdev < r_dva0_vdev) - return (-1); - else if (l_dva0_vdev > r_dva0_vdev) - return (+1); + cmp = TREE_CMP(DVA_GET_VDEV(&l->blk_dva[0]), + DVA_GET_VDEV(&r->blk_dva[0])); + if (cmp != 0) + return (cmp); /* if vdevs are equal, sort by offsets. */ - uint64_t l_dva0_offset; - uint64_t r_dva0_offset; - l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]); - r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]); - if (l_dva0_offset < r_dva0_offset) { - return (-1); - } else if (l_dva0_offset > r_dva0_offset) { - return (+1); - } + cmp = TREE_CMP(DVA_GET_OFFSET(&l->blk_dva[0]), + DVA_GET_OFFSET(&r->blk_dva[0])); + if (cmp != 0) + return (cmp); /* * Since we're storing blkptrs without cancelling FREE/ALLOC pairs, * it's possible the offsets are equal. In that case, sort by txg */ - if (BP_GET_BIRTH(l) < BP_GET_BIRTH(r)) { - return (-1); - } else if (BP_GET_BIRTH(l) > BP_GET_BIRTH(r)) { - return (+1); - } - return (0); + return (TREE_CMP(BP_GET_BIRTH(l), BP_GET_BIRTH(r))); } diff --git a/sys/contrib/openzfs/lib/libzfs/Makefile.am b/sys/contrib/openzfs/lib/libzfs/Makefile.am index 43b65d4dc1be..450c501556e9 100644 --- a/sys/contrib/openzfs/lib/libzfs/Makefile.am +++ b/sys/contrib/openzfs/lib/libzfs/Makefile.am @@ -16,6 +16,7 @@ dist_libzfs_la_SOURCES = \ %D%/libzfs_diff.c \ %D%/libzfs_import.c \ %D%/libzfs_iter.c \ + %D%/libzfs_mnttab.c \ %D%/libzfs_mount.c \ %D%/libzfs_pool.c \ %D%/libzfs_share.c \ diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs.abi b/sys/contrib/openzfs/lib/libzfs/libzfs.abi index 876433c0ba58..bed2c7979a1b 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs.abi +++ b/sys/contrib/openzfs/lib/libzfs/libzfs.abi @@ -204,7 +204,6 @@ <elf-symbol name='get_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='getexecname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='getextmntent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='getprop_uint64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='is_mounted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -356,6 +355,7 @@ <elf-symbol name='zfs_component_namecheck' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_create_ancestors' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='zfs_create_ancestors_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_crypto_attempt_load_keys' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_crypto_clone_check' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='zfs_crypto_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -1255,7 +1255,6 @@ <qualified-type-def type-id='a7e325e5' restrict='yes' id='4c428e67'/> <qualified-type-def type-id='e05e8614' restrict='yes' id='0be2e71c'/> <pointer-type-def type-id='29dbc0dd' size-in-bits='64' id='068c4f7e'/> - <pointer-type-def type-id='b9eccc8f' size-in-bits='64' id='78830f38'/> <pointer-type-def type-id='62fab762' size-in-bits='64' id='db285b03'/> <qualified-type-def type-id='db285b03' restrict='yes' id='2a468b41'/> <qualified-type-def type-id='18c91f9e' restrict='yes' id='6e745582'/> @@ -1659,21 +1658,6 @@ <parameter type-id='18c91f9e'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='mutex_init' mangled-name='mutex_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_init'> - <parameter type-id='78830f38' name='mp'/> - <parameter type-id='26a90f95' name='name'/> - <parameter type-id='95e97e5e' name='type'/> - <parameter type-id='eaa32e2f' name='cookie'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='mutex_destroy' mangled-name='mutex_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_destroy'> - <parameter type-id='78830f38' name='mp'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='mutex_enter' mangled-name='mutex_enter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_enter'> - <parameter type-id='78830f38' name='mp'/> - <return type-id='48b5725f'/> - </function-decl> <function-decl name='mutex_enter_check_return' mangled-name='mutex_enter_check_return' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_enter_check_return'> <parameter type-id='78830f38' name='mp'/> <return type-id='95e97e5e'/> @@ -1682,12 +1666,8 @@ <parameter type-id='78830f38' name='mp'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='mutex_exit' mangled-name='mutex_exit' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_exit'> - <parameter type-id='78830f38' name='mp'/> - <return type-id='48b5725f'/> - </function-decl> </abi-instr> - <abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'> + <abi-instr address-size='64' path='lib/libspl/os/linux/mnttab.c' language='LANG_C99'> <pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/> <qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/> <function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'> @@ -2343,6 +2323,15 @@ </data-member> </class-decl> <typedef-decl name='nvlist_t' type-id='ac266fd9' id='8e8d4be3'/> + <class-decl name='kmutex' size-in-bits='384' is-struct='yes' visibility='default' id='f1cacfe1'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='m_lock' type-id='7a6844eb' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='320'> + <var-decl name='m_owner' type-id='4051f5e7' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='kmutex_t' type-id='f1cacfe1' id='b9eccc8f'/> <enum-decl name='boolean_t' naming-typedef-id='c19b74c3' id='f58c8277'> <underlying-type type-id='9cac1fee'/> <enumerator name='B_FALSE' value='0'/> @@ -2402,6 +2391,7 @@ </class-decl> <typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/> <typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/> + <typedef-decl name='pthread_t' type-id='7359adad' id='4051f5e7'/> <union-decl name='pthread_mutex_t' size-in-bits='320' naming-typedef-id='7a6844eb' visibility='default' id='70681f9b'> <data-member access='public'> <var-decl name='__data' type-id='4c734837' visibility='default'/> @@ -2487,32 +2477,29 @@ <var-decl name='libzfs_printerr' type-id='95e97e5e' visibility='default'/> </data-member> <data-member access='public' layout-offset-in-bits='16960'> - <var-decl name='libzfs_mnttab_enable' type-id='c19b74c3' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='17024'> - <var-decl name='libzfs_mnttab_cache_lock' type-id='7a6844eb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='17344'> - <var-decl name='libzfs_mnttab_cache' type-id='f20fbd51' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='17664'> <var-decl name='libzfs_pool_iter' type-id='95e97e5e' visibility='default'/> </data-member> - <data-member access='public' layout-offset-in-bits='17696'> + <data-member access='public' layout-offset-in-bits='16992'> <var-decl name='libzfs_prop_debug' type-id='c19b74c3' visibility='default'/> </data-member> - <data-member access='public' layout-offset-in-bits='17728'> + <data-member access='public' layout-offset-in-bits='17024'> <var-decl name='libzfs_urire' type-id='aca3bac8' visibility='default'/> </data-member> - <data-member access='public' layout-offset-in-bits='18240'> + <data-member access='public' layout-offset-in-bits='17536'> <var-decl name='libzfs_max_nvlist' type-id='9c313c2d' visibility='default'/> </data-member> - <data-member access='public' layout-offset-in-bits='18304'> + <data-member access='public' layout-offset-in-bits='17600'> <var-decl name='libfetch' type-id='eaa32e2f' visibility='default'/> </data-member> - <data-member access='public' layout-offset-in-bits='18368'> + <data-member access='public' layout-offset-in-bits='17664'> <var-decl name='libfetch_load_error' type-id='26a90f95' visibility='default'/> </data-member> + <data-member access='public' layout-offset-in-bits='17728'> + <var-decl name='zh_mnttab_lock' type-id='b9eccc8f' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='18112'> + <var-decl name='zh_mnttab' type-id='f20fbd51' visibility='default'/> + </data-member> </class-decl> <class-decl name='zfs_handle' size-in-bits='4928' is-struct='yes' visibility='default' id='f6ee4445'> <data-member access='public' layout-offset-in-bits='0'> @@ -3372,7 +3359,64 @@ <enumerator name='ZPOOL_PROP_LAST_SCRUBBED_TXG' value='39'/> <enumerator name='ZPOOL_PROP_DEDUPUSED' value='40'/> <enumerator name='ZPOOL_PROP_DEDUPSAVED' value='41'/> - <enumerator name='ZPOOL_NUM_PROPS' value='42'/> + <enumerator name='ZPOOL_PROP_AVAILABLE' value='42'/> + <enumerator name='ZPOOL_PROP_USABLE' value='43'/> + <enumerator name='ZPOOL_PROP_USED' value='44'/> + <enumerator name='ZPOOL_PROP_NORMAL_SIZE' value='45'/> + <enumerator name='ZPOOL_PROP_NORMAL_CAPACITY' value='46'/> + <enumerator name='ZPOOL_PROP_NORMAL_FREE' value='47'/> + <enumerator name='ZPOOL_PROP_NORMAL_ALLOCATED' value='48'/> + <enumerator name='ZPOOL_PROP_NORMAL_AVAILABLE' value='49'/> + <enumerator name='ZPOOL_PROP_NORMAL_USABLE' value='50'/> + <enumerator name='ZPOOL_PROP_NORMAL_USED' value='51'/> + <enumerator name='ZPOOL_PROP_NORMAL_EXPANDSZ' value='52'/> + <enumerator name='ZPOOL_PROP_NORMAL_FRAGMENTATION' value='53'/> + <enumerator name='ZPOOL_PROP_SPECIAL_SIZE' value='54'/> + <enumerator name='ZPOOL_PROP_SPECIAL_CAPACITY' value='55'/> + <enumerator name='ZPOOL_PROP_SPECIAL_FREE' value='56'/> + <enumerator name='ZPOOL_PROP_SPECIAL_ALLOCATED' value='57'/> + <enumerator name='ZPOOL_PROP_SPECIAL_AVAILABLE' value='58'/> + <enumerator name='ZPOOL_PROP_SPECIAL_USABLE' value='59'/> + <enumerator name='ZPOOL_PROP_SPECIAL_USED' value='60'/> + <enumerator name='ZPOOL_PROP_SPECIAL_EXPANDSZ' value='61'/> + <enumerator name='ZPOOL_PROP_SPECIAL_FRAGMENTATION' value='62'/> + <enumerator name='ZPOOL_PROP_DEDUP_SIZE' value='63'/> + <enumerator name='ZPOOL_PROP_DEDUP_CAPACITY' value='64'/> + <enumerator name='ZPOOL_PROP_DEDUP_FREE' value='65'/> + <enumerator name='ZPOOL_PROP_DEDUP_ALLOCATED' value='66'/> + <enumerator name='ZPOOL_PROP_DEDUP_AVAILABLE' value='67'/> + <enumerator name='ZPOOL_PROP_DEDUP_USABLE' value='68'/> + <enumerator name='ZPOOL_PROP_DEDUP_USED' value='69'/> + <enumerator name='ZPOOL_PROP_DEDUP_EXPANDSZ' value='70'/> + <enumerator name='ZPOOL_PROP_DEDUP_FRAGMENTATION' value='71'/> + <enumerator name='ZPOOL_PROP_LOG_SIZE' value='72'/> + <enumerator name='ZPOOL_PROP_LOG_CAPACITY' value='73'/> + <enumerator name='ZPOOL_PROP_LOG_FREE' value='74'/> + <enumerator name='ZPOOL_PROP_LOG_ALLOCATED' value='75'/> + <enumerator name='ZPOOL_PROP_LOG_AVAILABLE' value='76'/> + <enumerator name='ZPOOL_PROP_LOG_USABLE' value='77'/> + <enumerator name='ZPOOL_PROP_LOG_USED' value='78'/> + <enumerator name='ZPOOL_PROP_LOG_EXPANDSZ' value='79'/> + <enumerator name='ZPOOL_PROP_LOG_FRAGMENTATION' value='80'/> + <enumerator name='ZPOOL_PROP_ELOG_SIZE' value='81'/> + <enumerator name='ZPOOL_PROP_ELOG_CAPACITY' value='82'/> + <enumerator name='ZPOOL_PROP_ELOG_FREE' value='83'/> + <enumerator name='ZPOOL_PROP_ELOG_ALLOCATED' value='84'/> + <enumerator name='ZPOOL_PROP_ELOG_AVAILABLE' value='85'/> + <enumerator name='ZPOOL_PROP_ELOG_USABLE' value='86'/> + <enumerator name='ZPOOL_PROP_ELOG_USED' value='87'/> + <enumerator name='ZPOOL_PROP_ELOG_EXPANDSZ' value='88'/> + <enumerator name='ZPOOL_PROP_ELOG_FRAGMENTATION' value='89'/> + <enumerator name='ZPOOL_PROP_SELOG_SIZE' value='90'/> + <enumerator name='ZPOOL_PROP_SELOG_CAPACITY' value='91'/> + <enumerator name='ZPOOL_PROP_SELOG_FREE' value='92'/> + <enumerator name='ZPOOL_PROP_SELOG_ALLOCATED' value='93'/> + <enumerator name='ZPOOL_PROP_SELOG_AVAILABLE' value='94'/> + <enumerator name='ZPOOL_PROP_SELOG_USABLE' value='95'/> + <enumerator name='ZPOOL_PROP_SELOG_USED' value='96'/> + <enumerator name='ZPOOL_PROP_SELOG_EXPANDSZ' value='97'/> + <enumerator name='ZPOOL_PROP_SELOG_FRAGMENTATION' value='98'/> + <enumerator name='ZPOOL_NUM_PROPS' value='99'/> </enum-decl> <typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/> <typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/> @@ -4055,9 +4099,6 @@ </function-type> </abi-instr> <abi-instr address-size='64' path='lib/libzfs/libzfs_dataset.c' language='LANG_C99'> - <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32' id='8e0573fd'> - <subrange length='4' type-id='7359adad' id='16fe7105'/> - </array-type-def> <class-decl name='prop_changelist' is-struct='yes' visibility='default' is-declaration-only='yes' id='d86edc51'/> <class-decl name='zprop_list' size-in-bits='448' is-struct='yes' visibility='default' id='bd9b4291'> <data-member access='public' layout-offset-in-bits='0'> @@ -4219,15 +4260,6 @@ <var-decl name='pw_shell' type-id='26a90f95' visibility='default'/> </data-member> </class-decl> - <union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'> - <data-member access='public'> - <var-decl name='__size' type-id='8e0573fd' visibility='default'/> - </data-member> - <data-member access='public'> - <var-decl name='__align' type-id='95e97e5e' visibility='default'/> - </data-member> - </union-decl> - <typedef-decl name='pthread_mutexattr_t' type-id='7300eb00' id='8afd6070'/> <typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/> <typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/> <typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/> @@ -4273,8 +4305,6 @@ <qualified-type-def type-id='26a90f95' restrict='yes' id='266fe297'/> <qualified-type-def type-id='56fe4a37' const='yes' id='a75125ce'/> <pointer-type-def type-id='a75125ce' size-in-bits='64' id='48bea5ec'/> - <qualified-type-def type-id='8afd6070' const='yes' id='1d853360'/> - <pointer-type-def type-id='1d853360' size-in-bits='64' id='c2afbd7e'/> <qualified-type-def type-id='c9d12d66' const='yes' id='588b3216'/> <pointer-type-def type-id='588b3216' size-in-bits='64' id='9f201474'/> <qualified-type-def type-id='9f201474' restrict='yes' id='d6e2847c'/> @@ -4304,6 +4334,12 @@ <pointer-type-def type-id='bdb8ac4f' size-in-bits='64' id='3a9b2288'/> <pointer-type-def type-id='3a9b2288' size-in-bits='64' id='e4378506'/> <class-decl name='prop_changelist' is-struct='yes' visibility='default' is-declaration-only='yes' id='d86edc51'/> + <function-decl name='libzfs_mnttab_find' mangled-name='libzfs_mnttab_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_find'> + <parameter type-id='b0382bb3'/> + <parameter type-id='80f4b756'/> + <parameter type-id='9d424d31'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zpool_open' mangled-name='zpool_open' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_open'> <parameter type-id='b0382bb3'/> <parameter type-id='80f4b756'/> @@ -4471,15 +4507,6 @@ <parameter type-id='b59d7dce'/> <return type-id='48b5725f'/> </function-decl> - <function-decl name='avl_add' mangled-name='avl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_add'> - <parameter type-id='a3681dea'/> - <parameter type-id='eaa32e2f'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='avl_numnodes' mangled-name='avl_numnodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_numnodes'> - <parameter type-id='a3681dea'/> - <return type-id='ee1f298e'/> - </function-decl> <function-decl name='zfs_prop_readonly' mangled-name='zfs_prop_readonly' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_readonly'> <parameter type-id='58603c44'/> <return type-id='c19b74c3'/> @@ -4683,17 +4710,6 @@ <parameter type-id='58603c44'/> <return type-id='31429eff'/> </function-decl> - <function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'> - <parameter type-id='822cd80b'/> - <parameter type-id='9d424d31'/> - <parameter type-id='9d424d31'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='_sol_getmntent' mangled-name='_sol_getmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_sol_getmntent'> - <parameter type-id='822cd80b'/> - <parameter type-id='9d424d31'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='getgrnam_r' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='9d26089a'/> <parameter type-id='c878edd6'/> @@ -4707,15 +4723,6 @@ <parameter type-id='80f4b756'/> <return type-id='26a90f95'/> </function-decl> - <function-decl name='pthread_mutex_init' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='18c91f9e'/> - <parameter type-id='c2afbd7e'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='pthread_mutex_destroy' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='18c91f9e'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='getpwnam_r' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='9d26089a'/> <parameter type-id='33518961'/> @@ -4795,37 +4802,6 @@ <parameter type-id='80f4b756' name='path'/> <return type-id='c19b74c3'/> </function-decl> - <function-decl name='libzfs_mnttab_init' mangled-name='libzfs_mnttab_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_init'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_fini' mangled-name='libzfs_mnttab_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_fini'> - <parameter type-id='b0382bb3' name='hdl'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_cache' mangled-name='libzfs_mnttab_cache' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_cache'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='c19b74c3' name='enable'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_find' mangled-name='libzfs_mnttab_find' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_find'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='fsname'/> - <parameter type-id='9d424d31' name='entry'/> - <return type-id='95e97e5e'/> - </function-decl> - <function-decl name='libzfs_mnttab_add' mangled-name='libzfs_mnttab_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_add'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='special'/> - <parameter type-id='80f4b756' name='mountp'/> - <parameter type-id='80f4b756' name='mntopts'/> - <return type-id='48b5725f'/> - </function-decl> - <function-decl name='libzfs_mnttab_remove' mangled-name='libzfs_mnttab_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_remove'> - <parameter type-id='b0382bb3' name='hdl'/> - <parameter type-id='80f4b756' name='fsname'/> - <return type-id='48b5725f'/> - </function-decl> <function-decl name='zfs_spa_version' mangled-name='zfs_spa_version' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_spa_version'> <parameter type-id='9200a744' name='zhp'/> <parameter type-id='7292109c' name='spa_version'/> @@ -5202,7 +5178,6 @@ <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='448' id='6093ff7c'> <subrange length='56' type-id='7359adad' id='f8137894'/> </array-type-def> - <typedef-decl name='pthread_t' type-id='7359adad' id='4051f5e7'/> <union-decl name='pthread_attr_t' size-in-bits='448' visibility='default' id='b63afacd'> <data-member access='public'> <var-decl name='__size' type-id='6093ff7c' visibility='default'/> @@ -5507,6 +5482,16 @@ </function-type> </abi-instr> <abi-instr address-size='64' path='lib/libzfs/libzfs_iter.c' language='LANG_C99'> + <function-decl name='avl_add' mangled-name='avl_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_add'> + <parameter type-id='a3681dea'/> + <parameter type-id='eaa32e2f'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='_sol_getmntent' mangled-name='_sol_getmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_sol_getmntent'> + <parameter type-id='822cd80b'/> + <parameter type-id='9d424d31'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='make_dataset_handle_zc' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='b0382bb3'/> <parameter type-id='e4ec4540'/> @@ -5590,6 +5575,57 @@ <return type-id='95e97e5e'/> </function-decl> </abi-instr> + <abi-instr address-size='64' path='lib/libzfs/libzfs_mnttab.c' language='LANG_C99'> + <pointer-type-def type-id='b9eccc8f' size-in-bits='64' id='78830f38'/> + <function-decl name='avl_numnodes' mangled-name='avl_numnodes' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='avl_numnodes'> + <parameter type-id='a3681dea'/> + <return type-id='ee1f298e'/> + </function-decl> + <function-decl name='mutex_init' mangled-name='mutex_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_init'> + <parameter type-id='78830f38'/> + <parameter type-id='26a90f95'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='eaa32e2f'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='mutex_destroy' mangled-name='mutex_destroy' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_destroy'> + <parameter type-id='78830f38'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='mutex_enter' mangled-name='mutex_enter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_enter'> + <parameter type-id='78830f38'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='mutex_exit' mangled-name='mutex_exit' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='mutex_exit'> + <parameter type-id='78830f38'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='libzfs_mnttab_init' mangled-name='libzfs_mnttab_init' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_init'> + <parameter type-id='b0382bb3' name='hdl'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='libzfs_mnttab_fini' mangled-name='libzfs_mnttab_fini' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_fini'> + <parameter type-id='b0382bb3' name='hdl'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='libzfs_mnttab_cache' mangled-name='libzfs_mnttab_cache' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_cache'> + <parameter type-id='b0382bb3' name='hdl'/> + <parameter type-id='c19b74c3' name='enable'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='libzfs_mnttab_add' mangled-name='libzfs_mnttab_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_add'> + <parameter type-id='b0382bb3' name='hdl'/> + <parameter type-id='80f4b756' name='special'/> + <parameter type-id='80f4b756' name='mountp'/> + <parameter type-id='80f4b756' name='mntopts'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='libzfs_mnttab_remove' mangled-name='libzfs_mnttab_remove' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libzfs_mnttab_remove'> + <parameter type-id='b0382bb3' name='hdl'/> + <parameter type-id='80f4b756' name='fsname'/> + <return type-id='48b5725f'/> + </function-decl> + </abi-instr> <abi-instr address-size='64' path='lib/libzfs/libzfs_mount.c' language='LANG_C99'> <array-type-def dimensions='1' type-id='6028cbfe' size-in-bits='256' id='b39b9aa7'> <subrange length='4' type-id='7359adad' id='16fe7105'/> @@ -5624,15 +5660,6 @@ </class-decl> <typedef-decl name='get_all_cb_t' type-id='803dac95' id='9b293607'/> <typedef-decl name='kcondvar_t' type-id='62fab762' id='29dbc0dd'/> - <class-decl name='kmutex' size-in-bits='384' is-struct='yes' visibility='default' id='f1cacfe1'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='m_lock' type-id='7a6844eb' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='320'> - <var-decl name='m_owner' type-id='4051f5e7' visibility='default'/> - </data-member> - </class-decl> - <typedef-decl name='kmutex_t' type-id='f1cacfe1' id='b9eccc8f'/> <class-decl name='krwlock' size-in-bits='576' is-struct='yes' visibility='default' id='4361e3b2'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='rw_lock' type-id='3f680bc6' visibility='default'/> @@ -6557,6 +6584,11 @@ <pointer-type-def type-id='35acf840' size-in-bits='64' id='17f3480d'/> <pointer-type-def type-id='688c495b' size-in-bits='64' id='cec6f2e4'/> <pointer-type-def type-id='d11b7617' size-in-bits='64' id='23432aaa'/> + <function-decl name='dump_nvlist' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5ce45b60'/> + <parameter type-id='95e97e5e'/> + <return type-id='48b5725f'/> + </function-decl> <function-decl name='zpool_get_handle' mangled-name='zpool_get_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_handle'> <parameter type-id='4c81de99'/> <return type-id='b0382bb3'/> @@ -7410,7 +7442,7 @@ <array-type-def dimensions='1' type-id='eaa32e2f' size-in-bits='256' id='209ef23f'> <subrange length='4' type-id='7359adad' id='16fe7105'/> </array-type-def> - <class-decl name='sendflags' size-in-bits='576' is-struct='yes' visibility='default' id='f6aa15be'> + <class-decl name='sendflags' size-in-bits='608' is-struct='yes' visibility='default' id='f6aa15be'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='verbosity' type-id='95e97e5e' visibility='default'/> </data-member> @@ -7465,6 +7497,9 @@ <data-member access='public' layout-offset-in-bits='544'> <var-decl name='saved' type-id='c19b74c3' visibility='default'/> </data-member> + <data-member access='public' layout-offset-in-bits='576'> + <var-decl name='no_preserve_encryption' type-id='c19b74c3' visibility='default'/> + </data-member> </class-decl> <typedef-decl name='sendflags_t' type-id='f6aa15be' id='945467e6'/> <typedef-decl name='snapfilter_cb_t' type-id='d2a5e211' id='3d3ffb69'/> @@ -8146,6 +8181,13 @@ <parameter type-id='5d6479ae'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='lzc_send_progress' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='80f4b756'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='5d6479ae'/> + <parameter type-id='5d6479ae'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='lzc_rename' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='80f4b756'/> <parameter type-id='80f4b756'/> @@ -8561,26 +8603,6 @@ </data-member> </class-decl> <typedef-decl name='zprop_desc_t' type-id='bbff5e4b' id='ffa52b96'/> - <class-decl name='extmnttab' size-in-bits='320' is-struct='yes' visibility='default' id='0c544dc0'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='mnt_special' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='mnt_mountp' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='mnt_fstype' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='mnt_major' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/> - </data-member> - </class-decl> <pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/> <qualified-type-def type-id='26a90f95' const='yes' id='57de658a'/> <pointer-type-def type-id='57de658a' size-in-bits='64' id='f319fae0'/> @@ -8590,7 +8612,6 @@ <pointer-type-def type-id='a0de50cd' size-in-bits='64' id='24f95ba5'/> <qualified-type-def type-id='64636ce3' const='yes' id='072f7953'/> <pointer-type-def type-id='072f7953' size-in-bits='64' id='c8bc397b'/> - <pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/> <pointer-type-def type-id='aca3bac8' size-in-bits='64' id='d33f11cb'/> <qualified-type-def type-id='d33f11cb' restrict='yes' id='5c53ba29'/> <pointer-type-def type-id='ffa52b96' size-in-bits='64' id='76c8174b'/> @@ -8686,7 +8707,7 @@ </function-decl> <function-decl name='getextmntent' mangled-name='getextmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getextmntent'> <parameter type-id='80f4b756'/> - <parameter type-id='394fc496'/> + <parameter type-id='9d424d31'/> <parameter type-id='62f7a03d'/> <return type-id='95e97e5e'/> </function-decl> @@ -9580,6 +9601,9 @@ </function-decl> </abi-instr> <abi-instr address-size='64' path='lib/libzutil/zutil_import.c' language='LANG_C99'> + <array-type-def dimensions='1' type-id='a84c031d' size-in-bits='32' id='8e0573fd'> + <subrange length='4' type-id='7359adad' id='16fe7105'/> + </array-type-def> <class-decl name='importargs' size-in-bits='512' is-struct='yes' visibility='default' id='7ac83801'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='path' type-id='9b23c9ad' visibility='default'/> @@ -9678,6 +9702,15 @@ <var-decl name='__glibc_reserved' type-id='16dc656a' visibility='default'/> </data-member> </class-decl> + <union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'> + <data-member access='public'> + <var-decl name='__size' type-id='8e0573fd' visibility='default'/> + </data-member> + <data-member access='public'> + <var-decl name='__align' type-id='95e97e5e' visibility='default'/> + </data-member> + </union-decl> + <typedef-decl name='pthread_mutexattr_t' type-id='7300eb00' id='8afd6070'/> <pointer-type-def type-id='e4957c49' size-in-bits='64' id='924bbc81'/> <qualified-type-def type-id='924bbc81' const='yes' id='5499dcde'/> <pointer-type-def type-id='5499dcde' size-in-bits='64' id='2236d41c'/> @@ -9685,6 +9718,8 @@ <pointer-type-def type-id='a3681dea' size-in-bits='64' id='fce6d540'/> <qualified-type-def type-id='e4957c49' const='yes' id='fced9da2'/> <pointer-type-def type-id='fced9da2' size-in-bits='64' id='b20efd18'/> + <qualified-type-def type-id='8afd6070' const='yes' id='1d853360'/> + <pointer-type-def type-id='1d853360' size-in-bits='64' id='c2afbd7e'/> <pointer-type-def type-id='7a842a6b' size-in-bits='64' id='07ee4a58'/> <pointer-type-def type-id='8a70a786' size-in-bits='64' id='5507783b'/> <pointer-type-def type-id='b1e62775' size-in-bits='64' id='f095e320'/> @@ -9701,10 +9736,13 @@ <function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'> <return type-id='b59d7dce'/> </function-decl> - <function-decl name='posix_memalign' visibility='default' binding='global' size-in-bits='64'> - <parameter type-id='63e171df'/> - <parameter type-id='b59d7dce'/> - <parameter type-id='b59d7dce'/> + <function-decl name='pthread_mutex_init' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='18c91f9e'/> + <parameter type-id='c2afbd7e'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-decl name='pthread_mutex_destroy' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='18c91f9e'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='sysconf' visibility='default' binding='global' size-in-bits='64'> @@ -9833,6 +9871,7 @@ <function-decl name='zpool_dump_ddt' mangled-name='zpool_dump_ddt' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_dump_ddt'> <parameter type-id='dfe59052' name='dds_total'/> <parameter type-id='932720f8' name='ddh'/> + <parameter type-id='c19b74c3' name='parsable'/> <return type-id='48b5725f'/> </function-decl> <function-decl name='fsleep' mangled-name='fsleep' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fsleep'> @@ -10641,4 +10680,238 @@ <return type-id='24f95ba5'/> </function-decl> </abi-instr> + <abi-instr address-size='64' path='module/zfs/btree.c' language='LANG_C99'> + <typedef-decl name='kmem_cache_t' type-id='2a49bcee' id='5cd0fe54'/> + <typedef-decl name='umem_constructor_t' type-id='7e872986' id='da6072ac'/> + <typedef-decl name='umem_destructor_t' type-id='c039af2e' id='19c23f45'/> + <typedef-decl name='umem_reclaim_t' type-id='c5c76c9c' id='f1a257c7'/> + <class-decl name='umem_cache' size-in-bits='768' is-struct='yes' visibility='default' id='e066f130'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='cache_name' type-id='16dc656a' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='256'> + <var-decl name='cache_bufsize' type-id='b59d7dce' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='320'> + <var-decl name='cache_align' type-id='b59d7dce' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='384'> + <var-decl name='cache_constructor' type-id='91f51f89' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='448'> + <var-decl name='cache_destructor' type-id='9cb5182c' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='512'> + <var-decl name='cache_reclaim' type-id='fbdc58f8' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='576'> + <var-decl name='cache_private' type-id='eaa32e2f' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='640'> + <var-decl name='cache_arena' type-id='eaa32e2f' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='704'> + <var-decl name='cache_cflags' type-id='95e97e5e' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='umem_cache_t' type-id='e066f130' id='2a49bcee'/> + <pointer-type-def type-id='5cd0fe54' size-in-bits='64' id='23bd1729'/> + <pointer-type-def type-id='da6072ac' size-in-bits='64' id='91f51f89'/> + <pointer-type-def type-id='19c23f45' size-in-bits='64' id='9cb5182c'/> + <pointer-type-def type-id='f1a257c7' size-in-bits='64' id='fbdc58f8'/> + <var-decl name='zfs_btree_leaf_cache' type-id='23bd1729' visibility='default'/> + <function-decl name='posix_memalign' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='63e171df'/> + <parameter type-id='b59d7dce'/> + <parameter type-id='b59d7dce'/> + <return type-id='95e97e5e'/> + </function-decl> + <function-type size-in-bits='64' id='7e872986'> + <parameter type-id='eaa32e2f'/> + <parameter type-id='eaa32e2f'/> + <parameter type-id='95e97e5e'/> + <return type-id='95e97e5e'/> + </function-type> + <function-type size-in-bits='64' id='c039af2e'> + <parameter type-id='eaa32e2f'/> + <parameter type-id='eaa32e2f'/> + <return type-id='48b5725f'/> + </function-type> + </abi-instr> + <abi-instr address-size='64' path='module/zfs/range_tree.c' language='LANG_C99'> + <array-type-def dimensions='1' type-id='b96825af' size-in-bits='infinite' id='048fe7bc'> + <subrange length='infinite' type-id='7359adad' id='031f2035'/> + </array-type-def> + <array-type-def dimensions='1' type-id='4dc107b1' size-in-bits='8128' id='017d5779'> + <subrange length='127' type-id='7359adad' id='5ed08de5'/> + </array-type-def> + <class-decl name='zfs_btree_hdr' size-in-bits='128' is-struct='yes' visibility='default' id='fc907d62'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='bth_parent' type-id='0cafbda7' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='bth_first' type-id='8f92235e' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='96'> + <var-decl name='bth_count' type-id='8f92235e' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='zfs_btree_hdr_t' type-id='fc907d62' id='336228ae'/> + <class-decl name='zfs_btree_core' size-in-bits='8256' is-struct='yes' visibility='default' id='c2a40bdf'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='btc_hdr' type-id='336228ae' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='128'> + <var-decl name='btc_children' type-id='017d5779' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='8256'> + <var-decl name='btc_elems' type-id='048fe7bc' visibility='default'/> + </data-member> + </class-decl> + <class-decl name='zfs_btree_leaf' size-in-bits='128' is-struct='yes' visibility='default' id='15b0aea0'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='btl_hdr' type-id='336228ae' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='128'> + <var-decl name='btl_elems' type-id='048fe7bc' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='zfs_btree_leaf_t' type-id='15b0aea0' id='b685aaea'/> + <class-decl name='zfs_btree_index' size-in-bits='128' is-struct='yes' visibility='default' id='378b800c'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='bti_node' type-id='4dc107b1' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='bti_offset' type-id='8f92235e' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='96'> + <var-decl name='bti_before' type-id='c19b74c3' visibility='default'/> + </data-member> + </class-decl> + <typedef-decl name='zfs_btree_index_t' type-id='378b800c' id='a481467c'/> + <typedef-decl name='zfs_btree_t' type-id='a0c8756d' id='aa8d6647'/> + <typedef-decl name='bt_find_in_buf_f' type-id='d12cb521' id='f3d91629'/> + <class-decl name='btree' size-in-bits='576' is-struct='yes' visibility='default' id='a0c8756d'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='bt_compar' type-id='585e1de9' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='bt_find_in_buf' type-id='f3d91629' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='128'> + <var-decl name='bt_elem_size' type-id='b59d7dce' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='192'> + <var-decl name='bt_leaf_size' type-id='b59d7dce' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='256'> + <var-decl name='bt_leaf_cap' type-id='8f92235e' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='288'> + <var-decl name='bt_height' type-id='3ff5601b' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='320'> + <var-decl name='bt_num_elems' type-id='9c313c2d' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='384'> + <var-decl name='bt_num_nodes' type-id='9c313c2d' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='448'> + <var-decl name='bt_root' type-id='4dc107b1' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='512'> + <var-decl name='bt_bulk' type-id='a37f572b' visibility='default'/> + </data-member> + </class-decl> + <qualified-type-def type-id='a481467c' const='yes' id='2e014c8c'/> + <pointer-type-def type-id='2e014c8c' size-in-bits='64' id='120ba952'/> + <pointer-type-def type-id='2273bcd5' size-in-bits='64' id='d12cb521'/> + <pointer-type-def type-id='c2a40bdf' size-in-bits='64' id='0cafbda7'/> + <pointer-type-def type-id='336228ae' size-in-bits='64' id='4dc107b1'/> + <pointer-type-def type-id='a481467c' size-in-bits='64' id='b79742cf'/> + <pointer-type-def type-id='b79742cf' size-in-bits='64' id='e81e4e7f'/> + <pointer-type-def type-id='b685aaea' size-in-bits='64' id='a37f572b'/> + <pointer-type-def type-id='aa8d6647' size-in-bits='64' id='5c16a66a'/> + <function-decl name='zfs_btree_create' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='585e1de9'/> + <parameter type-id='f3d91629'/> + <parameter type-id='b59d7dce'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_btree_find' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='eaa32e2f'/> + <parameter type-id='b79742cf'/> + <return type-id='eaa32e2f'/> + </function-decl> + <function-decl name='zfs_btree_add_idx' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='eaa32e2f'/> + <parameter type-id='120ba952'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_btree_first' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='b79742cf'/> + <return type-id='eaa32e2f'/> + </function-decl> + <function-decl name='zfs_btree_last' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='b79742cf'/> + <return type-id='eaa32e2f'/> + </function-decl> + <function-decl name='zfs_btree_next' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='120ba952'/> + <parameter type-id='b79742cf'/> + <return type-id='eaa32e2f'/> + </function-decl> + <function-decl name='zfs_btree_prev' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='120ba952'/> + <parameter type-id='b79742cf'/> + <return type-id='eaa32e2f'/> + </function-decl> + <function-decl name='zfs_btree_add' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='eaa32e2f'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_btree_remove' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='eaa32e2f'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_btree_remove_idx' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='b79742cf'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_btree_numnodes' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <return type-id='ee1f298e'/> + </function-decl> + <function-decl name='zfs_btree_destroy_nodes' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <parameter type-id='e81e4e7f'/> + <return type-id='eaa32e2f'/> + </function-decl> + <function-decl name='zfs_btree_clear' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <return type-id='48b5725f'/> + </function-decl> + <function-decl name='zfs_btree_destroy' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='5c16a66a'/> + <return type-id='48b5725f'/> + </function-decl> + <function-type size-in-bits='64' id='2273bcd5'> + <parameter type-id='5c16a66a'/> + <parameter type-id='ae3e8ca6'/> + <parameter type-id='8f92235e'/> + <parameter type-id='eaa32e2f'/> + <parameter type-id='b79742cf'/> + <return type-id='eaa32e2f'/> + </function-type> + </abi-instr> </abi-corpus> diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c index b9b76e0bdb8a..bf276a3aa916 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c @@ -806,190 +806,6 @@ zfs_close(zfs_handle_t *zhp) free(zhp); } -typedef struct mnttab_node { - struct mnttab mtn_mt; - avl_node_t mtn_node; -} mnttab_node_t; - -static int -libzfs_mnttab_cache_compare(const void *arg1, const void *arg2) -{ - const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1; - const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2; - int rv; - - rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special); - - return (TREE_ISIGN(rv)); -} - -void -libzfs_mnttab_init(libzfs_handle_t *hdl) -{ - pthread_mutex_init(&hdl->libzfs_mnttab_cache_lock, NULL); - assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0); - avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare, - sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node)); -} - -static int -libzfs_mnttab_update(libzfs_handle_t *hdl) -{ - FILE *mnttab; - struct mnttab entry; - - if ((mnttab = fopen(MNTTAB, "re")) == NULL) - return (ENOENT); - - while (getmntent(mnttab, &entry) == 0) { - mnttab_node_t *mtn; - avl_index_t where; - - if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) - continue; - - mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); - mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special); - mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp); - mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype); - mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts); - - /* Exclude duplicate mounts */ - if (avl_find(&hdl->libzfs_mnttab_cache, mtn, &where) != NULL) { - free(mtn->mtn_mt.mnt_special); - free(mtn->mtn_mt.mnt_mountp); - free(mtn->mtn_mt.mnt_fstype); - free(mtn->mtn_mt.mnt_mntopts); - free(mtn); - continue; - } - - avl_add(&hdl->libzfs_mnttab_cache, mtn); - } - - (void) fclose(mnttab); - return (0); -} - -void -libzfs_mnttab_fini(libzfs_handle_t *hdl) -{ - void *cookie = NULL; - mnttab_node_t *mtn; - - while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) - != NULL) { - free(mtn->mtn_mt.mnt_special); - free(mtn->mtn_mt.mnt_mountp); - free(mtn->mtn_mt.mnt_fstype); - free(mtn->mtn_mt.mnt_mntopts); - free(mtn); - } - avl_destroy(&hdl->libzfs_mnttab_cache); - (void) pthread_mutex_destroy(&hdl->libzfs_mnttab_cache_lock); -} - -void -libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable) -{ - hdl->libzfs_mnttab_enable = enable; -} - -int -libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname, - struct mnttab *entry) -{ - FILE *mnttab; - mnttab_node_t find; - mnttab_node_t *mtn; - int ret = ENOENT; - - if (!hdl->libzfs_mnttab_enable) { - struct mnttab srch = { 0 }; - - if (avl_numnodes(&hdl->libzfs_mnttab_cache)) - libzfs_mnttab_fini(hdl); - - if ((mnttab = fopen(MNTTAB, "re")) == NULL) - return (ENOENT); - - srch.mnt_special = (char *)fsname; - srch.mnt_fstype = (char *)MNTTYPE_ZFS; - ret = getmntany(mnttab, entry, &srch) ? ENOENT : 0; - (void) fclose(mnttab); - return (ret); - } - - pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock); - if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) { - int error; - - if ((error = libzfs_mnttab_update(hdl)) != 0) { - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); - return (error); - } - } - - find.mtn_mt.mnt_special = (char *)fsname; - mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL); - if (mtn) { - *entry = mtn->mtn_mt; - ret = 0; - } - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); - return (ret); -} - -void -libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special, - const char *mountp, const char *mntopts) -{ - mnttab_node_t *mtn; - - pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock); - if (avl_numnodes(&hdl->libzfs_mnttab_cache) != 0) { - mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); - mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special); - mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp); - mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS); - mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts); - /* - * Another thread may have already added this entry - * via libzfs_mnttab_update. If so we should skip it. - */ - if (avl_find(&hdl->libzfs_mnttab_cache, mtn, NULL) != NULL) { - free(mtn->mtn_mt.mnt_special); - free(mtn->mtn_mt.mnt_mountp); - free(mtn->mtn_mt.mnt_fstype); - free(mtn->mtn_mt.mnt_mntopts); - free(mtn); - } else { - avl_add(&hdl->libzfs_mnttab_cache, mtn); - } - } - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); -} - -void -libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname) -{ - mnttab_node_t find; - mnttab_node_t *ret; - - pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock); - find.mtn_mt.mnt_special = (char *)fsname; - if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) - != NULL) { - avl_remove(&hdl->libzfs_mnttab_cache, ret); - free(ret->mtn_mt.mnt_special); - free(ret->mtn_mt.mnt_mountp); - free(ret->mtn_mt.mnt_fstype); - free(ret->mtn_mt.mnt_mntopts); - free(ret); - } - pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock); -} - int zfs_spa_version(zfs_handle_t *zhp, int *spa_version) { @@ -1701,26 +1517,6 @@ zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl) return (1); } -static boolean_t -zfs_is_namespace_prop(zfs_prop_t prop) -{ - switch (prop) { - - case ZFS_PROP_ATIME: - case ZFS_PROP_RELATIME: - case ZFS_PROP_DEVICES: - case ZFS_PROP_EXEC: - case ZFS_PROP_SETUID: - case ZFS_PROP_READONLY: - case ZFS_PROP_XATTR: - case ZFS_PROP_NBMAND: - return (B_TRUE); - - default: - return (B_FALSE); - } -} - /* * Given a property name and value, set the property for the given dataset. */ @@ -1778,7 +1574,7 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags) int nvl_len = 0; int added_resv = 0; zfs_prop_t prop; - boolean_t nsprop = B_FALSE; + uint32_t nspflags = 0; nvpair_t *elem; (void) snprintf(errbuf, sizeof (errbuf), @@ -1825,7 +1621,7 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags) elem = nvlist_next_nvpair(nvl, elem)) { prop = zfs_name_to_prop(nvpair_name(elem)); - nsprop |= zfs_is_namespace_prop(prop); + nspflags |= zfs_namespace_prop_flag(prop); assert(cl_idx < nvl_len); /* @@ -1926,8 +1722,8 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags) * if one of the options handled by the generic * Linux namespace layer has been modified. */ - if (nsprop && zfs_is_mounted(zhp, NULL)) - ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0); + if (nspflags && zfs_is_mounted(zhp, NULL)) + ret = zfs_mount_setattr(zhp, nspflags); } } @@ -2049,7 +1845,8 @@ zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received) */ if (zfs_is_namespace_prop(prop) && zfs_is_mounted(zhp, NULL)) - ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0); + ret = zfs_mount_setattr(zhp, + zfs_namespace_prop_flag(prop)); } error: @@ -3600,7 +3397,8 @@ zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types) * Fail if the initial prefixlen-ancestor does not already exist. */ int -create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) +create_parents(libzfs_handle_t *hdl, char *target, int prefixlen, + nvlist_t *props) { zfs_handle_t *h; char *cp; @@ -3636,8 +3434,7 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) continue; } - if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, - NULL) != 0) { + if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, props) != 0) { opname = dgettext(TEXT_DOMAIN, "create"); goto ancestorerr; } @@ -3676,6 +3473,17 @@ ancestorerr: int zfs_create_ancestors(libzfs_handle_t *hdl, const char *path) { + return (zfs_create_ancestors_props(hdl, path, NULL)); +} + +/* + * Creates non-existing ancestors of the given path, applying extra + * properties provided in an nvlist. + */ +int +zfs_create_ancestors_props(libzfs_handle_t *hdl, const char *path, + nvlist_t *props) +{ int prefix; char *path_copy; char errbuf[ERRBUFLEN]; @@ -3698,7 +3506,7 @@ zfs_create_ancestors(libzfs_handle_t *hdl, const char *path) return (-1); if ((path_copy = strdup(path)) != NULL) { - rc = create_parents(hdl, path_copy, prefix); + rc = create_parents(hdl, path_copy, prefix, props); free(path_copy); } if (path_copy == NULL || rc != 0) diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c index 5f50bce531f7..8e71dfa450b1 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c @@ -821,10 +821,10 @@ zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap, (void) close(pipefd[1]); (void) pthread_join(tid, NULL); + teardown_differ_info(&di); if (di.zerr != 0) { zfs_error_aux(zhp->zfs_hdl, "%s", zfs_strerror(di.zerr)); return (zfs_error(zhp->zfs_hdl, EZFS_DIFF, di.errbuf)); } - teardown_differ_info(&di); return (0); } diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h b/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h index ef0524099a31..2ce8d49f08bc 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h @@ -34,6 +34,7 @@ #include <sys/nvpair.h> #include <sys/dmu.h> #include <sys/zfs_ioctl.h> +#include <sys/mutex.h> #include <regex.h> #include <libzfs.h> @@ -57,21 +58,14 @@ struct libzfs_handle { char libzfs_action[1024]; char libzfs_desc[1024]; int libzfs_printerr; - boolean_t libzfs_mnttab_enable; - /* - * We need a lock to handle the case where parallel mount - * threads are populating the mnttab cache simultaneously. The - * lock only protects the integrity of the avl tree, and does - * not protect the contents of the mnttab entries themselves. - */ - pthread_mutex_t libzfs_mnttab_cache_lock; - avl_tree_t libzfs_mnttab_cache; int libzfs_pool_iter; boolean_t libzfs_prop_debug; regex_t libzfs_urire; uint64_t libzfs_max_nvlist; void *libfetch; char *libfetch_load_error; + kmutex_t zh_mnttab_lock; + avl_tree_t zh_mnttab; }; struct zfs_handle { @@ -90,6 +84,19 @@ struct zfs_handle { }; /* + * Internal namespace property flags for selective remount via + * mount_setattr(2). Passed to zfs_mount_setattr(). + */ +#define ZFS_MNT_PROP_ATIME (1U << 0) +#define ZFS_MNT_PROP_RELATIME (1U << 1) +#define ZFS_MNT_PROP_DEVICES (1U << 2) +#define ZFS_MNT_PROP_EXEC (1U << 3) +#define ZFS_MNT_PROP_SETUID (1U << 4) +#define ZFS_MNT_PROP_READONLY (1U << 5) +#define ZFS_MNT_PROP_XATTR (1U << 6) +#define ZFS_MNT_PROP_NBMAND (1U << 7) + +/* * This is different from checking zfs_type, because it will also catch * snapshots of volumes. */ @@ -181,8 +188,12 @@ extern prop_changelist_t *changelist_gather(zfs_handle_t *, zfs_prop_t, int, extern int changelist_unshare(prop_changelist_t *, const enum sa_protocol *); extern int changelist_haszonedchild(prop_changelist_t *); +extern boolean_t zfs_is_namespace_prop(zfs_prop_t); +extern uint32_t zfs_namespace_prop_flag(zfs_prop_t); +extern boolean_t zfs_is_mountable_internal(zfs_handle_t *); +extern int zfs_mount_setattr(zfs_handle_t *, uint32_t); extern void remove_mountpoint(zfs_handle_t *); -extern int create_parents(libzfs_handle_t *, char *, int); +extern int create_parents(libzfs_handle_t *, char *, int, nvlist_t *); extern zfs_handle_t *make_dataset_handle(libzfs_handle_t *, const char *); extern zfs_handle_t *make_bookmark_handle(zfs_handle_t *, const char *, diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c b/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c new file mode 100644 index 000000000000..473e3a7b45a1 --- /dev/null +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2019 Joyent, Inc. + * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>. + * Copyright (c) 2013 Martin Matuska. All rights reserved. + * Copyright (c) 2013 Steven Hartland. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. + * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> + * Copyright 2017-2018 RackTop Systems. + * Copyright (c) 2019 Datto Inc. + * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com> + * Copyright (c) 2021 Matt Fiddaman + * Copyright (c) 2026, TrueNAS. + */ + +#include <sys/mntent.h> +#include <sys/mutex.h> +#include <libzfs.h> +#include "libzfs_impl.h" + +typedef struct mnttab_node { + struct mnttab mtn_mt; + avl_node_t mtn_node; +} mnttab_node_t; + +static mnttab_node_t * +mnttab_node_alloc(libzfs_handle_t *hdl, const char *special, + const char *mountp, const char *mntopts) +{ + mnttab_node_t *mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); + mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special); + mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp); + mtn->mtn_mt.mnt_fstype = (char *)MNTTYPE_ZFS; + mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts); + return (mtn); +} + +static void +mnttab_node_free(libzfs_handle_t *hdl, mnttab_node_t *mtn) +{ + (void) hdl; + free(mtn->mtn_mt.mnt_special); + free(mtn->mtn_mt.mnt_mountp); + free(mtn->mtn_mt.mnt_mntopts); + free(mtn); +} + +static int +mnttab_compare(const void *arg1, const void *arg2) +{ + const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1; + const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2; + int rv; + + rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special); + + return (TREE_ISIGN(rv)); +} + +void +libzfs_mnttab_init(libzfs_handle_t *hdl) +{ + mutex_init(&hdl->zh_mnttab_lock, NULL, MUTEX_DEFAULT, NULL); + assert(avl_numnodes(&hdl->zh_mnttab) == 0); + avl_create(&hdl->zh_mnttab, mnttab_compare, + sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node)); +} + +void +libzfs_mnttab_fini(libzfs_handle_t *hdl) +{ + void *cookie = NULL; + mnttab_node_t *mtn; + + while ((mtn = avl_destroy_nodes(&hdl->zh_mnttab, &cookie)) + != NULL) + mnttab_node_free(hdl, mtn); + + avl_destroy(&hdl->zh_mnttab); + (void) mutex_destroy(&hdl->zh_mnttab_lock); +} + +void +libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable) +{ + /* This is a no-op to preserve ABI backward compatibility. */ + (void) hdl, (void) enable; +} + +static int +mnttab_update(libzfs_handle_t *hdl) +{ + FILE *mnttab; + struct mnttab entry; + + ASSERT(MUTEX_HELD(&hdl->zh_mnttab_lock)); + + if ((mnttab = fopen(MNTTAB, "re")) == NULL) + return (ENOENT); + + while (getmntent(mnttab, &entry) == 0) { + mnttab_node_t *mtn; + avl_index_t where; + + if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) + continue; + + mtn = mnttab_node_alloc(hdl, entry.mnt_special, + entry.mnt_mountp, entry.mnt_mntopts); + + /* Exclude duplicate mounts */ + if (avl_find(&hdl->zh_mnttab, mtn, &where) != NULL) { + mnttab_node_free(hdl, mtn); + continue; + } + + avl_add(&hdl->zh_mnttab, mtn); + } + + (void) fclose(mnttab); + return (0); +} + +int +libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname, + struct mnttab *entry) +{ + mnttab_node_t find; + mnttab_node_t *mtn; + int ret = ENOENT; + + mutex_enter(&hdl->zh_mnttab_lock); + if (avl_numnodes(&hdl->zh_mnttab) == 0) { + int error; + + if ((error = mnttab_update(hdl)) != 0) { + mutex_exit(&hdl->zh_mnttab_lock); + return (error); + } + } + + find.mtn_mt.mnt_special = (char *)fsname; + mtn = avl_find(&hdl->zh_mnttab, &find, NULL); + if (mtn) { + *entry = mtn->mtn_mt; + ret = 0; + } + mutex_exit(&hdl->zh_mnttab_lock); + return (ret); +} + +void +libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special, + const char *mountp, const char *mntopts) +{ + mnttab_node_t *mtn; + + mutex_enter(&hdl->zh_mnttab_lock); + + mtn = mnttab_node_alloc(hdl, special, mountp, mntopts); + + /* + * Another thread may have already added this entry + * via mnttab_update. If so we should skip it. + */ + if (avl_find(&hdl->zh_mnttab, mtn, NULL) != NULL) + mnttab_node_free(hdl, mtn); + else + avl_add(&hdl->zh_mnttab, mtn); + + mutex_exit(&hdl->zh_mnttab_lock); +} + +void +libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname) +{ + mnttab_node_t find; + mnttab_node_t *ret; + + mutex_enter(&hdl->zh_mnttab_lock); + find.mtn_mt.mnt_special = (char *)fsname; + if ((ret = avl_find(&hdl->zh_mnttab, (void *)&find, NULL)) != NULL) { + avl_remove(&hdl->zh_mnttab, ret); + mnttab_node_free(hdl, ret); + } + mutex_exit(&hdl->zh_mnttab_lock); +} diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c index a6287fbe2785..130f0a2db5a9 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c @@ -103,6 +103,47 @@ zfs_share_protocol_name(enum sa_protocol protocol) return (sa_protocol_names[protocol]); } +/* + * Returns B_TRUE if the property is a namespace property that requires + * a remount to take effect. + */ +boolean_t +zfs_is_namespace_prop(zfs_prop_t prop) +{ + switch (prop) { + case ZFS_PROP_ATIME: + case ZFS_PROP_RELATIME: + case ZFS_PROP_DEVICES: + case ZFS_PROP_EXEC: + case ZFS_PROP_SETUID: + case ZFS_PROP_READONLY: + case ZFS_PROP_XATTR: + case ZFS_PROP_NBMAND: + return (B_TRUE); + default: + return (B_FALSE); + } +} + +/* + * Returns the ZFS_MNT_PROP_* flag for a namespace property. + */ +uint32_t +zfs_namespace_prop_flag(zfs_prop_t prop) +{ + switch (prop) { + case ZFS_PROP_ATIME: return (ZFS_MNT_PROP_ATIME); + case ZFS_PROP_RELATIME: return (ZFS_MNT_PROP_RELATIME); + case ZFS_PROP_DEVICES: return (ZFS_MNT_PROP_DEVICES); + case ZFS_PROP_EXEC: return (ZFS_MNT_PROP_EXEC); + case ZFS_PROP_SETUID: return (ZFS_MNT_PROP_SETUID); + case ZFS_PROP_READONLY: return (ZFS_MNT_PROP_READONLY); + case ZFS_PROP_XATTR: return (ZFS_MNT_PROP_XATTR); + case ZFS_PROP_NBMAND: return (ZFS_MNT_PROP_NBMAND); + default: return (0); + } +} + static boolean_t dir_is_empty_stat(const char *dirname) { @@ -225,7 +266,7 @@ zfs_is_mounted(zfs_handle_t *zhp, char **where) * that the caller has verified the sanity of mounting the dataset at * its mountpoint to the extent the caller wants. */ -static boolean_t +boolean_t zfs_is_mountable_internal(zfs_handle_t *zhp) { if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) && diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c index e12308b01ab1..49d5c3d5910a 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c @@ -370,8 +370,47 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, zfs_fallthrough; case ZPOOL_PROP_SIZE: + case ZPOOL_PROP_NORMAL_SIZE: + case ZPOOL_PROP_SPECIAL_SIZE: + case ZPOOL_PROP_DEDUP_SIZE: + case ZPOOL_PROP_LOG_SIZE: + case ZPOOL_PROP_ELOG_SIZE: + case ZPOOL_PROP_SELOG_SIZE: case ZPOOL_PROP_ALLOCATED: + case ZPOOL_PROP_NORMAL_ALLOCATED: + case ZPOOL_PROP_SPECIAL_ALLOCATED: + case ZPOOL_PROP_DEDUP_ALLOCATED: + case ZPOOL_PROP_LOG_ALLOCATED: + case ZPOOL_PROP_ELOG_ALLOCATED: + case ZPOOL_PROP_SELOG_ALLOCATED: + case ZPOOL_PROP_AVAILABLE: + case ZPOOL_PROP_NORMAL_AVAILABLE: + case ZPOOL_PROP_SPECIAL_AVAILABLE: + case ZPOOL_PROP_DEDUP_AVAILABLE: + case ZPOOL_PROP_LOG_AVAILABLE: + case ZPOOL_PROP_ELOG_AVAILABLE: + case ZPOOL_PROP_SELOG_AVAILABLE: case ZPOOL_PROP_FREE: + case ZPOOL_PROP_NORMAL_FREE: + case ZPOOL_PROP_SPECIAL_FREE: + case ZPOOL_PROP_DEDUP_FREE: + case ZPOOL_PROP_LOG_FREE: + case ZPOOL_PROP_ELOG_FREE: + case ZPOOL_PROP_SELOG_FREE: + case ZPOOL_PROP_USABLE: + case ZPOOL_PROP_NORMAL_USABLE: + case ZPOOL_PROP_SPECIAL_USABLE: + case ZPOOL_PROP_DEDUP_USABLE: + case ZPOOL_PROP_LOG_USABLE: + case ZPOOL_PROP_ELOG_USABLE: + case ZPOOL_PROP_SELOG_USABLE: + case ZPOOL_PROP_USED: + case ZPOOL_PROP_NORMAL_USED: + case ZPOOL_PROP_SPECIAL_USED: + case ZPOOL_PROP_DEDUP_USED: + case ZPOOL_PROP_LOG_USED: + case ZPOOL_PROP_ELOG_USED: + case ZPOOL_PROP_SELOG_USED: case ZPOOL_PROP_FREEING: case ZPOOL_PROP_LEAKED: case ZPOOL_PROP_ASHIFT: @@ -391,6 +430,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, break; case ZPOOL_PROP_EXPANDSZ: + case ZPOOL_PROP_NORMAL_EXPANDSZ: + case ZPOOL_PROP_SPECIAL_EXPANDSZ: + case ZPOOL_PROP_DEDUP_EXPANDSZ: + case ZPOOL_PROP_LOG_EXPANDSZ: + case ZPOOL_PROP_ELOG_EXPANDSZ: + case ZPOOL_PROP_SELOG_EXPANDSZ: case ZPOOL_PROP_CHECKPOINT: if (intval == 0) { (void) strlcpy(buf, "-", len); @@ -403,6 +448,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, break; case ZPOOL_PROP_CAPACITY: + case ZPOOL_PROP_NORMAL_CAPACITY: + case ZPOOL_PROP_SPECIAL_CAPACITY: + case ZPOOL_PROP_DEDUP_CAPACITY: + case ZPOOL_PROP_LOG_CAPACITY: + case ZPOOL_PROP_ELOG_CAPACITY: + case ZPOOL_PROP_SELOG_CAPACITY: if (literal) { (void) snprintf(buf, len, "%llu", (u_longlong_t)intval); @@ -413,7 +464,13 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, break; case ZPOOL_PROP_FRAGMENTATION: - if (intval == UINT64_MAX) { + case ZPOOL_PROP_NORMAL_FRAGMENTATION: + case ZPOOL_PROP_SPECIAL_FRAGMENTATION: + case ZPOOL_PROP_DEDUP_FRAGMENTATION: + case ZPOOL_PROP_LOG_FRAGMENTATION: + case ZPOOL_PROP_ELOG_FRAGMENTATION: + case ZPOOL_PROP_SELOG_FRAGMENTATION: + if (intval == ZFS_FRAG_INVALID) { (void) strlcpy(buf, "-", len); } else if (literal) { (void) snprintf(buf, len, "%llu", @@ -1639,6 +1696,11 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, "one or more devices could not be opened")); return (zfs_error(hdl, EZFS_BADDEV, errbuf)); + case EDOM: + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "block size out of range or does not match")); + return (zfs_error(hdl, EZFS_BADDEV, errbuf)); + default: return (zpool_standard_error(hdl, errno, errbuf)); } @@ -2806,8 +2868,11 @@ zpool_scan_range(zpool_handle_t *zhp, pool_scan_func_t func, nvlist_t *args = fnvlist_alloc(); fnvlist_add_uint64(args, "scan_type", (uint64_t)func); fnvlist_add_uint64(args, "scan_command", (uint64_t)cmd); - fnvlist_add_uint64(args, "scan_date_start", (uint64_t)date_start); - fnvlist_add_uint64(args, "scan_date_end", (uint64_t)date_end); + if (date_start != 0 || date_end != 0) { + fnvlist_add_uint64(args, "scan_date_start", + (uint64_t)date_start); + fnvlist_add_uint64(args, "scan_date_end", (uint64_t)date_end); + } err = lzc_scrub(ZFS_IOC_POOL_SCRUB, zhp->zpool_name, args, NULL); fnvlist_free(args); @@ -4350,7 +4415,8 @@ zpool_clear(zpool_handle_t *zhp, const char *path, nvlist_t *rewindnvl) zc.zc_cookie = policy.zlp_rewind; zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size * 2); - zcmd_write_src_nvlist(hdl, &zc, rewindnvl); + if (rewindnvl != NULL) + zcmd_write_src_nvlist(hdl, &zc, rewindnvl); while ((error = zfs_ioctl(hdl, ZFS_IOC_CLEAR, &zc)) != 0 && errno == ENOMEM) diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c index 0e5cecc6cca9..18130a34fea8 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c @@ -258,7 +258,10 @@ typedef struct send_data { boolean_t seento; boolean_t holds; /* were holds requested with send -h */ boolean_t props; + boolean_t no_preserve_encryption; + snapfilter_cb_t *filter_cb; + void *filter_cb_arg; /* * The header nvlist is of the following format: * { @@ -511,6 +514,10 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg) uint64_t fromsnap_txg_save = sd->fromsnap_txg; uint64_t tosnap_txg_save = sd->tosnap_txg; + if (sd->filter_cb && + (sd->filter_cb(zhp, sd->filter_cb_arg) == 0)) + return (0); + fromsnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->fromsnap); if (fromsnap_txg != 0) sd->fromsnap_txg = fromsnap_txg; @@ -587,20 +594,32 @@ send_iterate_fs(zfs_handle_t *zhp, void *arg) fnvlist_add_boolean(nvfs, "is_encroot"); /* - * Encrypted datasets can only be sent with properties if - * the raw flag is specified because the receive side doesn't - * currently have a mechanism for recursively asking the user - * for new encryption parameters. + * Encrypted datasets can only be sent with properties if the + * raw flag or the no-preserve-encryption flag are specified + * because the receive side doesn't currently have a mechanism + * for recursively asking the user for new encryption + * parameters. + * We allow sending the dataset unencrypted only if the user + * explicitly sets the no-preserve-encryption flag. */ - if (!sd->raw) { + if (!sd->raw && !sd->no_preserve_encryption) { (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "cannot send %s@%s: encrypted dataset %s may not " - "be sent with properties without the raw flag\n"), + "be sent with properties without the raw flag or " + "no-preserve-encryption flag\n"), sd->fsname, sd->tosnap, zhp->zfs_name); rv = -1; goto out; } + /* If no-preserve-encryption flag is set, warn the user again */ + if (!sd->raw && sd->no_preserve_encryption) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "WARNING: no-preserve-encryption flag set, sending " + "dataset %s without encryption\n"), + zhp->zfs_name); + } + } /* @@ -683,8 +702,9 @@ static int gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap, const char *tosnap, boolean_t recursive, boolean_t raw, boolean_t doall, boolean_t replicate, boolean_t skipmissing, boolean_t verbose, - boolean_t backup, boolean_t holds, boolean_t props, nvlist_t **nvlp, - avl_tree_t **avlp) + boolean_t backup, boolean_t holds, boolean_t props, + boolean_t no_preserve_encryption, nvlist_t **nvlp, avl_tree_t **avlp, + snapfilter_cb_t *filter_cb, void *filter_cb_arg) { zfs_handle_t *zhp; send_data_t sd = { 0 }; @@ -707,6 +727,9 @@ gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap, sd.backup = backup; sd.holds = holds; sd.props = props; + sd.no_preserve_encryption = no_preserve_encryption; + sd.filter_cb = filter_cb; + sd.filter_cb_arg = filter_cb_arg; if ((error = send_iterate_fs(zhp, &sd)) != 0) { fnvlist_free(sd.fss); @@ -913,21 +936,8 @@ int zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written, uint64_t *blocks_visited) { - zfs_cmd_t zc = {"\0"}; - - if (bytes_written != NULL) - *bytes_written = 0; - if (blocks_visited != NULL) - *blocks_visited = 0; - (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); - zc.zc_cookie = fd; - if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0) - return (errno); - if (bytes_written != NULL) - *bytes_written = zc.zc_cookie; - if (blocks_visited != NULL) - *blocks_visited = zc.zc_objset_type; - return (0); + return (lzc_send_progress(zhp->zfs_name, fd, bytes_written, + blocks_visited)); } static volatile boolean_t send_progress_thread_signal_duetotimer; @@ -2199,7 +2209,8 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd, boolean_t gather_props, boolean_t recursive, boolean_t verbose, boolean_t dryrun, boolean_t raw, boolean_t replicate, boolean_t skipmissing, boolean_t backup, boolean_t holds, boolean_t props, boolean_t doall, - nvlist_t **fssp, avl_tree_t **fsavlp) + boolean_t no_preserve_encryption, nvlist_t **fssp, avl_tree_t **fsavlp, + snapfilter_cb_t filter_func, void *cb_arg) { int err = 0; char *packbuf = NULL; @@ -2245,7 +2256,8 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd, if (gather_nvlist(zhp->zfs_hdl, tofs, from, tosnap, recursive, raw, doall, replicate, skipmissing, - verbose, backup, holds, props, &fss, fsavlp) != 0) { + verbose, backup, holds, props, no_preserve_encryption, + &fss, fsavlp, filter_func, cb_arg) != 0) { return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP, errbuf)); } @@ -2392,7 +2404,8 @@ zfs_send_cb_impl(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, flags->replicate, flags->verbosity > 0, flags->dryrun, flags->raw, flags->replicate, flags->skipmissing, flags->backup, flags->holds, flags->props, flags->doall, - &fss, &fsavl); + flags->no_preserve_encryption, &fss, &fsavl, + filter_func, cb_arg); zfs_close(tosnap); if (err != 0) goto err_out; @@ -2735,7 +2748,8 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd, err = send_prelim_records(zhp, NULL, fd, B_TRUE, B_FALSE, flags->verbosity > 0, flags->dryrun, flags->raw, flags->replicate, B_FALSE, flags->backup, flags->holds, - flags->props, flags->doall, NULL, NULL); + flags->props, flags->doall, flags->no_preserve_encryption, + NULL, NULL, NULL, NULL); if (err != 0) return (err); } @@ -3392,7 +3406,8 @@ recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *top_zfs, /* Using top_zfs, gather the nvlists for all local filesystems. */ if ((err = gather_nvlist(hdl, top_zfs, NULL, NULL, recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE, - B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0) + B_FALSE, B_TRUE, B_FALSE, &local_nv, &local_avl, + NULL, NULL)) != 0) return (err); /* @@ -3547,7 +3562,8 @@ again: if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL, recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE, - B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0) + B_FALSE, B_TRUE, B_FALSE, &local_nv, &local_avl, + NULL, NULL)) != 0) return (error); /* @@ -4944,7 +4960,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, *cp = '\0'; if (flags->isprefix && !flags->istail && !flags->dryrun && - create_parents(hdl, destsnap, strlen(tosnap)) != 0) { + create_parents(hdl, destsnap, strlen(tosnap), NULL) != 0) { err = zfs_error(hdl, EZFS_BADRESTORE, errbuf); goto out; } @@ -5138,7 +5154,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, *cp = '\0'; if (gather_nvlist(hdl, destsnap, NULL, NULL, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, - B_TRUE, &local_nv, &local_avl) == 0) { + B_TRUE, B_FALSE, &local_nv, &local_avl, + NULL, NULL) == 0) { *cp = '@'; fs = fsavl_find(local_avl, drrb->drr_toguid, NULL); fsavl_destroy(local_avl); diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_util.c b/sys/contrib/openzfs/lib/libzfs/libzfs_util.c index 26f5135dff62..021a1d8a407d 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_util.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_util.c @@ -1171,7 +1171,7 @@ zfs_handle_t * zfs_path_to_zhandle(libzfs_handle_t *hdl, const char *path, zfs_type_t argtype) { struct stat64 statbuf; - struct extmnttab entry; + struct mnttab entry; if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { /* diff --git a/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c b/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c index bc7d68b17eb1..3723769d4e30 100644 --- a/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c +++ b/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c @@ -116,6 +116,17 @@ do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags) return (0); } +/* + * FreeBSD does not support mount_setattr(2). Fall back to a full + * remount so that the updated namespace property takes effect. + */ +int +zfs_mount_setattr(zfs_handle_t *zhp, uint32_t nspflags) +{ + (void) nspflags; + return (zfs_mount(zhp, MNTOPT_REMOUNT, 0)); +} + int zfs_mount_delegation_check(void) { diff --git a/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c b/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c index cdfb432b10ad..7d8768d12dda 100644 --- a/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c +++ b/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c @@ -409,6 +409,149 @@ do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags) return (rc ? EINVAL : 0); } +#ifdef HAVE_MOUNT_SETATTR +/* + * Build a struct mount_attr for the changed namespace properties. + * Parallel to zfs_add_options() but produces mount_setattr(2) input + * instead of a mount options string. + */ +static void +zfs_add_options_setattr(zfs_handle_t *zhp, struct mount_attr *attr, + uint32_t nspflags) +{ + const char *source; + + if (nspflags & ZFS_MNT_PROP_READONLY) { + if (getprop_uint64(zhp, ZFS_PROP_READONLY, &source)) + attr->attr_set |= MOUNT_ATTR_RDONLY; + else + attr->attr_clr |= MOUNT_ATTR_RDONLY; + } + if (nspflags & ZFS_MNT_PROP_EXEC) { + if (getprop_uint64(zhp, ZFS_PROP_EXEC, &source)) + attr->attr_clr |= MOUNT_ATTR_NOEXEC; + else + attr->attr_set |= MOUNT_ATTR_NOEXEC; + } + if (nspflags & ZFS_MNT_PROP_SETUID) { + if (getprop_uint64(zhp, ZFS_PROP_SETUID, &source)) + attr->attr_clr |= MOUNT_ATTR_NOSUID; + else + attr->attr_set |= MOUNT_ATTR_NOSUID; + } + if (nspflags & ZFS_MNT_PROP_DEVICES) { + if (getprop_uint64(zhp, ZFS_PROP_DEVICES, &source)) + attr->attr_clr |= MOUNT_ATTR_NODEV; + else + attr->attr_set |= MOUNT_ATTR_NODEV; + } + if (nspflags & (ZFS_MNT_PROP_ATIME | ZFS_MNT_PROP_RELATIME)) { + uint64_t atime = getprop_uint64(zhp, ZFS_PROP_ATIME, &source); + uint64_t relatime = getprop_uint64(zhp, + ZFS_PROP_RELATIME, &source); + + attr->attr_clr |= MOUNT_ATTR__ATIME; + if (!atime) + attr->attr_set |= MOUNT_ATTR_NOATIME; + else if (relatime) + attr->attr_set |= MOUNT_ATTR_RELATIME; + else + attr->attr_set |= MOUNT_ATTR_STRICTATIME; + } +} +#endif /* HAVE_MOUNT_SETATTR */ + +/* + * Selectively update per-mount VFS flags for the changed namespace + * properties using mount_setattr(2). Unlike a full remount via mount(2), + * this only modifies the specified flags without resetting others -- + * avoiding clobbering temporary mount flags set by the administrator. + * + * For non-legacy datasets, the single known mountpoint is used. + * For legacy datasets, /proc/mounts is iterated since legacy datasets + * can be mounted at multiple locations. + * + * Falls back to a full remount via zfs_mount() when mount_setattr(2) + * is not available (ENOSYS), except for legacy mounts where a full + * remount would clobber temporary flags. + */ +int +zfs_mount_setattr(zfs_handle_t *zhp, uint32_t nspflags) +{ +#ifdef HAVE_MOUNT_SETATTR + struct mount_attr attr = { 0 }; + char mntpt_prop[ZFS_MAXPROPLEN]; + boolean_t legacy = B_FALSE; + libzfs_handle_t *hdl = zhp->zfs_hdl; + FILE *mnttab; + struct mnttab entry; + int ret = 0; + + if (!zfs_is_mountable_internal(zhp)) + return (0); + + zfs_add_options_setattr(zhp, &attr, nspflags); + if (attr.attr_set == 0 && attr.attr_clr == 0) + return (0); + + if (zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type, + B_FALSE)) { + verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mntpt_prop, + sizeof (mntpt_prop), NULL, NULL, 0, B_FALSE) == 0); + legacy = (strcmp(mntpt_prop, ZFS_MOUNTPOINT_LEGACY) == 0); + } + + if (!legacy) { + char *mntpt = NULL; + + if (!zfs_is_mounted(zhp, &mntpt)) + return (0); + + ret = mount_setattr(AT_FDCWD, mntpt, 0, + &attr, sizeof (attr)); + free(mntpt); + if (ret != 0) { + if (errno == ENOSYS) + return (zfs_mount(zhp, MNTOPT_REMOUNT, 0)); + return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, + dgettext(TEXT_DOMAIN, "cannot set mount " + "attributes for '%s'"), zhp->zfs_name)); + } + return (0); + } + + /* Legacy: iterate /proc/mounts for all mountpoints. */ + if ((mnttab = fopen(MNTTAB, "re")) == NULL) + return (0); + + while (getmntent(mnttab, &entry) == 0) { + if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) + continue; + if (strcmp(entry.mnt_special, zhp->zfs_name) != 0) + continue; + + ret = mount_setattr(AT_FDCWD, entry.mnt_mountp, 0, + &attr, sizeof (attr)); + if (ret != 0) { + if (errno == ENOSYS) { + ret = 0; + break; + } + ret = zfs_error_fmt(hdl, EZFS_MOUNTFAILED, + dgettext(TEXT_DOMAIN, "cannot set mount " + "attributes for '%s'"), zhp->zfs_name); + break; + } + } + + (void) fclose(mnttab); + return (ret); +#else + (void) nspflags; + return (zfs_mount(zhp, MNTOPT_REMOUNT, 0)); +#endif +} + int zfs_mount_delegation_check(void) { diff --git a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi index 1cfd2a81dbea..4cd003a718b2 100644 --- a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi +++ b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.abi @@ -147,7 +147,6 @@ <elf-symbol name='get_timestamp' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='getexecname' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='getextmntent' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> - <elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='kmem_asprintf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='kmem_cache_reap_active' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -224,6 +223,7 @@ <elf-symbol name='lzc_rollback_to' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='lzc_scrub' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='lzc_send' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='lzc_send_progress' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='lzc_send_redacted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='lzc_send_resume' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='lzc_send_resume_redacted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -1488,7 +1488,7 @@ <return type-id='7359adad'/> </function-decl> </abi-instr> - <abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'> + <abi-instr address-size='64' path='lib/libspl/os/linux/mnttab.c' language='LANG_C99'> <class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='mnt_special' type-id='26a90f95' visibility='default'/> @@ -1503,26 +1503,6 @@ <var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/> </data-member> </class-decl> - <class-decl name='extmnttab' size-in-bits='320' is-struct='yes' visibility='default' id='0c544dc0'> - <data-member access='public' layout-offset-in-bits='0'> - <var-decl name='mnt_special' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='64'> - <var-decl name='mnt_mountp' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='128'> - <var-decl name='mnt_fstype' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='192'> - <var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='256'> - <var-decl name='mnt_major' type-id='3502e3ff' visibility='default'/> - </data-member> - <data-member access='public' layout-offset-in-bits='288'> - <var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/> - </data-member> - </class-decl> <class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'> <data-member access='public' layout-offset-in-bits='0'> <var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/> @@ -1592,7 +1572,6 @@ </class-decl> <typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/> <typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/> - <pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/> <pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/> <qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/> <pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/> @@ -1618,12 +1597,6 @@ <parameter type-id='f1cadedf'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='getmntany' mangled-name='getmntany' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getmntany'> - <parameter type-id='822cd80b' name='fp'/> - <parameter type-id='9d424d31' name='mgetp'/> - <parameter type-id='9d424d31' name='mrefp'/> - <return type-id='95e97e5e'/> - </function-decl> <function-decl name='_sol_getmntent' mangled-name='_sol_getmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='_sol_getmntent'> <parameter type-id='822cd80b' name='fp'/> <parameter type-id='9d424d31' name='mgetp'/> @@ -1631,7 +1604,7 @@ </function-decl> <function-decl name='getextmntent' mangled-name='getextmntent' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getextmntent'> <parameter type-id='80f4b756' name='path'/> - <parameter type-id='394fc496' name='entry'/> + <parameter type-id='9d424d31' name='entry'/> <parameter type-id='62f7a03d' name='statbuf'/> <return type-id='95e97e5e'/> </function-decl> @@ -4004,6 +3977,13 @@ <parameter type-id='5d6479ae' name='spacep'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='lzc_send_progress' mangled-name='lzc_send_progress' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_send_progress'> + <parameter type-id='80f4b756' name='snapname'/> + <parameter type-id='95e97e5e' name='fd'/> + <parameter type-id='5d6479ae' name='bytes_written'/> + <parameter type-id='5d6479ae' name='blocks_visited'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='lzc_receive' mangled-name='lzc_receive' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzc_receive'> <parameter type-id='80f4b756' name='snapname'/> <parameter type-id='5ce45b60' name='props'/> diff --git a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.c b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.c index 9347aa7c6a28..c6cd62e76c51 100644 --- a/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.c +++ b/sys/contrib/openzfs/lib/libzfs_core/libzfs_core.c @@ -1016,6 +1016,39 @@ lzc_send_space(const char *snapname, const char *from, NULL, -1, spacep)); } +/* + * Query the progress of a send stream identified by the snapshot name and + * the file descriptor the stream is being written to. + * + * snapname name of the snapshot being sent + * fd file descriptor of the active send stream + * bytes_written on success, set to the number of bytes sent so far + * blocks_visited on success, set to the number of logical blocks traversed + * + * Returns 0 on success. Returns ENOENT if no send stream matching the + * snapshot name and file descriptor was found in the current process. + */ +int +lzc_send_progress(const char *snapname, int fd, uint64_t *bytes_written, + uint64_t *blocks_visited) +{ + zfs_cmd_t zc = {"\0"}; + + if (bytes_written != NULL) + *bytes_written = 0; + if (blocks_visited != NULL) + *blocks_visited = 0; + (void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name)); + zc.zc_cookie = fd; + if (lzc_ioctl_fd(g_fd, ZFS_IOC_SEND_PROGRESS, &zc) != 0) + return (errno); + if (bytes_written != NULL) + *bytes_written = zc.zc_cookie; + if (blocks_visited != NULL) + *blocks_visited = zc.zc_objset_type; + return (0); +} + static int recv_read(int fd, void *buf, int ilen) { diff --git a/sys/contrib/openzfs/lib/libzpool/Makefile.am b/sys/contrib/openzfs/lib/libzpool/Makefile.am index f8f1282683bb..8192553072fc 100644 --- a/sys/contrib/openzfs/lib/libzpool/Makefile.am +++ b/sys/contrib/openzfs/lib/libzpool/Makefile.am @@ -16,6 +16,7 @@ dist_libzpool_la_SOURCES = \ %D%/kernel.c \ %D%/util.c \ %D%/vdev_label_os.c \ + %D%/zfs_file_os.c \ %D%/zfs_racct.c \ %D%/zfs_debug.c diff --git a/sys/contrib/openzfs/lib/libzpool/kernel.c b/sys/contrib/openzfs/lib/libzpool/kernel.c index 197e0d1782e2..e132d50a5c6f 100644 --- a/sys/contrib/openzfs/lib/libzpool/kernel.c +++ b/sys/contrib/openzfs/lib/libzpool/kernel.c @@ -62,9 +62,6 @@ uint32_t hostid; -/* If set, all blocks read will be copied to the specified directory. */ -char *vn_dumpdir = NULL; - uint32_t zone_get_hostid(void *zonep) { @@ -495,391 +492,6 @@ zvol_rename_minors(spa_t *spa, const char *oldname, const char *newname, (void) spa, (void) oldname, (void) newname, (void) async; } -/* - * Open file - * - * path - fully qualified path to file - * flags - file attributes O_READ / O_WRITE / O_EXCL - * fpp - pointer to return file pointer - * - * Returns 0 on success underlying error on failure. - */ -int -zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp) -{ - int fd; - int dump_fd; - int err; - int old_umask = 0; - zfs_file_t *fp; - struct stat64 st; - - if (!(flags & O_CREAT) && stat64(path, &st) == -1) - return (errno); - - if (!(flags & O_CREAT) && S_ISBLK(st.st_mode)) - flags |= O_DIRECT; - - if (flags & O_CREAT) - old_umask = umask(0); - - fd = open64(path, flags, mode); - if (fd == -1) - return (errno); - - if (flags & O_CREAT) - (void) umask(old_umask); - - if (vn_dumpdir != NULL) { - char *dumppath = umem_zalloc(MAXPATHLEN, UMEM_NOFAIL); - const char *inpath = zfs_basename(path); - - (void) snprintf(dumppath, MAXPATHLEN, - "%s/%s", vn_dumpdir, inpath); - dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666); - umem_free(dumppath, MAXPATHLEN); - if (dump_fd == -1) { - err = errno; - close(fd); - return (err); - } - } else { - dump_fd = -1; - } - - (void) fcntl(fd, F_SETFD, FD_CLOEXEC); - - fp = umem_zalloc(sizeof (zfs_file_t), UMEM_NOFAIL); - fp->f_fd = fd; - fp->f_dump_fd = dump_fd; - *fpp = fp; - - return (0); -} - -void -zfs_file_close(zfs_file_t *fp) -{ - close(fp->f_fd); - if (fp->f_dump_fd != -1) - close(fp->f_dump_fd); - - umem_free(fp, sizeof (zfs_file_t)); -} - -/* - * Stateful write - use os internal file pointer to determine where to - * write and update on successful completion. - * - * fp - pointer to file (pipe, socket, etc) to write to - * buf - buffer to write - * count - # of bytes to write - * resid - pointer to count of unwritten bytes (if short write) - * - * Returns 0 on success errno on failure. - */ -int -zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid) -{ - ssize_t rc; - - rc = write(fp->f_fd, buf, count); - if (rc < 0) - return (errno); - - if (resid) { - *resid = count - rc; - } else if (rc != count) { - return (EIO); - } - - return (0); -} - -/* - * Stateless write - os internal file pointer is not updated. - * - * fp - pointer to file (pipe, socket, etc) to write to - * buf - buffer to write - * count - # of bytes to write - * off - file offset to write to (only valid for seekable types) - * resid - pointer to count of unwritten bytes - * - * Returns 0 on success errno on failure. - */ -int -zfs_file_pwrite(zfs_file_t *fp, const void *buf, - size_t count, loff_t pos, uint8_t ashift, ssize_t *resid) -{ - ssize_t rc, split, done; - int sectors; - - /* - * To simulate partial disk writes, we split writes into two - * system calls so that the process can be killed in between. - * This is used by ztest to simulate realistic failure modes. - */ - sectors = count >> ashift; - split = (sectors > 0 ? rand() % sectors : 0) << ashift; - rc = pwrite64(fp->f_fd, buf, split, pos); - if (rc != -1) { - done = rc; - rc = pwrite64(fp->f_fd, (char *)buf + split, - count - split, pos + split); - } -#ifdef __linux__ - if (rc == -1 && errno == EINVAL) { - /* - * Under Linux, this most likely means an alignment issue - * (memory or disk) due to O_DIRECT, so we abort() in order - * to catch the offender. - */ - abort(); - } -#endif - - if (rc < 0) - return (errno); - - done += rc; - - if (resid) { - *resid = count - done; - } else if (done != count) { - return (EIO); - } - - return (0); -} - -/* - * Stateful read - use os internal file pointer to determine where to - * read and update on successful completion. - * - * fp - pointer to file (pipe, socket, etc) to read from - * buf - buffer to write - * count - # of bytes to read - * resid - pointer to count of unread bytes (if short read) - * - * Returns 0 on success errno on failure. - */ -int -zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid) -{ - int rc; - - rc = read(fp->f_fd, buf, count); - if (rc < 0) - return (errno); - - if (resid) { - *resid = count - rc; - } else if (rc != count) { - return (EIO); - } - - return (0); -} - -/* - * Stateless read - os internal file pointer is not updated. - * - * fp - pointer to file (pipe, socket, etc) to read from - * buf - buffer to write - * count - # of bytes to write - * off - file offset to read from (only valid for seekable types) - * resid - pointer to count of unwritten bytes (if short write) - * - * Returns 0 on success errno on failure. - */ -int -zfs_file_pread(zfs_file_t *fp, void *buf, size_t count, loff_t off, - ssize_t *resid) -{ - ssize_t rc; - - rc = pread64(fp->f_fd, buf, count, off); - if (rc < 0) { -#ifdef __linux__ - /* - * Under Linux, this most likely means an alignment issue - * (memory or disk) due to O_DIRECT, so we abort() in order to - * catch the offender. - */ - if (errno == EINVAL) - abort(); -#endif - return (errno); - } - - if (fp->f_dump_fd != -1) { - int status; - - status = pwrite64(fp->f_dump_fd, buf, rc, off); - ASSERT(status != -1); - } - - if (resid) { - *resid = count - rc; - } else if (rc != count) { - return (EIO); - } - - return (0); -} - -/* - * lseek - set / get file pointer - * - * fp - pointer to file (pipe, socket, etc) to read from - * offp - value to seek to, returns current value plus passed offset - * whence - see man pages for standard lseek whence values - * - * Returns 0 on success errno on failure (ESPIPE for non seekable types) - */ -int -zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence) -{ - loff_t rc; - - rc = lseek(fp->f_fd, *offp, whence); - if (rc < 0) - return (errno); - - *offp = rc; - - return (0); -} - -/* - * Get file attributes - * - * filp - file pointer - * zfattr - pointer to file attr structure - * - * Currently only used for fetching size and file mode - * - * Returns 0 on success or error code of underlying getattr call on failure. - */ -int -zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr) -{ - struct stat64 st; - - if (fstat64_blk(fp->f_fd, &st) == -1) - return (errno); - - zfattr->zfa_size = st.st_size; - zfattr->zfa_mode = st.st_mode; - - return (0); -} - -/* - * Sync file to disk - * - * filp - file pointer - * flags - O_SYNC and or O_DSYNC - * - * Returns 0 on success or error code of underlying sync call on failure. - */ -int -zfs_file_fsync(zfs_file_t *fp, int flags) -{ - (void) flags; - - if (fsync(fp->f_fd) < 0) - return (errno); - - return (0); -} - -/* - * deallocate - zero and/or deallocate file storage - * - * fp - file pointer - * offset - offset to start zeroing or deallocating - * len - length to zero or deallocate - */ -int -zfs_file_deallocate(zfs_file_t *fp, loff_t offset, loff_t len) -{ - int rc; -#if defined(__linux__) - rc = fallocate(fp->f_fd, - FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, len); -#elif defined(__FreeBSD__) && (__FreeBSD_version >= 1400029) - struct spacectl_range rqsr = { - .r_offset = offset, - .r_len = len, - }; - rc = fspacectl(fp->f_fd, SPACECTL_DEALLOC, &rqsr, 0, &rqsr); -#else - (void) fp, (void) offset, (void) len; - rc = EOPNOTSUPP; -#endif - if (rc) - return (SET_ERROR(rc)); - return (0); -} - -/* - * Request current file pointer offset - * - * fp - pointer to file - * - * Returns current file offset. - */ -loff_t -zfs_file_off(zfs_file_t *fp) -{ - return (lseek(fp->f_fd, SEEK_CUR, 0)); -} - -/* - * unlink file - * - * path - fully qualified file path - * - * Returns 0 on success. - * - * OPTIONAL - */ -int -zfs_file_unlink(const char *path) -{ - return (remove(path)); -} - -/* - * Get reference to file pointer - * - * fd - input file descriptor - * - * Returns pointer to file struct or NULL. - * Unsupported in user space. - */ -zfs_file_t * -zfs_file_get(int fd) -{ - (void) fd; - abort(); - return (NULL); -} -/* - * Drop reference to file pointer - * - * fp - pointer to file struct - * - * Unsupported in user space. - */ -void -zfs_file_put(zfs_file_t *fp) -{ - abort(); - (void) fp; -} - void zfsvfs_update_fromname(const char *oldname, const char *newname) { diff --git a/sys/contrib/openzfs/lib/libzpool/zfs_file_os.c b/sys/contrib/openzfs/lib/libzpool/zfs_file_os.c new file mode 100644 index 000000000000..7a15e496386a --- /dev/null +++ b/sys/contrib/openzfs/lib/libzpool/zfs_file_os.c @@ -0,0 +1,420 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. + * Copyright (c) 2016 Actifio, Inc. All rights reserved. + * Copyright (c) 2025, Klara, Inc. + */ + +#include <sys/zfs_context.h> +#include <sys/zfs_file.h> +#include <libzpool.h> +#include <libzutil.h> + +/* If set, all blocks read will be copied to the specified directory. */ +char *vn_dumpdir = NULL; + +/* + * Open file + * + * path - fully qualified path to file + * flags - file attributes O_READ / O_WRITE / O_EXCL + * fpp - pointer to return file pointer + * + * Returns 0 on success underlying error on failure. + */ +int +zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp) +{ + int fd; + int dump_fd; + int err; + int old_umask = 0; + zfs_file_t *fp; + struct stat64 st; + + if (!(flags & O_CREAT) && stat64(path, &st) == -1) + return (errno); + + if (!(flags & O_CREAT) && S_ISBLK(st.st_mode)) + flags |= O_DIRECT; + + if (flags & O_CREAT) + old_umask = umask(0); + + fd = open64(path, flags, mode); + if (fd == -1) + return (errno); + + if (flags & O_CREAT) + (void) umask(old_umask); + + if (vn_dumpdir != NULL) { + char *dumppath = umem_zalloc(MAXPATHLEN, UMEM_NOFAIL); + const char *inpath = zfs_basename(path); + + (void) snprintf(dumppath, MAXPATHLEN, + "%s/%s", vn_dumpdir, inpath); + dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666); + umem_free(dumppath, MAXPATHLEN); + if (dump_fd == -1) { + err = errno; + close(fd); + return (err); + } + } else { + dump_fd = -1; + } + + (void) fcntl(fd, F_SETFD, FD_CLOEXEC); + + fp = umem_zalloc(sizeof (zfs_file_t), UMEM_NOFAIL); + fp->f_fd = fd; + fp->f_dump_fd = dump_fd; + *fpp = fp; + + return (0); +} + +void +zfs_file_close(zfs_file_t *fp) +{ + close(fp->f_fd); + if (fp->f_dump_fd != -1) + close(fp->f_dump_fd); + + umem_free(fp, sizeof (zfs_file_t)); +} + +/* + * Stateful write - use os internal file pointer to determine where to + * write and update on successful completion. + * + * fp - pointer to file (pipe, socket, etc) to write to + * buf - buffer to write + * count - # of bytes to write + * resid - pointer to count of unwritten bytes (if short write) + * + * Returns 0 on success errno on failure. + */ +int +zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid) +{ + ssize_t rc; + + rc = write(fp->f_fd, buf, count); + if (rc < 0) + return (errno); + + if (resid) { + *resid = count - rc; + } else if (rc != count) { + return (EIO); + } + + return (0); +} + +/* + * Stateless write - os internal file pointer is not updated. + * + * fp - pointer to file (pipe, socket, etc) to write to + * buf - buffer to write + * count - # of bytes to write + * off - file offset to write to (only valid for seekable types) + * resid - pointer to count of unwritten bytes + * + * Returns 0 on success errno on failure. + */ +int +zfs_file_pwrite(zfs_file_t *fp, const void *buf, + size_t count, loff_t pos, uint8_t ashift, ssize_t *resid) +{ + ssize_t rc, split, done; + int sectors; + + /* + * To simulate partial disk writes, we split writes into two + * system calls so that the process can be killed in between. + * This is used by ztest to simulate realistic failure modes. + */ + sectors = count >> ashift; + split = (sectors > 0 ? rand() % sectors : 0) << ashift; + rc = pwrite64(fp->f_fd, buf, split, pos); + if (rc != -1) { + done = rc; + rc = pwrite64(fp->f_fd, (char *)buf + split, + count - split, pos + split); + } +#ifdef __linux__ + if (rc == -1 && errno == EINVAL) { + /* + * Under Linux, this most likely means an alignment issue + * (memory or disk) due to O_DIRECT, so we abort() in order + * to catch the offender. + */ + abort(); + } +#endif + + if (rc < 0) + return (errno); + + done += rc; + + if (resid) { + *resid = count - done; + } else if (done != count) { + return (EIO); + } + + return (0); +} + +/* + * Stateful read - use os internal file pointer to determine where to + * read and update on successful completion. + * + * fp - pointer to file (pipe, socket, etc) to read from + * buf - buffer to write + * count - # of bytes to read + * resid - pointer to count of unread bytes (if short read) + * + * Returns 0 on success errno on failure. + */ +int +zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid) +{ + int rc; + + rc = read(fp->f_fd, buf, count); + if (rc < 0) + return (errno); + + if (resid) { + *resid = count - rc; + } else if (rc != count) { + return (EIO); + } + + return (0); +} + +/* + * Stateless read - os internal file pointer is not updated. + * + * fp - pointer to file (pipe, socket, etc) to read from + * buf - buffer to write + * count - # of bytes to write + * off - file offset to read from (only valid for seekable types) + * resid - pointer to count of unwritten bytes (if short write) + * + * Returns 0 on success errno on failure. + */ +int +zfs_file_pread(zfs_file_t *fp, void *buf, size_t count, loff_t off, + ssize_t *resid) +{ + ssize_t rc; + + rc = pread64(fp->f_fd, buf, count, off); + if (rc < 0) { +#ifdef __linux__ + /* + * Under Linux, this most likely means an alignment issue + * (memory or disk) due to O_DIRECT, so we abort() in order to + * catch the offender. + */ + if (errno == EINVAL) + abort(); +#endif + return (errno); + } + + if (fp->f_dump_fd != -1) { + int status; + + status = pwrite64(fp->f_dump_fd, buf, rc, off); + ASSERT(status != -1); + } + + if (resid) { + *resid = count - rc; + } else if (rc != count) { + return (EIO); + } + + return (0); +} + +/* + * lseek - set / get file pointer + * + * fp - pointer to file (pipe, socket, etc) to read from + * offp - value to seek to, returns current value plus passed offset + * whence - see man pages for standard lseek whence values + * + * Returns 0 on success errno on failure (ESPIPE for non seekable types) + */ +int +zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence) +{ + loff_t rc; + + rc = lseek(fp->f_fd, *offp, whence); + if (rc < 0) + return (errno); + + *offp = rc; + + return (0); +} + +/* + * Get file attributes + * + * filp - file pointer + * zfattr - pointer to file attr structure + * + * Currently only used for fetching size and file mode + * + * Returns 0 on success or error code of underlying getattr call on failure. + */ +int +zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr) +{ + struct stat64 st; + + if (fstat64_blk(fp->f_fd, &st) == -1) + return (errno); + + zfattr->zfa_size = st.st_size; + zfattr->zfa_mode = st.st_mode; + + return (0); +} + +/* + * Sync file to disk + * + * filp - file pointer + * flags - O_SYNC and or O_DSYNC + * + * Returns 0 on success or error code of underlying sync call on failure. + */ +int +zfs_file_fsync(zfs_file_t *fp, int flags) +{ + (void) flags; + + if (fsync(fp->f_fd) < 0) + return (errno); + + return (0); +} + +/* + * deallocate - zero and/or deallocate file storage + * + * fp - file pointer + * offset - offset to start zeroing or deallocating + * len - length to zero or deallocate + */ +int +zfs_file_deallocate(zfs_file_t *fp, loff_t offset, loff_t len) +{ + int rc; +#if defined(__linux__) + rc = fallocate(fp->f_fd, + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, len); +#elif defined(__FreeBSD__) && (__FreeBSD_version >= 1400029) + struct spacectl_range rqsr = { + .r_offset = offset, + .r_len = len, + }; + rc = fspacectl(fp->f_fd, SPACECTL_DEALLOC, &rqsr, 0, &rqsr); +#else + (void) fp, (void) offset, (void) len; + rc = EOPNOTSUPP; +#endif + if (rc) + return (SET_ERROR(rc)); + return (0); +} + +/* + * Request current file pointer offset + * + * fp - pointer to file + * + * Returns current file offset. + */ +loff_t +zfs_file_off(zfs_file_t *fp) +{ + return (lseek(fp->f_fd, SEEK_CUR, 0)); +} + +/* + * unlink file + * + * path - fully qualified file path + * + * Returns 0 on success. + * + * OPTIONAL + */ +int +zfs_file_unlink(const char *path) +{ + return (remove(path)); +} + +/* + * Get reference to file pointer + * + * fd - input file descriptor + * + * Returns pointer to file struct or NULL. + * Unsupported in user space. + */ +zfs_file_t * +zfs_file_get(int fd) +{ + (void) fd; + abort(); + return (NULL); +} +/* + * Drop reference to file pointer + * + * fp - pointer to file struct + * + * Unsupported in user space. + */ +void +zfs_file_put(zfs_file_t *fp) +{ + abort(); + (void) fp; +} diff --git a/sys/contrib/openzfs/lib/libzutil/zutil_pool.c b/sys/contrib/openzfs/lib/libzutil/zutil_pool.c index 2aacfa53b5e0..4d52be7ce090 100644 --- a/sys/contrib/openzfs/lib/libzutil/zutil_pool.c +++ b/sys/contrib/openzfs/lib/libzutil/zutil_pool.c @@ -34,11 +34,16 @@ #include <libzutil.h> static void -dump_ddt_stat(const ddt_stat_t *dds, int h) +dump_ddt_stat(const ddt_stat_t *dds, int h, boolean_t parsable) { - char refcnt[6]; - char blocks[6], lsize[6], psize[6], dsize[6]; - char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6]; + char refcnt[32]; + char blocks[32], lsize[32], psize[32], dsize[32]; + char ref_blocks[32], ref_lsize[32], ref_psize[32], ref_dsize[32]; + + enum zfs_nicenum_format count_format = parsable ? + ZFS_NICENUM_RAW : ZFS_NICENUM_1024; + enum zfs_nicenum_format byte_format = parsable ? + ZFS_NICENUM_RAW : ZFS_NICENUM_BYTES; if (dds == NULL || dds->dds_blocks == 0) return; @@ -46,16 +51,26 @@ dump_ddt_stat(const ddt_stat_t *dds, int h) if (h == -1) (void) strcpy(refcnt, "Total"); else - zfs_nicenum(1ULL << h, refcnt, sizeof (refcnt)); - - zfs_nicenum(dds->dds_blocks, blocks, sizeof (blocks)); - zfs_nicebytes(dds->dds_lsize, lsize, sizeof (lsize)); - zfs_nicebytes(dds->dds_psize, psize, sizeof (psize)); - zfs_nicebytes(dds->dds_dsize, dsize, sizeof (dsize)); - zfs_nicenum(dds->dds_ref_blocks, ref_blocks, sizeof (ref_blocks)); - zfs_nicebytes(dds->dds_ref_lsize, ref_lsize, sizeof (ref_lsize)); - zfs_nicebytes(dds->dds_ref_psize, ref_psize, sizeof (ref_psize)); - zfs_nicebytes(dds->dds_ref_dsize, ref_dsize, sizeof (ref_dsize)); + zfs_nicenum_format(1ULL << h, refcnt, sizeof (refcnt), + count_format); + + + zfs_nicenum_format(dds->dds_blocks, blocks, sizeof (blocks), + count_format); + zfs_nicenum_format(dds->dds_lsize, lsize, sizeof (lsize), + byte_format); + zfs_nicenum_format(dds->dds_psize, psize, sizeof (psize), + byte_format); + zfs_nicenum_format(dds->dds_dsize, dsize, sizeof (dsize), + byte_format); + zfs_nicenum_format(dds->dds_ref_blocks, ref_blocks, + sizeof (ref_blocks), count_format); + zfs_nicenum_format(dds->dds_ref_lsize, ref_lsize, + sizeof (ref_lsize), byte_format); + zfs_nicenum_format(dds->dds_ref_psize, ref_psize, + sizeof (ref_psize), byte_format); + zfs_nicenum_format(dds->dds_ref_dsize, ref_dsize, + sizeof (ref_dsize), byte_format); (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n", refcnt, @@ -67,7 +82,8 @@ dump_ddt_stat(const ddt_stat_t *dds, int h) * Print the DDT histogram and the column totals. */ void -zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh) +zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh, + boolean_t parsable) { int h; @@ -91,9 +107,9 @@ zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh) "------", "-----", "-----", "-----"); for (h = 0; h < 64; h++) - dump_ddt_stat(&ddh->ddh_stat[h], h); + dump_ddt_stat(&ddh->ddh_stat[h], h, parsable); - dump_ddt_stat(dds_total, -1); + dump_ddt_stat(dds_total, -1, parsable); (void) printf("\n"); } diff --git a/sys/contrib/openzfs/man/Makefile.am b/sys/contrib/openzfs/man/Makefile.am index ae7b707152ec..5eb7fd95d3c8 100644 --- a/sys/contrib/openzfs/man/Makefile.am +++ b/sys/contrib/openzfs/man/Makefile.am @@ -3,6 +3,8 @@ dist_noinst_man_MANS = \ %D%/man1/cstyle.1 dist_man_MANS = \ + %D%/man1/zilstat.1 \ + %D%/man1/zarcsummary.1 \ %D%/man1/zarcstat.1 \ %D%/man1/raidz_test.1 \ %D%/man1/test-runner.1 \ diff --git a/sys/contrib/openzfs/man/man1/zarcsummary.1 b/sys/contrib/openzfs/man/man1/zarcsummary.1 new file mode 100644 index 000000000000..6574417b4b67 --- /dev/null +++ b/sys/contrib/openzfs/man/man1/zarcsummary.1 @@ -0,0 +1,179 @@ +.\" SPDX-License-Identifier: CDDL-1.0 +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" Copyright (c) 2026 Christos Longros. All rights reserved. +.\" +.Dd March 14, 2026 +.Dt ZARCSUMMARY 1 +.Os +. +.Sh NAME +.Nm zarcsummary +.Nd print ZFS ARC and subsystem statistics +.Sh SYNOPSIS +.Nm +.Op Fl adghr +.Op Fl p Ar page +.Op Fl s Ar section +. +.Sh DESCRIPTION +.Nm +collects statistics from the running kernel and prints a human-readable +report on the state of the ZFS Adaptive Replacement Cache +.Pq ARC +and several related subsystems. +The output is a snapshot; for periodic sampling, use +.Xr zarcstat 1 +instead. +.Pp +When invoked without arguments, +.Nm +prints all sections in sequence. +A single section may be selected with the +.Fl s +option. +.Pp +The report is organized into the following sections: +.Bl -tag -offset Ds -width "tunables" +.It Sy arc +Current and target ARC sizes, the split between the Most Recently Used +.Pq MRU +and Most Frequently Used +.Pq MFU +lists, overall hit and miss ratios, compression savings, and whether the +ARC is experiencing memory pressure. +.It Sy archits +Breakdown of ARC hits and misses by demand reads versus prefetches +and data versus metadata. +.It Sy dmu +Data Management Unit predictive prefetcher statistics, including stream +hits, misses, and I/O issued ahead of and behind the current stream. +.It Sy l2arc +Level-2 ARC statistics for any cache devices attached to imported pools. +This section only appears when an L2ARC device is present and covers +bytes read and written, hit rates, and eviction activity. +.It Sy spl +Solaris Porting Layer memory allocator statistics. +This section is only available on Linux. +.It Sy tunables +Current values of kernel tunables that govern ARC behavior, including +.Va zfs_arc_max +and +.Va zfs_arc_min . +Combining this section with +.Fl d +adds a brief explanation of each tunable. +.It Sy zil +ZFS Intent Log statistics: committed transaction counts, flush requests +to stable storage, and the byte-level split between normal vdevs and +any separate log +.Pq SLOG +device. +.El +. +.Sh OPTIONS +.Bl -tag -width "-s" +.It Fl a , -alternate +Use an alternate layout for the tunables and SPL sections. +.It Fl d , -description +Print a short description next to each tunable and SPL entry. +.It Fl h , -help +Display a help message. +.It Fl g , -graph +Print an ASCII graph of current ARC use and exit. +.It Fl p Ar page , Fl -page Ar page +Print a section by its legacy page number. +.Sy Deprecated ; +use +.Fl s +instead. +.It Fl r , -raw +Dump all available data with minimal formatting. +.It Fl s Ar section , Fl -section Ar section +Print only the named section. +See +.Sx DESCRIPTION +for the list of valid section names. +.El +. +.Sh ENVIRONMENT +.Bl -tag -width "FreeBSD" +.It Sy Linux +Statistics are read from +.Pa /proc/spl/kstat/zfs/ . +.It Fx +Statistics are read via +.Xr sysctl 3 +from the +.Va vfs.zfs +and +.Va kstat.zfs.misc +trees. +The +.Pa py-sysctl +package must be installed for +.Nm +to function. +.El +. +.Sh EXIT STATUS +.Ex -std +. +.Sh EXAMPLES +Print the full report: +.Dl # zarcsummary +.Pp +Display only ARC size and hit rate information: +.Dl # zarcsummary -s arc +.Pp +Show a visual overview of ARC health: +.Dl # zarcsummary -g +.Pp +Search for all statistics containing +.Dq hit : +.Dl # zarcsummary -r | grep hit +.Pp +Review all tunables with their descriptions: +.Dl # zarcsummary -d -s tunables +. +.Sh SEE ALSO +.Xr zarcstat 1 , +.Xr zpool-status 8 +. +.Sh HISTORY +.Nm +originated as a Perl script called +.Nm arc_summary , +written by +.An Ben Rockwood +in 2008 for Solaris. +.An Martin Matuska +ported it to +.Fx +in 2010, and +.An Jason J. Hellenthal +took over maintenance. +.An Scot W. Stevenson +contributed a full rewrite in Python 3 in 2017, introducing the +.Fl g , +.Fl r , +and +.Fl s +options along with the section-based output layout. +The tool was renamed from +.Nm arc_summary +to +.Nm zarcsummary +in 2025 to align with the OpenZFS command naming convention. +. +.Sh AUTHORS +This manual page was written by +.An Christos Longros Aq Mt chris.longros@gmail.com . diff --git a/sys/contrib/openzfs/man/man1/zilstat.1 b/sys/contrib/openzfs/man/man1/zilstat.1 new file mode 100644 index 000000000000..320a6b64676e --- /dev/null +++ b/sys/contrib/openzfs/man/man1/zilstat.1 @@ -0,0 +1,191 @@ +.\" SPDX-License-Identifier: CDDL-1.0 +.\" +.\" CDDL HEADER START +.\" +.\" The contents of this file are subject to the terms of the +.\" Common Development and Distribution License, Version 1.0 only +.\" (the "License"). You may not use this file except in compliance +.\" with the License. +.\" +.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +.\" or https://opensource.org/licenses/CDDL-1.0. +.\" See the License for the specific language governing permissions +.\" and limitations under the License. +.\" +.\" When distributing Covered Code, include this CDDL HEADER in each +.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE. +.\" If applicable, add the following below this CDDL HEADER, with the +.\" fields enclosed by brackets "[]" replaced with your own identifying +.\" information: Portions Copyright [yyyy] [name of copyright owner] +.\" +.\" CDDL HEADER END +.\" +.\" Copyright (c) 2026 Christos Longros. All rights reserved. +.\" +.Dd March 9, 2026 +.Dt ZILSTAT 1 +.Os +. +.Sh NAME +.Nm zilstat +.Nd report ZFS Intent Log statistics +.Sh SYNOPSIS +.Nm +.Op Fl v +.Op Fl a Ns | Ns Fl p Ar pool Ns | Ns Fl d Ar dataset Ns Op , Ns Ar dataset Ns … +.Op Fl f Ar field Ns Op , Ns Ar field Ns … +.Op Fl s Ar separator +.Op Fl i Ar interval +. +.Sh DESCRIPTION +.Nm +prints statistics about the ZFS Intent Log (ZIL). +The ZIL is used to log synchronous write operations and is replayed on +pool import if the system crashes before those writes are committed to +the main pool. +.Pp +By default, global ZIL statistics are displayed. +When a pool or dataset is specified, per-dataset statistics are shown +instead. +.Pp +If an +.Ar interval +is specified, the output is repeated every +.Ar interval +seconds showing the change in values since the previous sample. +Without an interval, cumulative values are displayed. +.Pp +The following fields are available: +.Bl -tag -compact -offset Ds -width "imnw" +.It Sy time +Current time +.It Sy pool +Pool name +.It Sy ds +Dataset name +.It Sy obj +Objset ID +.It Sy cc +Commit count +.It Sy cwc +Commit writer count +.It Sy cec +Commit error count +.It Sy csc +Commit stall count +.It Sy cSc +Commit suspend count +.It Sy cCc +Commit crash count +.It Sy ic +In-transaction count +.It Sy iic +Indirect in-transaction count +.It Sy iib +Indirect in-transaction bytes +.It Sy icc +Copied in-transaction count +.It Sy icb +Copied in-transaction bytes +.It Sy inc +Needcopy in-transaction count +.It Sy inb +Needcopy in-transaction bytes +.It Sy idc +Direct (copied + needcopy) count +.It Sy idb +Direct (copied + needcopy) bytes +.It Sy iwc +Total write (indirect + direct) count +.It Sy iwb +Total write (indirect + direct) bytes +.It Sy imnc +Normal metaslab count +.It Sy imnb +Normal metaslab bytes +.It Sy imnw +Normal metaslab write bytes +.It Sy imna +Normal metaslab alloc bytes +.It Sy imsc +SLOG metaslab count +.It Sy imsb +SLOG metaslab bytes +.It Sy imsw +SLOG metaslab write bytes +.It Sy imsa +SLOG metaslab alloc bytes +.It Sy imc +Total metaslab (normal + SLOG) count +.It Sy imb +Total metaslab (normal + SLOG) bytes +.It Sy imw +Total metaslab (normal + SLOG) write bytes +.It Sy ima +Total metaslab (normal + SLOG) alloc bytes +.It Sy se% +Space efficiency percentage (bytes / alloc) +.It Sy sen% +Normal space efficiency percentage +.It Sy ses% +SLOG space efficiency percentage +.It Sy te% +Total efficiency percentage (bytes / write) +.It Sy ten% +Normal total efficiency percentage +.It Sy tes% +SLOG total efficiency percentage +.El +. +.Sh OPTIONS +.Bl -tag -width "-s" +.It Fl h +Display a help message. +.It Fl a +Print statistics for all datasets across all pools. +.It Fl d Ar dataset +Print statistics for the specified dataset(s). +Multiple datasets may be given as a comma-separated list. +.It Fl f Ar field +Display only the specified fields. +Multiple fields may be given as a comma-separated list. +See +.Sx DESCRIPTION +for available fields. +.It Fl i Ar interval +Print statistics every +.Ar interval +seconds. +Values are reported as rates per second. +.It Fl p Ar pool +Print statistics for all datasets in the specified pool. +.It Fl s Ar separator +Override the default field separator +.Pq two spaces +with a custom string. +.It Fl v +List all available field headers and their definitions. +.El +. +.Sh ENVIRONMENT +.Bl -tag -width "Linux" +.It Sy Linux +Statistics are read from +.Pa /proc/spl/kstat/zfs/zil +for global stats and from per-pool objset files under +.Pa /proc/spl/kstat/zfs/ Ns Ar pool Ns Pa / . +.It Sy FreeBSD +Statistics are read via +.Xr sysctl 8 +from the +.Sy kstat.zfs +tree. +.El +. +.Sh SEE ALSO +.Xr zarcstat 1 , +.Xr zpool-status 8 +. +.Sh AUTHORS +This manual page was written by +.An Christos Longros Aq Mt chris.longros@gmail.com . diff --git a/sys/contrib/openzfs/man/man4/zfs.4 b/sys/contrib/openzfs/man/man4/zfs.4 index 97c0ac6ab3e3..5ec9d045ed0d 100644 --- a/sys/contrib/openzfs/man/man4/zfs.4 +++ b/sys/contrib/openzfs/man/man4/zfs.4 @@ -108,12 +108,14 @@ and only applicable in related situations. Seconds between L2ARC writing. . .It Sy l2arc_headroom Ns = Ns Sy 8 Pq u64 -How far through the ARC lists to search for L2ARC cacheable content, +How far through the ARC lists to search for L2ARC cacheable content per cycle, expressed as a multiplier of the effective write size. -ARC persistence across reboots can be achieved with persistent L2ARC -by setting this parameter to -.Sy 0 , -allowing the full length of ARC lists to be searched for cacheable content. +Setting to +.Sy 0 +disables the per-cycle headroom limit. +Scan depth is also bounded by +.Sy l2arc_ext_headroom_pct +when persistent markers are active. . .It Sy l2arc_headroom_boost Ns = Ns Sy 200 Ns % Pq u64 Scales @@ -227,6 +229,19 @@ to enable caching/reading prefetches to/from L2ARC. .It Sy l2arc_norw Ns = Ns Sy 0 Ns | Ns 1 Pq int No reads during writes. . +.It Sy l2arc_ext_headroom_pct Ns = Ns Sy 25 Pq u64 +Percentage of each ARC state's size that a pass may scan before +resetting its markers to the tail. +Lower values keep the marker closer to the tail under active workloads. +Set to 0 to disable the depth cap. +. +.It Sy l2arc_meta_cycles Ns = Ns Sy 2 Pq u64 +How many consecutive cycles metadata may monopolize the write budget +before being skipped to let data run. +The default of 2 gives metadata roughly 67% and data 33% of L2ARC +write bandwidth under sustained load. +Higher values favor metadata; set to 0 to disable. +. .It Sy l2arc_write_max Ns = Ns Sy 33554432 Ns B Po 32 MiB Pc Pq u64 Maximum write rate in bytes per second for each L2ARC device. Used directly during initial fill, when DWPD limiting is disabled, diff --git a/sys/contrib/openzfs/man/man7/zpoolconcepts.7 b/sys/contrib/openzfs/man/man7/zpoolconcepts.7 index 07b78dda2396..1571bc6b8b76 100644 --- a/sys/contrib/openzfs/man/man7/zpoolconcepts.7 +++ b/sys/contrib/openzfs/man/man7/zpoolconcepts.7 @@ -430,19 +430,15 @@ is updated even if no metadata structures are written. L2ARC operates in one of two modes depending on total cache capacity. When total L2ARC capacity is less than twice .Sy arc_c_max , -L2ARC uses exclusive caching, -writing buffers to cache as they are evicted from ARC. +L2ARC writes buffers to cache as they are evicted from ARC. When total capacity is at least twice .Sy arc_c_max , -L2ARC switches to inclusive caching with persistent markers -that track scan positions, -attempting to duplicate ARC contents as much as write throughput allows. -Setting -.Sy l2arc_headroom Ns = Ns Sy 0 -will result in scanning the full-length ARC lists for cacheable content to be -written in L2ARC (persistent ARC). -In inclusive mode, markers progress toward the head across iterations, -naturally covering the full list. +L2ARC uses persistent markers that track scan positions across iterations, +writing cacheable content as write throughput allows. +A depth cap +.Pq Sy l2arc_ext_headroom_pct +limits how far markers advance from the tail, keeping them focused on +buffers soon to be evicted where caching adds the most value. .Pp If a cache device is added with .Nm zpool Cm add , diff --git a/sys/contrib/openzfs/man/man7/zpoolprops.7 b/sys/contrib/openzfs/man/man7/zpoolprops.7 index 3836ec764b34..c383805ac090 100644 --- a/sys/contrib/openzfs/man/man7/zpoolprops.7 +++ b/sys/contrib/openzfs/man/man7/zpoolprops.7 @@ -27,9 +27,9 @@ .\" Copyright 2017 Nexenta Systems, Inc. .\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved. .\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org> -.\" Copyright (c) 2023, Klara Inc. +.\" Copyright (c) 2023, 2026, Klara Inc. .\" -.Dd December 4, 2024 +.Dd March 2, 2026 .Dt ZPOOLPROPS 7 .Os . @@ -49,7 +49,7 @@ For more information about user properties, see the section. .Pp The following are read-only properties: -.Bl -tag -width "unsupported@guid" +.Bl -tag -width "last_scrubbed_txg" .It Sy allocated Amount of storage used within the pool. See @@ -57,6 +57,21 @@ See and .Sy free for more information. +.It Sy available +The amount of free space available in the pool, adjusted for raidz parity +overhead. +The +.Sy available +property is calculated as: +.Pp +.Sy usable - used +.Pp +See +.Sy usable , +.Sy used , +and +.Sy free +for more information. .It Sy bcloneratio The ratio of the total amount of storage that would be required to store all the cloned blocks without cloning to the actual storage used. @@ -184,6 +199,21 @@ Information about unsupported features that are enabled on the pool. See .Xr zpool-features 7 for details. +.It Sy usable +Estimate of total storage pool size, adjusted for raidz parity overhead. +The adjustment assumes a fixed 128KiB record size to compute a data-to-parity +ratio. +.Sy usable +is a heuristic for allocation and should not be interpreted as an exact measure +of usable space. +.It Sy used +Estimate of storage used within the storage pool, adjusted for raidz parity +overhead. +The adjustment assumes a fixed 128KiB record size to compute a data-to-parity +ratio. +.Sy used +is a heuristic for allocation and should not be interpreted as an exact measure +of used space. .El .Pp The space usage properties report actual physical space available to the @@ -201,6 +231,121 @@ For non-full pools of a reasonable size, these effects should be invisible. For small pools, or pools that are close to being completely full, these discrepancies may become more noticeable. .Pp +The following properties are read-only metrics for allocation classes: +.Bl -ohang +.It Xo Sy class_dedup_allocated , class_dedup_available , class_dedup_capacity , +.Sy class_dedup_expandsize , class_dedup_fragmentation , class_dedup_free , +.Sy class_dedup_size , class_dedup_usable , class_dedup_used +.Xc +.Bd -ragged -offset Ds -compact +Space usage properties of the pool's +.Sy dedup +metaslab allocator class. +.Ed +.It Xo Sy class_elog_allocated , class_elog_available , class_elog_capacity , +.Sy class_elog_expandsize , class_elog_fragmentation , class_elog_free , +.Sy class_elog_size , class_elog_usable , class_elog_used +.Xc +.Bd -ragged -offset Ds -compact +Space usage properties of the pool's +.Sy embedded_log +metaslab allocator class. +.Ed +.It Xo Sy class_log_allocated , class_log_available , class_log_capacity , +.Sy class_log_expandsize , class_log_fragmentation , class_log_free , +.Sy class_log_size , class_log_usable , class_log_used +.Xc +.Bd -ragged -offset Ds -compact +Space usage properties of the pool's +.Sy log +metaslab allocator class. +.Ed +.It Xo Sy class_normal_allocated , class_normal_available , +.Sy class_normal_capacity , class_normal_expandsize , +.Sy class_normal_fragmentation , class_normal_free , class_normal_size , +.Sy class_normal_usable , class_normal_used +.Xc +.Bd -ragged -offset Ds -compact +Space usage properties of the pool's +.Sy normal +metaslab allocator class. +.Ed +.It Xo Sy class_special_allocated , class_special_available , +.Sy class_special_capacity , class_special_expandsize , +.Sy class_special_fragmentation , class_special_free , class_special_size , +.Sy class_special_usable , class_special_used +.Xc +.Bd -ragged -offset Ds -compact +Space usage properties of the pool's +.Sy special +metaslab allocator class. +.Ed +.It Xo Sy class_special_elog_allocated , class_special_elog_available , +.Sy class_special_elog_capacity , class_special_elog_expandsize , +.Sy class_special_elog_fragmentation , class_special_elog_free , +.Sy class_special_elog_size , class_special_elog_usable , +.Sy class_special_elog_used +.Xc +.Bd -ragged -offset Ds -compact +Space usage properties of the pool's +.Sy special_embedded_log +metaslab allocator class. +.Ed +.El +.Pp +Each allocation class is described by these values: +.Bl -tag -width "fragmentation" +.It Sy allocated +Amount of storage used within the allocation class. +.It Sy available +Estimate of free space available in the allocation class, adjusted for raidz +parity overhead. +The adjustment assumes a fixed 128KiB record size to compute a data-to-parity +ratio. +.Sy available +is a heuristic for allocation and should not be interpreted as an exact measure +of usable space. +Actual usable space depends on a variety of factors such as dataset record size +and compression. +.It Sy capacity +Percentage of allocation class space used. +.It Sy expandsize +Amount of uninitialized space within the allocation class that can be used to +increase the capacity of the allocator. +See the pool-wide +.Sy expandsize +property. +.It Sy fragmentation +The amount of free space fragmentation in the allocation class. +See the pool-wide +.Sy fragmentation +property. +.It Sy free +The amount of free space available in the allocation class. +This value is not adjusted for factors such as dataset record size, compression, +or raidz parity overhead. +See the pool-wide +.Sy free +property. +.It Sy size +Total size of the allocation class. +.It Sy usable +Estimate of total allocation class size, adjusted for raidz parity overhead. +The adjustment assumes a fixed 128KiB record size to compute a data-to-parity +ratio. +.Sy usable +is a heuristic for allocation and should not be interpreted as an exact measure +of usable space. +.It Sy used +Estimate of storage used within the allocation class, adjusted for raidz parity +overhead. +The adjustment assumes a fixed 128KiB record size to compute a data-to-parity +ratio. +.Sy used +is a heuristic for allocation and should not be interpreted as an exact measure +of used space. +.El +.Pp The following property can be set at creation time and import time: .Bl -tag -width Ds .It Sy altroot diff --git a/sys/contrib/openzfs/man/man8/zdb.8 b/sys/contrib/openzfs/man/man8/zdb.8 index 2d1742811fb8..f500e7e8a130 100644 --- a/sys/contrib/openzfs/man/man8/zdb.8 +++ b/sys/contrib/openzfs/man/man8/zdb.8 @@ -282,6 +282,13 @@ Also dump the contents of the deduplication tables describing unique blocks. Decode and display block from an embedded block pointer specified by the .Ar word arguments. +.It Fl f , -file-layout +Display the file layout of an object for the disks of a raidz vdev. +With +.Fl H , +the output is in scripted mode for easy parsing, with all values +being presented as 512 byte blocks. +Only a single top-level raidz vdev is supported. .It Fl h , -history Display pool history similar to .Nm zpool Cm history , diff --git a/sys/contrib/openzfs/man/man8/zfs-clone.8 b/sys/contrib/openzfs/man/man8/zfs-clone.8 index 786b17521688..dc7283fe2d84 100644 --- a/sys/contrib/openzfs/man/man8/zfs-clone.8 +++ b/sys/contrib/openzfs/man/man8/zfs-clone.8 @@ -62,6 +62,10 @@ Creates all the non-existing parent datasets. Datasets created in this manner are automatically mounted according to the .Sy mountpoint property inherited from their parent. +If the +.Fl p +option is specified multiple times, parent datasets are created with +.Sy canmount Ns = Ns Ar off . If the target filesystem or volume already exists, the operation completes successfully. .It Fl u diff --git a/sys/contrib/openzfs/man/man8/zfs-create.8 b/sys/contrib/openzfs/man/man8/zfs-create.8 index b9d013e88d6f..b96a1c94a954 100644 --- a/sys/contrib/openzfs/man/man8/zfs-create.8 +++ b/sys/contrib/openzfs/man/man8/zfs-create.8 @@ -85,6 +85,10 @@ property inherited from their parent. Any property specified on the command line using the .Fl o option is ignored. +If the +.Fl p +option is specified multiple times, parent datasets are created with +.Sy canmount Ns = Ns Ar off . If the target filesystem already exists, the operation completes successfully. .It Fl n Do a dry-run @@ -177,6 +181,10 @@ property inherited from their parent. Any property specified on the command line using the .Fl o option is ignored. +If the +.Fl p +option is specified multiple times, parent datasets are created with +.Sy canmount Ns = Ns Ar off . If the target filesystem already exists, the operation completes successfully. .It Fl s Creates a sparse volume with no reservation. diff --git a/sys/contrib/openzfs/man/man8/zfs-rename.8 b/sys/contrib/openzfs/man/man8/zfs-rename.8 index b32987f191f1..fc9349303f7f 100644 --- a/sys/contrib/openzfs/man/man8/zfs-rename.8 +++ b/sys/contrib/openzfs/man/man8/zfs-rename.8 @@ -103,6 +103,10 @@ Creates all the non-existing parent datasets. Datasets created in this manner are automatically mounted according to the .Sy mountpoint property inherited from their parent. +Alernatively, if the +.Fl p +option is specified multiple times, parent datasets are created with +.Sy canmount Ns = Ns Ar off . .It Fl u Do not remount file systems during rename. If a file system's diff --git a/sys/contrib/openzfs/man/man8/zfs-send.8 b/sys/contrib/openzfs/man/man8/zfs-send.8 index 6c5f6b94afd5..07952e8f4366 100644 --- a/sys/contrib/openzfs/man/man8/zfs-send.8 +++ b/sys/contrib/openzfs/man/man8/zfs-send.8 @@ -31,7 +31,7 @@ .\" Copyright 2019 Joyent, Inc. .\" Copyright (c) 2024, Klara, Inc. .\" -.Dd August 29, 2025 +.Dd February 20, 2026 .Dt ZFS-SEND 8 .Os . @@ -41,13 +41,13 @@ .Sh SYNOPSIS .Nm zfs .Cm send -.Op Fl DLPVbcehnpsvw +.Op Fl DLPUVbcehnpsvw .Op Fl R Op Fl X Ar dataset Ns Oo , Ns Ar dataset Oc Ns … .Op Oo Fl I Ns | Ns Fl i Oc Ar snapshot .Ar snapshot .Nm zfs .Cm send -.Op Fl DLPVcensvw +.Op Fl DLPUVcensvw .Op Fl i Ar snapshot Ns | Ns Ar bookmark .Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot .Nm zfs @@ -75,7 +75,7 @@ .It Xo .Nm zfs .Cm send -.Op Fl DLPVbcehnpsvw +.Op Fl DLPUVbcehnpsvw .Op Fl R Op Fl X Ar dataset Ns Oo , Ns Ar dataset Oc Ns … .Op Oo Fl I Ns | Ns Fl i Oc Ar snapshot .Ar snapshot @@ -146,6 +146,8 @@ If the .Fl R flag is used to send encrypted datasets, then .Fl w +or +.Fl U must also be specified. .It Fl V , -proctitle Set the process title to a per-second report of how much data has been sent. @@ -293,6 +295,8 @@ is specified. The receiving system must also support this feature. Sends of encrypted datasets must use .Fl w +or +.Fl U when using this flag. .It Fl s , -skip-missing Allows sending a replication stream even when there are snapshots missing in the @@ -303,6 +307,11 @@ belongs and its descendants are skipped. This flag can only be used in conjunction with .Fl R . +.It Fl U , -no-preserve-encryption +Allow sending an encrypted dataset with properties, but without keeping +encryption. +When this flag is specified, encrypted datasets that would otherwise be blocked +from sending are sent as unencrypted data. .It Fl v , -verbose Print verbose information about the stream package generated. This information includes a per-second report of how much data has been sent. diff --git a/sys/contrib/openzfs/man/man8/zpool-iostat.8 b/sys/contrib/openzfs/man/man8/zpool-iostat.8 index 5dd9c9d55e20..4abe08950641 100644 --- a/sys/contrib/openzfs/man/man8/zpool-iostat.8 +++ b/sys/contrib/openzfs/man/man8/zpool-iostat.8 @@ -67,8 +67,8 @@ If is specified, the command exits after .Ar count reports are printed. -The first report printed is always the statistics since boot regardless of -whether +The first report printed is always the average per-second +statistics since boot regardless of whether .Ar interval and .Ar count diff --git a/sys/contrib/openzfs/man/man8/zstream.8 b/sys/contrib/openzfs/man/man8/zstream.8 index 5b3d063bc4a5..e38bde33c8b0 100644 --- a/sys/contrib/openzfs/man/man8/zstream.8 +++ b/sys/contrib/openzfs/man/man8/zstream.8 @@ -21,7 +21,7 @@ .\" .\" Copyright (c) 2020 by Delphix. All rights reserved. .\" -.Dd November 10, 2022 +.Dd February 20, 2026 .Dt ZSTREAM 8 .Os . @@ -38,6 +38,10 @@ .Op Fl v .Op Ar object Ns Sy \&, Ns Ar offset Ns Op Sy \&, Ns Ar type Ns ... .Nm +.Cm drop_record +.Op Fl v +.Op Ar object Ns Sy \&, Ns Ar offset Ns Op Sy \& Ns ... +.Nm .Cm redup .Op Fl v .Ar file @@ -127,6 +131,21 @@ Print summary of decompressed records. .El .It Xo .Nm +.Cm drop_record +.Op Fl v +.Op Ar object Ns Sy \&, Ns Ar offset Ns Op Sy \& ... +.Xc +Drop selected records from a ZFS send stream provided on standard input, +specified by object number and byte offset. +Only WRITE and WRITE_EMBEDDED are records are supported, currently. +The repaired stream will be written to standard output. +.Bl -tag -width "-v" +.It Fl v +Verbose. +Print summary of dropped records. +.El +.It Xo +.Nm .Cm redup .Op Fl v .Ar file @@ -178,7 +197,7 @@ non-default level is desired). .El . .Sh EXAMPLES -Heal a dataset that was corrupted due to OpenZFS bug #12762. +.Ss Recovering from OpenZFS bug #12762 First, determine which records are corrupt. That cannot be done automatically; it requires information beyond ZFS's metadata. @@ -193,8 +212,24 @@ then run this command: .No # Nm zfs Ar send Fl c Ar … | Nm zstream decompress Ar 128,0,lz4 | \ Nm zfs recv Ar … .Ed +. +.Ss Recovering from OpenZFS bug #18239 +The bogus records typically have an absurdly large offset, and can be seen with +a command like +.Nm zdb Fl ddddd Ar dataset Ar object +or +.Nm zstream Ar dump Fl v . +To recover, send the dataset and use +.Nm zstream +to drop the bogus record, then receive into a new dataset. +.Bd -literal +.No # Nm zfs Ar send Ar ... | Nm zstream drop_record Ar 3545761,18446744073709486080 | \ +Nm zfs recv Ar ... +.Ed .Sh SEE ALSO +.Xr zdb 8 , .Xr zfs 8 , .Xr zfs-receive 8 , .Xr zfs-send 8 , .Lk https://github.com/openzfs/zfs/issues/12762 +.Lk https://github.com/openzfs/zfs/issues/18239 diff --git a/sys/contrib/openzfs/module/Kbuild.in b/sys/contrib/openzfs/module/Kbuild.in index de093df3d5c7..47e739ea4d69 100644 --- a/sys/contrib/openzfs/module/Kbuild.in +++ b/sys/contrib/openzfs/module/Kbuild.in @@ -11,6 +11,7 @@ zfs_include = @abs_top_srcdir@/include icp_include = @abs_srcdir@/icp/include zstd_include = @abs_srcdir@/zstd/include ZFS_MODULE_CFLAGS += -include @abs_top_builddir@/zfs_config.h +ZFS_MODULE_CFLAGS += -include $(zfs_include)/sys/simd_config.h ZFS_MODULE_CFLAGS += -I@abs_top_builddir@/include src = @abs_srcdir@ obj = @abs_builddir@ @@ -19,6 +20,7 @@ zfs_include = $(srctree)/include/zfs icp_include = $(src)/icp/include zstd_include = $(src)/zstd/include ZFS_MODULE_CFLAGS += -include $(zfs_include)/zfs_config.h +ZFS_MODULE_CFLAGS += -include $(zfs_include)/sys/simd_config.h endif ZFS_MODULE_CFLAGS += -I$(zfs_include)/os/linux/kernel diff --git a/sys/contrib/openzfs/module/Makefile.bsd b/sys/contrib/openzfs/module/Makefile.bsd index 7a1bef6466db..30cf741b965b 100644 --- a/sys/contrib/openzfs/module/Makefile.bsd +++ b/sys/contrib/openzfs/module/Makefile.bsd @@ -38,6 +38,7 @@ CFLAGS+= -I${INCDIR}/os/freebsd CFLAGS+= -I${INCDIR}/os/freebsd/spl CFLAGS+= -I${INCDIR}/os/freebsd/zfs CFLAGS+= -I${SRCDIR}/zstd/include +CFLAGS+= -include ${INCDIR}/sys/simd_config.h CFLAGS+= -include ${INCDIR}/os/freebsd/spl/sys/ccompile.h CFLAGS+= -I${.CURDIR} @@ -46,8 +47,10 @@ CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \ -D_SYS_VMEM_H_ -DKDTRACE_HOOKS -DCOMPAT_FREEBSD11 .if ${MACHINE_ARCH} == "amd64" -CFLAGS+= -D__x86_64 -DHAVE_SSE2 -DHAVE_SSSE3 -DHAVE_SSE4_1 -DHAVE_SSE4_2 \ - -DHAVE_AVX -DHAVE_AVX2 -DHAVE_AVX512F -DHAVE_AVX512VL -DHAVE_AVX512BW +CFLAGS+= -D__x86_64 -DHAVE_TOOLCHAIN_SSE2 -DHAVE_TOOLCHAIN_SSSE3 \ + -DHAVE_TOOLCHAIN_SSE4_1 -DHAVE_TOOLCHAIN_AVX -DHAVE_TOOLCHAIN_AVX2 \ + -DHAVE_TOOLCHAIN_AVX512F -DHAVE_TOOLCHAIN_AVX512VL \ + -DHAVE_TOOLCHAIN_AVX512BW .endif .if defined(WITH_DEBUG) && ${WITH_DEBUG} == "true" diff --git a/sys/contrib/openzfs/module/icp/algs/aes/aes_impl.c b/sys/contrib/openzfs/module/icp/algs/aes/aes_impl.c index b652c8c72e04..fff672bc416f 100644 --- a/sys/contrib/openzfs/module/icp/algs/aes/aes_impl.c +++ b/sys/contrib/openzfs/module/icp/algs/aes/aes_impl.c @@ -231,7 +231,7 @@ static const aes_impl_ops_t *aes_all_impl[] = { #if defined(__x86_64) &aes_x86_64_impl, #endif -#if defined(__x86_64) && defined(HAVE_AES) +#if defined(__x86_64) && HAVE_SIMD(AES) &aes_aesni_impl, #endif }; @@ -315,7 +315,7 @@ aes_impl_init(void) * hardware accelerated version is the fastest. */ #if defined(__x86_64) -#if defined(HAVE_AES) +#if HAVE_SIMD(AES) if (aes_aesni_impl.is_supported()) { memcpy(&aes_fastest_impl, &aes_aesni_impl, sizeof (aes_fastest_impl)); diff --git a/sys/contrib/openzfs/module/icp/algs/aes/aes_impl_aesni.c b/sys/contrib/openzfs/module/icp/algs/aes/aes_impl_aesni.c index 1dbcb3b7133a..2cffaebb2cf3 100644 --- a/sys/contrib/openzfs/module/icp/algs/aes/aes_impl_aesni.c +++ b/sys/contrib/openzfs/module/icp/algs/aes/aes_impl_aesni.c @@ -23,7 +23,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ -#if defined(__x86_64) && defined(HAVE_AES) +#if defined(__x86_64) && HAVE_SIMD(AES) #include <sys/simd.h> #include <sys/types.h> @@ -123,4 +123,4 @@ const aes_impl_ops_t aes_aesni_impl = { .name = "aesni" }; -#endif /* defined(__x86_64) && defined(HAVE_AES) */ +#endif /* defined(__x86_64) && HAVE_SIMD(AES) */ diff --git a/sys/contrib/openzfs/module/icp/algs/blake3/blake3_impl.c b/sys/contrib/openzfs/module/icp/algs/blake3/blake3_impl.c index 2f4aabb52328..be2fb4b89cf4 100644 --- a/sys/contrib/openzfs/module/icp/algs/blake3/blake3_impl.c +++ b/sys/contrib/openzfs/module/icp/algs/blake3/blake3_impl.c @@ -32,7 +32,7 @@ #include "blake3_impl.h" #if !defined(OMIT_SIMD) && (defined(__aarch64__) || \ - (defined(__x86_64) && defined(HAVE_SSE2)) || \ + (defined(__x86_64) && HAVE_SIMD(SSE2)) || \ (defined(__PPC64__) && defined(__LITTLE_ENDIAN__))) #define USE_SIMD #endif @@ -164,7 +164,7 @@ const blake3_ops_t blake3_sse41_impl = { }; #endif -#if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2) +#if defined(__x86_64) && HAVE_SIMD(SSE4_1) && HAVE_SIMD(AVX2) extern void ASMABI zfs_blake3_hash_many_avx2(const uint8_t * const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, boolean_t increment_counter, uint8_t flags, @@ -197,7 +197,7 @@ blake3_avx2_impl = { }; #endif -#if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL) +#if defined(__x86_64) && HAVE_SIMD(AVX512F) && HAVE_SIMD(AVX512VL) extern void ASMABI zfs_blake3_compress_in_place_avx512(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); @@ -261,19 +261,19 @@ static const blake3_ops_t *const blake3_impls[] = { &blake3_generic_impl, #ifdef USE_SIMD #if defined(__aarch64__) || \ - (defined(__x86_64) && defined(HAVE_SSE2)) || \ + (defined(__x86_64) && HAVE_SIMD(SSE2)) || \ (defined(__PPC64__) && defined(__LITTLE_ENDIAN__)) &blake3_sse2_impl, #endif #if defined(__aarch64__) || \ - (defined(__x86_64) && defined(HAVE_SSE4_1)) || \ + (defined(__x86_64) && HAVE_SIMD(SSE4_1)) || \ (defined(__PPC64__) && defined(__LITTLE_ENDIAN__)) &blake3_sse41_impl, #endif -#if defined(__x86_64) && defined(HAVE_SSE4_1) && defined(HAVE_AVX2) +#if defined(__x86_64) && HAVE_SIMD(SSE4_1) && HAVE_SIMD(AVX2) &blake3_avx2_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX512F) && defined(HAVE_AVX512VL) +#if defined(__x86_64) && HAVE_SIMD(AVX512F) && HAVE_SIMD(AVX512VL) &blake3_avx512_impl, #endif #endif diff --git a/sys/contrib/openzfs/module/icp/algs/modes/gcm.c b/sys/contrib/openzfs/module/icp/algs/modes/gcm.c index ab2c5a49fdbf..7d92b208f164 100644 --- a/sys/contrib/openzfs/module/icp/algs/modes/gcm.c +++ b/sys/contrib/openzfs/module/icp/algs/modes/gcm.c @@ -714,7 +714,7 @@ static gcm_impl_ops_t gcm_fastest_impl = { /* All compiled in implementations */ static const gcm_impl_ops_t *gcm_all_impl[] = { &gcm_generic_impl, -#if defined(__x86_64) && defined(HAVE_PCLMULQDQ) +#if defined(__x86_64) && HAVE_SIMD(PCLMULQDQ) &gcm_pclmulqdq_impl, #endif }; @@ -801,7 +801,7 @@ gcm_impl_init(void) * Set the fastest implementation given the assumption that the * hardware accelerated version is the fastest. */ -#if defined(__x86_64) && defined(HAVE_PCLMULQDQ) +#if defined(__x86_64) && HAVE_SIMD(PCLMULQDQ) if (gcm_pclmulqdq_impl.is_supported()) { memcpy(&gcm_fastest_impl, &gcm_pclmulqdq_impl, sizeof (gcm_fastest_impl)); @@ -827,7 +827,7 @@ gcm_impl_init(void) } else #endif if (gcm_avx_will_work()) { -#ifdef HAVE_MOVBE +#if HAVE_SIMD(MOVBE) if (zfs_movbe_available() == B_TRUE) { atomic_swap_32(&gcm_avx_can_use_movbe, B_TRUE); } diff --git a/sys/contrib/openzfs/module/icp/algs/modes/gcm_pclmulqdq.c b/sys/contrib/openzfs/module/icp/algs/modes/gcm_pclmulqdq.c index 30653589fcef..53361921d50d 100644 --- a/sys/contrib/openzfs/module/icp/algs/modes/gcm_pclmulqdq.c +++ b/sys/contrib/openzfs/module/icp/algs/modes/gcm_pclmulqdq.c @@ -23,7 +23,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ -#if defined(__x86_64) && defined(HAVE_PCLMULQDQ) +#if defined(__x86_64) && HAVE_SIMD(PCLMULQDQ) #include <sys/types.h> #include <sys/simd.h> @@ -63,4 +63,4 @@ const gcm_impl_ops_t gcm_pclmulqdq_impl = { .name = "pclmulqdq" }; -#endif /* defined(__x86_64) && defined(HAVE_PCLMULQDQ) */ +#endif /* defined(__x86_64) && HAVE_SIMD(PCLMULQDQ) */ diff --git a/sys/contrib/openzfs/module/icp/algs/sha2/sha256_impl.c b/sys/contrib/openzfs/module/icp/algs/sha2/sha256_impl.c index dcb0a391dda4..a6a4a0d9aafd 100644 --- a/sys/contrib/openzfs/module/icp/algs/sha2/sha256_impl.c +++ b/sys/contrib/openzfs/module/icp/algs/sha2/sha256_impl.c @@ -65,7 +65,7 @@ const sha256_ops_t sha256_x64_impl = { .name = "x64" }; -#if defined(HAVE_SSSE3) +#if HAVE_SIMD(SSSE3) static boolean_t sha2_have_ssse3(void) { return (kfpu_allowed() && zfs_ssse3_available()); @@ -79,7 +79,7 @@ const sha256_ops_t sha256_ssse3_impl = { }; #endif -#if defined(HAVE_AVX) +#if HAVE_SIMD(AVX) static boolean_t sha2_have_avx(void) { return (kfpu_allowed() && zfs_avx_available()); @@ -93,7 +93,7 @@ const sha256_ops_t sha256_avx_impl = { }; #endif -#if defined(HAVE_AVX2) +#if HAVE_SIMD(AVX2) static boolean_t sha2_have_avx2(void) { return (kfpu_allowed() && zfs_avx2_available()); @@ -107,7 +107,7 @@ const sha256_ops_t sha256_avx2_impl = { }; #endif -#if defined(HAVE_SSE4_1) +#if HAVE_SIMD(SSE4_1) static boolean_t sha2_have_shani(void) { return (kfpu_allowed() && zfs_sse4_1_available() && \ @@ -186,16 +186,16 @@ static const sha256_ops_t *const sha256_impls[] = { #if defined(__x86_64) &sha256_x64_impl, #endif -#if defined(__x86_64) && defined(HAVE_SSSE3) +#if defined(__x86_64) && HAVE_SIMD(SSSE3) &sha256_ssse3_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX) +#if defined(__x86_64) && HAVE_SIMD(AVX) &sha256_avx_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX2) +#if defined(__x86_64) && HAVE_SIMD(AVX2) &sha256_avx2_impl, #endif -#if defined(__x86_64) && defined(HAVE_SSE4_1) +#if defined(__x86_64) && HAVE_SIMD(SSE4_1) &sha256_shani_impl, #endif #if defined(__aarch64__) || defined(__arm__) diff --git a/sys/contrib/openzfs/module/icp/algs/sha2/sha512_impl.c b/sys/contrib/openzfs/module/icp/algs/sha2/sha512_impl.c index 4206f8f20172..19f9a8cca750 100644 --- a/sys/contrib/openzfs/module/icp/algs/sha2/sha512_impl.c +++ b/sys/contrib/openzfs/module/icp/algs/sha2/sha512_impl.c @@ -65,7 +65,7 @@ const sha512_ops_t sha512_x64_impl = { .name = "x64" }; -#if defined(HAVE_AVX) +#if HAVE_SIMD(AVX) static boolean_t sha2_have_avx(void) { return (kfpu_allowed() && zfs_avx_available()); @@ -79,7 +79,7 @@ const sha512_ops_t sha512_avx_impl = { }; #endif -#if defined(HAVE_AVX2) +#if HAVE_SIMD(AVX2) static boolean_t sha2_have_avx2(void) { return (kfpu_allowed() && zfs_avx2_available()); @@ -93,7 +93,7 @@ const sha512_ops_t sha512_avx2_impl = { }; #endif -#if defined(HAVE_SHA512EXT) +#if HAVE_SIMD(SHA512EXT) static boolean_t sha2_have_sha512ext(void) { return (kfpu_allowed() && zfs_sha512ext_available()); @@ -173,13 +173,13 @@ static const sha512_ops_t *const sha512_impls[] = { #if defined(__x86_64) &sha512_x64_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX) +#if defined(__x86_64) && HAVE_SIMD(AVX) &sha512_avx_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX2) +#if defined(__x86_64) && HAVE_SIMD(AVX2) &sha512_avx2_impl, #endif -#if defined(__x86_64) && defined(HAVE_SHA512EXT) +#if defined(__x86_64) && HAVE_SIMD(SHA512EXT) &sha512_sha512ext_impl, #endif #if defined(__aarch64__) || defined(__arm__) diff --git a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S index 4e78f47121d2..a05e64b29419 100644 --- a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S +++ b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S @@ -34,8 +34,8 @@ #if defined(__aarch64__) -/* make gcc <= 9 happy */ -#if !defined(LD_VERSION) || LD_VERSION >= 233010000 +/* check for .cfi_negate_ra_state assembler support */ +#if defined(HAVE_AS_CFI_PSEUDO_OP) #define CFI_NEGATE_RA_STATE .cfi_negate_ra_state #else #define CFI_NEGATE_RA_STATE diff --git a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S index 41da0aff6953..19f5408d4ef5 100644 --- a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S +++ b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S @@ -34,8 +34,8 @@ #if defined(__aarch64__) -/* make gcc <= 9 happy */ -#if !defined(LD_VERSION) || LD_VERSION >= 233010000 +/* check for .cfi_negate_ra_state assembler support */ +#if defined(HAVE_AS_CFI_PSEUDO_OP) #define CFI_NEGATE_RA_STATE .cfi_negate_ra_state #else #define CFI_NEGATE_RA_STATE diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/aes/aes_aesni.S b/sys/contrib/openzfs/module/icp/asm-x86_64/aes/aes_aesni.S index b8ab937949e6..4a216274b826 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/aes/aes_aesni.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/aes/aes_aesni.S @@ -179,7 +179,7 @@ rijndael_key_setup_dec_intel(uint32_t rk[], const uint32_t cipherKey[], } -#elif defined(HAVE_AES) /* guard by instruction set */ +#elif HAVE_SIMD(AES) /* guard by instruction set */ #define _ASM #include <sys/asm_linkage.h> diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx2.S b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx2.S index 6edd59e6e668..3e52dfdad414 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx2.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx2.S @@ -26,7 +26,7 @@ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de> */ -#if defined(HAVE_AVX2) +#if HAVE_SIMD(AVX2) #define _ASM #include <sys/asm_linkage.h> @@ -1822,7 +1822,7 @@ CMP_MSB_MASK: .long 0x80000000, 0x80000000, 0x80000000, 0x80000000 BLAKE3_IV: .long 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A -#endif /* HAVE_AVX2 */ +#endif /* HAVE_SIMD(AVX2) */ #ifdef __ELF__ .section .note.GNU-stack,"",%progbits diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx512.S b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx512.S index 56af3e152bb8..51a83bf358c1 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx512.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_avx512.S @@ -26,7 +26,7 @@ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de> */ -#if defined(HAVE_AVX512F) && defined(HAVE_AVX512VL) +#if HAVE_SIMD(AVX512F) && HAVE_SIMD(AVX512VL) #define _ASM #include <sys/asm_linkage.h> @@ -2588,7 +2588,7 @@ BLAKE3_IV_2: BLAKE3_IV_3: .long 0xA54FF53A -#endif /* HAVE_AVX512 */ +#endif /* HAVE_SIMD(AVX512) */ #ifdef __ELF__ .section .note.GNU-stack,"",%progbits diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse2.S b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse2.S index 6d9c67206806..42b5d81db981 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse2.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse2.S @@ -26,7 +26,7 @@ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de> */ -#if defined(HAVE_SSE2) +#if HAVE_SIMD(SSE2) #define _ASM #include <sys/asm_linkage.h> @@ -2293,7 +2293,7 @@ PBLENDW_0x3F_MASK: PBLENDW_0xC0_MASK: .long 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF -#endif /* HAVE_SSE2 */ +#endif /* HAVE_SIMD(SSE2) */ #ifdef __ELF__ .section .note.GNU-stack,"",%progbits diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse41.S b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse41.S index eb46096228ce..98caf0cd2b4d 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse41.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/blake3/blake3_sse41.S @@ -26,7 +26,7 @@ * Copyright (c) 2022 Tino Reichardt <milky-zfs@mcmilk.de> */ -#if defined(HAVE_SSE4_1) +#if HAVE_SIMD(SSE4_1) #define _ASM #include <sys/asm_linkage.h> @@ -2031,7 +2031,7 @@ BLAKE3_BLOCK_LEN: CMP_MSB_MASK: .long 0x80000000, 0x80000000, 0x80000000, 0x80000000 -#endif /* HAVE_SSE4_1 */ +#endif /* HAVE_SIMD(SSE4_1) */ #ifdef __ELF__ .section .note.GNU-stack,"",%progbits diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-avx2-vaes.S b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-avx2-vaes.S index 626f4639ca06..bcba49b6dac9 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-avx2-vaes.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-avx2-vaes.S @@ -5,8 +5,8 @@ // perlasm source: https://github.com/google/boringssl/blob/d5440dd2c2c500ac2d3bba4afec47a054b4d99ae/crypto/fipsmodule/aes/asm/aes-gcm-avx2-x86_64.pl // generated source: https://github.com/google/boringssl/blob/d5440dd2c2c500ac2d3bba4afec47a054b4d99ae/gen/bcm/aes-gcm-avx2-x86_64-linux.S -#if defined(__x86_64__) && defined(HAVE_AVX2) && \ - defined(HAVE_VAES) && defined(HAVE_VPCLMULQDQ) +#if defined(__x86_64__) && HAVE_SIMD(AVX2) && \ + HAVE_SIMD(VAES) && HAVE_SIMD(VPCLMULQDQ) #define _ASM #include <sys/asm_linkage.h> @@ -1288,4 +1288,4 @@ SET_SIZE(aes_gcm_dec_update_vaes_avx2) .section .note.GNU-stack,"",%progbits #endif -#endif /* defined(__x86_64__) && defined(HAVE_AVX2) && defined(HAVE_VAES) ... */ +#endif /* defined(__x86_64__) && HAVE_SIMD(AVX2) && HAVE_SIMD(VAES) ... */ diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S index 2e0a88ec8cef..9929f6af9237 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/aesni-gcm-x86_64.S @@ -45,8 +45,8 @@ # and modified for ICP. Modification are kept at a bare minimum to ease later # upstream merges. -#if defined(__x86_64__) && defined(HAVE_AVX) && \ - defined(HAVE_AES) && defined(HAVE_PCLMULQDQ) +#if defined(__x86_64__) && HAVE_SIMD(AVX) && \ + HAVE_SIMD(AES) && HAVE_SIMD(PCLMULQDQ) #define _ASM #include <sys/asm_linkage.h> @@ -64,7 +64,7 @@ .text -#ifdef HAVE_MOVBE +#if HAVE_SIMD(MOVBE) .balign 32 FUNCTION(_aesni_ctr32_ghash_6x) .cfi_startproc @@ -380,7 +380,7 @@ FUNCTION(_aesni_ctr32_ghash_6x) .cfi_endproc SET_SIZE(_aesni_ctr32_ghash_6x) STACK_FRAME_NON_STANDARD _aesni_ctr32_ghash_6x -#endif /* ifdef HAVE_MOVBE */ +#endif /* HAVE_SIMD(MOVBE) */ .balign 32 FUNCTION(_aesni_ctr32_ghash_no_movbe_6x) @@ -781,7 +781,7 @@ ENTRY_ALIGN(aesni_gcm_decrypt, 32) vmovdqu %xmm2,96(%rsp) vmovdqu %xmm3,112(%rsp) -#ifdef HAVE_MOVBE +#if HAVE_SIMD(MOVBE) #ifdef _KERNEL testl $1,gcm_avx_can_use_movbe(%rip) #else @@ -992,7 +992,7 @@ ENTRY_ALIGN(aesni_gcm_encrypt, 32) movq $192,%r10 vpshufb %xmm0,%xmm8,%xmm8 -#ifdef HAVE_MOVBE +#if HAVE_SIMD(MOVBE) #ifdef _KERNEL testl $1,gcm_avx_can_use_movbe(%rip) #else @@ -1266,7 +1266,7 @@ SECTION_STATIC #if defined(__linux__) && defined(HAVE_STACK_FRAME_NON_STANDARD) && \ ! defined(HAVE_STACK_FRAME_NON_STANDARD_ASM) .section .discard.func_stack_frame_non_standard, "aw" -#ifdef HAVE_MOVBE +#if HAVE_SIMD(MOVBE) .long _aesni_ctr32_ghash_6x - . #endif .long _aesni_ctr32_ghash_no_movbe_6x - . @@ -1279,4 +1279,4 @@ SECTION_STATIC .section .note.GNU-stack,"",%progbits #endif -#endif /* defined(__x86_64__) && defined(HAVE_AVX) && defined(HAVE_AES) ... */ +#endif /* defined(__x86_64__) && HAVE_SIMD(AVX) && HAVE_SIMD(AES) ... */ diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S index f5d3b3362feb..82eac5b48349 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/gcm_pclmulqdq.S @@ -91,7 +91,7 @@ gcm_mul_pclmulqdq(uint64_t *x_in, uint64_t *y, uint64_t *res) { (void) x_in, (void) y, (void) res; } -#elif defined(HAVE_PCLMULQDQ) /* guard by instruction set */ +#elif HAVE_SIMD(PCLMULQDQ) /* guard by instruction set */ #define _ASM #include <sys/asm_linkage.h> diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/ghash-x86_64.S b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/ghash-x86_64.S index 8295f91d2e91..9027684a24f4 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/modes/ghash-x86_64.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/modes/ghash-x86_64.S @@ -95,8 +95,8 @@ # and modified for ICP. Modification are kept at a bare minimum to ease later # upstream merges. -#if defined(__x86_64__) && defined(HAVE_AVX) && \ - defined(HAVE_AES) && defined(HAVE_PCLMULQDQ) +#if defined(__x86_64__) && HAVE_SIMD(AVX) && \ + HAVE_SIMD(AES) && HAVE_SIMD(PCLMULQDQ) #define _ASM #include <sys/asm_linkage.h> @@ -654,4 +654,4 @@ SET_OBJ(.Lrem_8bit) .section .note.GNU-stack,"",%progbits #endif -#endif /* defined(__x86_64__) && defined(HAVE_AVX) && defined(HAVE_AES) ... */ +#endif /* defined(__x86_64__) && HAVE_SIMD(AVX) && HAVE_SIMD(AES) ... */ diff --git a/sys/contrib/openzfs/module/icp/asm-x86_64/sha2/sha512-x86_64.S b/sys/contrib/openzfs/module/icp/asm-x86_64/sha2/sha512-x86_64.S index 47e4edd51d10..c281bc64dd8c 100644 --- a/sys/contrib/openzfs/module/icp/asm-x86_64/sha2/sha512-x86_64.S +++ b/sys/contrib/openzfs/module/icp/asm-x86_64/sha2/sha512-x86_64.S @@ -4054,7 +4054,7 @@ ENTRY_ALIGN(zfs_sha512_transform_avx2, 64) SET_SIZE(zfs_sha512_transform_avx2) STACK_FRAME_NON_STANDARD zfs_sha512_transform_avx2 -#ifdef HAVE_SHA512EXT +#if HAVE_SIMD(SHA512EXT) ENTRY_ALIGN(zfs_sha512_transform_sha512ext, 64) .cfi_startproc ENDBR @@ -4324,7 +4324,7 @@ ENTRY_ALIGN(zfs_sha512_transform_sha512ext, 64) .cfi_endproc SET_SIZE(zfs_sha512_transform_sha512ext) STACK_FRAME_NON_STANDARD zfs_sha512_transform_sha512ext -#endif /* HAVE_SHA512EXT */ +#endif /* HAVE_SIMD(SHA512EXT) */ /* Workaround for missing asm macro in RHEL 8. */ #if defined(__linux__) && defined(HAVE_STACK_FRAME_NON_STANDARD) && \ @@ -4333,7 +4333,7 @@ STACK_FRAME_NON_STANDARD zfs_sha512_transform_sha512ext .long zfs_sha512_transform_x64 - . .long zfs_sha512_transform_avx - . .long zfs_sha512_transform_avx2 - . -#ifdef HAVE_SHA512EXT +#if HAVE_SIMD(SHA512EXT) .long zfs_sha512_transform_sha512ext - . #endif #endif diff --git a/sys/contrib/openzfs/module/icp/core/kcf_mech_tabs.c b/sys/contrib/openzfs/module/icp/core/kcf_mech_tabs.c index a082e858784a..c88b0d1145cb 100644 --- a/sys/contrib/openzfs/module/icp/core/kcf_mech_tabs.c +++ b/sys/contrib/openzfs/module/icp/core/kcf_mech_tabs.c @@ -90,8 +90,8 @@ static int kcf_mech_hash_compar(const void *lhs, const void *rhs) { const kcf_mech_entry_t *l = lhs, *r = rhs; - int cmp = strncmp(l->me_name, r->me_name, CRYPTO_MAX_MECH_NAME); - return ((0 < cmp) - (cmp < 0)); + return (TREE_ISIGN(strncmp(l->me_name, r->me_name, + CRYPTO_MAX_MECH_NAME))); } void diff --git a/sys/contrib/openzfs/module/icp/include/aes/aes_impl.h b/sys/contrib/openzfs/module/icp/include/aes/aes_impl.h index 17cbbac18604..4b7d13312cd7 100644 --- a/sys/contrib/openzfs/module/icp/include/aes/aes_impl.h +++ b/sys/contrib/openzfs/module/icp/include/aes/aes_impl.h @@ -196,7 +196,7 @@ extern ASMABI void aes_encrypt_amd64(const uint32_t rk[], int Nr, extern ASMABI void aes_decrypt_amd64(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4]); #endif -#if defined(__x86_64) && defined(HAVE_AES) +#if defined(__x86_64) && HAVE_SIMD(AES) extern const aes_impl_ops_t aes_aesni_impl; #endif diff --git a/sys/contrib/openzfs/module/icp/include/modes/gcm_impl.h b/sys/contrib/openzfs/module/icp/include/modes/gcm_impl.h index 238a4e27f8fe..0bc1567daf25 100644 --- a/sys/contrib/openzfs/module/icp/include/modes/gcm_impl.h +++ b/sys/contrib/openzfs/module/icp/include/modes/gcm_impl.h @@ -55,7 +55,7 @@ typedef struct gcm_impl_ops { } gcm_impl_ops_t; extern const gcm_impl_ops_t gcm_generic_impl; -#if defined(__x86_64) && defined(HAVE_PCLMULQDQ) +#if defined(__x86_64) && HAVE_SIMD(PCLMULQDQ) extern const gcm_impl_ops_t gcm_pclmulqdq_impl; #endif diff --git a/sys/contrib/openzfs/module/icp/include/modes/modes.h b/sys/contrib/openzfs/module/icp/include/modes/modes.h index de11d9eafafb..66fa11712807 100644 --- a/sys/contrib/openzfs/module/icp/include/modes/modes.h +++ b/sys/contrib/openzfs/module/icp/include/modes/modes.h @@ -40,9 +40,9 @@ extern "C" { * routines. AVX support should imply AES-NI and PCLMULQDQ, but make sure * anyhow. */ -#if defined(__x86_64__) && defined(HAVE_AVX) && \ - defined(HAVE_AES) && defined(HAVE_PCLMULQDQ) -#define CAN_USE_GCM_ASM (HAVE_VAES && HAVE_VPCLMULQDQ ? 2 : 1) +#if defined(__x86_64__) && HAVE_SIMD(AVX) && \ + HAVE_SIMD(AES) && HAVE_SIMD(PCLMULQDQ) +#define CAN_USE_GCM_ASM (HAVE_SIMD(VAES) && HAVE_SIMD(VPCLMULQDQ) ? 2 : 1) extern boolean_t gcm_avx_can_use_movbe; #endif diff --git a/sys/contrib/openzfs/module/os/freebsd/spl/acl_common.c b/sys/contrib/openzfs/module/os/freebsd/spl/acl_common.c index 33ff9ec02d1c..4e0112882b87 100644 --- a/sys/contrib/openzfs/module/os/freebsd/spl/acl_common.c +++ b/sys/contrib/openzfs/module/os/freebsd/spl/acl_common.c @@ -1213,15 +1213,7 @@ static int acevals_compare(const void *va, const void *vb) { const acevals_t *a = va, *b = vb; - - if (a->key == b->key) - return (0); - - if (a->key > b->key) - return (1); - - else - return (-1); + return (TREE_CMP(a->key, b->key)); } /* diff --git a/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c b/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c index 7b1bfd1caa07..5b2b0e5089c0 100644 --- a/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c +++ b/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c @@ -40,21 +40,21 @@ vcmn_err(int ce, const char *fmt, va_list adx) prefix = NULL; /* silence unwitty compilers */ switch (ce) { case CE_CONT: - prefix = "Solaris(cont): "; + prefix = "zfs(cont): "; break; case CE_NOTE: - prefix = "Solaris: NOTICE: "; + prefix = "zfs: NOTICE: "; break; case CE_WARN: - prefix = "Solaris: WARNING: "; + prefix = "zfs: WARNING: "; break; case CE_PANIC: - prefix = "Solaris(panic): "; + prefix = "zfs(panic): "; break; case CE_IGNORE: break; default: - panic("Solaris: unknown severity level"); + panic("zfs: unknown severity level"); } if (ce == CE_PANIC) { vsnprintf(buf, sizeof (buf), fmt, adx); diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c index 79fd8911102d..b1dc50b2d47d 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c @@ -251,16 +251,7 @@ snapentry_compare_by_name(const void *a, const void *b) { const zfs_snapentry_t *se_a = a; const zfs_snapentry_t *se_b = b; - int ret; - - ret = strcmp(se_a->se_name, se_b->se_name); - - if (ret < 0) - return (-1); - else if (ret > 0) - return (1); - else - return (0); + return (TREE_ISIGN(strcmp(se_a->se_name, se_b->se_name))); } /* @@ -272,15 +263,10 @@ snapentry_compare_by_objsetid(const void *a, const void *b) const zfs_snapentry_t *se_a = a; const zfs_snapentry_t *se_b = b; - if (se_a->se_spa != se_b->se_spa) - return ((ulong_t)se_a->se_spa < (ulong_t)se_b->se_spa ? -1 : 1); - - if (se_a->se_objsetid < se_b->se_objsetid) - return (-1); - else if (se_a->se_objsetid > se_b->se_objsetid) - return (1); - else - return (0); + int cmp = TREE_PCMP(se_a->se_spa, se_b->se_spa); + if (cmp != 0) + return (cmp); + return (TREE_CMP(se_a->se_objsetid, se_b->se_objsetid)); } /* diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c index 30f3e3855355..efcb400f196e 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c @@ -1268,6 +1268,7 @@ const struct file_operations zpl_dir_file_operations = { .read = generic_read_dir, .iterate_shared = zpl_iterate, .fsync = zpl_fsync, + .setlease = generic_setlease, .unlocked_ioctl = zpl_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = zpl_compat_ioctl, diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c index f8d1e2a55180..a970959531a3 100644 --- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c @@ -36,9 +36,7 @@ #include <linux/iversion.h> #include <linux/version.h> #include <linux/vfs_compat.h> -#ifdef HAVE_FS_CONTEXT #include <linux/fs_context.h> -#endif /* * What to do when the last reference to an inode is released. If 0, the kernel @@ -269,21 +267,6 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp) } static int -zpl_remount_fs(struct super_block *sb, int *flags, char *data) -{ - zfs_mnt_t zm = { .mnt_osname = NULL, .mnt_data = data }; - fstrans_cookie_t cookie; - int error; - - cookie = spl_fstrans_mark(); - error = -zfs_remount(sb, flags, &zm); - spl_fstrans_unmark(cookie); - ASSERT3S(error, <=, 0); - - return (error); -} - -static int __zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs) { int error; @@ -358,21 +341,6 @@ zpl_show_options(struct seq_file *seq, struct dentry *root) } static int -zpl_fill_super(struct super_block *sb, void *data, int silent) -{ - zfs_mnt_t *zm = (zfs_mnt_t *)data; - fstrans_cookie_t cookie; - int error; - - cookie = spl_fstrans_mark(); - error = -zfs_domount(sb, zm, silent); - spl_fstrans_unmark(cookie); - ASSERT3S(error, <=, 0); - - return (error); -} - -static int zpl_test_super(struct super_block *s, void *data) { zfsvfs_t *zfsvfs = s->s_fs_info; @@ -387,92 +355,6 @@ zpl_test_super(struct super_block *s, void *data) return (zfsvfs != NULL && os == zfsvfs->z_os); } -static struct super_block * -zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mnt_t *zm) -{ - struct super_block *s; - objset_t *os; - boolean_t issnap = B_FALSE; - int err; - - err = dmu_objset_hold(zm->mnt_osname, FTAG, &os); - if (err) - return (ERR_PTR(-err)); - - /* - * The dsl pool lock must be released prior to calling sget(). - * It is possible sget() may block on the lock in grab_super() - * while deactivate_super() holds that same lock and waits for - * a txg sync. If the dsl_pool lock is held over sget() - * this can prevent the pool sync and cause a deadlock. - */ - dsl_dataset_long_hold(dmu_objset_ds(os), FTAG); - dsl_pool_rele(dmu_objset_pool(os), FTAG); - - s = sget(fs_type, zpl_test_super, set_anon_super, flags, os); - - /* - * Recheck with the lock held to prevent mounting the wrong dataset - * since z_os can be stale when the teardown lock is held. - * - * We can't do this in zpl_test_super in since it's under spinlock and - * also s_umount lock is not held there so it would race with - * zfs_umount and zfsvfs can be freed. - */ - if (!IS_ERR(s) && s->s_fs_info != NULL) { - zfsvfs_t *zfsvfs = s->s_fs_info; - if (zpl_enter(zfsvfs, FTAG) == 0) { - if (os != zfsvfs->z_os) - err = -SET_ERROR(EBUSY); - issnap = zfsvfs->z_issnap; - zpl_exit(zfsvfs, FTAG); - } else { - err = -SET_ERROR(EBUSY); - } - } - dsl_dataset_long_rele(dmu_objset_ds(os), FTAG); - dsl_dataset_rele(dmu_objset_ds(os), FTAG); - - if (IS_ERR(s)) - return (ERR_CAST(s)); - - if (err) { - deactivate_locked_super(s); - return (ERR_PTR(err)); - } - - if (s->s_root == NULL) { - err = zpl_fill_super(s, zm, flags & SB_SILENT ? 1 : 0); - if (err) { - deactivate_locked_super(s); - return (ERR_PTR(err)); - } - s->s_flags |= SB_ACTIVE; - } else if (!issnap && ((flags ^ s->s_flags) & SB_RDONLY)) { - /* - * Skip ro check for snap since snap is always ro regardless - * ro flag is passed by mount or not. - */ - deactivate_locked_super(s); - return (ERR_PTR(-EBUSY)); - } - - return (s); -} - -static struct dentry * -zpl_mount(struct file_system_type *fs_type, int flags, - const char *osname, void *data) -{ - zfs_mnt_t zm = { .mnt_osname = osname, .mnt_data = data }; - - struct super_block *sb = zpl_mount_impl(fs_type, flags, &zm); - if (IS_ERR(sb)) - return (ERR_CAST(sb)); - - return (dget(sb->s_root)); -} - static void zpl_kill_sb(struct super_block *sb) { @@ -508,16 +390,6 @@ zpl_prune_sb(uint64_t nr_to_scan, void *arg) #endif } -#ifdef HAVE_FS_CONTEXT -/* - * Since kernel 5.2, the "new" fs_context-based mount API has been preferred - * over the traditional file_system_type->mount() and - * super_operations->remount_fs() callbacks, which were deprectate. In 7.0, - * those callbacks were removed. - * - * Currently, the old-style interface are the only ones we need, so this is - * a simple compatibility shim to adapt the new API to the old-style calls. - */ static int zpl_parse_monolithic(struct fs_context *fc, void *data) { @@ -532,8 +404,84 @@ zpl_parse_monolithic(struct fs_context *fc, void *data) static int zpl_get_tree(struct fs_context *fc) { - struct dentry *root = - zpl_mount(fc->fs_type, fc->sb_flags, fc->source, fc->fs_private); + struct super_block *sb; + objset_t *os; + boolean_t issnap = B_FALSE; + int err; + + err = dmu_objset_hold(fc->source, FTAG, &os); + if (err) + return (-err); + + /* + * The dsl pool lock must be released prior to calling sget(). + * It is possible sget() may block on the lock in grab_super() + * while deactivate_super() holds that same lock and waits for + * a txg sync. If the dsl_pool lock is held over sget() + * this can prevent the pool sync and cause a deadlock. + */ + dsl_dataset_long_hold(dmu_objset_ds(os), FTAG); + dsl_pool_rele(dmu_objset_pool(os), FTAG); + + sb = sget(fc->fs_type, zpl_test_super, set_anon_super, + fc->sb_flags, os); + + /* + * Recheck with the lock held to prevent mounting the wrong dataset + * since z_os can be stale when the teardown lock is held. + * + * We can't do this in zpl_test_super in since it's under spinlock and + * also s_umount lock is not held there so it would race with + * zfs_umount and zfsvfs can be freed. + */ + if (!IS_ERR(sb) && sb->s_fs_info != NULL) { + zfsvfs_t *zfsvfs = sb->s_fs_info; + if (zpl_enter(zfsvfs, FTAG) == 0) { + if (os != zfsvfs->z_os) + err = SET_ERROR(EBUSY); + issnap = zfsvfs->z_issnap; + zpl_exit(zfsvfs, FTAG); + } else { + err = SET_ERROR(EBUSY); + } + } + dsl_dataset_long_rele(dmu_objset_ds(os), FTAG); + dsl_dataset_rele(dmu_objset_ds(os), FTAG); + + if (IS_ERR(sb)) + return (PTR_ERR(sb)); + + if (err) { + deactivate_locked_super(sb); + return (-err); + } + + if (sb->s_root == NULL) { + zfs_mnt_t zm = { + .mnt_osname = fc->source, + .mnt_data = fc->fs_private, + }; + + fstrans_cookie_t cookie = spl_fstrans_mark(); + err = zfs_domount(sb, &zm, fc->sb_flags & SB_SILENT ? 1 : 0); + spl_fstrans_unmark(cookie); + + if (err) { + deactivate_locked_super(sb); + return (-err); + } + + sb->s_flags |= SB_ACTIVE; + } else if (!issnap && ((fc->sb_flags ^ sb->s_flags) & SB_RDONLY)) { + /* + * Skip ro check for snap since snap is always ro regardless + * ro flag is passed by mount or not. + */ + deactivate_locked_super(sb); + return (-SET_ERROR(EBUSY)); + } + + struct dentry *root = dget(sb->s_root); if (IS_ERR(root)) return (PTR_ERR(root)); @@ -544,7 +492,16 @@ zpl_get_tree(struct fs_context *fc) static int zpl_reconfigure(struct fs_context *fc) { - return (zpl_remount_fs(fc->root->d_sb, &fc->sb_flags, fc->fs_private)); + zfs_mnt_t zm = { .mnt_osname = NULL, .mnt_data = fc->fs_private }; + fstrans_cookie_t cookie; + int error; + + cookie = spl_fstrans_mark(); + error = -zfs_remount(fc->root->d_sb, &fc->sb_flags, &zm); + spl_fstrans_unmark(cookie); + ASSERT3S(error, <=, 0); + + return (error); } const struct fs_context_operations zpl_fs_context_operations = { @@ -559,7 +516,6 @@ zpl_init_fs_context(struct fs_context *fc) fc->ops = &zpl_fs_context_operations; return (0); } -#endif const struct super_operations zpl_super_operations = { .alloc_inode = zpl_inode_alloc, @@ -574,9 +530,6 @@ const struct super_operations zpl_super_operations = { .put_super = zpl_put_super, .sync_fs = zpl_sync_fs, .statfs = zpl_statfs, -#ifndef HAVE_FS_CONTEXT - .remount_fs = zpl_remount_fs, -#endif .show_devname = zpl_show_devname, .show_options = zpl_show_options, .show_stats = NULL, @@ -619,11 +572,7 @@ struct file_system_type zpl_fs_type = { #else .fs_flags = FS_USERNS_MOUNT, #endif -#ifdef HAVE_FS_CONTEXT .init_fs_context = zpl_init_fs_context, -#else - .mount = zpl_mount, -#endif .kill_sb = zpl_kill_sb, }; diff --git a/sys/contrib/openzfs/module/zcommon/zfs_fletcher.c b/sys/contrib/openzfs/module/zcommon/zfs_fletcher.c index 133217f4bae2..1a7dde1dd8f6 100644 --- a/sys/contrib/openzfs/module/zcommon/zfs_fletcher.c +++ b/sys/contrib/openzfs/module/zcommon/zfs_fletcher.c @@ -174,19 +174,19 @@ static const fletcher_4_ops_t *fletcher_4_impls[] = { &fletcher_4_scalar_ops, &fletcher_4_superscalar_ops, &fletcher_4_superscalar4_ops, -#if defined(HAVE_SSE2) +#if HAVE_SIMD(SSE2) &fletcher_4_sse2_ops, #endif -#if defined(HAVE_SSE2) && defined(HAVE_SSSE3) +#if HAVE_SIMD(SSE2) && HAVE_SIMD(SSSE3) &fletcher_4_ssse3_ops, #endif -#if defined(HAVE_AVX) && defined(HAVE_AVX2) +#if HAVE_SIMD(AVX) && HAVE_SIMD(AVX2) &fletcher_4_avx2_ops, #endif -#if defined(__x86_64) && defined(HAVE_AVX512F) +#if defined(__x86_64) && HAVE_SIMD(AVX512F) &fletcher_4_avx512f_ops, #endif -#if defined(__x86_64) && defined(HAVE_AVX512BW) +#if defined(__x86_64) && HAVE_SIMD(AVX512BW) &fletcher_4_avx512bw_ops, #endif #if defined(__aarch64__) && !defined(__FreeBSD__) diff --git a/sys/contrib/openzfs/module/zcommon/zfs_fletcher_avx512.c b/sys/contrib/openzfs/module/zcommon/zfs_fletcher_avx512.c index b42ebee57e52..ac3667d30b85 100644 --- a/sys/contrib/openzfs/module/zcommon/zfs_fletcher_avx512.c +++ b/sys/contrib/openzfs/module/zcommon/zfs_fletcher_avx512.c @@ -23,7 +23,7 @@ * Copyright (C) 2016 Gvozden Nešković. All rights reserved. */ -#if defined(__x86_64) && defined(HAVE_AVX512F) +#if defined(__x86_64) && HAVE_SIMD(AVX512F) #include <sys/byteorder.h> #include <sys/frame.h> @@ -167,7 +167,7 @@ const fletcher_4_ops_t fletcher_4_avx512f_ops = { .name = "avx512f" }; -#if defined(HAVE_AVX512BW) +#if HAVE_SIMD(AVX512BW) static void fletcher_4_avx512bw_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size) @@ -219,4 +219,4 @@ const fletcher_4_ops_t fletcher_4_avx512bw_ops = { }; #endif -#endif /* defined(__x86_64) && defined(HAVE_AVX512F) */ +#endif /* defined(__x86_64) && HAVE_SIMD(AVX512F) */ diff --git a/sys/contrib/openzfs/module/zcommon/zfs_fletcher_intel.c b/sys/contrib/openzfs/module/zcommon/zfs_fletcher_intel.c index 570076ba2b09..7da1dc4eeadd 100644 --- a/sys/contrib/openzfs/module/zcommon/zfs_fletcher_intel.c +++ b/sys/contrib/openzfs/module/zcommon/zfs_fletcher_intel.c @@ -41,7 +41,7 @@ * SOFTWARE. */ -#if defined(HAVE_AVX) && defined(HAVE_AVX2) +#if HAVE_SIMD(AVX) && HAVE_SIMD(AVX2) #include <sys/spa_checksum.h> #include <sys/string.h> @@ -164,4 +164,4 @@ const fletcher_4_ops_t fletcher_4_avx2_ops = { .name = "avx2" }; -#endif /* defined(HAVE_AVX) && defined(HAVE_AVX2) */ +#endif /* HAVE_SIMD(AVX) && HAVE_SIMD(AVX2) */ diff --git a/sys/contrib/openzfs/module/zcommon/zfs_fletcher_sse.c b/sys/contrib/openzfs/module/zcommon/zfs_fletcher_sse.c index 96aaf1622d73..a656790c6487 100644 --- a/sys/contrib/openzfs/module/zcommon/zfs_fletcher_sse.c +++ b/sys/contrib/openzfs/module/zcommon/zfs_fletcher_sse.c @@ -42,7 +42,7 @@ * SOFTWARE. */ -#if defined(HAVE_SSE2) +#if HAVE_SIMD(SSE2) #include <sys/simd.h> #include <sys/spa_checksum.h> @@ -165,9 +165,9 @@ const fletcher_4_ops_t fletcher_4_sse2_ops = { .name = "sse2" }; -#endif /* defined(HAVE_SSE2) */ +#endif /* HAVE_SIMD(SSE2) */ -#if defined(HAVE_SSE2) && defined(HAVE_SSSE3) +#if HAVE_SIMD(SSE2) && HAVE_SIMD(SSSE3) static void fletcher_4_ssse3_byteswap(fletcher_4_ctx_t *ctx, const void *buf, uint64_t size) { @@ -220,4 +220,4 @@ const fletcher_4_ops_t fletcher_4_ssse3_ops = { .name = "ssse3" }; -#endif /* defined(HAVE_SSE2) && defined(HAVE_SSSE3) */ +#endif /* HAVE_SIMD(SSE2) && HAVE_SIMD(SSSE3) */ diff --git a/sys/contrib/openzfs/module/zcommon/zpool_prop.c b/sys/contrib/openzfs/module/zcommon/zpool_prop.c index 2c6515e93676..ef21f17be8ca 100644 --- a/sys/contrib/openzfs/module/zcommon/zpool_prop.c +++ b/sys/contrib/openzfs/module/zcommon/zpool_prop.c @@ -50,6 +50,41 @@ zpool_prop_get_table(void) return (zpool_prop_table); } +/* BEGIN CSTYLED */ +#define zprop_register_mc_props_impl(mcp, uprefix, lprefix, sfeatures) ({ \ + zprop_register_number(mcp + ZPOOL_MC_PROP_SIZE, \ + #lprefix "_size", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \ + #uprefix "_SIZE", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_CAPACITY, \ + #lprefix "_capacity", 0, PROP_READONLY, ZFS_TYPE_POOL, \ + "<percent>", #uprefix "_CAP", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_FREE, \ + #lprefix "_free", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \ + #uprefix "_FREE", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_ALLOCATED, \ + #lprefix "_allocated", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \ + #uprefix "_ALLOC", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_AVAILABLE, \ + #lprefix "_available", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \ + #uprefix "_AVAIL", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_USABLE, \ + #lprefix "_usable", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \ + #uprefix "_USABLE", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_USED, \ + #lprefix "_used", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \ + #uprefix "_USED", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_EXPANDSZ, \ + #lprefix "_expandsize", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \ + #uprefix "_EXPANDSZ", B_FALSE, sfeatures); \ + zprop_register_number(mcp + ZPOOL_MC_PROP_FRAGMENTATION, \ + #lprefix "_fragmentation", 0, PROP_READONLY, ZFS_TYPE_POOL, \ + "<percent>", #uprefix "_FRAG", B_FALSE, sfeatures); \ +}) +#define zprop_register_mc_props(uclass, lclass, sfeatures) \ + zprop_register_mc_props_impl(ZPOOL_MC_PROPS_##uclass, \ + CLASS_##uclass, class_##lclass, sfeatures) +/* END CSTYLED */ + void zpool_prop_init(void) { @@ -138,6 +173,20 @@ zpool_prop_init(void) zprop_register_number(ZPOOL_PROP_LAST_SCRUBBED_TXG, "last_scrubbed_txg", 0, PROP_READONLY, ZFS_TYPE_POOL, "<txg>", "LAST_SCRUBBED_TXG", B_FALSE, sfeatures); + zprop_register_number(ZPOOL_PROP_AVAILABLE, "available", 0, + PROP_READONLY, ZFS_TYPE_POOL, "<size>", "AVAIL", B_FALSE, + sfeatures); + zprop_register_number(ZPOOL_PROP_USABLE, "usable", 0, PROP_READONLY, + ZFS_TYPE_POOL, "<size>", "USABLE", B_FALSE, sfeatures); + zprop_register_number(ZPOOL_PROP_USED, "used", 0, PROP_READONLY, + ZFS_TYPE_POOL, "<size>", "USED", B_FALSE, sfeatures); + + zprop_register_mc_props(NORMAL, normal, sfeatures); + zprop_register_mc_props(SPECIAL, special, sfeatures); + zprop_register_mc_props(DEDUP, dedup, sfeatures); + zprop_register_mc_props(LOG, log, sfeatures); + zprop_register_mc_props(ELOG, elog, sfeatures); + zprop_register_mc_props(SELOG, special_elog, sfeatures); /* default number properties */ zprop_register_number(ZPOOL_PROP_VERSION, "version", SPA_VERSION, @@ -377,7 +426,7 @@ vdev_prop_init(void) PROP_READONLY, ZFS_TYPE_VDEV, "<percent>", "FRAG", B_FALSE, sfeatures); zprop_register_number(VDEV_PROP_CAPACITY, "capacity", 0, PROP_READONLY, - ZFS_TYPE_VDEV, "<size>", "CAP", B_FALSE, sfeatures); + ZFS_TYPE_VDEV, "<percent>", "CAP", B_FALSE, sfeatures); zprop_register_number(VDEV_PROP_GUID, "guid", 0, PROP_READONLY, ZFS_TYPE_VDEV, "<guid>", "GUID", B_TRUE, sfeatures); zprop_register_number(VDEV_PROP_STATE, "state", 0, PROP_READONLY, diff --git a/sys/contrib/openzfs/module/zfs/arc.c b/sys/contrib/openzfs/module/zfs/arc.c index 9224ea34c4ba..be31cff50059 100644 --- a/sys/contrib/openzfs/module/zfs/arc.c +++ b/sys/contrib/openzfs/module/zfs/arc.c @@ -957,6 +957,22 @@ int l2arc_exclude_special = 0; static int l2arc_mfuonly = 0; /* + * Depth cap as percentage of state size. Each pass resets its markers + * to tail after scanning this fraction of the state. Keeps markers + * focused on the tail zone where L2ARC adds the most value. + */ +static uint64_t l2arc_ext_headroom_pct = 25; + +/* + * Metadata monopolization limit. When metadata fills the write budget + * for this many consecutive cycles while data gets nothing, skip metadata + * for one cycle to let data run, then reset the counter. + * With N=2, the steady-state pattern under sustained monopolization is + * 2 metadata cycles followed by 1 data cycle (67%/33% split). + */ +static uint64_t l2arc_meta_cycles = 2; + +/* * L2ARC TRIM * l2arc_trim_ahead : A ZFS module parameter that controls how much ahead of * the current write size (l2arc_write_max) we should TRIM if we @@ -9073,6 +9089,8 @@ l2arc_pool_markers_init(spa_t *spa) arc_state_alloc_markers(num_sublists); spa->spa_l2arc_info.l2arc_sublist_busy[pass] = kmem_zalloc(num_sublists * sizeof (boolean_t), KM_SLEEP); + spa->spa_l2arc_info.l2arc_sublist_reset[pass] = + kmem_zalloc(num_sublists * sizeof (boolean_t), KM_SLEEP); for (int i = 0; i < num_sublists; i++) { multilist_sublist_t *mls = @@ -9081,6 +9099,8 @@ l2arc_pool_markers_init(spa_t *spa) spa->spa_l2arc_info.l2arc_markers[pass][i]); multilist_sublist_unlock(mls); } + + spa->spa_l2arc_info.l2arc_ext_scanned[pass] = 0; } } @@ -9117,12 +9137,18 @@ l2arc_pool_markers_fini(spa_t *spa) num_sublists); spa->spa_l2arc_info.l2arc_markers[pass] = NULL; - /* Free sublist busy flags for this pass */ + /* Free sublist busy and reset flags for this pass */ ASSERT3P(spa->spa_l2arc_info.l2arc_sublist_busy[pass], !=, NULL); kmem_free(spa->spa_l2arc_info.l2arc_sublist_busy[pass], num_sublists * sizeof (boolean_t)); spa->spa_l2arc_info.l2arc_sublist_busy[pass] = NULL; + + ASSERT3P(spa->spa_l2arc_info.l2arc_sublist_reset[pass], !=, + NULL); + kmem_free(spa->spa_l2arc_info.l2arc_sublist_reset[pass], + num_sublists * sizeof (boolean_t)); + spa->spa_l2arc_info.l2arc_sublist_reset[pass] = NULL; } mutex_destroy(&spa->spa_l2arc_info.l2arc_sublist_lock); @@ -9596,7 +9622,7 @@ l2arc_write_sublist(spa_t *spa, l2arc_dev_t *dev, int pass, int sublist_idx, uint64_t *consumed, uint64_t sublist_headroom, boolean_t save_position) { multilist_sublist_t *mls; - arc_buf_hdr_t *hdr, *prev_hdr; + arc_buf_hdr_t *hdr; arc_buf_hdr_t *persistent_marker, *local_marker; boolean_t full = B_FALSE; boolean_t scan_from_head = B_FALSE; @@ -9608,6 +9634,19 @@ l2arc_write_sublist(spa_t *spa, l2arc_dev_t *dev, int pass, int sublist_idx, persistent_marker = spa->spa_l2arc_info. l2arc_markers[pass][sublist_idx]; + /* + * Check if this sublist's marker was flagged for reset to tail. + * This handles depth cap resets and global resets without needing + * to coordinate with actively-scanning threads. + */ + if (save_position && + spa->spa_l2arc_info.l2arc_sublist_reset[pass][sublist_idx]) { + multilist_sublist_remove(mls, persistent_marker); + multilist_sublist_insert_tail(mls, persistent_marker); + spa->spa_l2arc_info.l2arc_sublist_reset[pass][sublist_idx] = + B_FALSE; + } + if (save_position && persistent_marker == multilist_sublist_head(mls)) { multilist_sublist_unlock(mls); return (B_FALSE); @@ -9630,12 +9669,9 @@ l2arc_write_sublist(spa_t *spa, l2arc_dev_t *dev, int pass, int sublist_idx, ASSERT3P(hdr, !=, NULL); } - prev_hdr = hdr; - while (hdr != NULL) { kmutex_t *hash_lock; abd_t *to_write = NULL; - prev_hdr = hdr; hash_lock = HDR_LOCK(hdr); if (!mutex_tryenter(hash_lock)) { @@ -9797,32 +9833,25 @@ next: multilist_sublist_remove(mls, local_marker); } - /* - * Position persistent marker for next iteration. In case of - * save_position, validate that prev_hdr still belongs to the current - * sublist. The sublist lock is dropped during L2ARC write I/O, allowing - * ARC eviction to potentially free prev_hdr. If freed, we can't do much - * except to reset the marker. - */ + /* Reposition persistent marker for next iteration. */ multilist_sublist_remove(mls, persistent_marker); if (save_position && - multilist_link_active(&prev_hdr->b_l1hdr.b_arc_node)) { - if (hdr != NULL) { - /* - * Break: prev_hdr not written, retry next time. - * Scan is TAIL->HEAD, so insert_after = retry. - */ - multilist_sublist_insert_after(mls, prev_hdr, - persistent_marker); - } else { - /* - * List end: prev_hdr processed, move on. - * insert_before = skip prev_hdr next scan. - */ - multilist_sublist_insert_before(mls, prev_hdr, - persistent_marker); - } + spa->spa_l2arc_info.l2arc_sublist_reset[pass][sublist_idx]) { + /* Reset flagged during scan, restart from tail. */ + multilist_sublist_insert_tail(mls, persistent_marker); + spa->spa_l2arc_info.l2arc_sublist_reset[pass][sublist_idx] = + B_FALSE; + } else if (save_position && hdr != NULL) { + /* + * Write budget or sublist headroom exhausted, position + * marker after hdr to retry it next time. + */ + multilist_sublist_insert_after(mls, hdr, persistent_marker); + } else if (save_position) { + /* End of sublist, position marker at head. */ + multilist_sublist_insert_head(mls, persistent_marker); } else { + /* Non-persistent, reset marker to tail. */ multilist_sublist_insert_tail(mls, persistent_marker); } @@ -9845,40 +9874,60 @@ l2arc_blk_fetch_done(zio_t *zio) } /* - * Reset all L2ARC markers to tail position for the given spa. + * Return the total size of the ARC state corresponding to the given + * L2ARC pass number (0..3). + */ +static uint64_t +l2arc_get_state_size(int pass) +{ + switch (pass) { + case L2ARC_MFU_META: + return (zfs_refcount_count( + &arc_mfu->arcs_size[ARC_BUFC_METADATA])); + case L2ARC_MRU_META: + return (zfs_refcount_count( + &arc_mru->arcs_size[ARC_BUFC_METADATA])); + case L2ARC_MFU_DATA: + return (zfs_refcount_count( + &arc_mfu->arcs_size[ARC_BUFC_DATA])); + case L2ARC_MRU_DATA: + return (zfs_refcount_count( + &arc_mru->arcs_size[ARC_BUFC_DATA])); + default: + return (0); + } +} + +/* + * Flag all sublists for a single pass for lazy marker reset to tail. + * Each sublist's marker will be reset when next visited by a feed thread. */ static void -l2arc_reset_all_markers(spa_t *spa) +l2arc_flag_pass_reset(spa_t *spa, int pass) { - ASSERT(spa->spa_l2arc_info.l2arc_markers != NULL); ASSERT(MUTEX_HELD(&spa->spa_l2arc_info.l2arc_sublist_lock)); - for (int pass = 0; pass < L2ARC_FEED_TYPES; pass++) { - if (spa->spa_l2arc_info.l2arc_markers[pass] == NULL) - continue; - - multilist_t *ml = l2arc_get_list(pass); - int num_sublists = multilist_get_num_sublists(ml); - - for (int i = 0; i < num_sublists; i++) { - ASSERT3P(spa->spa_l2arc_info.l2arc_markers[pass][i], - !=, NULL); - multilist_sublist_t *mls = - multilist_sublist_lock_idx(ml, i); + multilist_t *ml = l2arc_get_list(pass); + int num_sublists = multilist_get_num_sublists(ml); - /* Remove from current position */ - ASSERT(multilist_link_active(&spa->spa_l2arc_info. - l2arc_markers[pass][i]->b_l1hdr.b_arc_node)); - multilist_sublist_remove(mls, spa->spa_l2arc_info. - l2arc_markers[pass][i]); + for (int i = 0; i < num_sublists; i++) { + multilist_sublist_t *mls = multilist_sublist_lock_idx(ml, i); + spa->spa_l2arc_info.l2arc_sublist_reset[pass][i] = B_TRUE; + multilist_sublist_unlock(mls); + } - /* Insert at tail (like initialization) */ - multilist_sublist_insert_tail(mls, - spa->spa_l2arc_info.l2arc_markers[pass][i]); + spa->spa_l2arc_info.l2arc_ext_scanned[pass] = 0; +} - multilist_sublist_unlock(mls); - } - } +/* + * Flag all L2ARC markers for lazy reset to tail for the given spa. + * Each sublist's marker will be reset when next visited by a feed thread. + */ +static void +l2arc_reset_all_markers(spa_t *spa) +{ + for (int pass = 0; pass < L2ARC_FEED_TYPES; pass++) + l2arc_flag_pass_reset(spa, pass); /* Reset write counter */ spa->spa_l2arc_info.l2arc_total_writes = 0; @@ -9938,6 +9987,12 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) /* * Copy buffers for L2ARC writing. */ + boolean_t skip_meta = (save_position && + l2arc_meta_cycles > 0 && + dev->l2ad_meta_cycles >= l2arc_meta_cycles); + if (skip_meta) + dev->l2ad_meta_cycles = 0; + for (int pass = 0; pass < L2ARC_FEED_TYPES; pass++) { /* * pass == 0: MFU meta @@ -9953,6 +10008,9 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) continue; } + if (skip_meta && pass <= L2ARC_MRU_META) + continue; + headroom = target_sz * l2arc_headroom; if (zfs_compressed_arc_enabled) headroom = (headroom * l2arc_headroom_boost) / 100; @@ -9960,22 +10018,22 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) multilist_t *ml = l2arc_get_list(pass); ASSERT3P(ml, !=, NULL); int num_sublists = multilist_get_num_sublists(ml); - int current_sublist = multilist_get_random_index(ml); uint64_t consumed_headroom = 0; + /* + * Equal per-sublist headroom prevents later + * sublists from getting disproportionate shares + * that would defeat the depth cap. + */ + uint64_t sublist_headroom = headroom / num_sublists; + + int current_sublist = spa->spa_l2arc_info. + l2arc_next_sublist[pass]; int processed_sublists = 0; while (processed_sublists < num_sublists && !full) { - uint64_t sublist_headroom; - if (consumed_headroom >= headroom) break; - sublist_headroom = (headroom - consumed_headroom) / - (num_sublists - processed_sublists); - - if (sublist_headroom == 0) - break; - /* * Check if sublist is busy (being processed by another * L2ARC device thread). If so, skip to next sublist. @@ -10016,10 +10074,54 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz) processed_sublists++; } + spa->spa_l2arc_info.l2arc_next_sublist[pass] = + (spa->spa_l2arc_info.l2arc_next_sublist[pass] + 1) % + num_sublists; + + /* + * Count consecutive metadata monopolization toward + * l2arc_meta_cycles. Only count when metadata actually + * filled the write budget, starving data passes. + */ + if (save_position && pass <= L2ARC_MRU_META && full) + dev->l2ad_meta_cycles++; + + /* + * Depth cap: track cumulative bytes scanned per pass + * and reset markers when the scan cap is reached. + * Keeps the marker near the tail where L2ARC adds + * the most value. + */ + if (save_position) { + mutex_enter(&spa->spa_l2arc_info.l2arc_sublist_lock); + + spa->spa_l2arc_info.l2arc_ext_scanned[pass] += + consumed_headroom; + + uint64_t state_sz = l2arc_get_state_size(pass); + uint64_t scan_cap = + state_sz * l2arc_ext_headroom_pct / 100; + + if (scan_cap > 0 && + spa->spa_l2arc_info.l2arc_ext_scanned[pass] >= + scan_cap) { + l2arc_flag_pass_reset(spa, pass); + } + + mutex_exit(&spa->spa_l2arc_info.l2arc_sublist_lock); + } + if (full == B_TRUE) break; } + /* + * If nothing was written at all, reset monopolization counter. + * No point skipping metadata if data has nothing either. + */ + if (write_asize == 0) + dev->l2ad_meta_cycles = 0; + /* No buffers selected for writing? */ if (pio == NULL) { ASSERT0(write_psize); @@ -11663,6 +11765,12 @@ ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, mfuonly, INT, ZMOD_RW, ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, exclude_special, INT, ZMOD_RW, "Exclude dbufs on special vdevs from being cached to L2ARC if set."); +ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, meta_cycles, U64, ZMOD_RW, + "Consecutive metadata cycles before skipping to let data run"); + +ZFS_MODULE_PARAM(zfs_l2arc, l2arc_, ext_headroom_pct, U64, ZMOD_RW, + "Depth cap as percentage of state size for marker reset"); + ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, lotsfree_percent, param_set_arc_int, param_get_uint, ZMOD_RW, "System free memory I/O throttle in bytes"); diff --git a/sys/contrib/openzfs/module/zfs/dmu_redact.c b/sys/contrib/openzfs/module/zfs/dmu_redact.c index c087be4c811d..75d43d3be21c 100644 --- a/sys/contrib/openzfs/module/zfs/dmu_redact.c +++ b/sys/contrib/openzfs/module/zfs/dmu_redact.c @@ -176,11 +176,7 @@ objnode_compare(const void *o1, const void *o2) { const struct objnode *obj1 = o1; const struct objnode *obj2 = o2; - if (obj1->obj < obj2->obj) - return (-1); - if (obj1->obj > obj2->obj) - return (1); - return (0); + return (TREE_CMP(obj1->obj, obj2->obj)); } @@ -425,11 +421,11 @@ redact_node_compare_start(const void *arg1, const void *arg2) if (rr2->eos_marker) return (-1); - int cmp = redact_range_compare(rr1->start_object, rr1->start_blkid, - rr1->datablksz, rr2->start_object, rr2->start_blkid, - rr2->datablksz); + int cmp = redact_range_compare( + rr1->start_object, rr1->start_blkid, rr1->datablksz, + rr2->start_object, rr2->start_blkid, rr2->datablksz); if (cmp == 0) - cmp = (rn1->thread_num < rn2->thread_num ? -1 : 1); + cmp = TREE_CMP(rn1->thread_num, rn2->thread_num); return (cmp); } @@ -451,11 +447,11 @@ redact_node_compare_end(const void *arg1, const void *arg2) if (srr2->eos_marker) return (-1); - int cmp = redact_range_compare(srr1->end_object, srr1->end_blkid, - srr1->datablksz, srr2->end_object, srr2->end_blkid, - srr2->datablksz); + int cmp = redact_range_compare( + srr1->end_object, srr1->end_blkid, srr1->datablksz, + srr2->end_object, srr2->end_blkid, srr2->datablksz); if (cmp == 0) - cmp = (rn1->thread_num < rn2->thread_num ? -1 : 1); + cmp = TREE_CMP(rn1->thread_num, rn2->thread_num); return (cmp); } diff --git a/sys/contrib/openzfs/module/zfs/dsl_bookmark.c b/sys/contrib/openzfs/module/zfs/dsl_bookmark.c index ee574c499f9f..8533657ad03b 100644 --- a/sys/contrib/openzfs/module/zfs/dsl_bookmark.c +++ b/sys/contrib/openzfs/module/zfs/dsl_bookmark.c @@ -837,8 +837,7 @@ dsl_bookmark_compare(const void *l, const void *r) (rdbn->dbn_phys.zbm_flags & ZBM_FLAG_HAS_FBN)); if (likely(cmp)) return (cmp); - cmp = strcmp(ldbn->dbn_name, rdbn->dbn_name); - return (TREE_ISIGN(cmp)); + return (TREE_ISIGN(strcmp(ldbn->dbn_name, rdbn->dbn_name))); } /* diff --git a/sys/contrib/openzfs/module/zfs/dsl_crypt.c b/sys/contrib/openzfs/module/zfs/dsl_crypt.c index f519b937edc0..9cb1536642d1 100644 --- a/sys/contrib/openzfs/module/zfs/dsl_crypt.c +++ b/sys/contrib/openzfs/module/zfs/dsl_crypt.c @@ -259,12 +259,7 @@ spa_crypto_key_compare(const void *a, const void *b) { const dsl_crypto_key_t *dcka = a; const dsl_crypto_key_t *dckb = b; - - if (dcka->dck_obj < dckb->dck_obj) - return (-1); - if (dcka->dck_obj > dckb->dck_obj) - return (1); - return (0); + return (TREE_CMP(dcka->dck_obj, dckb->dck_obj)); } /* @@ -306,12 +301,7 @@ spa_key_mapping_compare(const void *a, const void *b) { const dsl_key_mapping_t *kma = a; const dsl_key_mapping_t *kmb = b; - - if (kma->km_dsobj < kmb->km_dsobj) - return (-1); - if (kma->km_dsobj > kmb->km_dsobj) - return (1); - return (0); + return (TREE_CMP(kma->km_dsobj, kmb->km_dsobj)); } static int @@ -319,12 +309,7 @@ spa_wkey_compare(const void *a, const void *b) { const dsl_wrapping_key_t *wka = a; const dsl_wrapping_key_t *wkb = b; - - if (wka->wk_ddobj < wkb->wk_ddobj) - return (-1); - if (wka->wk_ddobj > wkb->wk_ddobj) - return (1); - return (0); + return (TREE_CMP(wka->wk_ddobj, wkb->wk_ddobj)); } void diff --git a/sys/contrib/openzfs/module/zfs/dsl_deadlist.c b/sys/contrib/openzfs/module/zfs/dsl_deadlist.c index 41ac72bf1c16..8b7b7cef1806 100644 --- a/sys/contrib/openzfs/module/zfs/dsl_deadlist.c +++ b/sys/contrib/openzfs/module/zfs/dsl_deadlist.c @@ -1001,16 +1001,14 @@ livelist_compare(const void *larg, const void *rarg) const blkptr_t *r = &((livelist_entry_t *)rarg)->le_bp; /* Sort them according to dva[0] */ - uint64_t l_dva0_vdev = DVA_GET_VDEV(&l->blk_dva[0]); - uint64_t r_dva0_vdev = DVA_GET_VDEV(&r->blk_dva[0]); - - if (l_dva0_vdev != r_dva0_vdev) - return (TREE_CMP(l_dva0_vdev, r_dva0_vdev)); + int cmp = TREE_CMP(DVA_GET_VDEV(&l->blk_dva[0]), + DVA_GET_VDEV(&r->blk_dva[0])); + if (cmp != 0) + return (cmp); /* if vdevs are equal, sort by offsets. */ - uint64_t l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]); - uint64_t r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]); - return (TREE_CMP(l_dva0_offset, r_dva0_offset)); + return (TREE_CMP(DVA_GET_OFFSET(&l->blk_dva[0]), + DVA_GET_OFFSET(&r->blk_dva[0]))); } struct livelist_iter_arg { diff --git a/sys/contrib/openzfs/module/zfs/dsl_deleg.c b/sys/contrib/openzfs/module/zfs/dsl_deleg.c index fdd37b36e280..200bee200d34 100644 --- a/sys/contrib/openzfs/module/zfs/dsl_deleg.c +++ b/sys/contrib/openzfs/module/zfs/dsl_deleg.c @@ -395,11 +395,7 @@ perm_set_compare(const void *arg1, const void *arg2) { const perm_set_t *node1 = (const perm_set_t *)arg1; const perm_set_t *node2 = (const perm_set_t *)arg2; - int val; - - val = strcmp(node1->p_setname, node2->p_setname); - - return (TREE_ISIGN(val)); + return (TREE_ISIGN(strcmp(node1->p_setname, node2->p_setname))); } /* diff --git a/sys/contrib/openzfs/module/zfs/dsl_scan.c b/sys/contrib/openzfs/module/zfs/dsl_scan.c index ae36161dd1b6..6f5dfac7b9d7 100644 --- a/sys/contrib/openzfs/module/zfs/dsl_scan.c +++ b/sys/contrib/openzfs/module/zfs/dsl_scan.c @@ -1473,12 +1473,7 @@ static int scan_ds_queue_compare(const void *a, const void *b) { const scan_ds_t *sds_a = a, *sds_b = b; - - if (sds_a->sds_dsobj < sds_b->sds_dsobj) - return (-1); - if (sds_a->sds_dsobj == sds_b->sds_dsobj) - return (0); - return (1); + return (TREE_CMP(sds_a->sds_dsobj, sds_b->sds_dsobj)); } static void diff --git a/sys/contrib/openzfs/module/zfs/metaslab.c b/sys/contrib/openzfs/module/zfs/metaslab.c index 0c359928a8d4..6ea3ecd74fc3 100644 --- a/sys/contrib/openzfs/module/zfs/metaslab.c +++ b/sys/contrib/openzfs/module/zfs/metaslab.c @@ -808,6 +808,12 @@ metaslab_class_fragmentation(metaslab_class_t *mc) spa_config_enter(mc->mc_spa, SCL_VDEV, FTAG, RW_READER); + uint64_t space = metaslab_class_get_space(mc); + if (space == 0) { + spa_config_exit(mc->mc_spa, SCL_VDEV, FTAG); + return (ZFS_FRAG_INVALID); + } + for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; metaslab_group_t *mg = tvd->vdev_mg; @@ -837,7 +843,7 @@ metaslab_class_fragmentation(metaslab_class_t *mc) fragmentation += mg->mg_fragmentation * metaslab_group_get_space(mg); } - fragmentation /= metaslab_class_get_space(mc); + fragmentation /= space; ASSERT3U(fragmentation, <=, 100); spa_config_exit(mc->mc_spa, SCL_VDEV, FTAG); diff --git a/sys/contrib/openzfs/module/zfs/refcount.c b/sys/contrib/openzfs/module/zfs/refcount.c index aa2902d0b84e..ffee54687ddd 100644 --- a/sys/contrib/openzfs/module/zfs/refcount.c +++ b/sys/contrib/openzfs/module/zfs/refcount.c @@ -57,10 +57,12 @@ zfs_refcount_compare(const void *x1, const void *x2) const reference_t *r1 = (const reference_t *)x1; const reference_t *r2 = (const reference_t *)x2; - int cmp1 = TREE_CMP(r1->ref_holder, r2->ref_holder); - int cmp2 = TREE_CMP(r1->ref_number, r2->ref_number); - int cmp = cmp1 ? cmp1 : cmp2; - return ((cmp || r1->ref_search) ? cmp : TREE_PCMP(r1, r2)); + int cmp = TREE_CMP(r1->ref_holder, r2->ref_holder); + if (cmp == 0) + cmp = TREE_CMP(r1->ref_number, r2->ref_number); + if (cmp | r1->ref_search) + return (cmp); + return (TREE_PCMP(r1, r2)); } void diff --git a/sys/contrib/openzfs/module/zfs/spa.c b/sys/contrib/openzfs/module/zfs/spa.c index 843b1b9d66bb..4397c14b5c77 100644 --- a/sys/contrib/openzfs/module/zfs/spa.c +++ b/sys/contrib/openzfs/module/zfs/spa.c @@ -418,6 +418,44 @@ spa_prop_get_nvlist(spa_t *spa, char **props, unsigned int n_props, } /* + * Add metaslab class properties to an nvlist. + */ +static void +spa_prop_add_metaslab_class(nvlist_t *nv, metaslab_class_t *mc, + zpool_mc_props_t mcp, uint64_t *sizep, uint64_t *allocp, uint64_t *usablep, + uint64_t *usedp) +{ + uint64_t size = metaslab_class_get_space(mc); + uint64_t alloc = metaslab_class_get_alloc(mc); + uint64_t dsize = metaslab_class_get_dspace(mc); + uint64_t dalloc = metaslab_class_get_dalloc(mc); + uint64_t cap = (size == 0) ? 0 : (alloc * 100 / size); + const zprop_source_t src = ZPROP_SRC_NONE; + + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_SIZE, NULL, size, src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_ALLOCATED, NULL, alloc, src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_USABLE, NULL, dsize, src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_USED, NULL, dalloc, src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_FRAGMENTATION, NULL, + metaslab_class_fragmentation(mc), src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_EXPANDSZ, NULL, + metaslab_class_expandable_space(mc), src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_FREE, NULL, size - alloc, + src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_AVAILABLE, NULL, + dsize - dalloc, src); + spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_CAPACITY, NULL, cap, src); + if (sizep != NULL) + *sizep += size; + if (allocp != NULL) + *allocp += alloc; + if (usablep != NULL) + *usablep += dsize; + if (usedp != NULL) + *usedp += dalloc; +} + +/* * Add a user property (source=src, propname=propval) to an nvlist. */ static void @@ -441,7 +479,7 @@ spa_prop_get_config(spa_t *spa, nvlist_t *nv) { vdev_t *rvd = spa->spa_root_vdev; dsl_pool_t *pool = spa->spa_dsl_pool; - uint64_t size, alloc, cap, version; + uint64_t size, alloc, usable, used, cap, version; const zprop_source_t src = ZPROP_SRC_NONE; spa_config_dirent_t *dp; metaslab_class_t *mc = spa_normal_class(spa); @@ -449,37 +487,42 @@ spa_prop_get_config(spa_t *spa, nvlist_t *nv) ASSERT(MUTEX_HELD(&spa->spa_props_lock)); if (rvd != NULL) { - alloc = metaslab_class_get_alloc(mc); - alloc += metaslab_class_get_alloc(spa_special_class(spa)); - alloc += metaslab_class_get_alloc(spa_dedup_class(spa)); - alloc += metaslab_class_get_alloc(spa_embedded_log_class(spa)); - alloc += metaslab_class_get_alloc( - spa_special_embedded_log_class(spa)); + spa_prop_add_list(nv, ZPOOL_PROP_NAME, spa_name(spa), 0, src); - size = metaslab_class_get_space(mc); - size += metaslab_class_get_space(spa_special_class(spa)); - size += metaslab_class_get_space(spa_dedup_class(spa)); - size += metaslab_class_get_space(spa_embedded_log_class(spa)); - size += metaslab_class_get_space( - spa_special_embedded_log_class(spa)); + size = alloc = usable = used = 0; + spa_prop_add_metaslab_class(nv, mc, ZPOOL_MC_PROPS_NORMAL, + &size, &alloc, &usable, &used); + spa_prop_add_metaslab_class(nv, spa_special_class(spa), + ZPOOL_MC_PROPS_SPECIAL, &size, &alloc, &usable, &used); + spa_prop_add_metaslab_class(nv, spa_dedup_class(spa), + ZPOOL_MC_PROPS_DEDUP, &size, &alloc, &usable, &used); + spa_prop_add_metaslab_class(nv, spa_log_class(spa), + ZPOOL_MC_PROPS_LOG, NULL, NULL, NULL, NULL); + spa_prop_add_metaslab_class(nv, spa_embedded_log_class(spa), + ZPOOL_MC_PROPS_ELOG, &size, &alloc, &usable, &used); + spa_prop_add_metaslab_class(nv, + spa_special_embedded_log_class(spa), ZPOOL_MC_PROPS_SELOG, + &size, &alloc, &usable, &used); - spa_prop_add_list(nv, ZPOOL_PROP_NAME, spa_name(spa), 0, src); spa_prop_add_list(nv, ZPOOL_PROP_SIZE, NULL, size, src); spa_prop_add_list(nv, ZPOOL_PROP_ALLOCATED, NULL, alloc, src); spa_prop_add_list(nv, ZPOOL_PROP_FREE, NULL, size - alloc, src); - spa_prop_add_list(nv, ZPOOL_PROP_CHECKPOINT, NULL, - spa->spa_checkpoint_info.sci_dspace, src); - spa_prop_add_list(nv, ZPOOL_PROP_FRAGMENTATION, NULL, metaslab_class_fragmentation(mc), src); spa_prop_add_list(nv, ZPOOL_PROP_EXPANDSZ, NULL, metaslab_class_expandable_space(mc), src); - spa_prop_add_list(nv, ZPOOL_PROP_READONLY, NULL, - (spa_mode(spa) == SPA_MODE_READ), src); - cap = (size == 0) ? 0 : (alloc * 100 / size); spa_prop_add_list(nv, ZPOOL_PROP_CAPACITY, NULL, cap, src); + spa_prop_add_list(nv, ZPOOL_PROP_AVAILABLE, NULL, usable - used, + src); + spa_prop_add_list(nv, ZPOOL_PROP_USABLE, NULL, usable, src); + spa_prop_add_list(nv, ZPOOL_PROP_USED, NULL, used, src); + + spa_prop_add_list(nv, ZPOOL_PROP_CHECKPOINT, NULL, + spa->spa_checkpoint_info.sci_dspace, src); + spa_prop_add_list(nv, ZPOOL_PROP_READONLY, NULL, + (spa_mode(spa) == SPA_MODE_READ), src); spa_prop_add_list(nv, ZPOOL_PROP_DEDUPRATIO, NULL, ddt_get_pool_dedup_ratio(spa), src); diff --git a/sys/contrib/openzfs/module/zfs/spa_misc.c b/sys/contrib/openzfs/module/zfs/spa_misc.c index eaaa429eda33..9b110f31f9ed 100644 --- a/sys/contrib/openzfs/module/zfs/spa_misc.c +++ b/sys/contrib/openzfs/module/zfs/spa_misc.c @@ -1891,6 +1891,12 @@ spa_syncing_txg(spa_t *spa) return (spa->spa_syncing_txg); } +uint64_t +spa_open_txg(spa_t *spa) +{ + return (spa->spa_dsl_pool->dp_tx.tx_open_txg); +} + /* * Return the last txg where data can be dirtied. The final txgs * will be used to just clear out any deferred frees that remain. @@ -2616,11 +2622,8 @@ spa_name_compare(const void *a1, const void *a2) { const spa_t *s1 = a1; const spa_t *s2 = a2; - int s; - - s = strcmp(s1->spa_name, s2->spa_name); - return (TREE_ISIGN(s)); + return (TREE_ISIGN(strcmp(s1->spa_name, s2->spa_name))); } void diff --git a/sys/contrib/openzfs/module/zfs/vdev.c b/sys/contrib/openzfs/module/zfs/vdev.c index aedc4714fe4b..9def59b06727 100644 --- a/sys/contrib/openzfs/module/zfs/vdev.c +++ b/sys/contrib/openzfs/module/zfs/vdev.c @@ -31,6 +31,7 @@ * Copyright (c) 2019, Datto Inc. All rights reserved. * Copyright (c) 2021, 2025, Klara, Inc. * Copyright (c) 2021, 2023 Hewlett Packard Enterprise Development LP. + * Copyright (c) 2026, Seagate Technology, LLC. */ #include <sys/zfs_context.h> @@ -3096,8 +3097,11 @@ vdev_dtl_dirty(vdev_t *vd, vdev_dtl_type_t t, uint64_t txg, uint64_t size) ASSERT(spa_writeable(vd->vdev_spa)); mutex_enter(&vd->vdev_dtl_lock); - if (!zfs_range_tree_contains(rt, txg, size)) + if (!zfs_range_tree_contains(rt, txg, size)) { + /* Clear whatever is there already. */ + zfs_range_tree_clear(rt, txg, size); zfs_range_tree_add(rt, txg, size); + } mutex_exit(&vd->vdev_dtl_lock); } @@ -5220,11 +5224,13 @@ vdev_stat_update(zio_t *zio, uint64_t psize) if (type == ZIO_TYPE_WRITE && txg != 0 && (!(flags & ZIO_FLAG_IO_REPAIR) || (flags & ZIO_FLAG_SCAN_THREAD) || + zio->io_priority == ZIO_PRIORITY_REBUILD || spa->spa_claiming)) { /* * This is either a normal write (not a repair), or it's * a repair induced by the scrub thread, or it's a repair - * made by zil_claim() during spa_load() in the first txg. + * made by zil_claim() during spa_load() in the first txg, + * or its repair induced by rebuild (sequential resilver). * In the normal case, we commit the DTL change in the same * txg as the block was born. In the scrub-induced repair * case, we know that scrubs run in first-pass syncing context, @@ -5235,27 +5241,38 @@ vdev_stat_update(zio_t *zio, uint64_t psize) * self-healing writes triggered by normal (non-scrubbing) * reads, because we have no transactional context in which to * do so -- and it's not clear that it'd be desirable anyway. + * + * For rebuild, since we don't have any information about BPs + * and txgs that are being rebuilt, we need to add all known + * txgs (starting from TXG_INITIAL) to DTL so that during + * healing resilver we would be able to check all txgs at + * vdev_draid_need_resilver(). */ + uint64_t size = 1; if (vd->vdev_ops->vdev_op_leaf) { uint64_t commit_txg = txg; if (flags & ZIO_FLAG_SCAN_THREAD) { ASSERT(flags & ZIO_FLAG_IO_REPAIR); ASSERT(spa_sync_pass(spa) == 1); - vdev_dtl_dirty(vd, DTL_SCRUB, txg, 1); + vdev_dtl_dirty(vd, DTL_SCRUB, txg, size); commit_txg = spa_syncing_txg(spa); } else if (spa->spa_claiming) { ASSERT(flags & ZIO_FLAG_IO_REPAIR); commit_txg = spa_first_txg(spa); + } else if (zio->io_priority == ZIO_PRIORITY_REBUILD) { + ASSERT(flags & ZIO_FLAG_IO_REPAIR); + vdev_rebuild_txgs(vd->vdev_top, &txg, &size); + commit_txg = spa_open_txg(spa); } ASSERT(commit_txg >= spa_syncing_txg(spa)); - if (vdev_dtl_contains(vd, DTL_MISSING, txg, 1)) + if (vdev_dtl_contains(vd, DTL_MISSING, txg, size)) return; for (pvd = vd; pvd != rvd; pvd = pvd->vdev_parent) - vdev_dtl_dirty(pvd, DTL_PARTIAL, txg, 1); + vdev_dtl_dirty(pvd, DTL_PARTIAL, txg, size); vdev_dirty(vd->vdev_top, VDD_DTL, vd, commit_txg); } if (vd != rvd) - vdev_dtl_dirty(vd, DTL_MISSING, txg, 1); + vdev_dtl_dirty(vd, DTL_MISSING, txg, size); } } diff --git a/sys/contrib/openzfs/module/zfs/vdev_draid.c b/sys/contrib/openzfs/module/zfs/vdev_draid.c index 8588cfee3f7d..9e02d868213b 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_draid.c +++ b/sys/contrib/openzfs/module/zfs/vdev_draid.c @@ -1452,13 +1452,6 @@ vdev_draid_group_missing(vdev_t *vd, uint64_t offset, uint64_t txg, /* Transaction group is known to be partially replicated. */ if (vdev_draid_partial(cvd, physical_offset, txg, size)) return (B_TRUE); - - /* - * Always check groups with active distributed spares - * because any vdev failure in the pool will affect them. - */ - if (vdev_draid_find_spare(cvd) != NULL) - return (B_TRUE); } return (B_FALSE); diff --git a/sys/contrib/openzfs/module/zfs/vdev_queue.c b/sys/contrib/openzfs/module/zfs/vdev_queue.c index 1dc447c727d6..1c740bf81af3 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_queue.c +++ b/sys/contrib/openzfs/module/zfs/vdev_queue.c @@ -226,10 +226,10 @@ vdev_queue_to_compare(const void *x1, const void *x2) const zio_t *z1 = (const zio_t *)x1; const zio_t *z2 = (const zio_t *)x2; - int tcmp = TREE_CMP(z1->io_timestamp >> VDQ_T_SHIFT, + int cmp = TREE_CMP(z1->io_timestamp >> VDQ_T_SHIFT, z2->io_timestamp >> VDQ_T_SHIFT); - int ocmp = TREE_CMP(z1->io_offset, z2->io_offset); - int cmp = tcmp ? tcmp : ocmp; + if (cmp == 0) + cmp = TREE_CMP(z1->io_offset, z2->io_offset); if (likely(cmp | (z1->io_queue_state == ZIO_QS_NONE))) return (cmp); diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz_math.c b/sys/contrib/openzfs/module/zfs/vdev_raidz_math.c index bdc159d8ec80..ca8ead23e6fa 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz_math.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz_math.c @@ -47,19 +47,19 @@ static raidz_impl_ops_t vdev_raidz_fastest_impl = { static const raidz_impl_ops_t *const raidz_all_maths[] = { &vdev_raidz_original_impl, &vdev_raidz_scalar_impl, -#if defined(__x86_64) && defined(HAVE_SSE2) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(SSE2) /* only x86_64 for now */ &vdev_raidz_sse2_impl, #endif -#if defined(__x86_64) && defined(HAVE_SSSE3) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(SSSE3) /* only x86_64 for now */ &vdev_raidz_ssse3_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX2) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(AVX2) /* only x86_64 for now */ &vdev_raidz_avx2_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX512F) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(AVX512F) /* only x86_64 for now */ &vdev_raidz_avx512f_impl, #endif -#if defined(__x86_64) && defined(HAVE_AVX512BW) /* only x86_64 for now */ +#if defined(__x86_64) && HAVE_SIMD(AVX512BW) /* only x86_64 for now */ &vdev_raidz_avx512bw_impl, #endif #if defined(__aarch64__) && !defined(__FreeBSD__) diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx2.c b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx2.c index d0311e522632..03444ccdfd3f 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx2.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx2.c @@ -22,9 +22,10 @@ /* * Copyright (C) 2016 Gvozden Nešković. All rights reserved. */ + #include <sys/isa_defs.h> -#if defined(__x86_64) && defined(HAVE_AVX2) +#if defined(__x86_64) && HAVE_SIMD(AVX2) #include <sys/types.h> #include <sys/simd.h> @@ -411,4 +412,4 @@ const raidz_impl_ops_t vdev_raidz_avx2_impl = { .name = "avx2" }; -#endif /* defined(__x86_64) && defined(HAVE_AVX2) */ +#endif /* defined(__x86_64) && HAVE_SIMD(AVX2) */ diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512bw.c b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512bw.c index 5ad2915e3266..0d9ed3938322 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512bw.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512bw.c @@ -26,7 +26,7 @@ #include <sys/isa_defs.h> -#if defined(__x86_64) && defined(HAVE_AVX512BW) +#if defined(__x86_64) && HAVE_SIMD(AVX512BW) #include <sys/param.h> #include <sys/types.h> @@ -411,4 +411,4 @@ const raidz_impl_ops_t vdev_raidz_avx512bw_impl = { .name = "avx512bw" }; -#endif /* defined(__x86_64) && defined(HAVE_AVX512BW) */ +#endif /* defined(__x86_64) && HAVE_SIMD(AVX512BW) */ diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512f.c b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512f.c index 17eb9f7097c4..e7738ff41db5 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512f.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_avx512f.c @@ -26,7 +26,7 @@ #include <sys/isa_defs.h> -#if defined(__x86_64) && defined(HAVE_AVX512F) +#if defined(__x86_64) && HAVE_SIMD(AVX512F) #include <sys/types.h> #include <sys/simd.h> @@ -492,4 +492,4 @@ const raidz_impl_ops_t vdev_raidz_avx512f_impl = { .name = "avx512f" }; -#endif /* defined(__x86_64) && defined(HAVE_AVX512F) */ +#endif /* defined(__x86_64) && HAVE_SIMD(AVX512F) */ diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_sse2.c b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_sse2.c index 3be4edeaab18..05037881a436 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_sse2.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_sse2.c @@ -25,7 +25,7 @@ #include <sys/isa_defs.h> -#if defined(__x86_64) && defined(HAVE_SSE2) +#if defined(__x86_64) && HAVE_SIMD(SSE2) #include <sys/types.h> #include <sys/simd.h> @@ -629,4 +629,4 @@ const raidz_impl_ops_t vdev_raidz_sse2_impl = { .name = "sse2" }; -#endif /* defined(__x86_64) && defined(HAVE_SSE2) */ +#endif /* defined(__x86_64) && HAVE_SIMD(SSE2) */ diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_ssse3.c b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_ssse3.c index 4067aaead4b0..88dcde379323 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_ssse3.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_ssse3.c @@ -25,7 +25,7 @@ #include <sys/isa_defs.h> -#if defined(__x86_64) && defined(HAVE_SSSE3) +#if defined(__x86_64) && HAVE_SIMD(SSSE3) #include <sys/types.h> #include <sys/simd.h> @@ -415,11 +415,11 @@ const raidz_impl_ops_t vdev_raidz_ssse3_impl = { .name = "ssse3" }; -#endif /* defined(__x86_64) && defined(HAVE_SSSE3) */ +#endif /* defined(__x86_64) && HAVE_SIMD(SSSE3) */ #if defined(__x86_64) -#if defined(HAVE_SSSE3) || defined(HAVE_AVX2) || defined(HAVE_AVX512BW) +#if HAVE_SIMD(SSSE3) || HAVE_SIMD(AVX2) || HAVE_SIMD(AVX512BW) /* BEGIN CSTYLED */ const uint8_t __attribute__((aligned(256))) gf_clmul_mod_lt[4*256][16] = @@ -2474,5 +2474,5 @@ __attribute__((aligned(256))) gf_clmul_mod_lt[4*256][16] = 0xf8, 0x07, 0x06, 0xf9, 0x04, 0xfb, 0xfa, 0x05 } }; /* END CSTYLED */ -#endif /* defined(HAVE_SSSE3) || defined(HAVE_AVX2) || defined(HAVE_AVX512BW) */ +#endif /* HAVE_SIMD(SSSE3) || HAVE_SIMD(AVX2) || HAVE_SIMD(AVX512BW) */ #endif /* defined(__x86_64) */ diff --git a/sys/contrib/openzfs/module/zfs/vdev_rebuild.c b/sys/contrib/openzfs/module/zfs/vdev_rebuild.c index 68a953780837..4fe6dc9d6fbb 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_rebuild.c +++ b/sys/contrib/openzfs/module/zfs/vdev_rebuild.c @@ -233,7 +233,7 @@ vdev_rebuild_initiate_sync(void *arg, dmu_tx_t *tx) mutex_enter(&vd->vdev_rebuild_lock); memset(vrp, 0, sizeof (uint64_t) * REBUILD_PHYS_ENTRIES); vrp->vrp_rebuild_state = VDEV_REBUILD_ACTIVE; - vrp->vrp_min_txg = 0; + vrp->vrp_min_txg = TXG_INITIAL; vrp->vrp_max_txg = dmu_tx_get_txg(tx); vrp->vrp_start_time = gethrestime_sec(); vrp->vrp_scan_time_ms = 0; @@ -415,7 +415,7 @@ vdev_rebuild_reset_sync(void *arg, dmu_tx_t *tx) ASSERT0P(vd->vdev_rebuild_thread); vrp->vrp_last_offset = 0; - vrp->vrp_min_txg = 0; + vrp->vrp_min_txg = TXG_INITIAL; vrp->vrp_max_txg = dmu_tx_get_txg(tx); vrp->vrp_bytes_scanned = 0; vrp->vrp_bytes_issued = 0; @@ -616,7 +616,6 @@ vdev_rebuild_range(vdev_rebuild_t *vr, uint64_t start, uint64_t size) return (SET_ERROR(EINTR)); } mutex_exit(&vd->vdev_rebuild_lock); - dmu_tx_commit(tx); vr->vr_scan_offset[txg & TXG_MASK] = start + size; vr->vr_pass_bytes_issued += size; @@ -626,6 +625,9 @@ vdev_rebuild_range(vdev_rebuild_t *vr, uint64_t start, uint64_t size) abd_alloc(psize, B_FALSE), psize, vdev_rebuild_cb, vr, ZIO_PRIORITY_REBUILD, ZIO_FLAG_RAW | ZIO_FLAG_CANFAIL | ZIO_FLAG_RESILVER, NULL)); + /* vdev_rebuild_cb releases SCL_STATE_ALL */ + + dmu_tx_commit(tx); return (0); } @@ -1126,6 +1128,22 @@ vdev_rebuild_stop_all(spa_t *spa) } /* + * Return rebuild transaction groups range. It's used to populate DTLs + * of the non-writable devices during the rebuild so that they could be + * healed correctly, in case they are cleared, and not miss the data + * that was written to their spares during the rebuild. + */ +void +vdev_rebuild_txgs(vdev_t *vd, uint64_t *min_txg, uint64_t *size) +{ + vdev_rebuild_t *vr = &vd->vdev_rebuild_config; + vdev_rebuild_phys_t *vrp = &vr->vr_rebuild_phys; + + *min_txg = vrp->vrp_min_txg; + *size = vrp->vrp_max_txg - vrp->vrp_min_txg; +} + +/* * Rebuild statistics reported per top-level vdev. */ int diff --git a/sys/contrib/openzfs/module/zfs/vdev_removal.c b/sys/contrib/openzfs/module/zfs/vdev_removal.c index 81e6ecb68ff1..e222f3f2dce0 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_removal.c +++ b/sys/contrib/openzfs/module/zfs/vdev_removal.c @@ -2151,7 +2151,6 @@ spa_vdev_remove_log(vdev_t *vd, uint64_t *txg) ASSERT0P(vd->vdev_log_mg); return (error); } - ASSERT0(vd->vdev_stat.vs_alloc); /* * The evacuation succeeded. Remove any remaining MOS metadata diff --git a/sys/contrib/openzfs/module/zfs/zfs_fuid.c b/sys/contrib/openzfs/module/zfs/zfs_fuid.c index aa10741ba870..62f5c33467d7 100644 --- a/sys/contrib/openzfs/module/zfs/zfs_fuid.c +++ b/sys/contrib/openzfs/module/zfs/zfs_fuid.c @@ -84,11 +84,8 @@ domain_compare(const void *arg1, const void *arg2) { const fuid_domain_t *node1 = (const fuid_domain_t *)arg1; const fuid_domain_t *node2 = (const fuid_domain_t *)arg2; - int val; - - val = strcmp(node1->f_ksid->kd_name, node2->f_ksid->kd_name); - - return (TREE_ISIGN(val)); + return (TREE_ISIGN(strcmp(node1->f_ksid->kd_name, + node2->f_ksid->kd_name))); } void diff --git a/sys/contrib/openzfs/module/zfs/zil.c b/sys/contrib/openzfs/module/zfs/zil.c index 0307df55aa21..0fa58d5ccb64 100644 --- a/sys/contrib/openzfs/module/zfs/zil.c +++ b/sys/contrib/openzfs/module/zfs/zil.c @@ -1096,7 +1096,7 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first) zilog->zl_old_header = *zh; /* debugging aid */ - if (BP_IS_HOLE(&zh->zh_log)) + if (BP_IS_HOLE(&zh->zh_log) && zh->zh_flags == 0) return (B_FALSE); tx = dmu_tx_create(zilog->zl_os); @@ -1166,6 +1166,15 @@ zil_claim(dsl_pool_t *dp, dsl_dataset_t *ds, void *txarg) zilog = dmu_objset_zil(os); zh = zil_header_in_syncing_context(zilog); ASSERT3U(tx->tx_txg, ==, spa_first_txg(zilog->zl_spa)); + + /* + * If the log is empty, then there is nothing to do here. + */ + if (BP_IS_HOLE(&zh->zh_log)) { + dmu_objset_disown(os, B_FALSE, FTAG); + return (0); + } + first_txg = spa_min_claim_txg(zilog->zl_spa); /* @@ -1198,11 +1207,14 @@ zil_claim(dsl_pool_t *dp, dsl_dataset_t *ds, void *txarg) if (spa_get_log_state(zilog->zl_spa) == SPA_LOG_CLEAR || (zilog->zl_spa->spa_uberblock.ub_checkpoint_txg != 0 && zh->zh_claim_txg == 0)) { - if (!BP_IS_HOLE(&zh->zh_log)) { + if (zilog->zl_spa->spa_uberblock.ub_checkpoint_txg != 0 && + BP_GET_BIRTH(&zh->zh_log) < first_txg) { (void) zil_parse(zilog, zil_clear_log_block, zil_noop_log_record, tx, first_txg, B_FALSE); + } else { + zio_free(zilog->zl_spa, first_txg, &zh->zh_log); } - BP_ZERO(&zh->zh_log); + memset(zh, 0, sizeof (zil_header_t)); if (os->os_encrypted) os->os_next_write_raw[tx->tx_txg & TXG_MASK] = B_TRUE; dsl_dataset_dirty(dmu_objset_ds(os), tx); @@ -1224,7 +1236,7 @@ zil_claim(dsl_pool_t *dp, dsl_dataset_t *ds, void *txarg) * or destroy beyond the last block we successfully claimed. */ ASSERT3U(zh->zh_claim_txg, <=, first_txg); - if (zh->zh_claim_txg == 0 && !BP_IS_HOLE(&zh->zh_log)) { + if (zh->zh_claim_txg == 0) { (void) zil_parse(zilog, zil_claim_log_block, zil_claim_log_record, tx, first_txg, B_FALSE); zh->zh_claim_txg = first_txg; diff --git a/sys/contrib/openzfs/module/zfs/zio.c b/sys/contrib/openzfs/module/zfs/zio.c index a48854563044..08cea9156688 100644 --- a/sys/contrib/openzfs/module/zfs/zio.c +++ b/sys/contrib/openzfs/module/zfs/zio.c @@ -910,33 +910,26 @@ zio_bookmark_compare(const void *x1, const void *x2) { const zio_t *z1 = x1; const zio_t *z2 = x2; + const zbookmark_phys_t *zb1 = &z1->io_bookmark; + const zbookmark_phys_t *zb2 = &z2->io_bookmark; - if (z1->io_bookmark.zb_objset < z2->io_bookmark.zb_objset) - return (-1); - if (z1->io_bookmark.zb_objset > z2->io_bookmark.zb_objset) - return (1); + int cmp = TREE_CMP(zb1->zb_objset, zb2->zb_objset); + if (cmp != 0) + return (cmp); - if (z1->io_bookmark.zb_object < z2->io_bookmark.zb_object) - return (-1); - if (z1->io_bookmark.zb_object > z2->io_bookmark.zb_object) - return (1); + cmp = TREE_CMP(zb1->zb_object, zb2->zb_object); + if (cmp != 0) + return (cmp); - if (z1->io_bookmark.zb_level < z2->io_bookmark.zb_level) - return (-1); - if (z1->io_bookmark.zb_level > z2->io_bookmark.zb_level) - return (1); + cmp = TREE_CMP(zb1->zb_level, zb2->zb_level); + if (cmp != 0) + return (cmp); - if (z1->io_bookmark.zb_blkid < z2->io_bookmark.zb_blkid) - return (-1); - if (z1->io_bookmark.zb_blkid > z2->io_bookmark.zb_blkid) - return (1); + cmp = TREE_CMP(zb1->zb_blkid, zb2->zb_blkid); + if (cmp != 0) + return (cmp); - if (z1 < z2) - return (-1); - if (z1 > z2) - return (1); - - return (0); + return (TREE_PCMP(z1, z2)); } /* diff --git a/sys/contrib/openzfs/module/zfs/zvol.c b/sys/contrib/openzfs/module/zfs/zvol.c index 407758641580..285b194a6969 100644 --- a/sys/contrib/openzfs/module/zfs/zvol.c +++ b/sys/contrib/openzfs/module/zfs/zvol.c @@ -108,6 +108,7 @@ unsigned int zvol_request_sync = 0; struct hlist_head *zvol_htable; static list_t zvol_state_list; krwlock_t zvol_state_lock; +extern int zfs_bclone_strict_properties; extern int zfs_bclone_wait_dirty; zv_taskq_t zvol_taskqs; @@ -663,14 +664,67 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst, error = SET_ERROR(EXDEV); goto out; } + + /* + * Block cloning from an unencrypted dataset into an encrypted + * dataset and vice versa is not supported. + */ if (inos->os_encrypted != outos->os_encrypted) { error = SET_ERROR(EXDEV); goto out; } + + /* + * Cloning across encrypted datasets is possible only if they + * share the same master key. + */ + if (inos != outos && inos->os_encrypted && + !dmu_objset_crypto_key_equal(inos, outos)) { + error = SET_ERROR(EXDEV); + goto out; + } + + /* + * Cloning between datasets with different properties is possible, + * but it may cause confusions when copying data between them and + * expecting new properties to apply. + */ + if (zfs_bclone_strict_properties && inos != outos && + !dmu_objset_is_snapshot(inos) && + (inos->os_checksum != outos->os_checksum || + inos->os_compress != outos->os_compress || + inos->os_copies != outos->os_copies || + inos->os_dedup_checksum != outos->os_dedup_checksum)) { + error = SET_ERROR(EXDEV); + goto out; + } + if (zv_src->zv_volblocksize != zv_dst->zv_volblocksize) { error = SET_ERROR(EINVAL); goto out; } + + /* + * Cloning between datasets with different special_small_blocks would + * bypass storage tier migration that would occur with a regular copy. + */ + if (zfs_bclone_strict_properties && inos != outos && + !dmu_objset_is_snapshot(inos) && + spa_has_special(dmu_objset_spa(inos))) { + uint64_t in_smallblk = inos->os_zpl_special_smallblock; + uint64_t out_smallblk = outos->os_zpl_special_smallblock; + if (in_smallblk != out_smallblk) { + uint64_t min_smallblk = MIN(in_smallblk, out_smallblk); + uint64_t max_smallblk = MAX(in_smallblk, out_smallblk); + if (min_smallblk < zv_src->zv_volblocksize && + (inos->os_compress != ZIO_COMPRESS_OFF || + max_smallblk >= zv_src->zv_volblocksize)) { + error = SET_ERROR(EXDEV); + goto out; + } + } + } + if (inoff >= zv_src->zv_volsize || outoff >= zv_dst->zv_volsize) { goto out; } @@ -686,6 +740,15 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst, goto out; /* + * Callers might not be able to detect properly that we are read-only, + * so check it explicitly here. + */ + if (zv_dst->zv_flags & ZVOL_RDONLY) { + error = SET_ERROR(EROFS); + goto out; + } + + /* * No overlapping if we are cloning within the same file */ if (zv_src == zv_dst) { diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run index 8394bc4bcda0..f22f3c759e9b 100644 --- a/sys/contrib/openzfs/tests/runfiles/common.run +++ b/sys/contrib/openzfs/tests/runfiles/common.run @@ -196,8 +196,8 @@ tags = ['functional', 'cli_root', 'zfs_change-key'] tests = ['zfs_clone_001_neg', 'zfs_clone_002_pos', 'zfs_clone_003_pos', 'zfs_clone_004_pos', 'zfs_clone_005_pos', 'zfs_clone_006_pos', 'zfs_clone_007_pos', 'zfs_clone_008_neg', 'zfs_clone_009_neg', - 'zfs_clone_010_pos', 'zfs_clone_encrypted', 'zfs_clone_deeply_nested', - 'zfs_clone_rm_nested', 'zfs_clone_nomount'] + 'zfs_clone_010_pos', 'zfs_clone_011_pos', 'zfs_clone_encrypted', + 'zfs_clone_deeply_nested', 'zfs_clone_rm_nested', 'zfs_clone_nomount'] tags = ['functional', 'cli_root', 'zfs_clone'] [tests/functional/cli_root/zfs_copies] @@ -210,9 +210,9 @@ tests = ['zfs_create_001_pos', 'zfs_create_002_pos', 'zfs_create_003_pos', 'zfs_create_004_pos', 'zfs_create_005_pos', 'zfs_create_006_pos', 'zfs_create_007_pos', 'zfs_create_008_neg', 'zfs_create_009_neg', 'zfs_create_010_neg', 'zfs_create_011_pos', 'zfs_create_012_pos', - 'zfs_create_013_pos', 'zfs_create_014_pos', 'zfs_create_encrypted', - 'zfs_create_crypt_combos', 'zfs_create_dryrun', 'zfs_create_nomount', - 'zfs_create_verbose'] + 'zfs_create_013_pos', 'zfs_create_014_pos', 'zfs_create_015_pos', + 'zfs_create_encrypted', 'zfs_create_crypt_combos', 'zfs_create_dryrun', + 'zfs_create_nomount', 'zfs_create_verbose'] tags = ['functional', 'cli_root', 'zfs_create'] [tests/functional/cli_root/zpool_prefetch] @@ -300,8 +300,9 @@ tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos', 'zfs_rename_004_neg', 'zfs_rename_005_neg', 'zfs_rename_006_pos', 'zfs_rename_007_pos', 'zfs_rename_008_pos', 'zfs_rename_009_neg', 'zfs_rename_010_neg', 'zfs_rename_011_pos', 'zfs_rename_012_neg', - 'zfs_rename_013_pos', 'zfs_rename_014_neg', 'zfs_rename_encrypted_child', - 'zfs_rename_to_encrypted', 'zfs_rename_mountpoint', 'zfs_rename_nounmount'] + 'zfs_rename_013_pos', 'zfs_rename_014_neg', 'zfs_rename_015_pos', + 'zfs_rename_encrypted_child', 'zfs_rename_to_encrypted', 'zfs_rename_mountpoint', + 'zfs_rename_nounmount'] tags = ['functional', 'cli_root', 'zfs_rename'] [tests/functional/cli_root/zfs_reservation] @@ -420,7 +421,7 @@ tests = ['zpool_create_001_pos', 'zpool_create_002_pos', 'zpool_create_017_neg', 'zpool_create_018_pos', 'zpool_create_019_pos', 'zpool_create_020_pos', 'zpool_create_021_pos', 'zpool_create_022_pos', 'zpool_create_023_neg', 'zpool_create_024_pos', - 'zpool_create_encrypted', 'zpool_create_crypt_combos', + 'zpool_create_encrypted', 'zpool_create_edom_neg', 'zpool_create_crypt_combos', 'zpool_create_draid_001_pos', 'zpool_create_draid_002_pos', 'zpool_create_draid_003_pos', 'zpool_create_draid_004_pos', 'zpool_create_features_001_pos', 'zpool_create_features_002_pos', @@ -456,8 +457,8 @@ tags = ['functional', 'cli_root', 'zpool_export'] [tests/functional/cli_root/zpool_get] tests = ['zpool_get_001_pos', 'zpool_get_002_pos', 'zpool_get_003_pos', - 'zpool_get_004_neg', 'zpool_get_005_pos', 'vdev_get_001_pos', - 'vdev_get_all'] + 'zpool_get_004_neg', 'zpool_get_005_pos', 'zpool_get_006_pos', + 'vdev_get_001_pos', 'vdev_get_all'] tags = ['functional', 'cli_root', 'zpool_get'] [tests/functional/cli_root/zpool_history] @@ -947,7 +948,7 @@ tests = ['removal_all_vdev', 'removal_cancel', 'removal_check_space', 'removal_with_write', 'removal_with_zdb', 'remove_expanded', 'remove_mirror', 'remove_mirror_sanity', 'remove_raidz', 'remove_indirect', 'remove_attach_mirror', 'removal_reservation', - 'removal_with_hole'] + 'removal_with_hole', 'removal_with_missing_log'] tags = ['functional', 'removal'] [tests/functional/rename_dirs] @@ -986,7 +987,8 @@ tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos', 'rsend_014_pos', 'rsend_016_neg', 'rsend_019_pos', 'rsend_020_pos', 'rsend_021_pos', 'rsend_022_pos', 'rsend_024_pos', 'rsend_025_pos', 'rsend_026_neg', 'rsend_027_pos', 'rsend_028_neg', 'rsend_029_neg', - 'rsend_030_pos', 'rsend_031_pos', 'send-c_verify_ratio', + 'rsend_030_pos', 'rsend_031_pos', 'rsend-exclude_001_pos', + 'rsend-exclude_002_pos', 'send-c_verify_ratio', 'send-c_verify_contents', 'send-c_props', 'send-c_incremental', 'send-c_volume', 'send-c_zstream_recompress', 'send-c_zstreamdump', 'send-c_lz4_disabled', 'send-c_recv_lz4_disabled', @@ -997,7 +999,8 @@ tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos', 'send_encrypted_props', 'send_encrypted_truncated_files', 'send_freeobjects', 'send_realloc_files', 'send_realloc_encrypted_files', 'send_spill_block', 'send_holds', 'send_hole_birth', 'send_mixed_raw', - 'send-wR_encrypted_zvol', 'send_partial_dataset', 'send_invalid', + 'send-wR_encrypted_zvol', 'send-zstream_drop_record', + 'send_partial_dataset', 'send_invalid', 'send_large_blocks_incremental', 'send_large_blocks_initial', 'send_large_microzap_incremental', 'send_large_microzap_transitive', 'send_doall', 'send_raw_spill_block', 'send_raw_ashift', diff --git a/sys/contrib/openzfs/tests/runfiles/sanity.run b/sys/contrib/openzfs/tests/runfiles/sanity.run index dad51d2e99be..9b49f63c5a90 100644 --- a/sys/contrib/openzfs/tests/runfiles/sanity.run +++ b/sys/contrib/openzfs/tests/runfiles/sanity.run @@ -270,7 +270,7 @@ tests = ['zpool_create_001_pos', 'zpool_create_002_pos', 'zpool_create_012_neg', 'zpool_create_014_neg', 'zpool_create_015_neg', 'zpool_create_017_neg', 'zpool_create_018_pos', 'zpool_create_019_pos', 'zpool_create_020_pos', 'zpool_create_021_pos', 'zpool_create_022_pos', - 'zpool_create_encrypted', + 'zpool_create_encrypted', 'zpool_create_edom_neg', 'zpool_create_features_001_pos', 'zpool_create_features_002_pos', 'zpool_create_features_003_pos', 'zpool_create_features_004_neg', 'zpool_create_features_005_pos'] @@ -557,7 +557,8 @@ tags = ['functional', 'reservation'] tests = ['recv_dedup', 'recv_dedup_encrypted_zvol', 'rsend_001_pos', 'rsend_002_pos', 'rsend_003_pos', 'rsend_004_pos', 'rsend_005_pos', 'rsend_006_pos', 'rsend_009_pos', 'rsend_010_pos', 'rsend_011_pos', - 'rsend_014_pos', 'rsend_016_neg', 'send-c_verify_contents', + 'rsend_014_pos', 'rsend_016_neg', 'rsend-exclude_001_pos', + 'rsend-exclude_002_pos', 'send-c_verify_contents', 'send-c_volume', 'send-c_zstreamdump', 'send-c_recv_dedup', 'send-L_toggle', 'send_encrypted_hierarchy', 'send_encrypted_props', 'send_encrypted_freeobjects', diff --git a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in index a3d3679714ea..a8251c511ac4 100755 --- a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in +++ b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in @@ -226,6 +226,7 @@ maybe = { ['FAIL', 11948], 'cli_root/zpool_initialize/zpool_initialize_suspend_resume': ['FAIL', known_reason], + 'cli_root/zpool_iostat/zpool_iostat_interval_all': ['FAIL', 18273], 'cli_root/zpool_labelclear/zpool_labelclear_removed': ['FAIL', known_reason], 'cli_root/zpool_trim/setup': ['SKIP', trim_reason], @@ -252,8 +253,8 @@ maybe = { 'projectquota/setup': ['SKIP', exec_reason], 'raidz/raidz_002_pos': ['FAIL', known_reason], 'raidz/raidz_expand_001_pos': ['FAIL', 16421], - 'redundancy/redundancy_draid_spare1': ['FAIL', known_reason], - 'redundancy/redundancy_draid_spare3': ['FAIL', known_reason], + 'redundancy/redundancy_draid_spare1': ['FAIL', 18307], + 'redundancy/redundancy_draid_spare3': ['FAIL', 18319], 'removal/removal_condense_export': ['FAIL', known_reason], 'renameat2/setup': ['SKIP', renameat2_reason], 'reservation/reservation_008_pos': ['FAIL', 7741], @@ -351,6 +352,7 @@ elif sys.platform.startswith('linux'): 'cli_root/zfs_rename/zfs_rename_002_pos': ['FAIL', known_reason], 'cli_root/zpool_reopen/zpool_reopen_003_pos': ['FAIL', known_reason], 'cp_files/cp_files_002_pos': ['SKIP', cfr_reason], + 'events/events_002_pos': ['FAIL', 18271], 'fault/auto_online_002_pos': ['FAIL', 11889], 'fault/auto_replace_001_pos': ['FAIL', 14851], 'fault/auto_spare_002_pos': ['FAIL', 11889], diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib index d979d6874f9b..974e19c04269 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib +++ b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib @@ -1171,6 +1171,22 @@ function datasetnonexists return 0 } +# Check if the specified dataset property has the expected value or fail +function dataset_has_prop # property expected_value dataset +{ + typeset prop=$1 + typeset expected=$2 + typeset dataset=$3 + + typeset value="" + + value="$(get_prop "$prop" "$dataset")" + [[ "$value" == "$expected" ]] || { + log_note "dataset $dataset: property $prop == $value (!= $expected)" + return 1 + } +} + # FreeBSD breaks exports(5) at whitespace and doesn't process escapes # Solaris just breaks # @@ -2629,11 +2645,16 @@ function verify_opt_p_ops typeset datatype=$2 typeset dataset=$3 typeset newdataset=$4 + typeset popt=$5 if [[ $datatype != "fs" && $datatype != "vol" ]]; then log_fail "$datatype is not supported." fi + if [[ -z "$popt" ]]; then + popt=-p + fi + # check parameters accordingly case $ops in create) @@ -2671,7 +2692,7 @@ function verify_opt_p_ops log_mustnot datasetexists $newdataset ${newdataset%/*} # with -p option, operation should succeed - log_must zfs $ops -p $dataset $newdataset + log_must zfs $ops $popt $dataset $newdataset block_device_wait if ! datasetexists $newdataset ; then @@ -2680,7 +2701,7 @@ function verify_opt_p_ops # when $ops is create or clone, redo the operation still return zero if [[ $ops != "rename" ]]; then - log_must zfs $ops -p $dataset $newdataset + log_must zfs $ops $popt $dataset $newdataset fi return 0 @@ -3140,6 +3161,21 @@ function wait_scrubbed #pool timeout done } +# Wait for a pool to be resilvered +# +# $1 pool name +# $2 timeout +# +function wait_resilvered #pool timeout +{ + typeset timeout=${2:-300} + typeset pool=${1:-$TESTPOOL} + for (( timer = 0; timer < $timeout; timer++ )); do + is_pool_resilvered $pool && break; + sleep 1; + done +} + # Backup the zed.rc in our test directory so that we can edit it for our test. # # Returns: Backup file name. You will need to pass this to zed_rc_restore(). diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg index 2bcd147d3e69..1bed7b1dbaee 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg +++ b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg @@ -47,11 +47,13 @@ INITIALIZE_VALUE initialize_value zfs_initialize_value KEEP_LOG_SPACEMAPS_AT_EXPORT keep_log_spacemaps_at_export zfs_keep_log_spacemaps_at_export LUA_MAX_MEMLIMIT lua.max_memlimit zfs_lua_max_memlimit L2ARC_DWPD_LIMIT l2arc.dwpd_limit l2arc_dwpd_limit +L2ARC_EXT_HEADROOM_PCT l2arc.ext_headroom_pct l2arc_ext_headroom_pct L2ARC_MFUONLY l2arc.mfuonly l2arc_mfuonly L2ARC_NOPREFETCH l2arc.noprefetch l2arc_noprefetch L2ARC_REBUILD_BLOCKS_MIN_L2SIZE l2arc.rebuild_blocks_min_l2size l2arc_rebuild_blocks_min_l2size L2ARC_REBUILD_ENABLED l2arc.rebuild_enabled l2arc_rebuild_enabled L2ARC_TRIM_AHEAD l2arc.trim_ahead l2arc_trim_ahead +L2ARC_META_CYCLES l2arc.meta_cycles l2arc_meta_cycles L2ARC_WRITE_MAX l2arc.write_max l2arc_write_max LIVELIST_CONDENSE_NEW_ALLOC livelist.condense.new_alloc zfs_livelist_condense_new_alloc LIVELIST_CONDENSE_SYNC_CANCEL livelist.condense.sync_cancel zfs_livelist_condense_sync_cancel diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am index e3fcce9840d9..fdf211877e62 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am @@ -677,6 +677,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh \ functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh \ functional/cli_root/zfs_clone/zfs_clone_010_pos.ksh \ + functional/cli_root/zfs_clone/zfs_clone_011_pos.ksh \ functional/cli_root/zfs_clone/zfs_clone_deeply_nested.ksh \ functional/cli_root/zfs_clone/zfs_clone_encrypted.ksh \ functional/cli_root/zfs_clone/zfs_clone_nomount.ksh \ @@ -705,6 +706,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zfs_create/zfs_create_012_pos.ksh \ functional/cli_root/zfs_create/zfs_create_013_pos.ksh \ functional/cli_root/zfs_create/zfs_create_014_pos.ksh \ + functional/cli_root/zfs_create/zfs_create_015_pos.ksh \ functional/cli_root/zfs_create/zfs_create_crypt_combos.ksh \ functional/cli_root/zfs_create/zfs_create_dryrun.ksh \ functional/cli_root/zfs_create/zfs_create_encrypted.ksh \ @@ -864,6 +866,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh \ functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh \ functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh \ + functional/cli_root/zfs_rename/zfs_rename_015_pos.ksh \ functional/cli_root/zfs_rename/zfs_rename_encrypted_child.ksh \ functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh \ functional/cli_root/zfs_rename/zfs_rename_nounmount.ksh \ @@ -1082,6 +1085,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_create/zpool_create_draid_004_pos.ksh \ functional/cli_root/zpool_create/zpool_create_dryrun_output.ksh \ functional/cli_root/zpool_create/zpool_create_encrypted.ksh \ + functional/cli_root/zpool_create/zpool_create_edom_neg.ksh \ functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh \ functional/cli_root/zpool_create/zpool_create_features_002_pos.ksh \ functional/cli_root/zpool_create/zpool_create_features_003_pos.ksh \ @@ -1132,6 +1136,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_get/zpool_get_003_pos.ksh \ functional/cli_root/zpool_get/zpool_get_004_neg.ksh \ functional/cli_root/zpool_get/zpool_get_005_pos.ksh \ + functional/cli_root/zpool_get/zpool_get_006_pos.ksh \ functional/cli_root/zpool_history/cleanup.ksh \ functional/cli_root/zpool_history/setup.ksh \ functional/cli_root/zpool_history/zpool_history_001_neg.ksh \ @@ -1946,6 +1951,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/removal/removal_with_faulted.ksh \ functional/removal/removal_with_ganging.ksh \ functional/removal/removal_with_hole.ksh \ + functional/removal/removal_with_missing_log.ksh \ functional/removal/removal_with_indirect.ksh \ functional/removal/removal_with_remove.ksh \ functional/removal/removal_with_scrub.ksh \ @@ -2045,6 +2051,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/rsend/rsend_029_neg.ksh \ functional/rsend/rsend_030_pos.ksh \ functional/rsend/rsend_031_pos.ksh \ + functional/rsend/rsend-exclude_001_pos.ksh \ + functional/rsend/rsend-exclude_002_pos.ksh \ functional/rsend/send-c_embedded_blocks.ksh \ functional/rsend/send-c_incremental.ksh \ functional/rsend/send-c_longname.ksh \ @@ -2088,6 +2096,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/rsend/send_realloc_files.ksh \ functional/rsend/send_spill_block.ksh \ functional/rsend/send-wR_encrypted_zvol.ksh \ + functional/rsend/send-zstream_drop_record.ksh \ functional/rsend/setup.ksh \ functional/scrub_mirror/cleanup.ksh \ functional/scrub_mirror/scrub_mirror_001_pos.ksh \ diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh index 09ee00ce5b85..f2ba0003bd2a 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh @@ -57,7 +57,7 @@ set -A args "create" "add" "destroy" "import fakepool" \ "add mirror fakepool" "add raidz fakepool" \ "add raidz1 fakepool" "add raidz2 fakepool" \ "setvprop" "blah blah" "-%" "--?" "-*" "-=" \ - "-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" \ + "-a" "-g" "-j" "-n" "-o" "-p" "-p /tmp" \ "-t" "-w" "-z" "-E" "-H" "-I" "-J" \ "-Q" "-R" "-W" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_011_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_011_pos.ksh new file mode 100755 index 000000000000..9e71db3177c1 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_011_pos.ksh @@ -0,0 +1,94 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2026 Ivan Shapovalov <intelfx@intelfx.name> +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# `zfs clone -pp` should create the parent of the new filesystem with `canmount=off`. +# +# STRATEGY: +# 1. Prepare snapshots +# 2. Make sure the parent of the clone target does not exist +# 3. Make sure that `zfs clone -pp` works the same as `-p` +# 4. Make sure that the newly created parent has `canmount=off` +# + +verify_runnable "both" + +function setup +{ + log_note "Create snapshots and mount them..." + + for snap in $SNAPFS $SNAPFS1 ; do + if ! snapexists "$snap" ; then + log_must zfs snapshot "$snap" + fi + done + + return 0 +} + +function cleanup +{ + + datasetexists "$TESTPOOL/notexist" && destroy_dataset "$TESTPOOL/notexist" -rRf + + for snap in $SNAPFS $SNAPFS1 ; do + snapexists "$snap" && destroy_dataset "$snap" -Rf + done + + return 0 +} + +log_onexit cleanup + +log_assert "'zfs clone -pp' should work as expected." + +setup + +log_mustnot datasetexists "$TESTPOOL/notexist" +log_mustnot datasetexists "$TESTPOOL/notexist/new" +log_mustnot datasetexists "$TESTPOOL/notexist/new2" + +log_must verify_opt_p_ops "clone" "fs" "$SNAPFS" \ + "$TESTPOOL/notexist/new/clonefs$$" "-pp" + +log_must dataset_has_prop canmount off "$TESTPOOL/notexist" +log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new" +log_mustnot ismounted "$TESTPOOL/notexist" +log_mustnot ismounted "$TESTPOOL/notexist/new" + +if is_global_zone ; then + log_must verify_opt_p_ops "clone" "vol" "$SNAPFS1" \ + "$TESTPOOL/notexist/new2/clonevol$$" "-pp" + + log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new2" + log_mustnot ismounted "$TESTPOOL/notexist/new2" +fi + +log_pass "'zfs clone -pp' works as expected." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_015_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_015_pos.ksh new file mode 100755 index 000000000000..d4c009c22d46 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_015_pos.ksh @@ -0,0 +1,74 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2026 Ivan Shapovalov <intelfx@intelfx.name> +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# `zfs create -pp` should create the parent of the new filesystem with `canmount=off`. +# +# STRATEGY: +# 1. Make sure the parent of the dataset to be created does not exist +# 2. Make sure that `zfs create -pp` works the same as `-p` +# 3. Make sure that the newly created parent has `canmount=off` + +verify_runnable "both" + +function cleanup +{ + datasetexists "$TESTPOOL/notexist" && \ + destroy_dataset "$TESTPOOL/notexist" -rRf + + return 0 +} + +log_onexit cleanup + +log_assert "'zfs create -p' should work as expected." + +log_mustnot datasetexists "$TESTPOOL/notexist" +log_mustnot datasetexists "$TESTPOOL/notexist/new" +log_mustnot datasetexists "$TESTPOOL/notexist/new2" + +log_must verify_opt_p_ops "create" "fs" \ + "$TESTPOOL/notexist/new/create$$" "" "-pp" + +log_must dataset_has_prop canmount off "$TESTPOOL/notexist" +log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new" +log_mustnot ismounted "$TESTPOOL/notexist" +log_mustnot ismounted "$TESTPOOL/notexist/new" + +# verify volume creation +if is_global_zone; then + log_must verify_opt_p_ops "create" "vol" \ + "$TESTPOOL/notexist/new2/volume$$" "" "-pp" + + log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new2" + log_mustnot ismounted "$TESTPOOL/notexist/new2" +fi + +log_pass "'zfs create -p' works as expected." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_015_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_015_pos.ksh new file mode 100755 index 000000000000..124c3eed7c88 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_015_pos.ksh @@ -0,0 +1,86 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2026 Ivan Shapovalov <intelfx@intelfx.name> +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION +# `zfs rename -pp` should create the parent of the new filesystem with `canmount=off`. +# +# STRATEGY: +# 1. Make sure the parent of the rename target does not exist +# 2. Make sure that `zfs rename -pp` works the same as `-p` +# 3. Make sure that the newly created parent has `canmount=off` +# + +verify_runnable "both" + +function cleanup +{ + datasetexists "$TESTPOOL/notexist" && \ + destroy_dataset "$TESTPOOL/notexist" -Rf + + datasetexists "$TESTPOOL/$TESTFS" && \ + destroy_dataset "$TESTPOOL/$TESTFS" -Rf + + log_must zfs create "$TESTPOOL/$TESTFS" + + if is_global_zone ; then + datasetexists "$TESTPOOL/$TESTVOL" && \ + destroy_dataset "$TESTPOOL/$TESTVOL" -Rf + + log_must zfs create -V "$VOLSIZE" "$TESTPOOL/$TESTVOL" + fi + + return 0 +} + +log_onexit cleanup + +log_assert "'zfs rename -pp' should work as expected." + +log_must_not datasetexists "$TESTPOOL/notexist" +log_must_not datasetexists "$TESTPOOL/notexist/new" +log_must_not datasetexists "$TESTPOOL/notexist/new2" + +log_must verify_opt_p_ops "rename" "fs" "$TESTPOOL/$TESTFS" \ + "$TESTPOOL/notexist/new/$TESTFS1" "-pp" + +log_must dataset_has_prop canmount off "$TESTPOOL/notexist" +log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new" +log_mustnot ismounted "$TESTPOOL/notexist" +log_mustnot ismounted "$TESTPOOL/notexist/new" + +if is_global_zone; then + log_must verify_opt_p_ops "rename" "vol" "$TESTPOOL/$TESTVOL" \ + "$TESTPOOL/notexist/new2/$TESTVOL1" "-pp" + + log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new2" + log_mustnot ismounted "$TESTPOOL/notexist/new2" +fi + +log_pass "'zfs rename -pp' works as expected." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_edom_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_edom_neg.ksh new file mode 100755 index 000000000000..21ebae5eeb6a --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_edom_neg.ksh @@ -0,0 +1,68 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright (c) 2026, Christos Longros. All rights reserved. +# + +# +# DESCRIPTION: +# Verify that zpool create with an out-of-range block size +# reports a clear error about block size rather than a +# misleading "invalid property value" message. +# +# STRATEGY: +# 1. Set vdev_file_logical_ashift above ASHIFT_MAX to force EDOM. +# 2. Attempt to create a pool. +# 3. Verify the error mentions "block size". +# 4. Verify it does not say "property". +# + +. $STF_SUITE/include/libtest.shlib + +verify_runnable "global" + +function cleanup +{ + poolexists $TESTPOOL && destroy_pool $TESTPOOL + log_must set_tunable64 VDEV_FILE_LOGICAL_ASHIFT 9 + rm -f $TEST_BASE_DIR/vdev_edom +} + +log_assert "zpool create with bad ashift reports block size error" +log_onexit cleanup + +truncate -s $MINVDEVSIZE $TEST_BASE_DIR/vdev_edom + +# Force ashift above ASHIFT_MAX (16) to trigger EDOM +log_must set_tunable64 VDEV_FILE_LOGICAL_ASHIFT 17 + +errmsg=$(zpool create $TESTPOOL $TEST_BASE_DIR/vdev_edom 2>&1) +typeset -i ret=$? + +log_note "Return code: $ret" +log_note "Error message: $errmsg" + +(( ret != 0 )) || log_fail "zpool create should have failed" + +echo "$errmsg" | grep -qi "block size" || \ + log_fail "Error should mention block size: $errmsg" + +echo "$errmsg" | grep -qi "property" && \ + log_fail "Error should not mention property: $errmsg" + +log_pass "zpool create with bad ashift reports block size error" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg index 99a4556f70d5..dcb2b92cc0e1 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg @@ -67,6 +67,63 @@ typeset -a properties=( "last_scrubbed_txg" "dedupused" "dedupsaved" + "available" + "usable" + "used" + "class_normal_size" + "class_normal_capacity" + "class_normal_free" + "class_normal_allocated" + "class_normal_available" + "class_normal_usable" + "class_normal_used" + "class_normal_expandsize" + "class_normal_fragmentation" + "class_special_size" + "class_special_capacity" + "class_special_free" + "class_special_allocated" + "class_special_available" + "class_special_usable" + "class_special_used" + "class_special_expandsize" + "class_special_fragmentation" + "class_dedup_size" + "class_dedup_capacity" + "class_dedup_free" + "class_dedup_allocated" + "class_dedup_available" + "class_dedup_usable" + "class_dedup_used" + "class_dedup_expandsize" + "class_dedup_fragmentation" + "class_log_size" + "class_log_capacity" + "class_log_free" + "class_log_allocated" + "class_log_available" + "class_log_usable" + "class_log_used" + "class_log_expandsize" + "class_log_fragmentation" + "class_elog_size" + "class_elog_capacity" + "class_elog_free" + "class_elog_allocated" + "class_elog_available" + "class_elog_usable" + "class_elog_used" + "class_elog_expandsize" + "class_elog_fragmentation" + "class_special_elog_size" + "class_special_elog_capacity" + "class_special_elog_free" + "class_special_elog_allocated" + "class_special_elog_available" + "class_special_elog_usable" + "class_special_elog_used" + "class_special_elog_expandsize" + "class_special_elog_fragmentation" "feature@async_destroy" "feature@empty_bpobj" "feature@lz4_compress" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh index f0b7a0450451..524bcd61b354 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_005_pos.ksh @@ -47,6 +47,8 @@ if ! is_global_zone ; then fi typeset -i i=0 +typeset class="@(normal|special|dedup|log|elog|special_elog)" +typeset optclass="@(special|dedup|log|elog|special_elog)" while [[ $i -lt "${#properties[@]}" ]]; do log_note "Checking for parsable ${properties[$i]} property" @@ -61,10 +63,14 @@ while [[ $i -lt "${#properties[@]}" ]]; do # All properties must be positive integers in order to be # parsable (i.e. a return code of 0 or 1 from expr above). - # The only exception is "expandsize", which may be "-". - if [[ ! ($? -eq 0 || $? -eq 1 || \ - ("${properties[$i]}" = "expandsize" && "$v" = "-")) ]]; then - log_fail "${properties[$i]} is not parsable" + # The only exceptions are "expandsize", "class_<class>_expandsize", + # and "class_<optclass>_fragmentation", which may be "-". + if [[ ! ($? -eq 0 || $? -eq 1) ]]; then + case "${properties[$i]}" in + ?(class_${class}_)expandsize) ;& + class_${optclass}_fragmentation) ;; + *) log_fail "${properties[$i]} is not parsable" + esac fi i=$(( $i + 1 )) diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_006_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_006_pos.ksh new file mode 100755 index 000000000000..5d939f43c487 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_006_pos.ksh @@ -0,0 +1,416 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2026 Klara, Inc. +# + +. $STF_SUITE/include/libtest.shlib + +verify_runnable "global" + +# +# DESCRIPTION: +# +# Several zpool properties exist to expose metaslab allocation class space +# accounting. +# +# STRATEGY: +# 1. Create a pool with raidz (to validate expansion and deflation metrics). +# 2. For each allocation class: +# - Add any required vdevs for this allocation class. +# - Prepare a dataset configured to utilize this allocation class. +# - Validate metrics reported by pool properties for allocation classes. +# 3. For the whole pool, confirm that AVAIL, USABLE and USED report reasonable +# values. +# + +bs=128K +count=100 + +function writefile +{ + dd if=/dev/urandom of=$1 bs=$bs count=$count 2>/dev/null +} + +nfiles=5 + +function writefiles # datadir [nfiles] +{ + typeset datadir=$1 + typeset -i n=${2:-$nfiles} + + for i in {1..$n}; do + log_must writefile $TESTDIR/$datadir/file$i + done +} + +pool=$TESTPOOL1 + +function get_class_prop +{ + get_pool_prop "class_${1}_${2}" $pool +} + +# Wrapper for test to give more context to logs +function check +{ + shift 2 # class prop (test args) + test "$@" +} + +function check_raidz_used # [mincap=1] +{ + typeset -i mincap=${1:-1} + + log_must check $class size $size -gt 0 + log_must check $class capacity $cap -ge $mincap -a $cap -le 100 + log_must check $class free $free -gt 0 -a $free -lt $size + log_must check $class allocated $alloc -gt 0 -a $alloc -lt $size + log_must check $class available $avail -gt 0 -a $avail -lt $free + log_must check $class usable $usable -gt 0 -a $usable -lt $size + log_must check $class used $used -gt 0 -a $used -lt $alloc + log_must check $class expandsize $expandsz = "-" + log_must check $class fragmentation $frag -lt 50 +} + +function check_raidz_unused +{ + log_must check $class size $size -gt 0 + log_must check $class capacity $cap -eq 0 + log_must check $class free $free -eq $size + log_must check $class allocated $alloc -eq 0 + log_must check $class available $avail -gt 0 -a $avail -lt $free + log_must check $class usable $usable -gt 0 -a $usable -lt $size + log_must check $class used $used -eq 0 + log_must check $class expandsize $expandsz = "-" + log_must check $class fragmentation $frag -eq 0 +} + +function check_nonraidz_used # [mincap=1] +{ + typeset -i mincap=${1:-1} + + log_must check $class size $size -gt 0 + log_must check $class capacity $cap -ge $mincap -a $cap -le 100 + log_must check $class free $free -gt 0 -a $free -lt $size + log_must check $class allocated $alloc -gt 0 -a $alloc -lt $size + log_must check $class available $avail -eq $free + log_must check $class usable $usable -eq $size + log_must check $class used $used -eq $alloc + log_must check $class expandsize $expandsz = "-" + log_must check $class fragmentation $frag -lt 50 +} + +function check_nonraidz_unused +{ + log_must check $class size $size -gt 0 + log_must check $class capacity $cap -eq 0 + log_must check $class free $free -eq $size + log_must check $class allocated $alloc -eq 0 + log_must check $class available $avail -eq $free + log_must check $class usable $usable -eq $size + log_must check $class used $used -eq $alloc + log_must check $class expandsize $expandsz = "-" + log_must check $class fragmentation $frag -eq 0 +} + +# Log capacity tends to be >0% but <1% in these tests, so gets reported as 0. +# Let that slide and rely on allocated/free checks for sanity, rather than +# trying to tweak txg sync parameters to widen the race window. + +function check_raidz_log_used +{ + check_raidz_used 0 +} + +function check_nonraidz_log_used +{ + check_nonraidz_used 0 +} + +function check_unavailable +{ + log_must check $class size $size -eq 0 + log_must check $class capacity $cap -eq 0 + log_must check $class free $free -eq 0 + log_must check $class allocated $alloc -eq 0 + log_must check $class available $avail -eq 0 + log_must check $class usable $usable -eq 0 + log_must check $class used $used -eq 0 + log_must check $class expandsize $expandsz = "-" + log_must check $class fragmentation $frag = "-" +} + +typeset -a classes=("normal" "special" "dedup" "log" "elog" "special_elog") + +normal_vdevs=$(seq -f $TEST_BASE_DIR/normal-vdev-%g 3) +normal_vdev_size=$((1 << 30)) # 1 GiB + +special_vdevs=$(seq -f $TEST_BASE_DIR/special-vdev-%g 3) +special_vdev_size=$((512 << 20)) # 512 MiB + +# Use a mirror for dedup to test expandsize. +dedup_vdevs=$(seq -f $TEST_BASE_DIR/dedup-vdev-%g 2) +dedup_vdev_size=$((256 << 20)) # 256 MiB + +# The log class can't be raided or expanded, so we only need one vdev. +log_vdev="$TEST_BASE_DIR/log-vdev" +log_vdev_size=$((128 << 20)) # 128 MiB + +embedded_slog_min_ms=$(get_tunable EMBEDDED_SLOG_MIN_MS) + +function cleanup +{ + zpool destroy -f $pool + rm -f $normal_vdevs $normal_expand_vdev + rm -f $special_vdevs $special_expand_vdev + rm -f $dedup_vdevs $dedup_expand_vdev + rm -f $log_vdev + set_tunable32 EMBEDDED_SLOG_MIN_MS $embedded_slog_min_ms +} +log_onexit cleanup + +log_assert "zpool allocation class properties report metrics correctly" + +# Lower the threshold for provisioning embedded log metaslabs on small vdevs. +log_must set_tunable32 EMBEDDED_SLOG_MIN_MS 8 + +log_must truncate -s $normal_vdev_size $normal_vdevs +log_must zpool create $pool \ + raidz $normal_vdevs +log_must zfs set mountpoint=$TESTDIR $pool + +log_note "Normal Class" +log_must zfs create \ + $pool/normal +writefiles normal +sync_pool $pool +for class in "${classes[@]}"; do + typeset -il size=$(get_class_prop $class size) + typeset -i cap=$(get_class_prop $class capacity) + typeset -il free=$(get_class_prop $class free) + typeset -il alloc=$(get_class_prop $class allocated) + typeset -il avail=$(get_class_prop $class available) + typeset -il usable=$(get_class_prop $class usable) + typeset -il used=$(get_class_prop $class used) + typeset expandsz=$(get_class_prop $class expandsize) + typeset frag=$(get_class_prop $class fragmentation) + case $class in + normal) + check_raidz_used + ;; + elog) + check_raidz_unused + ;; + *) + check_unavailable + ;; + esac +done + +log_note "Embedded Log Class" +log_must zfs create \ + -o sync=always \ + $pool/elog +writefiles elog +for class in "${classes[@]}"; do + typeset -il size=$(get_class_prop $class size) + typeset -i cap=$(get_class_prop $class capacity) + typeset -il free=$(get_class_prop $class free) + typeset -il alloc=$(get_class_prop $class allocated) + typeset -il avail=$(get_class_prop $class available) + typeset -il usable=$(get_class_prop $class usable) + typeset -il used=$(get_class_prop $class used) + typeset expandsz=$(get_class_prop $class expandsize) + typeset frag=$(get_class_prop $class fragmentation) + case $class in + normal) + check_raidz_used + ;; + elog) + check_raidz_log_used + ;; + *) + check_unavailable + ;; + esac +done + +log_note "Special Class" +log_must truncate -s $special_vdev_size $special_vdevs +log_must zpool add $pool \ + special raidz $special_vdevs +log_must zfs create \ + -o recordsize=32K -o special_small_blocks=32K \ + $pool/special +writefiles special +sync_pool $pool +for class in "${classes[@]}"; do + typeset -il size=$(get_class_prop $class size) + typeset -i cap=$(get_class_prop $class capacity) + typeset -il free=$(get_class_prop $class free) + typeset -il alloc=$(get_class_prop $class allocated) + typeset -il avail=$(get_class_prop $class available) + typeset -il usable=$(get_class_prop $class usable) + typeset -il used=$(get_class_prop $class used) + typeset expandsz=$(get_class_prop $class expandsize) + typeset frag=$(get_class_prop $class fragmentation) + case $class in + normal|special) + check_raidz_used + ;; + elog) + check_raidz_log_used + ;; + special_elog) + check_raidz_unused + ;; + *) + check_unavailable + ;; + esac +done + +log_note "Special Embedded Log Class" +log_must zfs create \ + -o recordsize=32K -o special_small_blocks=32K \ + -o sync=always \ + $pool/special_elog +writefiles special_elog +for class in "${classes[@]}"; do + typeset -il size=$(get_class_prop $class size) + typeset -i cap=$(get_class_prop $class capacity) + typeset -il free=$(get_class_prop $class free) + typeset -il alloc=$(get_class_prop $class allocated) + typeset -il avail=$(get_class_prop $class available) + typeset -il usable=$(get_class_prop $class usable) + typeset -il used=$(get_class_prop $class used) + typeset expandsz=$(get_class_prop $class expandsize) + typeset frag=$(get_class_prop $class fragmentation) + case $class in + normal|special) + check_raidz_used + ;; + elog|special_elog) + check_raidz_log_used + ;; + *) + check_unavailable + ;; + esac +done + +log_note "Log Class" +log_must truncate -s $log_vdev_size $log_vdev +log_must zpool add $pool \ + log $log_vdev +log_must zfs create \ + -o sync=always \ + $pool/log +writefiles log +for class in "${classes[@]}"; do + typeset -il size=$(get_class_prop $class size) + typeset -i cap=$(get_class_prop $class capacity) + typeset -il free=$(get_class_prop $class free) + typeset -il alloc=$(get_class_prop $class allocated) + typeset -il avail=$(get_class_prop $class available) + typeset -il usable=$(get_class_prop $class usable) + typeset -il used=$(get_class_prop $class used) + typeset expandsz=$(get_class_prop $class expandsize) + typeset frag=$(get_class_prop $class fragmentation) + case $class in + normal|special) + check_raidz_used + ;; + elog|special_elog) + check_raidz_log_used + ;; + log) + check_nonraidz_log_used + ;; + *) + check_unavailable + ;; + esac +done + +log_note "Dedup Class" +log_must truncate -s $dedup_vdev_size $dedup_vdevs +log_must zpool add $pool \ + dedup mirror $dedup_vdevs +log_must zfs create \ + -o dedup=on -o recordsize=4k \ + $pool/dedup +writefiles dedup $((3 * nfiles)) +sync_pool $pool +for class in "${classes[@]}"; do + typeset -il size=$(get_class_prop $class size) + typeset -i cap=$(get_class_prop $class capacity) + typeset -il free=$(get_class_prop $class free) + typeset -il alloc=$(get_class_prop $class allocated) + typeset -il avail=$(get_class_prop $class available) + typeset -il usable=$(get_class_prop $class usable) + typeset -il used=$(get_class_prop $class used) + typeset expandsz=$(get_class_prop $class expandsize) + typeset frag=$(get_class_prop $class fragmentation) + case $class in + normal|special) + check_raidz_used + ;; + elog|special_elog) + check_raidz_log_used + ;; + log) + check_nonraidz_log_used + ;; + dedup) + check_nonraidz_used + ;; + *) + log_fail "unhandled class: $class" + ;; + esac +done + +# Expansion +typeset -il delta=$((32 << 20)) # 32 MiB +log_must truncate -s $((dedup_vdev_size + delta)) $dedup_vdevs +typeset -a vdevs=($dedup_vdevs) +log_must zpool online -e $pool ${vdevs[0]} +typeset -il size=$(get_class_prop dedup size) +typeset -il expandsz=$(get_class_prop dedup expandsize) +log_must test $expandsz -eq $delta + +# Pool-wide AVAIL/USABLE/USED +typeset -il free=$(get_pool_prop free $pool) +typeset -il avail=$(get_pool_prop available $pool) +log_must test $avail -gt 0 -a $avail -lt $free +typeset -il size=$(get_pool_prop size $pool) +typeset -il usable=$(get_pool_prop usable $pool) +log_must test $usable -gt 0 -a $usable -lt $size +typeset -il alloc=$(get_pool_prop alloc $pool) +typeset -il used=$(get_pool_prop used $pool) +log_must test $used -gt 0 -a $used -lt $alloc + +cleanup diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg index 2d45ba344a6e..86fa13130d4c 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_parsable.cfg @@ -29,6 +29,75 @@ # Copyright (c) 2013, 2014 by Delphix. All rights reserved. # -# Set the expected properties of zpool -typeset -a properties=("allocated" "bcloneused" "bclonesaved" "capacity" - "dedupused" "dedupsaved" "expandsize" "free" "freeing" "leaked" "size") +# Set the expected parsable properties of zpool +typeset -a properties=( + "size" + "capacity" + "free" + "allocated" + "expandsize" + "freeing" + "fragmentation" + "leaked" + "bcloneused" + "bclonesaved" + "dedupused" + "dedupsaved" + "available" + "usable" + "used" + "class_normal_size" + "class_normal_capacity" + "class_normal_free" + "class_normal_allocated" + "class_normal_available" + "class_normal_usable" + "class_normal_used" + "class_normal_expandsize" + "class_normal_fragmentation" + "class_special_size" + "class_special_capacity" + "class_special_free" + "class_special_allocated" + "class_special_available" + "class_special_usable" + "class_special_used" + "class_special_expandsize" + "class_special_fragmentation" + "class_dedup_size" + "class_dedup_capacity" + "class_dedup_free" + "class_dedup_allocated" + "class_dedup_available" + "class_dedup_usable" + "class_dedup_used" + "class_dedup_expandsize" + "class_dedup_fragmentation" + "class_log_size" + "class_log_capacity" + "class_log_free" + "class_log_allocated" + "class_log_available" + "class_log_usable" + "class_log_used" + "class_log_expandsize" + "class_log_fragmentation" + "class_elog_size" + "class_elog_capacity" + "class_elog_free" + "class_elog_allocated" + "class_elog_available" + "class_elog_usable" + "class_elog_used" + "class_elog_expandsize" + "class_elog_fragmentation" + "class_special_elog_size" + "class_special_elog_capacity" + "class_special_elog_free" + "class_special_elog_allocated" + "class_special_elog_available" + "class_special_elog_usable" + "class_special_elog_used" + "class_special_elog_expandsize" + "class_special_elog_fragmentation" +) diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_ratelimit_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_ratelimit_pos.ksh index 65b2bf07aa9b..51223790bf2d 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_ratelimit_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_ratelimit_pos.ksh @@ -51,6 +51,7 @@ function cleanup restore_tunable L2ARC_WRITE_MAX restore_tunable L2ARC_NOPREFETCH restore_tunable L2ARC_DWPD_LIMIT + restore_tunable L2ARC_EXT_HEADROOM_PCT restore_tunable ARC_MIN restore_tunable ARC_MAX } @@ -60,6 +61,7 @@ log_onexit cleanup save_tunable L2ARC_WRITE_MAX save_tunable L2ARC_NOPREFETCH save_tunable L2ARC_DWPD_LIMIT +save_tunable L2ARC_EXT_HEADROOM_PCT save_tunable ARC_MIN save_tunable ARC_MAX @@ -73,6 +75,7 @@ log_must set_tunable64 ARC_MAX $((400 * 1024 * 1024)) log_must set_tunable64 ARC_MIN $((200 * 1024 * 1024)) log_must set_tunable32 L2ARC_NOPREFETCH 0 log_must set_tunable32 L2ARC_WRITE_MAX $((200 * 1024 * 1024)) +log_must set_tunable64 L2ARC_EXT_HEADROOM_PCT 0 # Create larger main vdev to accommodate fill data log_must truncate -s 5G $VDEV @@ -133,6 +136,6 @@ if [[ ${results[5000]} -le ${results[1800]} ]]; then log_fail "DWPD=5000 should write more than DWPD=1800" fi -log_must zpool destroy $TESTPOOL +destroy_pool $TESTPOOL log_pass "L2ARC DWPD rate limiting correctly limits write rate." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_reimport_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_reimport_pos.ksh index 50208bce2f84..1cf8e7d6e9f9 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_reimport_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_dwpd_reimport_pos.ksh @@ -50,6 +50,7 @@ function cleanup restore_tunable L2ARC_WRITE_MAX restore_tunable L2ARC_NOPREFETCH restore_tunable L2ARC_DWPD_LIMIT + restore_tunable L2ARC_EXT_HEADROOM_PCT restore_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE restore_tunable ARC_MIN restore_tunable ARC_MAX @@ -60,6 +61,7 @@ log_onexit cleanup save_tunable L2ARC_WRITE_MAX save_tunable L2ARC_NOPREFETCH save_tunable L2ARC_DWPD_LIMIT +save_tunable L2ARC_EXT_HEADROOM_PCT save_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE save_tunable ARC_MIN save_tunable ARC_MAX @@ -78,6 +80,7 @@ log_must set_tunable64 ARC_MAX $((400 * 1024 * 1024)) log_must set_tunable64 ARC_MIN $((200 * 1024 * 1024)) log_must set_tunable32 L2ARC_NOPREFETCH 0 log_must set_tunable32 L2ARC_WRITE_MAX $((200 * 1024 * 1024)) +log_must set_tunable64 L2ARC_EXT_HEADROOM_PCT 0 # Create larger main vdev to accommodate fill data log_must truncate -s 8G $VDEV @@ -164,6 +167,6 @@ if [[ $writes_after -eq 0 ]]; then log_fail "No writes after import - rate limiting may be broken" fi -log_must zpool destroy $TESTPOOL +destroy_pool $TESTPOOL log_pass "L2ARC DWPD rate limiting works after pool export/import." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_scaling_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_scaling_pos.ksh index 8e8c9078c7e7..0938068623cd 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_scaling_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_scaling_pos.ksh @@ -27,14 +27,14 @@ # L2ARC parallel writes scale with number of cache devices. # # STRATEGY: -# 1. Configure L2ARC write rate to 16MB/s per device. -# 2. Disable DWPD rate limiting to test pure parallel throughput. -# 3. Create pool with single 2100MB cache device. -# 4. Generate continuous writes, wait for L2ARC activity, measure over 25s. -# 5. Verify single-device throughput ~400MB (16MB/s × 25s). -# 6. Recreate pool with dual 2100MB cache devices. -# 7. Generate continuous writes, wait for L2ARC activity, measure over 25s. -# 8. Verify dual-device throughput ~800MB (2×16MB/s × 25s). +# 1. Configure L2ARC write rate to 4MB/s per device. +# 2. Disable DWPD rate limiting and depth cap to test pure parallel throughput. +# 3. Create pool with single 3072MB cache device. +# 4. Generate continuous writes, wait for L2ARC activity, measure over 12s. +# 5. Verify single-device throughput ~48MB (4MB/s × 12s). +# 6. Recreate pool with dual 3072MB cache devices. +# 7. Generate continuous writes, wait for L2ARC activity, measure over 12s. +# 8. Verify dual-device throughput ~96MB (2×4MB/s × 12s). # verify_runnable "global" @@ -50,6 +50,7 @@ function cleanup restore_tunable L2ARC_WRITE_MAX restore_tunable L2ARC_NOPREFETCH restore_tunable L2ARC_DWPD_LIMIT + restore_tunable L2ARC_EXT_HEADROOM_PCT restore_tunable ARC_MIN restore_tunable ARC_MAX } @@ -59,19 +60,23 @@ log_onexit cleanup save_tunable L2ARC_WRITE_MAX save_tunable L2ARC_NOPREFETCH save_tunable L2ARC_DWPD_LIMIT +save_tunable L2ARC_EXT_HEADROOM_PCT save_tunable ARC_MIN save_tunable ARC_MAX -# Test parameters -typeset cache_sz=1000 +# Test parameters — cache_sz and write_max are chosen so that total writes +# per phase stay below the global marker reset threshold +# (smallest_capacity/8) to avoid throughput disruption from marker resets. +typeset cache_sz=3072 typeset fill_mb=2500 # 2.5GB initial data -typeset test_time=12 # Measurement window: 16MB/s × 12s = ~200MB per device +typeset test_time=12 # Measurement window: 4MB/s × 12s = ~48MB per device -# Disable DWPD to test pure parallel throughput +# Disable DWPD and depth cap to test pure parallel throughput log_must set_tunable32 L2ARC_DWPD_LIMIT 0 +log_must set_tunable64 L2ARC_EXT_HEADROOM_PCT 0 -# Set L2ARC_WRITE_MAX to 16MB/s to test parallel scaling -log_must set_tunable32 L2ARC_WRITE_MAX $((16 * 1024 * 1024)) +# Set L2ARC_WRITE_MAX to 4MB/s to test parallel scaling +log_must set_tunable32 L2ARC_WRITE_MAX $((4 * 1024 * 1024)) log_must set_tunable32 L2ARC_NOPREFETCH 0 # Configure arc_max so L2ARC >= arc_c_max * 2 threshold for persistent markers @@ -107,12 +112,12 @@ kill $dd_pid 2>/dev/null wait $dd_pid 2>/dev/null typeset single_writes=$((end - start)) -# expected = 16MB/s * 1 device * 25s = 400MB -typeset single_expected=$((16 * 1024 * 1024 * test_time)) +# expected = 4MB/s * 1 device * 12s = 48MB +typeset single_expected=$((4 * 1024 * 1024 * test_time)) log_note "Single-device writes: $((single_writes / 1024 / 1024))MB (expected ~$((single_expected / 1024 / 1024))MB)" # Dual device test -log_must zpool destroy $TESTPOOL +destroy_pool $TESTPOOL log_must truncate -s ${cache_sz}M $VDEV_CACHE log_must truncate -s ${cache_sz}M $VDEV_CACHE2 @@ -142,8 +147,8 @@ kill $dd_pid 2>/dev/null wait $dd_pid 2>/dev/null typeset dual_writes=$((end - start)) -# expected = 16MB/s * 2 devices * 25s = 800MB -typeset dual_expected=$((16 * 1024 * 1024 * 2 * test_time)) +# expected = 4MB/s * 2 devices * 12s = 96MB +typeset dual_expected=$((4 * 1024 * 1024 * 2 * test_time)) log_note "Dual-device writes: $((dual_writes / 1024 / 1024))MB (expected ~$((dual_expected / 1024 / 1024))MB)" # Verify writes are within expected range (80-150%) @@ -157,6 +162,6 @@ if [[ $dual_writes -lt $dual_min ]]; then log_fail "Dual-device writes $((dual_writes / 1024 / 1024))MB below minimum $((dual_min / 1024 / 1024))MB" fi -log_must zpool destroy $TESTPOOL +destroy_pool $TESTPOOL log_pass "L2ARC parallel writes scale with number of cache devices." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_throughput_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_throughput_pos.ksh index abdaeb41f879..fea0a5a8ad49 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_throughput_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc_multidev_throughput_pos.ksh @@ -24,18 +24,20 @@ # # DESCRIPTION: -# L2ARC parallel writes scale with number of cache devices. +# L2ARC parallel writes sustain throughput over time without degradation. # # STRATEGY: -# 1. Disable DWPD rate limiting. -# 2. Create pool with 2 cache devices. -# 3. Write data and measure L2ARC throughput. -# 4. Verify throughput scales with device count (~16MB/s per device). +# 1. Disable DWPD rate limiting and depth cap. +# 2. Create pool without cache devices, fill ARC to arc_max. +# 3. Add 2 cache devices after ARC is full and stable. +# 4. Measure L2ARC throughput over 3 consecutive windows. +# 5. Verify throughput remains stable (no window drops below 50% +# of the first). # verify_runnable "global" -log_assert "L2ARC parallel writes scale with number of cache devices." +log_assert "L2ARC parallel writes sustain throughput without degradation." function cleanup { @@ -46,6 +48,7 @@ function cleanup restore_tunable L2ARC_WRITE_MAX restore_tunable L2ARC_NOPREFETCH restore_tunable L2ARC_DWPD_LIMIT + restore_tunable L2ARC_EXT_HEADROOM_PCT restore_tunable ARC_MIN restore_tunable ARC_MAX } @@ -55,41 +58,47 @@ log_onexit cleanup save_tunable L2ARC_WRITE_MAX save_tunable L2ARC_NOPREFETCH save_tunable L2ARC_DWPD_LIMIT +save_tunable L2ARC_EXT_HEADROOM_PCT save_tunable ARC_MIN save_tunable ARC_MAX -# Test parameters -typeset num_devs=2 -typeset cache_sz=1000 # 2000MB total > 1900MB (arc_max*2) threshold -typeset test_time=10 -typeset fill_mb=1500 -typeset expected_rate=$((32 * 1024 * 1024)) # 32 MB/s per device +# Test parameters — cache_sz and write_max are chosen so that total writes +# across all windows stay below the global marker reset threshold +# (smallest_capacity/8) to avoid throughput disruption from marker resets. +typeset cache_sz=3072 +typeset window_time=10 +typeset num_windows=3 +typeset arc_max_mb=950 +typeset fill_mb=$arc_max_mb -# Disable DWPD rate limiting +# Disable DWPD rate limiting and depth cap log_must set_tunable32 L2ARC_DWPD_LIMIT 0 +log_must set_tunable64 L2ARC_EXT_HEADROOM_PCT 0 -# Set L2ARC_WRITE_MAX to 32MB/s per device (64MB/s total with 2 devices) -log_must set_tunable32 L2ARC_WRITE_MAX $expected_rate +# Set L2ARC_WRITE_MAX to 4MB/s per device +log_must set_tunable32 L2ARC_WRITE_MAX $((4 * 1024 * 1024)) log_must set_tunable32 L2ARC_NOPREFETCH 0 -# Configure arc_max large enough to feed L2ARC -log_must set_tunable64 ARC_MAX $((950 * 1024 * 1024)) +# Configure ARC size +log_must set_tunable64 ARC_MAX $((arc_max_mb * 1024 * 1024)) log_must set_tunable64 ARC_MIN $((512 * 1024 * 1024)) -# Create cache devices (using letters e-f to follow cfg naming convention) +# Create pool without cache devices +log_must truncate -s 5G $VDEV +log_must zpool create -f $TESTPOOL $VDEV + +# Fill ARC to arc_max so eviction lists have stable evictable buffers +log_must dd if=/dev/urandom of=/$TESTPOOL/file1 bs=1M count=$fill_mb +log_must zpool sync $TESTPOOL + +# Create and add cache devices now that ARC is full typeset cache_devs="" for letter in e f; do typeset dev="$VDIR/$letter" log_must truncate -s ${cache_sz}M $dev cache_devs="$cache_devs $dev" done - -log_must truncate -s 2G $VDEV -log_must zpool create -f $TESTPOOL $VDEV cache $cache_devs - -# Generate data in background -dd if=/dev/urandom of=/$TESTPOOL/file1 bs=1M count=$fill_mb & -typeset dd_pid=$! +log_must zpool add -f $TESTPOOL cache $cache_devs # Wait for L2ARC to start writing typeset l2_size=0 @@ -99,35 +108,34 @@ for i in {1..30}; do sleep 1 done if [[ $l2_size -eq 0 ]]; then - kill $dd_pid 2>/dev/null log_fail "L2ARC did not start writing" fi -# Measure L2ARC throughput over test window -typeset start=$(kstat arcstats.l2_write_bytes) -log_must sleep $test_time -typeset end=$(kstat arcstats.l2_write_bytes) -kill $dd_pid 2>/dev/null -wait $dd_pid 2>/dev/null - -typeset bytes=$((end - start)) -typeset bytes_mb=$((bytes / 1024 / 1024)) -# expected = 32MB/s * 2 devices * 10 seconds = 640MB -typeset expected=$((expected_rate * num_devs * test_time)) -typeset expected_mb=$((expected / 1024 / 1024)) - -log_note "L2ARC writes: ${bytes_mb}MB (expected ~${expected_mb}MB)" - -# Verify writes are within expected range (75-150%) -typeset min_bytes=$((expected * 75 / 100)) -typeset max_bytes=$((expected * 150 / 100)) -if [[ $bytes -lt $min_bytes ]]; then - log_fail "Writes ${bytes_mb}MB below minimum $((min_bytes/1024/1024))MB" -fi -if [[ $bytes -gt $max_bytes ]]; then - log_fail "Writes ${bytes_mb}MB above maximum $((max_bytes/1024/1024))MB" +# Measure throughput over consecutive windows +typeset -a window_bytes +for w in $(seq 1 $num_windows); do + typeset start=$(kstat arcstats.l2_write_bytes) + log_must sleep $window_time + typeset end=$(kstat arcstats.l2_write_bytes) + window_bytes[$w]=$((end - start)) + log_note "Window $w: $((window_bytes[$w] / 1024 / 1024))MB" +done + +# First window must have non-trivial writes +if [[ ${window_bytes[1]} -le 0 ]]; then + log_fail "No L2ARC writes in first window" fi -log_must zpool destroy $TESTPOOL +# Each subsequent window must be at least 50% of the first +typeset min_bytes=$((window_bytes[1] * 50 / 100)) +for w in $(seq 2 $num_windows); do + if [[ ${window_bytes[$w]} -lt $min_bytes ]]; then + log_fail "Window $w ($((window_bytes[$w] / 1024 / 1024))MB)" \ + "degraded below 50% of window 1" \ + "($((window_bytes[1] / 1024 / 1024))MB)" + fi +done + +destroy_pool $TESTPOOL -log_pass "L2ARC parallel writes scale with number of cache devices." +log_pass "L2ARC parallel writes sustain throughput without degradation." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh index 53c0b0729f54..54fe2fa35ac7 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh @@ -44,7 +44,7 @@ EXPECTED=$((($(echo $DISKS | wc -w) * $DURATION * 1000) / $MMP_INTERVAL_DEFAULT) FUDGE=$((EXPECTED * 20 / 100)) MIN_UB_WRITES=$((EXPECTED - FUDGE)) MAX_UB_WRITES=$((EXPECTED + FUDGE)) -MIN_SEQ_VALUES=10 +MIN_SEQ_VALUES=8 function cleanup { diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh index b0f312f26e60..0604f7f48c7e 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh @@ -19,6 +19,7 @@ # # Copyright (c) 2019, Datto Inc. All rights reserved. # Copyright (c) 2020 by Lawrence Livermore National Security, LLC. +# Copyright (c) 2026, Seagate Technology, LLC. # . $STF_SUITE/include/libtest.shlib @@ -82,7 +83,8 @@ for replace_mode in "healing" "sequential"; do log_must check_vdev_state spare-$i "DEGRADED" log_must check_vdev_state $spare_vdev "ONLINE" log_must check_hotspare_state $TESTPOOL $spare_vdev "INUSE" - log_must zpool detach $TESTPOOL $fault_vdev + # Preserve the 1st faulted vdev for the next test. + [[ $i -eq 0 ]] || log_must zpool detach $TESTPOOL $fault_vdev log_must verify_pool $TESTPOOL log_must check_pool_status $TESTPOOL "scan" "repaired 0B" log_must check_pool_status $TESTPOOL "scan" "with 0 errors" @@ -93,6 +95,13 @@ for replace_mode in "healing" "sequential"; do log_must is_data_valid $TESTPOOL log_must check_pool_status $TESTPOOL "errors" "No known data errors" + # Verify that after clearing the 1st faulted vdev, all is healed. + log_must zpool clear $TESTPOOL "$BASEDIR/vdev0" + log_must wait_resilvered $TESTPOOL + log_must verify_pool $TESTPOOL + log_must check_pool_status $TESTPOOL "scan" "repaired 0B" + log_must check_pool_status $TESTPOOL "scan" "with 0 errors" + cleanup done diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/removal/removal_with_missing_log.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/removal/removal_with_missing_log.ksh new file mode 100755 index 000000000000..ddf8a4505adf --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/removal/removal_with_missing_log.ksh @@ -0,0 +1,95 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright (c) 2026, TrueNAS. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/removal/removal.kshlib + +# +# DESCRIPTION: +# Verify that a missing SLOG device can be removed even when +# ZIL blocks exist on it. +# +# STRATEGY: +# 1. Create a pool with a SLOG device +# 2. Freeze the pool and write data to ZIL +# 3. Export the pool (ZIL blocks remain uncommitted) +# 4. Import with -N to claim logs without replay +# 5. Export and clear SLOG device labels to simulate failure +# 6. Import with -m (missing devices allowed) +# 7. Remove the missing SLOG vdev +# 8. Verify pool is healthy and space accounting is correct +# + +verify_runnable "global" + +log_assert "Removal of missing SLOG with ZIL blocks succeeds" + +function cleanup +{ + poolexists $TESTPOOL && destroy_pool $TESTPOOL +} + +log_onexit cleanup + +VDEV1="$(echo $DISKS | cut -d' ' -f1)" +VDEV2="$(echo $DISKS | cut -d' ' -f2)" + +# Create pool with SLOG and dataset +log_must zpool create $TESTPOOL $VDEV1 log $VDEV2 +log_must zfs create $TESTPOOL/$TESTFS + +# Create initial ZIL header (required before freezing) +log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/init \ + conv=fdatasync,fsync bs=1 count=1 + +# Freeze pool and write data to ZIL +log_must zpool freeze $TESTPOOL +log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file1 \ + oflag=sync bs=128k count=128 + +# Export with uncommitted ZIL transactions +log_must zpool export $TESTPOOL + +# Import with -N to claim logs without mounting/replaying +log_must zpool import -N $TESTPOOL +log_must zpool export $TESTPOOL + +# Clear SLOG labels to simulate device failure +log_must zpool labelclear -f $VDEV2 + +# Import with missing SLOG allowed +log_must zpool import -m $TESTPOOL +log_must eval "zpool status $TESTPOOL | grep UNAVAIL" + +# Remove the missing SLOG - should succeed +log_must zpool remove $TESTPOOL $VDEV2 +log_must zpool wait -t remove $TESTPOOL +sync_pool $TESTPOOL +log_mustnot eval "zpool status -v $TESTPOOL | grep $VDEV2" + +# Verify pool health +log_must zpool scrub -w $TESTPOOL +log_must check_pool_status $TESTPOOL "errors" "No known data errors" + +# Verify space accounting is correct +log_must zdb -c $TESTPOOL + +log_pass "Removal of missing SLOG with ZIL blocks succeeded" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/rsend-exclude_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/rsend-exclude_001_pos.ksh new file mode 100755 index 000000000000..0b16a1890e11 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/rsend-exclude_001_pos.ksh @@ -0,0 +1,68 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2023 by Delphix. All rights reserved. +# Copyright (c) 2026 by Sean Eric Fagan. All rights reserved. +# + +. $STF_SUITE/tests/functional/rsend/rsend.kshlib + +# +# Description: +# Verify recursive incremental with -X properly excludes +# specified datasets. +# +# Strategy: +# 1. Create multiple datasets on source pool. +# 2. Create snapshots on source pool. +# 3. Recursively send snapshots excluding datasets +# 4. Confirm destination pool does not include excluded datasets. +# + +verify_runnable "both" + +sendfs=$POOL/sendfs +recvfs=$POOL2/recvfs + +function cleanup { + rm -f $BACKDIR/list + rm -f $BACKDIR/stream1 + zfs destroy -rf $sendfs + zfs destroy -rf $recvfs +} + +log_assert "Verify recursive sends excluding datasets behave properly." +log_onexit cleanup + +log_must zfs create $sendfs +log_must zfs create $sendfs/ds1 +log_must zfs create $sendfs/ds1/sub1 +log_must zfs create $sendfs/ds1/sub1/sub2 +log_must zfs create $sendfs/ds2 +log_must zfs create $sendfs/ds2/sub1 +log_must zfs create $sendfs/ds2/sub1/sub3 +log_must zfs create $recvfs + +log_must zfs snapshot -r $sendfs@A + +# Now we'll send $sendfs@A, but exclude ds1/sub1 +log_must zfs send -R --exclude ds1/sub1 $sendfs@A > $BACKDIR/stream1 +log_must zfs recv -dFu $recvfs < $BACKDIR/stream1 +log_must zfs list -r $recvfs > $BACKDIR/list +lost_mustnot grep -q ds1/sub1/sub2 $BACKDIR/list +lost_mustnot grep -q ds1/sub1 $BACKDIR/list +log_must grep -q ds2/sub1 $BACKDIR/list + +log_pass "Verify recursive incremental excluding datasets behave properly." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/rsend-exclude_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/rsend-exclude_002_pos.ksh new file mode 100755 index 000000000000..b16d427a4d2a --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/rsend-exclude_002_pos.ksh @@ -0,0 +1,73 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2023 by Delphix. All rights reserved. +# Copyright (c) 2026 by Sean Eric Fagan. All rights reserved. +# + +. $STF_SUITE/tests/functional/rsend/rsend.kshlib + +# +# Description: +# Verify recursive incremental with -X properly excludes +# encrypted specified datasets. +# +# Strategy: +# 1. Create multiple datasets on source pool. +# 2. Create snapshots on source pool. +# 3. Recursively send snapshots excluding datasets +# 4. Confirm destination pool does not include excluded datasets. +# + +verify_runnable "both" + +sendfs=$POOL/sendfs +recvfs=$POOL2/recvfs +PASSPHRASE=${PASSPHRASE:-password} + +function cleanup { + rm -f $BACKDIR/list + rm -f $BACKDIR/stream1 + zfs destroy -rf $sendfs + zfs destroy -rf $recvfs +} + +log_assert "Verify recursive sends excluding datasets behave properly." +log_onexit cleanup + +log_must zfs create $sendfs +log_must zfs create $sendfs/ds1 +log_must zfs create $sendfs/ds1/sub1 +log_must zfs create $sendfs/ds1/sub1/sub2 +log_must zfs create $sendfs/ds2 +log_must zfs create $sendfs/ds2/sub1 +log_must zfs create $sendfs/ds2/sub1/sub3 +log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \ + "-o keyformat=passphrase $sendfs/enc" +log_must zfs create $sendfs/enc/enc2 + +log_must zfs create $recvfs + +log_must zfs snapshot -r $sendfs@A + +# Now we'll send $sendfs@A, but exclude enc +log_must zfs send -R --exclude $sendfs/enc $sendfs@A > $BACKDIR/stream1 +log_must zfs recv -dFu $recvfs < $BACKDIR/stream1 +log_must zfs list -r $recvfs > $BACKDIR/list +lost_mustnot grep -q enc/enc2 $BACKDIR/list +lost_mustnot grep -q enc $BACKDIR/list +log_must grep -q ds2/sub1 $BACKDIR/list + +log_pass "Verify recursive incremental excluding encrypted datasets behave properly." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send-zstream_drop_record.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send-zstream_drop_record.ksh new file mode 100755 index 000000000000..a2e810fd40dc --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send-zstream_drop_record.ksh @@ -0,0 +1,79 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2026 by ConnectWise. All rights reserved. +# + +. $STF_SUITE/tests/functional/rsend/rsend.kshlib +. $STF_SUITE/include/math.shlib + +# +# Description: +# Verify that "zstream drop_record" can remove a record from a stream +# +# Strategy: +# 1. Create a file containing multiple records, both full size and embedded. +# 2. Send the dataset and drop some records +# 3. Verify the dropped records are no longer present +# 4. Verify that "zfs recv" can still receive the dataset. + +verify_runnable "both" + +log_assert "Verify zstream drop_record correctly drops records." +log_onexit cleanup_pool $POOL2 + +typeset sendfs=$POOL2/fs +typeset recvfs=$POOL2/fs2 +typeset stream=$BACKDIR/stream +typeset filtered=$BACKDIR/filtered +typeset dump=$BACKDIR/dump + +log_must zfs create -o compress=lz4 $sendfs +typeset dir=$(get_prop mountpoint $sendfs) + +truncate -s 1m $dir/full_records +# Create some full size records +log_must dd if=/dev/urandom of=$dir/full_records conv=notrunc bs=128k count=2 + +# Create a file with an embedded record. I don't know how to create a file +# with two embedded records. +recsize=16384 +# For lz4, this method works for blocks up to 16k, but not larger +[[ $recsize -eq $((32 * 1024)) ]] && break +if is_illumos; then + log_must mkholes -h 0:$((recsize - 8)) -d $((recsize - 8)):8 \ + $dir/embedded_records +else + log_must truncate -s 16384 $dir/embedded_records + log_must dd if=/dev/urandom of=$dir/embedded_records \ + seek=$((recsize - 8)) bs=1 count=8 conv=notrunc +fi + +log_must zfs snapshot $sendfs@snap +typeset inode1=$(get_objnum $dir/full_records) +typeset inode2=$(get_objnum $dir/embedded_records) + +# Verify that the requested records, and only them, were dropped +log_must eval "zfs send -ce $sendfs@snap > $stream" +log_must eval "zstream drop_record $inode1,131072 $inode2,0 < $stream > $filtered" +log_must eval "zstream dump -v < $filtered > $dump" +log_must grep -qE "^WRITE object = $inode1\>.*offset = 0" $dump +log_mustnot grep -qE "^WRITE object = $inode1\>.*offset = 131072" $dump +log_mustnot grep -qE "^WRITE_EMBEDDED object = $inode2\>.*offset = 0" $dump + +# Verify that the stream can be received +log_must eval "zfs recv $recvfs < $stream" + +log_pass "zstream drop_record correctly drops records." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh index 1e7ca56a143e..0c9006d9be46 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh @@ -41,6 +41,7 @@ # encryption child # 10. Verify that an unencrypted recursive send can be received as an # encryption child +# 11. Verify an encrypted pool can be sent with props only when -U is set # verify_runnable "both" @@ -119,6 +120,13 @@ log_mustnot eval "zfs send -i $esnap $esnap2 |" \ "zfs recv -o pbkdf2iters=100k $TESTPOOL/recv" log_must zfs destroy -r $TESTPOOL/recv +# The user has to explicitly allow sending a dataset unecrypted when sending +# an encrypted dataset with properties +log_note "Must not be able to send an encrypted dataset with props unless the -U flag is set" +log_mustnot eval "zfs send -p $esnap | zfs recv $TESTPOOL/recv" +log_must eval "zfs send -p -U $esnap | zfs recv $TESTPOOL/recv" +log_must zfs destroy -r $TESTPOOL/recv + # Test that we can receive a simple stream as an encryption root. log_note "Must be able to receive stream as encryption root" ds=$TESTPOOL/recv diff --git a/sys/modules/zfs/Makefile b/sys/modules/zfs/Makefile index 4479c3c6eb12..8fd023005b54 100644 --- a/sys/modules/zfs/Makefile +++ b/sys/modules/zfs/Makefile @@ -34,14 +34,15 @@ CFLAGS+= -I${ZINCDIR}/os/freebsd/zfs CFLAGS+= -I${SRCDIR}/zstd/include CFLAGS+= -I${.CURDIR} -CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS \ +CFLAGS+= -D__KERNEL__ -DFREEBSD_NAMECACHE -DBUILDING_ZFS -D__BSD_VISIBLE=1 \ -DHAVE_UIO_ZEROCOPY -DWITHOUT_NETDUMP -D__KERNEL -D_SYS_CONDVAR_H_ \ -D_SYS_VMEM_H_ .if ${MACHINE_ARCH} == "amd64" -CFLAGS+= -D__x86_64 -DHAVE_SSE2 -DHAVE_SSSE3 -DHAVE_SSE4_1 -DHAVE_SSE4_2 \ - -DHAVE_AVX -DHAVE_AVX2 -DHAVE_AVX512F -DHAVE_AVX512VL -DHAVE_AVX512BW \ - -DHAVE_VAES -DHAVE_VPCLMULQDQ +CFLAGS+= -D__x86_64 -DHAVE_TOOLCHAIN_SSE2 -DHAVE_TOOLCHAIN_SSSE3 \ + -DHAVE_TOOLCHAIN_SSE4_1 -DHAVE_TOOLCHAIN_AVX -DHAVE_TOOLCHAIN_AVX2 \ + -DHAVE_TOOLCHAIN_AVX512F -DHAVE_TOOLCHAIN_AVX512VL \ + -DHAVE_TOOLCHAIN_AVX512BW .endif .if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "powerpc" || \ @@ -53,18 +54,14 @@ CFLAGS+= -DBITS_PER_LONG=64 SRCS= vnode_if.h device_if.h bus_if.h -# avl +#avl SRCS+= avl.c -# icp -SRCS+= edonr.c - #icp/algs/blake3 SRCS+= blake3.c \ blake3_generic.c \ blake3_impl.c - .if ${MACHINE_ARCH} == "aarch64" #icp/asm-aarch64/blake3 SRCS+= b3_aarch64_sse2.S \ @@ -88,9 +85,12 @@ SRCS+= blake3_avx2.S \ SRCS+= aesni-gcm-avx2-vaes.S .endif +#icp/algs/edonr +SRCS+= edonr.c + #icp/algs/sha2 -SRCS+= sha2_generic.c \ - sha256_impl.c \ +SRCS+= sha256_impl.c \ + sha2_generic.c \ sha512_impl.c .if ${MACHINE_ARCH} == "armv7" @@ -108,8 +108,8 @@ OBJS+= zfs-sha256-armv8.o \ .if ${MACHINE_ARCH} == "powerpc64" || ${MACHINE_ARCH} == "powerpc64le" #icp/asm-ppc64/sha2 SRCS+= sha256-p8.S \ - sha512-p8.S \ sha256-ppc.S \ + sha512-p8.S \ sha512-ppc.S .endif @@ -146,10 +146,10 @@ SRCS+= lapi.c \ lzio.c #nvpair -SRCS+= nvpair.c \ - fnvpair.c \ - nvpair_alloc_spl.c \ - nvpair_alloc_fixed.c +SRCS+= fnvpair.c \ + nvpair.c \ + nvpair_alloc_fixed.c \ + nvpair_alloc_spl.c #os/freebsd/spl SRCS+= acl_common.c \ @@ -196,6 +196,7 @@ SRCS+= abd_os.c \ zfs_crrd.c \ zfs_debug.c \ zfs_dir.c \ + zfs_file_os.c \ zfs_ioctl_compat.c \ zfs_ioctl_os.c \ zfs_racct.c \ @@ -206,15 +207,16 @@ SRCS+= abd_os.c \ zvol_os.c #zcommon -SRCS+= zfeature_common.c \ +SRCS+= cityhash.c \ + zfeature_common.c \ zfs_comutil.c \ zfs_deleg.c \ - zfs_fletcher.c \ zfs_fletcher_avx512.c \ + zfs_fletcher.c \ zfs_fletcher_intel.c \ zfs_fletcher_sse.c \ - zfs_fletcher_superscalar.c \ zfs_fletcher_superscalar4.c \ + zfs_fletcher_superscalar.c \ zfs_namecheck.c \ zfs_prop.c \ zfs_valstr.c \ @@ -229,14 +231,13 @@ SRCS+= abd.c \ blkptr.c \ bplist.c \ bpobj.c \ + bptree.c \ + bqueue.c \ brt.c \ btree.c \ - cityhash.c \ + dataset_kstats.c \ dbuf.c \ dbuf_stats.c \ - bptree.c \ - bqueue.c \ - dataset_kstats.c \ ddt.c \ ddt_log.c \ ddt_stats.c \ @@ -254,13 +255,13 @@ SRCS+= abd.c \ dmu_zfetch.c \ dnode.c \ dnode_sync.c \ + dsl_bookmark.c \ + dsl_crypt.c \ dsl_dataset.c \ dsl_deadlist.c \ dsl_deleg.c \ - dsl_bookmark.c \ - dsl_dir.c \ - dsl_crypt.c \ dsl_destroy.c \ + dsl_dir.c \ dsl_pool.c \ dsl_prop.c \ dsl_scan.c \ @@ -269,9 +270,9 @@ SRCS+= abd.c \ edonr_zfs.c \ fm.c \ gzip.c \ - lzjb.c \ lz4.c \ lz4_zfs.c \ + lzjb.c \ metaslab.c \ mmp.c \ multilist.c \ @@ -284,6 +285,8 @@ SRCS+= abd.c \ sha2_zfs.c \ skein_zfs.c \ spa.c \ + space_map.c \ + space_reftree.c \ spa_checkpoint.c \ spa_config.c \ spa_errlog.c \ @@ -291,8 +294,6 @@ SRCS+= abd.c \ spa_log_spacemap.c \ spa_misc.c \ spa_stats.c \ - space_map.c \ - space_reftree.c \ txg.c \ u8_textprep.c \ uberblock.c \ @@ -301,8 +302,8 @@ SRCS+= abd.c \ vdev_draid.c \ vdev_draid_rand.c \ vdev_file.c \ - vdev_indirect.c \ vdev_indirect_births.c \ + vdev_indirect.c \ vdev_indirect_mapping.c \ vdev_initialize.c \ vdev_label.c \ @@ -310,11 +311,11 @@ SRCS+= abd.c \ vdev_missing.c \ vdev_queue.c \ vdev_raidz.c \ - vdev_raidz_math.c \ - vdev_raidz_math_scalar.c \ vdev_raidz_math_avx2.c \ vdev_raidz_math_avx512bw.c \ vdev_raidz_math_avx512f.c \ + vdev_raidz_math.c \ + vdev_raidz_math_scalar.c \ vdev_raidz_math_sse2.c \ vdev_raidz_math_ssse3.c \ vdev_rebuild.c \ @@ -333,7 +334,6 @@ SRCS+= abd.c \ zfeature.c \ zfs_byteswap.c \ zfs_chksum.c \ - zfs_file_os.c \ zfs_fm.c \ zfs_fuid.c \ zfs_impl.c \ @@ -358,23 +358,23 @@ SRCS+= abd.c \ zvol.c #zstd -SRCS+= zfs_zstd.c \ - entropy_common.c \ +SRCS+= zfs_zstd.c + +#zstd/common +SRCS+= entropy_common.c \ error_private.c \ - fse_compress.c \ fse_decompress.c \ + pool.c \ + zstd_common.c + +#zstd/compress +SRCS+= fse_compress.c \ hist.c \ huf_compress.c \ - huf_decompress.c \ - pool.c \ - zstd_common.c \ zstd_compress.c \ zstd_compress_literals.c \ zstd_compress_sequences.c \ zstd_compress_superblock.c \ - zstd_ddict.c \ - zstd_decompress.c \ - zstd_decompress_block.c \ zstd_double_fast.c \ zstd_fast.c \ zstd_lazy.c \ @@ -382,9 +382,16 @@ SRCS+= zfs_zstd.c \ zstd_opt.c \ zstd_preSplit.c +#zstd/decompress +SRCS+= huf_decompress.c \ + zstd_ddict.c \ + zstd_decompress_block.c \ + zstd_decompress.c + .include <bsd.kmod.mk> CFLAGS+= -include ${SRCTOP}/sys/cddl/compat/opensolaris/sys/debug_compat.h +CFLAGS+= -include ${ZINCDIR}/sys/simd_config.h CFLAGS+= -include ${ZINCDIR}/os/freebsd/spl/sys/ccompile.h CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/static_ccompile.h diff --git a/sys/modules/zfs/zfs_config.h b/sys/modules/zfs/zfs_config.h index 8b5e3ffc4573..d61e2643fa5c 100644 --- a/sys/modules/zfs/zfs_config.h +++ b/sys/modules/zfs/zfs_config.h @@ -20,48 +20,11 @@ /* add_disk() returns int */ /* #undef HAVE_ADD_DISK_RET */ -/* Define if host toolchain supports AES */ -#define HAVE_AES 1 - /* Define if you have [rt] */ #define HAVE_AIO_H 1 -#ifdef __amd64__ -#ifndef RESCUE -/* Define if host toolchain supports AVX */ -#define HAVE_AVX 1 -#endif - -/* Define if host toolchain supports AVX2 */ -#define HAVE_AVX2 1 - -/* Define if host toolchain supports AVX512BW */ -#define HAVE_AVX512BW 1 - -/* Define if host toolchain supports AVX512CD */ -#define HAVE_AVX512CD 1 - -/* Define if host toolchain supports AVX512DQ */ -#define HAVE_AVX512DQ 1 - -/* Define if host toolchain supports AVX512ER */ -#define HAVE_AVX512ER 1 - -/* Define if host toolchain supports AVX512F */ -#define HAVE_AVX512F 1 - -/* Define if host toolchain supports AVX512IFMA */ -#define HAVE_AVX512IFMA 1 - -/* Define if host toolchain supports AVX512PF */ -#define HAVE_AVX512PF 1 - -/* Define if host toolchain supports AVX512VBMI */ -#define HAVE_AVX512VBMI 1 - -/* Define if host toolchain supports AVX512VL */ -#define HAVE_AVX512VL 1 -#endif +/* Define if your assembler supports .cfi_negate_ra_state. */ +/* #undef HAVE_AS_CFI_PSEUDO_OP */ /* backtrace() is available */ /* #undef HAVE_BACKTRACE */ @@ -382,6 +345,9 @@ /* inode_set_mtime_to_ts() exists in linux/fs.h */ /* #undef HAVE_INODE_SET_MTIME_TO_TS */ +/* inode_state_read_once() exists */ +/* #undef HAVE_INODE_STATE_READ_ONCE */ + /* timestamp_truncate() exists */ /* #undef HAVE_INODE_TIMESTAMP_TRUNCATE */ @@ -445,6 +411,24 @@ /* kasan_enabled() is GPL-only */ /* #undef HAVE_KASAN_ENABLED_GPL_ONLY */ +/* Define if kernel toolchain supports AES */ +/* #undef HAVE_KERNEL_AES */ + +/* Define if kernel toolchain supports AVX */ +/* #undef HAVE_KERNEL_AVX */ + +/* Define if kernel toolchain supports AVX2 */ +/* #undef HAVE_KERNEL_AVX2 */ + +/* Define if kernel toolchain supports AVX512BW */ +/* #undef HAVE_KERNEL_AVX512BW */ + +/* Define if kernel toolchain supports AVX512F */ +/* #undef HAVE_KERNEL_AVX512F */ + +/* Define if kernel toolchain supports AVX512VL */ +/* #undef HAVE_KERNEL_AVX512VL */ + /* kernel has kernel_fpu_* functions */ /* #undef HAVE_KERNEL_FPU */ @@ -463,6 +447,9 @@ /* kernel defines intptr_t */ /* #undef HAVE_KERNEL_INTPTR_T */ +/* Define if kernel toolchain supports MOVBE */ +/* #undef HAVE_KERNEL_MOVBE */ + /* kernel has kernel_neon_* functions */ /* #undef HAVE_KERNEL_NEON */ @@ -472,9 +459,39 @@ /* kernel has linux/objtool.h */ /* #undef HAVE_KERNEL_OBJTOOL_HEADER */ +/* Define if kernel toolchain supports PCLMULQDQ */ +/* #undef HAVE_KERNEL_PCLMULQDQ */ + +/* Define if kernel toolchain supports SHA512EXT */ +/* #undef HAVE_KERNEL_SHA512EXT */ + +/* Define if kernel toolchain supports SSE2 */ +/* #undef HAVE_KERNEL_SSE2 */ + +/* Define if kernel toolchain supports SSE4_1 */ +/* #undef HAVE_KERNEL_SSE4_1 */ + +/* Define if kernel toolchain supports SSSE3 */ +/* #undef HAVE_KERNEL_SSSE3 */ + /* strlcpy() exists */ /* #undef HAVE_KERNEL_STRLCPY */ +/* Define if kernel toolchain supports VAES */ +/* #undef HAVE_KERNEL_VAES */ + +/* Define if kernel toolchain supports VPCLMULQDQ */ +/* #undef HAVE_KERNEL_VPCLMULQDQ */ + +/* Define if kernel toolchain supports XSAVE */ +/* #undef HAVE_KERNEL_XSAVE */ + +/* Define if kernel toolchain supports XSAVEOPT */ +/* #undef HAVE_KERNEL_XSAVEOPT */ + +/* Define if kernel toolchain supports XSAVES */ +/* #undef HAVE_KERNEL_XSAVES */ + /* kernel has kmap_local_page */ /* #undef HAVE_KMAP_LOCAL_PAGE */ @@ -529,8 +546,8 @@ /* page_size() is available */ /* #undef HAVE_MM_PAGE_SIZE */ -/* Define if host toolchain supports MOVBE */ -#define HAVE_MOVBE 1 +/* mount_setattr() and struct mount_attr are available */ +/* #undef HAVE_MOUNT_SETATTR */ /* Define if ns_type is accessible through ns_common */ /* #undef HAVE_NS_COMMON_TYPE */ @@ -547,9 +564,6 @@ /* iops->getattr() takes a path */ /* #undef HAVE_PATH_IOPS_GETATTR */ -/* Define if host toolchain supports PCLMULQDQ */ -#define HAVE_PCLMULQDQ 1 - /* pin_user_pages_unlocked() is available */ /* #undef HAVE_PIN_USER_PAGES_UNLOCKED */ @@ -613,9 +627,6 @@ /* Define if set_default_d_op() is available */ /* #undef HAVE_SET_DEFAULT_D_OP */ -/* Define if host toolchain supports SHA512 */ -#define HAVE_SHA512EXT 1 - /* shrinker_register exists */ /* #undef HAVE_SHRINKER_REGISTER */ @@ -625,26 +636,6 @@ /* sops->free_inode() exists */ /* #undef HAVE_SOPS_FREE_INODE */ -#if defined(__amd64__) || defined(__i386__) -/* Define if host toolchain supports SSE */ -#define HAVE_SSE 1 - -/* Define if host toolchain supports SSE2 */ -#define HAVE_SSE2 1 - -/* Define if host toolchain supports SSE3 */ -#define HAVE_SSE3 1 - -/* Define if host toolchain supports SSE4.1 */ -#define HAVE_SSE4_1 1 - -/* Define if host toolchain supports SSE4.2 */ -#define HAVE_SSE4_2 1 - -/* Define if host toolchain supports SSSE3 */ -#define HAVE_SSSE3 1 -#endif - /* STACK_FRAME_NON_STANDARD is defined */ /* #undef HAVE_STACK_FRAME_NON_STANDARD */ @@ -717,6 +708,65 @@ /* i_op->tmpfile() has userns */ /* #undef HAVE_TMPFILE_USERNS */ +/* Define if host toolchain supports AES */ +#define HAVE_TOOLCHAIN_AES 1 + +#ifdef __amd64__ +#ifndef RESCUE +/* Define if host toolchain supports AVX */ +#define HAVE_TOOLCHAIN_AVX 1 + +/* Define if host toolchain supports AVX2 */ +#define HAVE_TOOLCHAIN_AVX2 1 +#endif + +/* Define if host toolchain supports AVX512BW */ +#define HAVE_TOOLCHAIN_AVX512BW 1 + +/* Define if host toolchain supports AVX512F */ +#define HAVE_TOOLCHAIN_AVX512F 1 + +/* Define if host toolchain supports AVX512VL */ +#define HAVE_TOOLCHAIN_AVX512VL 1 +#endif + +/* Define if host toolchain supports MOVBE */ +#define HAVE_TOOLCHAIN_MOVBE 1 + +/* Define if host toolchain supports PCLMULQDQ */ +#define HAVE_TOOLCHAIN_PCLMULQDQ 1 + +/* Define if host toolchain supports SHA512EXT */ +#define HAVE_TOOLCHAIN_SHA512EXT 1 + +#if defined(__amd64__) || defined(__i386__) +/* Define if host toolchain supports SSE2 */ +#define HAVE_TOOLCHAIN_SSE2 1 + +/* Define if host toolchain supports SSE4_1 */ +#define HAVE_TOOLCHAIN_SSE4_1 1 + +/* Define if host toolchain supports SSSE3 */ +#define HAVE_TOOLCHAIN_SSSE3 1 +#endif + +#ifdef __amd64__ +/* Define if host toolchain supports VAES */ +#define HAVE_TOOLCHAIN_VAES 1 + +/* Define if host toolchain supports VPCLMULQDQ */ +#define HAVE_TOOLCHAIN_VPCLMULQDQ 1 +#endif + +/* Define if host toolchain supports XSAVE */ +#define HAVE_TOOLCHAIN_XSAVE 1 + +/* Define if host toolchain supports XSAVEOPT */ +#define HAVE_TOOLCHAIN_XSAVEOPT 1 + +/* Define if host toolchain supports XSAVES */ +#define HAVE_TOOLCHAIN_XSAVES 1 + /* totalhigh_pages() exists */ /* #undef HAVE_TOTALHIGH_PAGES */ @@ -738,11 +788,6 @@ /* iops->setattr() takes struct user_namespace* */ /* #undef HAVE_USERNS_IOPS_SETATTR */ -#ifdef __amd64__ -/* Define if host toolchain supports VAES */ -#define HAVE_VAES 1 -#endif - /* fops->clone_file_range() is available */ /* #undef HAVE_VFS_CLONE_FILE_RANGE */ @@ -782,11 +827,6 @@ /* __vmalloc page flags exists */ /* #undef HAVE_VMALLOC_PAGE_KERNEL */ -#ifdef __amd64__ -/* Define if host toolchain supports VPCLMULQDQ */ -#define HAVE_VPCLMULQDQ 1 -#endif - /* int (*writepage_t)() takes struct folio* */ /* #undef HAVE_WRITEPAGE_T_FOLIO */ @@ -805,15 +845,6 @@ /* xattr_handler->set() takes user_namespace */ /* #undef HAVE_XATTR_SET_USERNS */ -/* Define if host toolchain supports XSAVE */ -#define HAVE_XSAVE 1 - -/* Define if host toolchain supports XSAVEOPT */ -#define HAVE_XSAVEOPT 1 - -/* Define if host toolchain supports XSAVES */ -#define HAVE_XSAVES 1 - /* ZERO_PAGE() is GPL-only */ /* #undef HAVE_ZERO_PAGE_GPL_ONLY */ @@ -880,7 +911,7 @@ /* #undef ZFS_DEVICE_MINOR */ /* Define the project alias string. */ -#define ZFS_META_ALIAS "zfs-2.4.99-402-FreeBSD_gf8e5af53e" +#define ZFS_META_ALIAS "zfs-2.4.99-468-FreeBSD_g3ee08abd2" /* Define the project author. */ #define ZFS_META_AUTHOR "OpenZFS" @@ -910,7 +941,7 @@ #define ZFS_META_NAME "zfs" /* Define the project release. */ -#define ZFS_META_RELEASE "402-FreeBSD_gf8e5af53e" +#define ZFS_META_RELEASE "468-FreeBSD_g3ee08abd2" /* Define the project version. */ #define ZFS_META_VERSION "2.4.99" diff --git a/sys/modules/zfs/zfs_gitrev.h b/sys/modules/zfs/zfs_gitrev.h index 5868c6ed60e2..156d9a25fdcb 100644 --- a/sys/modules/zfs/zfs_gitrev.h +++ b/sys/modules/zfs/zfs_gitrev.h @@ -1 +1 @@ -#define ZFS_META_GITREV "zfs-2.4.99-402-gf8e5af53e-dirty" +#define ZFS_META_GITREV "zfs-2.4.99-468-g3ee08abd2" |
