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:	3ee08abd2f
This commit is contained in:
Martin Matuska committed 2026-03-19 21:25:34 +01:00
commit 80aae8a3f8
180 files changed
+5804 -2661

No files matched your search

+1
View File
@@ -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
+1
View File
@@ -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
+1 -1
View File
@@ -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
+1
View File
@@ -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
+2
View File
@@ -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
+2
View File
@@ -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 \
+4 -1
View File
@@ -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
+1
View File
@@ -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
+1
View File
@@ -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
+1
View File
@@ -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
+3 -1
View File
@@ -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
+1
View File
@@ -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
+39 -3
View File
@@ -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**.
+362 -21
View File
@@ -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);
@@ -4169,6 +4420,60 @@ out:
dnode_rele(dn, FTAG);
}
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)
{
@@ -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;
}
@@ -4477,6 +4782,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)
{
@@ -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) {
+3 -14
View File
@@ -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;
+3 -19
View File
@@ -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)));
}
/*
+3 -5
View File
@@ -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);
}
}
+89 -41
View File
@@ -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);
+1 -1
View File
@@ -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];
+29 -34
View File
@@ -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
+4 -1
View File
@@ -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 \
@@ -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) {
+1 -3
View File
@@ -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);
@@ -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[])
@@ -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);
}
+1 -12
View File
@@ -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.
*
@@ -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[])
@@ -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)
@@ -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);
}
@@ -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 */
+1
View File
@@ -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 \
@@ -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.
])
])
])
+4 -9
View File
@@ -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)
@@ -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
])
+73 -565
View File
@@ -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 # 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 #
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 # 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])
])
])
])
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])
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);
])
])
])
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])
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 #
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 # 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 #
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 # 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"])
@@ -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])
])
])
])
+1
View File
@@ -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;
+1
View File
@@ -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
+2 -1
View File
@@ -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
@@ -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
+1
View File
@@ -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 \
+5
View File
@@ -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 *);
+1 -1
View File
@@ -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 *);
+2 -1
View File
@@ -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);
@@ -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) */
+21 -2
View File
@@ -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;
/*
+81
View File
@@ -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
@@ -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
+1
View File
@@ -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);
@@ -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__)
@@ -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 *);
+8 -8
View File
@@ -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
+2 -2
View File
@@ -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
@@ -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);
@@ -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)
{
@@ -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);
}
@@ -26,8 +26,7 @@
*/
/*
* This file implements Solaris compatible getmntany() and hasmntopt()
* functions.
* This file implements Solaris compatible hasmntopt() functions.
*/
#include <sys/param.h>
@@ -176,38 +175,6 @@ fail:
return (error);
}
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)
{
@@ -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);
}
+10 -22
View File
@@ -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)));
}
@@ -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 \
+421 -148
View File
@@ -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>
+21 -213
View File
@@ -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;
}
@@ -3675,6 +3472,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;
@@ -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)
+1 -1
View File
@@ -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);
}
+21 -10
View File
@@ -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 {
@@ -89,6 +83,19 @@ struct zfs_handle {
uint8_t *zfs_props_table;
};
/*
* 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 *,
@@ -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);
}
+42 -1
View File
@@ -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) &&
+70 -4
View File
@@ -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)
@@ -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);
+1 -1
View File
@@ -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) {
/*
@@ -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)
{
@@ -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)
{
@@ -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'/>
@@ -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)
{
@@ -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
-388
View File
@@ -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)
{
@@ -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;
}
+32 -16
View File
@@ -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_format(1ULL << h, refcnt, sizeof (refcnt),
count_format);
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(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");
}
+2
View File
@@ -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 \
+179
View File
@@ -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 [email protected] .
+191
View File
@@ -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 [email protected] .
+20 -5
View File
@@ -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,
+7 -11
View File
@@ -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 ,
+148 -3
View File
@@ -27,9 +27,9 @@
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\" Copyright (c) 2021, Colm Buckley <[email protected]>
.\" 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
+7
View File
@@ -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 ,
+4
View File
@@ -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
@@ -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.
@@ -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
+13 -4
View File
@@ -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.
+2 -2
View File
@@ -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
+37 -2
View File
@@ -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
+2
View File
@@ -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
+5 -2
View File
@@ -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"
@@ -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));
@@ -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) */
@@ -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
@@ -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);
}
@@ -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) */
@@ -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__)
@@ -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__)
@@ -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
Loaded 100 of 180 files, more files were not shown because too many files have changed in this diff. Show more