Notable upstream pull request merges:
 #16853 894edd084 Add TXG timestamp database
 #17004 -multiple Implement dynamic gang header sizes
 #17405 dea0fc969 ZVOL: Return early, if volmode is ZFS_VOLMODE_NONE
                  on FreeBSD side
 #17455 cf146460c Default to zfs_bclone_wait_dirty=1
 #17481 523d9d600 Validate mountpoint on path-based unmount using statx
 #17482 92da9e0e9 ZVOL: Implement zvol_alloc() function on FreeBSD side
 #17489 dee62e074 spa: ZIO_TASKQ_ISSUE: Use symbolic priority
 #17496 bf846dcb7 Release topology restrictions on special/dedup
 #17497 4e92aee23 Relax special_small_blocks restrictions
 #17503 ea38787f2 Revert "Fix incorrect expected error in ztest"
 #17505 be1e991a1 Allow and prefer special vdevs as ZIL
 #17506 ee0cb4cb8 ztest: Fix false positive of ENOSPC handling
 #17507 92d3b4ee2 zio: rename `io_reexecute` as `io_post`;
                  use it for the direct IO checksum error flag
 #17508 6af8db61b metaslab: don't pass whole zio to throttle reserve APIs
 #17518 4c2a7f85d FreeBSD: Add support for _PC_HAS_HIDDENSYSTEM
 #17521 d7ab07dfb ZIL: Force writing of open LWB on suspend
 #17524 b6e8db509 zpool/zfs: Add '-a|--all' option to scrub, trim,
                  initialize
 #17531 c1e51c55f Correct weight recalculation of space-based metaslabs
 #17533 d323fbf49 FreeBSD: zfs_putpages: don't undirty pages until
                  after write completes
 #17536 b21e04e8d Fix zdb pool/ with -k
 #17537 -multiple Userspace tunables
 #17540 2957eabbe Add support for FreeBSD's Solaris style extended
                  attribute interface
 #17547 4bd7a2eaa zdb: fix checksum calculation for decompressed blocks
 #17551 -multiple cleanup: remove var init/update
 #17561 0f8a1105e Skip dbuf_evict_one() from dbuf_evict_notify()
                  for reclaim thread
 #17563 10a78e264 Faster checksum benchmark on system boot
 #17564 00ce064d8 spa: update blkptr diagram to include vdev padding
                  on encrypted blocks
 #17565 -multiple Physical rewrite
 #17566 fc885f308 Don't use wrong weight when passivating group
 #17572 f70c85086 BRT: Fix ZAP entry endianness
 #17575 0b6fd024a ZVOL: Unify zvol minors operations and improve error
                  handling
 #17581 cb5e7e097 range_tree: Provide more debug details upon unexpected
                  add/remove
 #17587 -multiple Fix two issues with dynamic gang headers

Obtained from:	OpenZFS
OpenZFS commit:	8302b6e32b
This commit is contained in:
Martin Matuska 2025-08-07 09:06:31 +02:00
commit df58e8b150
217 changed files with 5837 additions and 1728 deletions

View file

@ -16,6 +16,7 @@ SRCS = \
os/freebsd/zone.c \
page.c \
timestamp.c \
tunables.c \
include/sys/list.h \
include/sys/list_impl.h

View file

@ -175,6 +175,8 @@ KERNEL_C = \
zfeature.c \
zfs_byteswap.c \
zfs_chksum.c \
zfs_crrd.c \
zfs_debug_common.c \
zfs_fm.c \
zfs_fuid.c \
zfs_sa.c \

View file

@ -20,7 +20,7 @@
#include_next <sys/zfs_context.h>
#define ZFS_MODULE_PARAM_ARGS void
#define SYSCTL_HANDLER_ARGS void
/*
* Not sure why I need these, but including the canonical stand.h fails because

View file

@ -359,6 +359,7 @@ contrib/openzfs/module/zfs/zcp_synctask.c optional zfs compile-with "${ZFS_C}"
contrib/openzfs/module/zfs/zfeature.c optional zfs compile-with "${ZFS_C}"
contrib/openzfs/module/zfs/zfs_byteswap.c optional zfs compile-with "${ZFS_C}"
contrib/openzfs/module/zfs/zfs_chksum.c optional zfs compile-with "${ZFS_C}"
contrib/openzfs/module/zfs/zfs_crrd.c optional zfs compile-with "${ZFS_C}"
contrib/openzfs/module/zfs/zfs_fm.c optional zfs compile-with "${ZFS_C} ${NO_WUNUSED_BUT_SET_VARIABLE}"
contrib/openzfs/module/zfs/zfs_fuid.c optional zfs compile-with "${ZFS_C}"
contrib/openzfs/module/zfs/zfs_impl.c optional zfs compile-with "${ZFS_C}"

View file

@ -1,21 +0,0 @@
env:
CIRRUS_CLONE_DEPTH: 1
ARCH: amd64
build_task:
matrix:
freebsd_instance:
image_family: freebsd-13-5
freebsd_instance:
image_family: freebsd-14-2
freebsd_instance:
image_family: freebsd-15-0-snap
prepare_script:
- pkg install -y autoconf automake libtool gettext-runtime gmake ksh93 py311-packaging py311-cffi py311-sysctl
configure_script:
- env MAKE=gmake ./autogen.sh
- env MAKE=gmake ./configure --with-config="user" --with-python=3.11
build_script:
- gmake -j `sysctl -n kern.smp.cpus`
install_script:
- gmake install

View file

@ -2,3 +2,4 @@ name: "Custom CodeQL Analysis"
queries:
- uses: ./.github/codeql/custom-queries/cpp/deprecatedFunctionUsage.ql
- uses: ./.github/codeql/custom-queries/cpp/dslDatasetHoldReleMismatch.ql

View file

@ -0,0 +1,34 @@
/**
* @name Detect mismatched dsl_dataset_hold/_rele pairs
* @description Flags instances of issue #12014 where
* - a dataset held with dsl_dataset_hold_obj() ends up in dsl_dataset_rele_flags(), or
* - a dataset held with dsl_dataset_hold_obj_flags() ends up in dsl_dataset_rele().
* @kind problem
* @severity error
* @tags correctness
* @id cpp/dslDatasetHoldReleMismatch
*/
import cpp
from Variable ds, Call holdCall, Call releCall, string message
where
ds.getType().toString() = "dsl_dataset_t *" and
holdCall.getASuccessor*() = releCall and
(
(holdCall.getTarget().getName() = "dsl_dataset_hold_obj_flags" and
holdCall.getArgument(4).(AddressOfExpr).getOperand().(VariableAccess).getTarget() = ds and
releCall.getTarget().getName() = "dsl_dataset_rele" and
releCall.getArgument(0).(VariableAccess).getTarget() = ds and
message = "Held with dsl_dataset_hold_obj_flags but released with dsl_dataset_rele")
or
(holdCall.getTarget().getName() = "dsl_dataset_hold_obj" and
holdCall.getArgument(3).(AddressOfExpr).getOperand().(VariableAccess).getTarget() = ds and
releCall.getTarget().getName() = "dsl_dataset_rele_flags" and
releCall.getArgument(0).(VariableAccess).getTarget() = ds and
message = "Held with dsl_dataset_hold_obj but released with dsl_dataset_rele_flags")
)
select releCall,
"Mismatched release: held with $@ but released with " + releCall.getTarget().getName() + " for dataset $@",
holdCall, holdCall.getTarget().getName(),
ds, ds.toString()

View file

@ -71,14 +71,6 @@ case "$OS" in
OSv="fedora-unknown"
URL="https://download.fedoraproject.org/pub/fedora/linux/releases/42/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-42-1.1.x86_64.qcow2"
;;
freebsd13-4r)
FreeBSD="13.4-RELEASE"
OSNAME="FreeBSD $FreeBSD"
OSv="freebsd13.0"
URLxz="$FREEBSD_REL/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI.raw.xz"
KSRC="$FREEBSD_REL/../amd64/$FreeBSD/src.txz"
NIC="rtl8139"
;;
freebsd13-5r)
FreeBSD="13.5-RELEASE"
OSNAME="FreeBSD $FreeBSD"

View file

@ -28,6 +28,7 @@ function debian() {
export DEBIAN_FRONTEND="noninteractive"
echo "##[group]Running apt-get update+upgrade"
sudo sed -i '/[[:alpha:]]-backports/d' /etc/apt/sources.list
sudo apt-get update -y
sudo apt-get upgrade -y
echo "##[endgroup]"
@ -51,7 +52,7 @@ function freebsd() {
echo "##[group]Install Development Tools"
sudo pkg install -y autoconf automake autotools base64 checkbashisms fio \
gdb gettext gettext-runtime git gmake gsed jq ksh93 lcov libtool lscpu \
gdb gettext gettext-runtime git gmake gsed jq ksh lcov libtool lscpu \
pkgconf python python3 pamtester pamtester qemu-guest-agent rsync xxhash
sudo pkg install -xy \
'^samba4[[:digit:]]+$' \

View file

@ -21,11 +21,13 @@ function prefix() {
S=$((DIFF-(M*60)))
CTR=$(cat /tmp/ctr)
echo $LINE| grep -q "^Test[: ]" && CTR=$((CTR+1)) && echo $CTR > /tmp/ctr
echo $LINE| grep -q '^\[.*] Test[: ]' && CTR=$((CTR+1)) && echo $CTR > /tmp/ctr
BASE="$HOME/work/zfs/zfs"
COLOR="$BASE/scripts/zfs-tests-color.sh"
CLINE=$(echo $LINE| grep "^Test[ :]" | sed -e 's|/usr/local|/usr|g' \
CLINE=$(echo $LINE| grep '^\[.*] Test[: ]' \
| sed -e 's|^\[.*] Test|Test|g' \
| sed -e 's|/usr/local|/usr|g' \
| sed -e 's| /usr/share/zfs/zfs-tests/tests/| |g' | $COLOR)
if [ -z "$CLINE" ]; then
printf "vm${ID}: %s\n" "$LINE"

View file

@ -5,16 +5,6 @@ on:
pull_request:
workflow_dispatch:
inputs:
include_stream9:
type: boolean
required: false
default: false
description: 'Test on CentOS 9 stream'
include_stream10:
type: boolean
required: false
default: false
description: 'Test on CentOS 10 stream'
fedora_kernel_ver:
type: string
required: false
@ -39,7 +29,7 @@ jobs:
- name: Generate OS config and CI type
id: os
run: |
FULL_OS='["almalinux8", "almalinux9", "almalinux10", "debian11", "debian12", "fedora41", "fedora42", "freebsd13-4r", "freebsd14-3s", "freebsd15-0c", "ubuntu22", "ubuntu24"]'
FULL_OS='["almalinux8", "almalinux9", "almalinux10", "centos-stream9", "centos-stream10", "debian11", "debian12", "fedora41", "fedora42", "freebsd13-5r", "freebsd14-3s", "freebsd15-0c", "ubuntu22", "ubuntu24"]'
QUICK_OS='["almalinux8", "almalinux9", "almalinux10", "debian12", "fedora42", "freebsd14-3s", "ubuntu24"]'
# determine CI type when running on PR
ci_type="full"
@ -63,14 +53,6 @@ jobs:
os_json=$(echo ${os_selection} | jq -c)
fi
# Add optional runners
if [ "${{ github.event.inputs.include_stream9 }}" == 'true' ]; then
os_json=$(echo $os_json | jq -c '. += ["centos-stream9"]')
fi
if [ "${{ github.event.inputs.include_stream10 }}" == 'true' ]; then
os_json=$(echo $os_json | jq -c '. += ["centos-stream10"]')
fi
echo $os_json
echo "os=$os_json" >> $GITHUB_OUTPUT
echo "ci_type=$ci_type" >> $GITHUB_OUTPUT
@ -85,7 +67,7 @@ jobs:
# debian: debian11, debian12, ubuntu22, ubuntu24
# misc: archlinux, tumbleweed
# FreeBSD variants of 2025-06:
# FreeBSD Release: freebsd13-4r, freebsd13-5r, freebsd14-1r, freebsd14-2r, freebsd14-3r
# FreeBSD Release: freebsd13-5r, freebsd14-2r, freebsd14-3r
# FreeBSD Stable: freebsd13-5s, freebsd14-3s
# FreeBSD Current: freebsd15-0c
os: ${{ fromJson(needs.test-config.outputs.test_os) }}

View file

@ -12,7 +12,8 @@ jobs:
zloop:
runs-on: ubuntu-24.04
env:
TEST_DIR: /var/tmp/zloop
WORK_DIR: /mnt/zloop
CORE_DIR: /mnt/zloop/cores
steps:
- uses: actions/checkout@v4
with:
@ -40,38 +41,37 @@ jobs:
sudo modprobe zfs
- name: Tests
run: |
sudo mkdir -p $TEST_DIR
# run for 10 minutes or at most 6 iterations for a maximum runner
# time of 60 minutes.
sudo /usr/share/zfs/zloop.sh -t 600 -I 6 -l -m 1 -- -T 120 -P 60
sudo truncate -s 256G /mnt/vdev
sudo zpool create cipool -m $WORK_DIR -O compression=on -o autotrim=on /mnt/vdev
sudo /usr/share/zfs/zloop.sh -t 600 -I 6 -l -m 1 -c $CORE_DIR -f $WORK_DIR -- -T 120 -P 60
- name: Prepare artifacts
if: failure()
run: |
sudo chmod +r -R $TEST_DIR/
sudo chmod +r -R $WORK_DIR/
- name: Ztest log
if: failure()
run: |
grep -B10 -A1000 'ASSERT' $TEST_DIR/*/ztest.out || tail -n 1000 $TEST_DIR/*/ztest.out
grep -B10 -A1000 'ASSERT' $CORE_DIR/*/ztest.out || tail -n 1000 $CORE_DIR/*/ztest.out
- name: Gdb log
if: failure()
run: |
sed -n '/Backtraces (full)/q;p' $TEST_DIR/*/ztest.gdb
sed -n '/Backtraces (full)/q;p' $CORE_DIR/*/ztest.gdb
- name: Zdb log
if: failure()
run: |
cat $TEST_DIR/*/ztest.zdb
cat $CORE_DIR/*/ztest.zdb
- uses: actions/upload-artifact@v4
if: failure()
with:
name: Logs
path: |
/var/tmp/zloop/*/
!/var/tmp/zloop/*/vdev/
/mnt/zloop/*/
!/mnt/zloop/cores/*/vdev/
if-no-files-found: ignore
- uses: actions/upload-artifact@v4
if: failure()
with:
name: Pool files
path: |
/var/tmp/zloop/*/vdev/
/mnt/zloop/cores/*/vdev/
if-no-files-found: ignore

View file

@ -559,6 +559,7 @@ def section_arc(kstats_dict):
print()
compressed_size = arc_stats['compressed_size']
uncompressed_size = arc_stats['uncompressed_size']
overhead_size = arc_stats['overhead_size']
bonus_size = arc_stats['bonus_size']
dnode_size = arc_stats['dnode_size']
@ -671,6 +672,8 @@ def section_arc(kstats_dict):
print()
print('ARC misc:')
prt_i2('Uncompressed size:', f_perc(uncompressed_size, compressed_size),
f_bytes(uncompressed_size))
prt_i1('Memory throttles:', arc_stats['memory_throttle_count'])
prt_i1('Memory direct reclaims:', arc_stats['memory_direct_count'])
prt_i1('Memory indirect reclaims:', arc_stats['memory_indirect_count'])

View file

@ -208,7 +208,7 @@ sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
sublivelist_verify_block_t svb = {
.svb_dva = bp->blk_dva[i],
.svb_allocated_txg =
BP_GET_LOGICAL_BIRTH(bp)
BP_GET_BIRTH(bp)
};
if (zfs_btree_find(&sv->sv_leftover, &svb,
@ -619,8 +619,9 @@ livelist_metaslab_validate(spa_t *spa)
metaslab_calculate_range_tree_type(vd, m,
&start, &shift);
metaslab_verify_t mv;
mv.mv_allocated = zfs_range_tree_create(NULL,
type, NULL, start, shift);
mv.mv_allocated = zfs_range_tree_create_flags(
NULL, type, NULL, start, shift,
0, "livelist_metaslab_validate:mv_allocated");
mv.mv_vdid = vd->vdev_id;
mv.mv_msid = m->ms_id;
mv.mv_start = m->ms_start;
@ -797,8 +798,8 @@ usage(void)
"[default is 200]\n");
(void) fprintf(stderr, " -K --key=KEY "
"decryption key for encrypted dataset\n");
(void) fprintf(stderr, " -o --option=\"OPTION=INTEGER\" "
"set global variable to an unsigned 32-bit integer\n");
(void) fprintf(stderr, " -o --option=\"NAME=VALUE\" "
"set the named tunable to the given value\n");
(void) fprintf(stderr, " -p --path==PATH "
"use one or more with -e to specify path to vdev dir\n");
(void) fprintf(stderr, " -P --parseable "
@ -1991,7 +1992,7 @@ dump_ddt_log(ddt_t *ddt)
c += strlcpy(&flagstr[c], " UNKNOWN",
sizeof (flagstr) - c);
flagstr[1] = '[';
flagstr[c++] = ']';
flagstr[c] = ']';
}
uint64_t count = avl_numnodes(&ddl->ddl_tree);
@ -2568,7 +2569,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp,
(u_longlong_t)BP_GET_PSIZE(bp),
(u_longlong_t)BP_GET_FILL(bp),
(u_longlong_t)BP_GET_LOGICAL_BIRTH(bp),
(u_longlong_t)BP_GET_BIRTH(bp));
(u_longlong_t)BP_GET_PHYSICAL_BIRTH(bp));
if (bp_freed)
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), " %s", "FREE");
@ -2618,7 +2619,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
{
int err = 0;
if (BP_GET_LOGICAL_BIRTH(bp) == 0)
if (BP_GET_BIRTH(bp) == 0)
return (0);
print_indirect(spa, bp, zb, dnp);
@ -2806,7 +2807,7 @@ dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
if (BP_GET_LOGICAL_BIRTH(bp) != 0) {
if (BP_GET_BIRTH(bp) != 0) {
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("\t%s\n", blkbuf);
}
@ -2847,7 +2848,7 @@ dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed, dmu_tx_t *tx)
(void) arg, (void) tx;
char blkbuf[BP_SPRINTF_LEN];
ASSERT(BP_GET_LOGICAL_BIRTH(bp) != 0);
ASSERT(BP_GET_BIRTH(bp) != 0);
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp, bp_freed);
(void) printf("\t%s\n", blkbuf);
return (0);
@ -5921,11 +5922,11 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
* entry back to the block pointer before we claim it.
*/
if (v == DDT_PHYS_FLAT) {
ASSERT3U(BP_GET_BIRTH(bp), ==,
ASSERT3U(BP_GET_PHYSICAL_BIRTH(bp), ==,
ddt_phys_birth(dde->dde_phys, v));
tempbp = *bp;
ddt_bp_fill(dde->dde_phys, v, &tempbp,
BP_GET_BIRTH(bp));
BP_GET_PHYSICAL_BIRTH(bp));
bp = &tempbp;
}
@ -6151,7 +6152,7 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
if (zb->zb_level == ZB_DNODE_LEVEL)
return (0);
if (dump_opt['b'] >= 5 && BP_GET_LOGICAL_BIRTH(bp) > 0) {
if (dump_opt['b'] >= 5 && BP_GET_BIRTH(bp) > 0) {
char blkbuf[BP_SPRINTF_LEN];
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
(void) printf("objset %llu object %llu "
@ -6322,8 +6323,9 @@ zdb_claim_removing(spa_t *spa, zdb_cb_t *zcb)
ASSERT0(zfs_range_tree_space(svr->svr_allocd_segs));
zfs_range_tree_t *allocs = zfs_range_tree_create(NULL, ZFS_RANGE_SEG64,
NULL, 0, 0);
zfs_range_tree_t *allocs = zfs_range_tree_create_flags(
NULL, ZFS_RANGE_SEG64, NULL, 0, 0,
0, "zdb_claim_removing:allocs");
for (uint64_t msi = 0; msi < vd->vdev_ms_count; msi++) {
metaslab_t *msp = vd->vdev_ms[msi];
@ -6750,6 +6752,7 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
spa->spa_normal_class->mc_ops = &zdb_metaslab_ops;
spa->spa_log_class->mc_ops = &zdb_metaslab_ops;
spa->spa_embedded_log_class->mc_ops = &zdb_metaslab_ops;
spa->spa_special_embedded_log_class->mc_ops = &zdb_metaslab_ops;
zcb->zcb_vd_obsolete_counts =
umem_zalloc(rvd->vdev_children * sizeof (uint32_t *),
@ -6887,7 +6890,9 @@ zdb_leak_fini(spa_t *spa, zdb_cb_t *zcb)
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
ASSERT3P(msp->ms_group, ==, (msp->ms_group->mg_class ==
spa_embedded_log_class(spa)) ?
spa_embedded_log_class(spa) ||
msp->ms_group->mg_class ==
spa_special_embedded_log_class(spa)) ?
vd->vdev_log_mg : vd->vdev_mg);
/*
@ -7121,6 +7126,8 @@ dump_block_stats(spa_t *spa)
zcb->zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
zcb->zcb_totalasize +=
metaslab_class_get_alloc(spa_embedded_log_class(spa));
zcb->zcb_totalasize +=
metaslab_class_get_alloc(spa_special_embedded_log_class(spa));
zcb->zcb_start = zcb->zcb_lastprint = gethrtime();
err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, zcb);
@ -7169,6 +7176,7 @@ dump_block_stats(spa_t *spa)
total_alloc = norm_alloc +
metaslab_class_get_alloc(spa_log_class(spa)) +
metaslab_class_get_alloc(spa_embedded_log_class(spa)) +
metaslab_class_get_alloc(spa_special_embedded_log_class(spa)) +
metaslab_class_get_alloc(spa_special_class(spa)) +
metaslab_class_get_alloc(spa_dedup_class(spa)) +
get_unflushed_alloc_space(spa);
@ -7252,6 +7260,18 @@ dump_block_stats(spa_t *spa)
100.0 * alloc / space);
}
if (spa_special_embedded_log_class(spa)->mc_allocator[0].mca_rotor
!= NULL) {
uint64_t alloc = metaslab_class_get_alloc(
spa_special_embedded_log_class(spa));
uint64_t space = metaslab_class_get_space(
spa_special_embedded_log_class(spa));
(void) printf("\t%-16s %14llu used: %5.2f%%\n",
"Special embedded log", (u_longlong_t)alloc,
100.0 * alloc / space);
}
for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
if (zcb->zcb_embedded_blocks[i] == 0)
continue;
@ -7706,7 +7726,8 @@ zdb_set_skip_mmp(char *target)
* applies to the new_path parameter if allocated.
*/
static char *
import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
import_checkpointed_state(char *target, nvlist_t *cfg, boolean_t target_is_spa,
char **new_path)
{
int error = 0;
char *poolname, *bogus_name = NULL;
@ -7714,11 +7735,11 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
/* If the target is not a pool, the extract the pool name */
char *path_start = strchr(target, '/');
if (path_start != NULL) {
if (target_is_spa || path_start == NULL) {
poolname = target;
} else {
size_t poolname_len = path_start - target;
poolname = strndup(target, poolname_len);
} else {
poolname = target;
}
if (cfg == NULL) {
@ -7749,10 +7770,11 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
"with error %d\n", bogus_name, error);
}
if (new_path != NULL && path_start != NULL) {
if (asprintf(new_path, "%s%s", bogus_name, path_start) == -1) {
if (new_path != NULL && !target_is_spa) {
if (asprintf(new_path, "%s%s", bogus_name,
path_start != NULL ? path_start : "") == -1) {
free(bogus_name);
if (path_start != NULL)
if (!target_is_spa && path_start != NULL)
free(poolname);
return (NULL);
}
@ -7981,7 +8003,7 @@ verify_checkpoint_blocks(spa_t *spa)
* name) so we can do verification on it against the current state
* of the pool.
*/
checkpoint_pool = import_checkpointed_state(spa->spa_name, NULL,
checkpoint_pool = import_checkpointed_state(spa->spa_name, NULL, B_TRUE,
NULL);
ASSERT(strcmp(spa->spa_name, checkpoint_pool) != 0);
@ -8451,8 +8473,9 @@ dump_zpool(spa_t *spa)
if (dump_opt['d'] || dump_opt['i']) {
spa_feature_t f;
mos_refd_objs = zfs_range_tree_create(NULL, ZFS_RANGE_SEG64,
NULL, 0, 0);
mos_refd_objs = zfs_range_tree_create_flags(
NULL, ZFS_RANGE_SEG64, NULL, 0, 0,
0, "dump_zpool:mos_refd_objs");
dump_objset(dp->dp_meta_objset);
if (dump_opt['d'] >= 3) {
@ -8588,9 +8611,9 @@ zdb_dump_indirect(blkptr_t *bp, int nbps, int flags)
}
static void
zdb_dump_gbh(void *buf, int flags)
zdb_dump_gbh(void *buf, uint64_t size, int flags)
{
zdb_dump_indirect((blkptr_t *)buf, SPA_GBH_NBLKPTRS, flags);
zdb_dump_indirect((blkptr_t *)buf, gbh_nblkptrs(size), flags);
}
static void
@ -8780,7 +8803,6 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
(void) buf;
uint64_t orig_lsize = lsize;
boolean_t tryzle = ((getenv("ZDB_NO_ZLE") == NULL));
boolean_t found = B_FALSE;
/*
* We don't know how the data was compressed, so just try
* every decompress function at every inflated blocksize.
@ -8823,20 +8845,19 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
for (cfuncp = cfuncs; *cfuncp; cfuncp++) {
if (try_decompress_block(pabd, lsize, psize, flags,
*cfuncp, lbuf, lbuf2)) {
found = B_TRUE;
tryzle = B_FALSE;
break;
}
}
if (*cfuncp != 0)
break;
}
if (!found && tryzle) {
if (tryzle) {
for (lsize = orig_lsize; lsize <= maxlsize;
lsize += SPA_MINBLOCKSIZE) {
if (try_decompress_block(pabd, lsize, psize, flags,
ZIO_COMPRESS_ZLE, lbuf, lbuf2)) {
*cfuncp = ZIO_COMPRESS_ZLE;
found = B_TRUE;
break;
}
}
@ -9073,7 +9094,7 @@ zdb_read_block(char *thing, spa_t *spa)
zdb_dump_indirect((blkptr_t *)buf,
orig_lsize / sizeof (blkptr_t), flags);
else if (flags & ZDB_FLAG_GBH)
zdb_dump_gbh(buf, flags);
zdb_dump_gbh(buf, lsize, flags);
else
zdb_dump_block(thing, buf, lsize, flags);
@ -9120,7 +9141,7 @@ zdb_read_block(char *thing, spa_t *spa)
ck_zio->io_offset =
DVA_GET_OFFSET(&bp->blk_dva[0]);
ck_zio->io_bp = bp;
zio_checksum_compute(ck_zio, ck, pabd, lsize);
zio_checksum_compute(ck_zio, ck, pabd, psize);
printf(
"%12s\t"
"cksum=%016llx:%016llx:%016llx:%016llx\n",
@ -9377,9 +9398,11 @@ main(int argc, char **argv)
while (*optarg != '\0') { *optarg++ = '*'; }
break;
case 'o':
error = set_global_var(optarg);
dump_opt[c]++;
dump_all = 0;
error = handle_tunable_option(optarg, B_FALSE);
if (error != 0)
usage();
zdb_exit(1);
break;
case 'p':
if (searchdirs == NULL) {
@ -9545,6 +9568,12 @@ main(int argc, char **argv)
error = 0;
goto fini;
}
if (dump_opt['o'])
/*
* Avoid blasting tunable options off the top of the
* screen.
*/
zdb_exit(1);
usage();
}
@ -9697,7 +9726,7 @@ main(int argc, char **argv)
char *checkpoint_target = NULL;
if (dump_opt['k']) {
checkpoint_pool = import_checkpointed_state(target, cfg,
&checkpoint_target);
target_is_spa, &checkpoint_target);
if (checkpoint_target != NULL)
target = checkpoint_target;

View file

@ -176,7 +176,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
(void) printf("%shas blkptr, %s\n", tab_prefix,
!BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
!BP_IS_HOLE(bp) && BP_GET_BIRTH(bp) >=
spa_min_claim_txg(zilog->zl_spa) ?
"will claim" : "won't claim");
print_log_bp(bp, tab_prefix);
@ -189,7 +189,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
(void) printf("%s<hole>\n", tab_prefix);
return;
}
if (BP_GET_LOGICAL_BIRTH(bp) < zilog->zl_header->zh_claim_txg) {
if (BP_GET_BIRTH(bp) < zilog->zl_header->zh_claim_txg) {
(void) printf("%s<block already committed>\n",
tab_prefix);
return;
@ -240,7 +240,7 @@ zil_prt_rec_write_enc(zilog_t *zilog, int txtype, const void *arg)
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
(void) printf("%shas blkptr, %s\n", tab_prefix,
!BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
!BP_IS_HOLE(bp) && BP_GET_BIRTH(bp) >=
spa_min_claim_txg(zilog->zl_spa) ?
"will claim" : "won't claim");
print_log_bp(bp, tab_prefix);
@ -476,7 +476,7 @@ print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
if (claim_txg != 0)
claim = "already claimed";
else if (BP_GET_LOGICAL_BIRTH(bp) >= spa_min_claim_txg(zilog->zl_spa))
else if (BP_GET_BIRTH(bp) >= spa_min_claim_txg(zilog->zl_spa))
claim = "will claim";
else
claim = "won't claim";

View file

@ -134,11 +134,13 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
* of blkid cache and L2ARC VDEV does not contain pool guid in its
* blkid, so this is a special case for L2ARC VDEV.
*/
else if (gsp->gs_vdev_guid != 0 && gsp->gs_devid == NULL &&
else if (gsp->gs_vdev_guid != 0 &&
nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &vdev_guid) == 0 &&
gsp->gs_vdev_guid == vdev_guid) {
(void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
&gsp->gs_devid);
if (gsp->gs_devid == NULL) {
(void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
&gsp->gs_devid);
}
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
&gsp->gs_vdev_expandtime);
return (B_TRUE);
@ -156,22 +158,28 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
/*
* For each vdev in this pool, look for a match by devid
*/
if ((config = zpool_get_config(zhp, NULL)) != NULL) {
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvl) == 0) {
(void) zfs_agent_iter_vdev(zhp, nvl, gsp);
}
}
/*
* if a match was found then grab the pool guid
*/
if (gsp->gs_vdev_guid && gsp->gs_devid) {
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
&gsp->gs_pool_guid);
}
boolean_t found = B_FALSE;
uint64_t pool_guid;
/* Get pool configuration and extract pool GUID */
if ((config = zpool_get_config(zhp, NULL)) == NULL ||
nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
&pool_guid) != 0)
goto out;
/* Skip this pool if we're looking for a specific pool */
if (gsp->gs_pool_guid != 0 && pool_guid != gsp->gs_pool_guid)
goto out;
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvl) == 0)
found = zfs_agent_iter_vdev(zhp, nvl, gsp);
if (found && gsp->gs_pool_guid == 0)
gsp->gs_pool_guid = pool_guid;
out:
zpool_close(zhp);
return (gsp->gs_devid != NULL && gsp->gs_vdev_guid != 0);
return (found);
}
void
@ -233,20 +241,17 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
* ZFS_EV_POOL_GUID may be missing so find them.
*/
if (devid == NULL || pool_guid == 0 || vdev_guid == 0) {
if (devid == NULL)
search.gs_vdev_guid = vdev_guid;
else
search.gs_devid = devid;
zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
if (devid == NULL)
devid = search.gs_devid;
if (pool_guid == 0)
pool_guid = search.gs_pool_guid;
if (vdev_guid == 0)
vdev_guid = search.gs_vdev_guid;
devtype = search.gs_vdev_type;
}
search.gs_devid = devid;
search.gs_vdev_guid = vdev_guid;
search.gs_pool_guid = pool_guid;
zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
if (devid == NULL)
devid = search.gs_devid;
if (pool_guid == 0)
pool_guid = search.gs_pool_guid;
if (vdev_guid == 0)
vdev_guid = search.gs_vdev_guid;
devtype = search.gs_vdev_type;
/*
* We want to avoid reporting "remove" events coming from

View file

@ -110,7 +110,7 @@ zed_event_fini(struct zed_conf *zcp)
static void
_bump_event_queue_length(void)
{
int zzlm = -1, wr;
int zzlm, wr;
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
long int qlen, orig_qlen;

View file

@ -440,7 +440,7 @@ get_usage(zfs_help_t idx)
return (gettext("\tredact <snapshot> <bookmark> "
"<redaction_snapshot> ...\n"));
case HELP_REWRITE:
return (gettext("\trewrite [-rvx] [-o <offset>] [-l <length>] "
return (gettext("\trewrite [-Prvx] [-o <offset>] [-l <length>] "
"<directory|file ...>\n"));
case HELP_JAIL:
return (gettext("\tjail <jailid|jailname> <filesystem>\n"));
@ -1974,9 +1974,8 @@ fill_dataset_info(nvlist_t *list, zfs_handle_t *zhp, boolean_t as_int)
}
if (type == ZFS_TYPE_SNAPSHOT) {
char *ds, *snap;
ds = snap = strdup(zfs_get_name(zhp));
ds = strsep(&snap, "@");
char *snap = strdup(zfs_get_name(zhp));
char *ds = strsep(&snap, "@");
fnvlist_add_string(list, "dataset", ds);
fnvlist_add_string(list, "snapshot_name", snap);
free(ds);
@ -2019,8 +2018,7 @@ get_callback(zfs_handle_t *zhp, void *data)
nvlist_t *user_props = zfs_get_user_props(zhp);
zprop_list_t *pl = cbp->cb_proplist;
nvlist_t *propval;
nvlist_t *item, *d, *props;
item = d = props = NULL;
nvlist_t *item, *d = NULL, *props = NULL;
const char *strval;
const char *sourceval;
boolean_t received = is_recvd_column(cbp);
@ -5879,7 +5877,7 @@ parse_fs_perm_set(fs_perm_set_t *fspset, nvlist_t *nvl)
static inline const char *
deleg_perm_comment(zfs_deleg_note_t note)
{
const char *str = "";
const char *str;
/* subcommands */
switch (note) {
@ -7729,6 +7727,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
struct extmnttab 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.
@ -7770,6 +7769,24 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
goto out;
}
/*
* If the filesystem is mounted, check that the mountpoint matches
* the one in the mnttab entry w.r.t. provided path. If it doesn't,
* then we should not proceed further.
*/
entry_mntpnt = strdup(entry.mnt_mountp);
if (zfs_is_mounted(zhp, &zfs_mntpnt)) {
if (strcmp(zfs_mntpnt, entry_mntpnt) != 0) {
(void) fprintf(stderr, gettext("cannot %s '%s': "
"not an original mountpoint\n"), cmdname, path);
free(zfs_mntpnt);
free(entry_mntpnt);
goto out;
}
free(zfs_mntpnt);
}
free(entry_mntpnt);
if (op == OP_SHARE) {
char nfs_mnt_prop[ZFS_MAXPROPLEN];
char smbshare_prop[ZFS_MAXPROPLEN];
@ -9160,8 +9177,11 @@ zfs_do_rewrite(int argc, char **argv)
zfs_rewrite_args_t args;
memset(&args, 0, sizeof (args));
while ((c = getopt(argc, argv, "l:o:rvx")) != -1) {
while ((c = getopt(argc, argv, "Pl:o:rvx")) != -1) {
switch (c) {
case 'P':
args.flags |= ZFS_REWRITE_PHYSICAL;
break;
case 'l':
args.len = strtoll(optarg, NULL, 0);
break;

View file

@ -379,8 +379,8 @@ process_unique_cmd_columns(vdev_cmd_data_list_t *vcdl)
static int
vdev_process_cmd_output(vdev_cmd_data_t *data, char *line)
{
char *col = NULL;
char *val = line;
char *col;
char *val;
char *equals;
char **tmp;
@ -397,6 +397,7 @@ vdev_process_cmd_output(vdev_cmd_data_t *data, char *line)
col = line;
val = equals + 1;
} else {
col = NULL;
val = line;
}

View file

@ -34,7 +34,7 @@
* Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
* Copyright (c) 2021, 2023, Klara Inc.
* Copyright [2021] Hewlett Packard Enterprise Development LP
* Copyright (c) 2021, 2025 Hewlett Packard Enterprise Development LP.
*/
#include <assert.h>
@ -510,16 +510,16 @@ get_usage(zpool_help_t idx)
case HELP_REOPEN:
return (gettext("\treopen [-n] <pool>\n"));
case HELP_INITIALIZE:
return (gettext("\tinitialize [-c | -s | -u] [-w] <pool> "
"[<device> ...]\n"));
return (gettext("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
"[<device> ...]>\n"));
case HELP_SCRUB:
return (gettext("\tscrub [-e | -s | -p | -C] [-w] "
"<pool> ...\n"));
return (gettext("\tscrub [-e | -s | -p | -C | -E | -S] [-w] "
"<-a | <pool> [<pool> ...]>\n"));
case HELP_RESILVER:
return (gettext("\tresilver <pool> ...\n"));
case HELP_TRIM:
return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> "
"[<device> ...]\n"));
return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] "
"<-a | <pool> [<device> ...]>\n"));
case HELP_STATUS:
return (gettext("\tstatus [-DdegiLPpstvx] "
"[-c script1[,script2,...]] ...\n"
@ -560,33 +560,6 @@ get_usage(zpool_help_t idx)
}
}
static void
zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
{
uint_t children = 0;
nvlist_t **child;
uint_t i;
(void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&child, &children);
if (children == 0) {
char *path = zpool_vdev_name(g_zfs, zhp, nvroot,
VDEV_NAME_PATH);
if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
strcmp(path, VDEV_TYPE_HOLE) != 0)
fnvlist_add_boolean(res, path);
free(path);
return;
}
for (i = 0; i < children; i++) {
zpool_collect_leaves(zhp, child[i], res);
}
}
/*
* Callback routine that will print out a pool property value.
*/
@ -794,22 +767,26 @@ zpool_do_initialize(int argc, char **argv)
int c;
char *poolname;
zpool_handle_t *zhp;
nvlist_t *vdevs;
int err = 0;
boolean_t wait = B_FALSE;
boolean_t initialize_all = B_FALSE;
struct option long_options[] = {
{"cancel", no_argument, NULL, 'c'},
{"suspend", no_argument, NULL, 's'},
{"uninit", no_argument, NULL, 'u'},
{"wait", no_argument, NULL, 'w'},
{"all", no_argument, NULL, 'a'},
{0, 0, 0, 0}
};
pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
while ((c = getopt_long(argc, argv, "csuw", long_options,
while ((c = getopt_long(argc, argv, "acsuw", long_options,
NULL)) != -1) {
switch (c) {
case 'a':
initialize_all = B_TRUE;
break;
case 'c':
if (cmd_type != POOL_INITIALIZE_START &&
cmd_type != POOL_INITIALIZE_CANCEL) {
@ -856,7 +833,18 @@ zpool_do_initialize(int argc, char **argv)
argc -= optind;
argv += optind;
if (argc < 1) {
initialize_cbdata_t cbdata = {
.wait = wait,
.cmd_type = cmd_type
};
if (initialize_all && argc > 0) {
(void) fprintf(stderr, gettext("-a cannot be combined with "
"individual pools or vdevs\n"));
usage(B_FALSE);
}
if (argc < 1 && !initialize_all) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
return (-1);
@ -868,30 +856,35 @@ zpool_do_initialize(int argc, char **argv)
usage(B_FALSE);
}
poolname = argv[0];
zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);
vdevs = fnvlist_alloc();
if (argc == 1) {
/* no individual leaf vdevs specified, so add them all */
nvlist_t *config = zpool_get_config(zhp, NULL);
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE);
zpool_collect_leaves(zhp, nvroot, vdevs);
if (argc == 0 && initialize_all) {
/* Initilize each pool recursively */
err = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
B_FALSE, zpool_initialize_one, &cbdata);
return (err);
} else if (argc == 1) {
/* no individual leaf vdevs specified, initialize the pool */
poolname = argv[0];
zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);
err = zpool_initialize_one(zhp, &cbdata);
} else {
/* individual leaf vdevs specified, initialize them */
poolname = argv[0];
zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);
nvlist_t *vdevs = fnvlist_alloc();
for (int i = 1; i < argc; i++) {
fnvlist_add_boolean(vdevs, argv[i]);
}
if (wait)
err = zpool_initialize_wait(zhp, cmd_type, vdevs);
else
err = zpool_initialize(zhp, cmd_type, vdevs);
fnvlist_free(vdevs);
}
if (wait)
err = zpool_initialize_wait(zhp, cmd_type, vdevs);
else
err = zpool_initialize(zhp, cmd_type, vdevs);
fnvlist_free(vdevs);
zpool_close(zhp);
return (err);
@ -1788,7 +1781,7 @@ zpool_do_labelclear(int argc, char **argv)
{
char vdev[MAXPATHLEN];
char *name = NULL;
int c, fd = -1, ret = 0;
int c, fd, ret = 0;
nvlist_t *config;
pool_state_t state;
boolean_t inuse = B_FALSE;
@ -6157,7 +6150,6 @@ static void
get_interval_count_filter_guids(int *argc, char **argv, float *interval,
unsigned long *count, iostat_cbdata_t *cb)
{
char **tmpargv = argv;
int argc_for_interval = 0;
/* Is the last arg an interval value? Or a guid? */
@ -6181,7 +6173,7 @@ get_interval_count_filter_guids(int *argc, char **argv, float *interval,
}
/* Point to our list of possible intervals */
tmpargv = &argv[*argc - argc_for_interval];
char **tmpargv = &argv[*argc - argc_for_interval];
*argc = *argc - argc_for_interval;
get_interval_count(&argc_for_interval, tmpargv,
@ -6377,7 +6369,6 @@ zpool_do_iostat(int argc, char **argv)
int npools;
float interval = 0;
unsigned long count = 0;
int winheight = 24;
zpool_list_t *list;
boolean_t verbose = B_FALSE;
boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
@ -6673,7 +6664,7 @@ zpool_do_iostat(int argc, char **argv)
* even when terminal window has its height
* changed.
*/
winheight = terminal_height();
int winheight = terminal_height();
/*
* Are we connected to TTY? If not, headers_once
* should be true, to avoid breaking scripts.
@ -8368,6 +8359,8 @@ zpool_do_reopen(int argc, char **argv)
typedef struct scrub_cbdata {
int cb_type;
pool_scrub_cmd_t cb_scrub_cmd;
time_t cb_date_start;
time_t cb_date_end;
} scrub_cbdata_t;
static boolean_t
@ -8411,8 +8404,8 @@ scrub_callback(zpool_handle_t *zhp, void *data)
return (1);
}
err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
err = zpool_scan_range(zhp, cb->cb_type, cb->cb_scrub_cmd,
cb->cb_date_start, cb->cb_date_end);
if (err == 0 && zpool_has_checkpoint(zhp) &&
cb->cb_type == POOL_SCAN_SCRUB) {
(void) printf(gettext("warning: will not scrub state that "
@ -8430,10 +8423,34 @@ wait_callback(zpool_handle_t *zhp, void *data)
return (zpool_wait(zhp, *act));
}
static time_t
date_string_to_sec(const char *timestr, boolean_t rounding)
{
struct tm tm = {0};
int adjustment = rounding ? 1 : 0;
/* Allow mktime to determine timezone. */
tm.tm_isdst = -1;
if (strptime(timestr, "%Y-%m-%d %H:%M", &tm) == NULL) {
if (strptime(timestr, "%Y-%m-%d", &tm) == NULL) {
fprintf(stderr, gettext("Failed to parse the date.\n"));
usage(B_FALSE);
}
adjustment *= 24 * 60 * 60;
} else {
adjustment *= 60;
}
return (mktime(&tm) + adjustment);
}
/*
* zpool scrub [-e | -s | -p | -C] [-w] <pool> ...
* zpool scrub [-e | -s | -p | -C | -E | -S] [-w] <pool> ...
*
* -e Only scrub blocks in the error log.
* -E End date of scrub.
* -S Start date of scrub.
* -s Stop. Stops any in-progress scrub.
* -p Pause. Pause in-progress scrub.
* -w Wait. Blocks until scrub has completed.
@ -8449,21 +8466,36 @@ zpool_do_scrub(int argc, char **argv)
cb.cb_type = POOL_SCAN_SCRUB;
cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
cb.cb_date_start = cb.cb_date_end = 0;
boolean_t is_error_scrub = B_FALSE;
boolean_t is_pause = B_FALSE;
boolean_t is_stop = B_FALSE;
boolean_t is_txg_continue = B_FALSE;
boolean_t scrub_all = B_FALSE;
/* check options */
while ((c = getopt(argc, argv, "spweC")) != -1) {
while ((c = getopt(argc, argv, "aspweCE:S:")) != -1) {
switch (c) {
case 'a':
scrub_all = B_TRUE;
break;
case 'e':
is_error_scrub = B_TRUE;
break;
case 'E':
/*
* Round the date. It's better to scrub more data than
* less. This also makes the date inclusive.
*/
cb.cb_date_end = date_string_to_sec(optarg, B_TRUE);
break;
case 's':
is_stop = B_TRUE;
break;
case 'S':
cb.cb_date_start = date_string_to_sec(optarg, B_FALSE);
break;
case 'p':
is_pause = B_TRUE;
break;
@ -8511,6 +8543,19 @@ zpool_do_scrub(int argc, char **argv)
}
}
if ((cb.cb_date_start != 0 || cb.cb_date_end != 0) &&
cb.cb_scrub_cmd != POOL_SCRUB_NORMAL) {
(void) fprintf(stderr, gettext("invalid option combination: "
"start/end date is available only with normal scrub\n"));
usage(B_FALSE);
}
if (cb.cb_date_start != 0 && cb.cb_date_end != 0 &&
cb.cb_date_start > cb.cb_date_end) {
(void) fprintf(stderr, gettext("invalid arguments: "
"end date has to be later than start date\n"));
usage(B_FALSE);
}
if (wait && (cb.cb_type == POOL_SCAN_NONE ||
cb.cb_scrub_cmd == POOL_SCRUB_PAUSE)) {
(void) fprintf(stderr, gettext("invalid option combination: "
@ -8521,7 +8566,7 @@ zpool_do_scrub(int argc, char **argv)
argc -= optind;
argv += optind;
if (argc < 1) {
if (argc < 1 && !scrub_all) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
}
@ -8551,6 +8596,7 @@ zpool_do_resilver(int argc, char **argv)
cb.cb_type = POOL_SCAN_RESILVER;
cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
cb.cb_date_start = cb.cb_date_end = 0;
/* check options */
while ((c = getopt(argc, argv, "")) != -1) {
@ -8593,6 +8639,7 @@ zpool_do_trim(int argc, char **argv)
{"rate", required_argument, NULL, 'r'},
{"suspend", no_argument, NULL, 's'},
{"wait", no_argument, NULL, 'w'},
{"all", no_argument, NULL, 'a'},
{0, 0, 0, 0}
};
@ -8600,11 +8647,16 @@ zpool_do_trim(int argc, char **argv)
uint64_t rate = 0;
boolean_t secure = B_FALSE;
boolean_t wait = B_FALSE;
boolean_t trimall = B_FALSE;
int error;
int c;
while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL))
while ((c = getopt_long(argc, argv, "acdr:sw", long_options, NULL))
!= -1) {
switch (c) {
case 'a':
trimall = B_TRUE;
break;
case 'c':
if (cmd_type != POOL_TRIM_START &&
cmd_type != POOL_TRIM_CANCEL) {
@ -8663,7 +8715,18 @@ zpool_do_trim(int argc, char **argv)
argc -= optind;
argv += optind;
if (argc < 1) {
trimflags_t trim_flags = {
.secure = secure,
.rate = rate,
.wait = wait,
};
trim_cbdata_t cbdata = {
.trim_flags = trim_flags,
.cmd_type = cmd_type
};
if (argc < 1 && !trimall) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
return (-1);
@ -8671,41 +8734,46 @@ zpool_do_trim(int argc, char **argv)
if (wait && (cmd_type != POOL_TRIM_START)) {
(void) fprintf(stderr, gettext("-w cannot be used with -c or "
"-s\n"));
"-s options\n"));
usage(B_FALSE);
}
char *poolname = argv[0];
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);
if (trimall && argc > 0) {
(void) fprintf(stderr, gettext("-a cannot be combined with "
"individual zpools or vdevs\n"));
usage(B_FALSE);
}
trimflags_t trim_flags = {
.secure = secure,
.rate = rate,
.wait = wait,
};
nvlist_t *vdevs = fnvlist_alloc();
if (argc == 1) {
if (argc == 0 && trimall) {
cbdata.trim_flags.fullpool = B_TRUE;
/* Trim each pool recursively */
error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
B_FALSE, zpool_trim_one, &cbdata);
} else if (argc == 1) {
char *poolname = argv[0];
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);
/* no individual leaf vdevs specified, so add them all */
nvlist_t *config = zpool_get_config(zhp, NULL);
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE);
zpool_collect_leaves(zhp, nvroot, vdevs);
trim_flags.fullpool = B_TRUE;
error = zpool_trim_one(zhp, &cbdata);
zpool_close(zhp);
} else {
trim_flags.fullpool = B_FALSE;
char *poolname = argv[0];
zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
if (zhp == NULL)
return (-1);
/* leaf vdevs specified, trim only those */
cbdata.trim_flags.fullpool = B_FALSE;
nvlist_t *vdevs = fnvlist_alloc();
for (int i = 1; i < argc; i++) {
fnvlist_add_boolean(vdevs, argv[i]);
}
error = zpool_trim(zhp, cbdata.cmd_type, vdevs,
&cbdata.trim_flags);
fnvlist_free(vdevs);
zpool_close(zhp);
}
int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
fnvlist_free(vdevs);
zpool_close(zhp);
return (error);
}
@ -10706,7 +10774,6 @@ status_callback_json(zpool_handle_t *zhp, void *data)
uint_t c;
vdev_stat_t *vs;
nvlist_t *item, *d, *load_info, *vds;
item = d = NULL;
/* If dedup stats were requested, also fetch dedupcached. */
if (cbp->cb_dedup_stats > 1)
@ -11330,7 +11397,8 @@ upgrade_enable_all(zpool_handle_t *zhp, int *countp)
const char *fname = spa_feature_table[i].fi_uname;
const char *fguid = spa_feature_table[i].fi_guid;
if (!spa_feature_table[i].fi_zfs_mod_supported)
if (!spa_feature_table[i].fi_zfs_mod_supported ||
(spa_feature_table[i].fi_flags & ZFEATURE_FLAG_NO_UPGRADE))
continue;
if (!nvlist_exists(enabled, fguid) && requested_features[i]) {
@ -11485,7 +11553,11 @@ upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
"Note that the pool "
"'compatibility' feature can be "
"used to inhibit\nfeature "
"upgrades.\n\n"));
"upgrades.\n\n"
"Features marked with (*) are not "
"applied automatically on upgrade, "
"and\nmust be applied explicitly "
"with zpool-set(7).\n\n"));
(void) printf(gettext("POOL "
"FEATURE\n"));
(void) printf(gettext("------"
@ -11499,7 +11571,9 @@ upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
poolfirst = B_FALSE;
}
(void) printf(gettext(" %s\n"), fname);
(void) printf(gettext(" %s%s\n"), fname,
spa_feature_table[i].fi_flags &
ZFEATURE_FLAG_NO_UPGRADE ? "(*)" : "");
}
/*
* If they did "zpool upgrade -a", then we could

View file

@ -574,7 +574,6 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
nvlist_t *cnv = child[c];
const char *path;
struct stat64 statbuf;
int64_t size = -1LL;
const char *childtype;
int fd, err;
@ -656,7 +655,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
statbuf.st_size == MAXOFFSET_T)
continue;
size = statbuf.st_size;
int64_t size = statbuf.st_size;
/*
* Also make sure that devices and
@ -876,6 +875,18 @@ check_replication(nvlist_t *config, nvlist_t *newroot)
(u_longlong_t)mirror->zprl_children);
ret = -1;
}
} else if (is_raidz_draid(current, new)) {
if (current->zprl_parity != new->zprl_parity) {
vdev_error(gettext(
"mismatched replication level: pool and "
"new vdev with different redundancy, %s "
"and %s vdevs, %llu vs. %llu\n"),
current->zprl_type,
new->zprl_type,
(u_longlong_t)current->zprl_parity,
(u_longlong_t)new->zprl_parity);
ret = -1;
}
} else if (strcmp(current->zprl_type, new->zprl_type) != 0) {
vdev_error(gettext(
"mismatched replication level: pool uses %s "
@ -1353,7 +1364,7 @@ is_grouping(const char *type, int *mindev, int *maxdev)
static int
draid_config_by_type(nvlist_t *nv, const char *type, uint64_t children)
{
uint64_t nparity = 1;
uint64_t nparity;
uint64_t nspares = 0;
uint64_t ndata = UINT64_MAX;
uint64_t ngroups = 1;
@ -1581,13 +1592,12 @@ construct_spec(nvlist_t *props, int argc, char **argv)
is_dedup = is_spare = B_FALSE;
}
if (is_log || is_special || is_dedup) {
if (is_log) {
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
(void) fprintf(stderr,
gettext("invalid vdev "
"specification: unsupported '%s' "
"device: %s\n"), is_log ? "log" :
"special", type);
"specification: unsupported 'log' "
"device: %s\n"), type);
goto spec_out;
}
nlogs++;

View file

@ -809,8 +809,8 @@ static ztest_option_t option_table[] = {
{ 'X', "raidz-expansion", NULL,
"Perform a dedicated raidz expansion test",
NO_DEFAULT, NULL},
{ 'o', "option", "\"OPTION=INTEGER\"",
"Set global variable to an unsigned 32-bit integer value",
{ 'o', "option", "\"NAME=VALUE\"",
"Set the named tunable to the given value",
NO_DEFAULT, NULL},
{ 'G', "dump-debug-msg", NULL,
"Dump zfs_dbgmsg buffer before exiting due to an error",
@ -919,7 +919,7 @@ ztest_parse_name_value(const char *input, ztest_shared_opts_t *zo)
{
char name[32];
char *value;
int state = ZTEST_VDEV_CLASS_RND;
int state;
(void) strlcpy(name, input, sizeof (name));
@ -3882,7 +3882,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
* If newvd is too small, it should fail with EOVERFLOW.
*
* If newvd is a distributed spare and it's being attached to a
* dRAID which is not its parent it should fail with EINVAL.
* dRAID which is not its parent it should fail with ENOTSUP.
*/
if (pvd->vdev_ops != &vdev_mirror_ops &&
pvd->vdev_ops != &vdev_root_ops && (!replacing ||
@ -3901,7 +3901,7 @@ ztest_vdev_attach_detach(ztest_ds_t *zd, uint64_t id)
else if (ashift > oldvd->vdev_top->vdev_ashift)
expected_error = EDOM;
else if (newvd_is_dspare && pvd != vdev_draid_spare_get_parent(newvd))
expected_error = EINVAL;
expected_error = ENOTSUP;
else
expected_error = 0;
@ -7069,7 +7069,7 @@ ztest_set_global_vars(void)
char *kv = ztest_opts.zo_gvars[i];
VERIFY3U(strlen(kv), <=, ZO_GVARS_MAX_ARGLEN);
VERIFY3U(strlen(kv), >, 0);
int err = set_global_var(kv);
int err = handle_tunable_option(kv, B_TRUE);
if (ztest_opts.zo_verbose > 0) {
(void) printf("setting global var %s ... %s\n", kv,
err ? "failed" : "ok");
@ -7813,6 +7813,9 @@ ztest_dataset_open(int d)
ztest_dataset_name(name, ztest_opts.zo_pool, d);
if (ztest_opts.zo_verbose >= 6)
(void) printf("Opening %s\n", name);
(void) pthread_rwlock_rdlock(&ztest_name_lock);
error = ztest_dataset_create(name);
@ -8308,41 +8311,44 @@ static void
ztest_generic_run(ztest_shared_t *zs, spa_t *spa)
{
kthread_t **run_threads;
int t;
int i, ndatasets;
run_threads = umem_zalloc(ztest_opts.zo_threads * sizeof (kthread_t *),
UMEM_NOFAIL);
/*
* Actual number of datasets to be used.
*/
ndatasets = MIN(ztest_opts.zo_datasets, ztest_opts.zo_threads);
/*
* Prepare the datasets first.
*/
for (i = 0; i < ndatasets; i++)
VERIFY0(ztest_dataset_open(i));
/*
* Kick off all the tests that run in parallel.
*/
for (t = 0; t < ztest_opts.zo_threads; t++) {
if (t < ztest_opts.zo_datasets && ztest_dataset_open(t) != 0) {
umem_free(run_threads, ztest_opts.zo_threads *
sizeof (kthread_t *));
return;
}
run_threads[t] = thread_create(NULL, 0, ztest_thread,
(void *)(uintptr_t)t, 0, NULL, TS_RUN | TS_JOINABLE,
for (i = 0; i < ztest_opts.zo_threads; i++) {
run_threads[i] = thread_create(NULL, 0, ztest_thread,
(void *)(uintptr_t)i, 0, NULL, TS_RUN | TS_JOINABLE,
defclsyspri);
}
/*
* Wait for all of the tests to complete.
*/
for (t = 0; t < ztest_opts.zo_threads; t++)
VERIFY0(thread_join(run_threads[t]));
for (i = 0; i < ztest_opts.zo_threads; i++)
VERIFY0(thread_join(run_threads[i]));
/*
* Close all datasets. This must be done after all the threads
* are joined so we can be sure none of the datasets are in-use
* by any of the threads.
*/
for (t = 0; t < ztest_opts.zo_threads; t++) {
if (t < ztest_opts.zo_datasets)
ztest_dataset_close(t);
}
for (i = 0; i < ndatasets; i++)
ztest_dataset_close(i);
txg_wait_synced(spa_get_dsl(spa), 0);
@ -8465,6 +8471,7 @@ ztest_run(ztest_shared_t *zs)
int d = ztest_random(ztest_opts.zo_datasets);
ztest_dataset_destroy(d);
txg_wait_synced(spa_get_dsl(spa), 0);
}
zs->zs_enospc_count = 0;

View file

@ -72,7 +72,7 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 36
#serial 37
AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL])
AC_DEFUN([AX_PYTHON_DEVEL],[
@ -316,7 +316,7 @@ EOD`
PYTHON_LIBS="-L$ac_python_libdir -lpython$ac_python_version"
fi
if test -z "PYTHON_LIBS"; then
if test -z "$PYTHON_LIBS"; then
AC_MSG_WARN([
Cannot determine location of your Python DSO. Please check it was installed with
dynamic libraries enabled, or try setting PYTHON_LIBS by hand.

View file

@ -0,0 +1,24 @@
dnl #
dnl # Linux 5.2 API change
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_SOPS_FREE_INODE], [
ZFS_LINUX_TEST_SRC([super_operations_free_inode], [
#include <linux/fs.h>
static void free_inode(struct inode *) { }
static struct super_operations sops __attribute__ ((unused)) = {
.free_inode = free_inode,
};
],[])
])
AC_DEFUN([ZFS_AC_KERNEL_SOPS_FREE_INODE], [
AC_MSG_CHECKING([whether sops->free_inode() exists])
ZFS_LINUX_TEST_RESULT([super_operations_free_inode], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SOPS_FREE_INODE, 1, [sops->free_inode() exists])
],[
AC_MSG_RESULT(no)
])
])

View file

@ -134,6 +134,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_PIN_USER_PAGES
ZFS_AC_KERNEL_SRC_TIMER
ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_WB_ERR
ZFS_AC_KERNEL_SRC_SOPS_FREE_INODE
case "$host_cpu" in
powerpc*)
ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
@ -252,6 +253,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_PIN_USER_PAGES
ZFS_AC_KERNEL_TIMER
ZFS_AC_KERNEL_SUPER_BLOCK_S_WB_ERR
ZFS_AC_KERNEL_SOPS_FREE_INODE
case "$host_cpu" in
powerpc*)
ZFS_AC_KERNEL_CPU_HAS_FEATURE

View file

@ -0,0 +1,34 @@
dnl #
dnl # Check for statx() function and STATX_MNT_ID availability
dnl #
AC_DEFUN([ZFS_AC_CONFIG_USER_STATX], [
AC_CHECK_HEADERS([linux/stat.h],
[have_stat_headers=yes],
[have_stat_headers=no])
AS_IF([test "x$have_stat_headers" = "xyes"], [
AC_CHECK_FUNC([statx], [
AC_DEFINE([HAVE_STATX], [1], [statx() is available])
dnl Check for STATX_MNT_ID availability
AC_MSG_CHECKING([for STATX_MNT_ID])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#include <linux/stat.h>
]], [[
struct statx stx;
int mask = STATX_MNT_ID;
(void)mask;
(void)stx.stx_mnt_id;
]])
], [
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_STATX_MNT_ID], [1], [STATX_MNT_ID is available])
], [
AC_MSG_RESULT([no])
])
])
], [
AC_MSG_WARN([linux/stat.h not found; skipping statx support])
])
]) dnl end AC_DEFUN

View file

@ -17,6 +17,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
ZFS_AC_CONFIG_USER_LIBUDEV
ZFS_AC_CONFIG_USER_LIBUUID
ZFS_AC_CONFIG_USER_LIBBLKID
ZFS_AC_CONFIG_USER_STATX
])
ZFS_AC_CONFIG_USER_LIBTIRPC
ZFS_AC_CONFIG_USER_LIBCRYPTO

View file

@ -8,6 +8,7 @@ lib/systemd/system/zfs-import-scan.service
lib/systemd/system/zfs-import.target
lib/systemd/system/zfs-load-key.service
lib/systemd/system/zfs-mount.service
lib/systemd/system/zfs-mount@.service
lib/systemd/system/zfs-scrub-monthly@.timer
lib/systemd/system/zfs-scrub-weekly@.timer
lib/systemd/system/zfs-scrub@.service

View file

@ -56,6 +56,7 @@ systemdunit_DATA = \
%D%/systemd/system/zfs-import-scan.service \
%D%/systemd/system/zfs-import.target \
%D%/systemd/system/zfs-mount.service \
%D%/systemd/system/zfs-mount@.service \
%D%/systemd/system/zfs-scrub-monthly@.timer \
%D%/systemd/system/zfs-scrub-weekly@.timer \
%D%/systemd/system/zfs-scrub@.service \

View file

@ -0,0 +1,26 @@
[Unit]
Description=Mount ZFS filesystem %I
Documentation=man:zfs(8)
DefaultDependencies=no
After=systemd-udev-settle.service
After=zfs-import.target
After=zfs-mount.service
After=systemd-remount-fs.service
Before=local-fs.target
ConditionPathIsDirectory=/sys/module/zfs
# This merely tells the service manager
# that unmounting everything undoes the
# effect of this service. No extra logic
# is ran as a result of these settings.
Conflicts=umount.target
Before=umount.target
[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-@initconfdir@/zfs
ExecStart=@sbindir@/zfs mount -R %I
[Install]
WantedBy=zfs.target

View file

@ -10,6 +10,7 @@ COMMON_H = \
cityhash.h \
zfeature_common.h \
zfs_comutil.h \
zfs_crrd.h \
zfs_deleg.h \
zfs_fletcher.h \
zfs_namecheck.h \
@ -69,7 +70,6 @@ COMMON_H = \
sys/metaslab_impl.h \
sys/mmp.h \
sys/mntent.h \
sys/mod.h \
sys/multilist.h \
sys/nvpair.h \
sys/nvpair_impl.h \

View file

@ -30,6 +30,7 @@
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
* Copyright (c) 2019 Datto Inc.
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
* Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
*/
#ifndef _LIBZFS_H
@ -288,10 +289,22 @@ typedef struct trimflags {
uint64_t rate;
} trimflags_t;
typedef struct trim_cbdata {
trimflags_t trim_flags;
pool_trim_func_t cmd_type;
} trim_cbdata_t;
typedef struct initialize_cbdata {
boolean_t wait;
pool_initialize_func_t cmd_type;
} initialize_cbdata_t;
/*
* Functions to manipulate pool and vdev state
*/
_LIBZFS_H int zpool_scan(zpool_handle_t *, pool_scan_func_t, pool_scrub_cmd_t);
_LIBZFS_H int zpool_scan_range(zpool_handle_t *, pool_scan_func_t,
pool_scrub_cmd_t, time_t, time_t);
_LIBZFS_H int zpool_initialize_one(zpool_handle_t *, void *);
_LIBZFS_H int zpool_initialize(zpool_handle_t *, pool_initialize_func_t,
nvlist_t *);
_LIBZFS_H int zpool_initialize_wait(zpool_handle_t *, pool_initialize_func_t,
@ -304,7 +317,9 @@ _LIBZFS_H int zpool_reguid(zpool_handle_t *);
_LIBZFS_H int zpool_set_guid(zpool_handle_t *, const uint64_t *);
_LIBZFS_H int zpool_reopen_one(zpool_handle_t *, void *);
_LIBZFS_H void zpool_collect_leaves(zpool_handle_t *, nvlist_t *, nvlist_t *);
_LIBZFS_H int zpool_sync_one(zpool_handle_t *, void *);
_LIBZFS_H int zpool_trim_one(zpool_handle_t *, void *);
_LIBZFS_H int zpool_ddt_prune(zpool_handle_t *, zpool_ddt_prune_unit_t,
uint64_t);

View file

@ -33,7 +33,7 @@ noinst_HEADERS = \
%D%/spl/sys/list_impl.h \
%D%/spl/sys/lock.h \
%D%/spl/sys/misc.h \
%D%/spl/sys/mod_os.h \
%D%/spl/sys/mod.h \
%D%/spl/sys/mode.h \
%D%/spl/sys/mount.h \
%D%/spl/sys/mutex.h \

View file

@ -56,4 +56,9 @@ struct opensolaris_utsname {
#define task_io_account_read(n)
#define task_io_account_write(n)
/*
* Check if the current thread is a memory reclaim thread.
*/
extern int current_is_reclaim_thread(void);
#endif /* _OPENSOLARIS_SYS_MISC_H_ */

View file

@ -35,6 +35,7 @@
extern const int zfs_vm_pagerret_bad;
extern const int zfs_vm_pagerret_error;
extern const int zfs_vm_pagerret_ok;
extern const int zfs_vm_pagerret_pend;
extern const int zfs_vm_pagerput_sync;
extern const int zfs_vm_pagerput_inval;

View file

@ -227,6 +227,7 @@ struct taskq;
#define LOOKUP_XATTR 0x02 /* lookup up extended attr dir */
#define CREATE_XATTR_DIR 0x04 /* Create extended attr dir */
#define LOOKUP_HAVE_SYSATTR_DIR 0x08 /* Already created virtual GFS dir */
#define LOOKUP_NAMED_ATTR 0x10 /* Lookup a named attribute */
/*
* Public vnode manipulation functions.

View file

@ -75,7 +75,7 @@ kernel_spl_sys_HEADERS = \
%D%/spl/sys/kstat.h \
%D%/spl/sys/list.h \
%D%/spl/sys/misc.h \
%D%/spl/sys/mod_os.h \
%D%/spl/sys/mod.h \
%D%/spl/sys/mutex.h \
%D%/spl/sys/param.h \
%D%/spl/sys/proc.h \

View file

@ -71,6 +71,22 @@ atomic_cas_ptr(volatile void *target, void *cmp, void *newval)
return ((void *)atomic_cas_64((volatile uint64_t *)target,
(uint64_t)cmp, (uint64_t)newval));
}
static __inline__ void *
atomic_swap_ptr(volatile void *target, void *newval)
{
return ((void *)atomic_swap_64((volatile uint64_t *)target,
(uint64_t)newval));
}
static __inline__ void *
atomic_load_ptr(volatile void *target)
{
return ((void *)atomic_load_64((volatile uint64_t *)target));
}
static __inline__ void
atomic_store_ptr(volatile void *target, void *newval)
{
atomic_store_64((volatile uint64_t *)target, (uint64_t)newval);
}
#else /* _LP64 */
static __inline__ void *
atomic_cas_ptr(volatile void *target, void *cmp, void *newval)
@ -78,6 +94,22 @@ atomic_cas_ptr(volatile void *target, void *cmp, void *newval)
return ((void *)atomic_cas_32((volatile uint32_t *)target,
(uint32_t)cmp, (uint32_t)newval));
}
static __inline__ void *
atomic_swap_ptr(volatile void *target, void *newval)
{
return ((void *)atomic_swap_32((volatile uint32_t *)target,
(uint32_t)newval));
}
static __inline__ void *
atomic_load_ptr(volatile void *target)
{
return ((void *)atomic_load_32((volatile uint32_t *)target));
}
static __inline__ void
atomic_store_ptr(volatile void *target, void *newval)
{
atomic_store_32((volatile uint32_t *)target, (uint32_t)newval);
}
#endif /* _LP64 */
#endif /* _SPL_ATOMIC_H */

View file

@ -61,7 +61,7 @@ void *spl_kvmalloc(size_t size, gfp_t flags);
/*
* Convert a KM_* flags mask to its Linux GFP_* counterpart. The conversion
* function is context aware which means that KM_SLEEP allocations can be
* safely used in syncing contexts which have set PF_FSTRANS.
* safely used in syncing contexts which have set SPL_FSTRANS.
*/
static inline gfp_t
kmem_flags_convert(int flags)
@ -91,25 +91,11 @@ typedef struct {
} fstrans_cookie_t;
/*
* Introduced in Linux 3.9, however this cannot be solely relied on before
* Linux 3.18 as it doesn't turn off __GFP_FS as it should.
* SPL_FSTRANS is the set of flags that indicate that the task is in a
* filesystem or IO codepath, and so any allocation must not call back into
* those codepaths (eg to swap).
*/
#ifdef PF_MEMALLOC_NOIO
#define __SPL_PF_MEMALLOC_NOIO (PF_MEMALLOC_NOIO)
#else
#define __SPL_PF_MEMALLOC_NOIO (0)
#endif
/*
* PF_FSTRANS is removed from Linux 4.12
*/
#ifdef PF_FSTRANS
#define __SPL_PF_FSTRANS (PF_FSTRANS)
#else
#define __SPL_PF_FSTRANS (0)
#endif
#define SPL_FSTRANS (__SPL_PF_FSTRANS|__SPL_PF_MEMALLOC_NOIO)
#define SPL_FSTRANS (PF_MEMALLOC_NOIO)
static inline fstrans_cookie_t
spl_fstrans_mark(void)
@ -141,43 +127,8 @@ spl_fstrans_check(void)
return (current->flags & SPL_FSTRANS);
}
/*
* specifically used to check PF_FSTRANS flag, cannot be relied on for
* checking spl_fstrans_mark().
*/
static inline int
__spl_pf_fstrans_check(void)
{
return (current->flags & __SPL_PF_FSTRANS);
}
/*
* Kernel compatibility for GFP flags
*/
/* < 4.13 */
#ifndef __GFP_RETRY_MAYFAIL
#define __GFP_RETRY_MAYFAIL __GFP_REPEAT
#endif
/* < 4.4 */
#ifndef __GFP_RECLAIM
#define __GFP_RECLAIM __GFP_WAIT
#endif
#ifdef HAVE_ATOMIC64_T
#define kmem_alloc_used_add(size) atomic64_add(size, &kmem_alloc_used)
#define kmem_alloc_used_sub(size) atomic64_sub(size, &kmem_alloc_used)
#define kmem_alloc_used_read() atomic64_read(&kmem_alloc_used)
#define kmem_alloc_used_set(size) atomic64_set(&kmem_alloc_used, size)
extern atomic64_t kmem_alloc_used;
extern unsigned long long kmem_alloc_max;
#else /* HAVE_ATOMIC64_T */
#define kmem_alloc_used_add(size) atomic_add(size, &kmem_alloc_used)
#define kmem_alloc_used_sub(size) atomic_sub(size, &kmem_alloc_used)
#define kmem_alloc_used_read() atomic_read(&kmem_alloc_used)
#define kmem_alloc_used_set(size) atomic_set(&kmem_alloc_used, size)
extern atomic_t kmem_alloc_used;
extern unsigned long long kmem_alloc_max;
#endif /* HAVE_ATOMIC64_T */
extern uint64_t kmem_alloc_max;
extern unsigned int spl_kmem_alloc_warn;
extern unsigned int spl_kmem_alloc_max;

View file

@ -24,7 +24,13 @@
#define _OS_LINUX_SPL_MISC_H
#include <linux/kobject.h>
#include <linux/swap.h>
extern void spl_signal_kobj_evt(struct block_device *bdev);
/*
* Check if the current thread is a memory reclaim thread.
*/
extern int current_is_reclaim_thread(void);
#endif

View file

@ -59,8 +59,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
__field(uint64_t, z_size)
__field(uint64_t, z_pflags)
__field(uint32_t, z_sync_cnt)
__field(uint32_t, z_sync_writes_cnt)
__field(uint32_t, z_async_writes_cnt)
__field(mode_t, z_mode)
__field(boolean_t, z_is_sa)
__field(boolean_t, z_is_ctldir)
@ -92,8 +90,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
__entry->z_size = zn->z_size;
__entry->z_pflags = zn->z_pflags;
__entry->z_sync_cnt = zn->z_sync_cnt;
__entry->z_sync_writes_cnt = zn->z_sync_writes_cnt;
__entry->z_async_writes_cnt = zn->z_async_writes_cnt;
__entry->z_mode = zn->z_mode;
__entry->z_is_sa = zn->z_is_sa;
__entry->z_is_ctldir = zn->z_is_ctldir;
@ -117,7 +113,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
TP_printk("zn { id %llu unlinked %u atime_dirty %u "
"zn_prefetch %u blksz %u seq %u "
"mapcnt %llu size %llu pflags %llu "
"sync_cnt %u sync_writes_cnt %u async_writes_cnt %u "
"sync_cnt %u "
"mode 0x%x is_sa %d is_ctldir %d "
"inode { uid %u gid %u ino %lu nlink %u size %lli "
"blkbits %u bytes %u mode 0x%x generation %x } } "
@ -126,7 +122,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
__entry->z_zn_prefetch, __entry->z_blksz,
__entry->z_seq, __entry->z_mapcnt, __entry->z_size,
__entry->z_pflags, __entry->z_sync_cnt,
__entry->z_sync_writes_cnt, __entry->z_async_writes_cnt,
__entry->z_mode, __entry->z_is_sa, __entry->z_is_ctldir,
__entry->i_uid, __entry->i_gid, __entry->i_ino, __entry->i_nlink,
__entry->i_size, __entry->i_blkbits,

View file

@ -45,7 +45,7 @@
__field(zio_flag_t, zio_orig_flags) \
__field(enum zio_stage, zio_orig_stage) \
__field(enum zio_stage, zio_orig_pipeline) \
__field(uint8_t, zio_reexecute) \
__field(uint8_t, zio_post) \
__field(uint64_t, zio_txg) \
__field(int, zio_error) \
__field(uint64_t, zio_ena) \
@ -74,7 +74,7 @@
__entry->zio_orig_flags = zio->io_orig_flags; \
__entry->zio_orig_stage = zio->io_orig_stage; \
__entry->zio_orig_pipeline = zio->io_orig_pipeline; \
__entry->zio_reexecute = zio->io_reexecute; \
__entry->zio_post = zio->io_post; \
__entry->zio_txg = zio->io_txg; \
__entry->zio_error = zio->io_error; \
__entry->zio_ena = zio->io_ena; \
@ -92,7 +92,7 @@
"zio { type %u prio %u size %llu orig_size %llu " \
"offset %llu timestamp %llu delta %llu delay %llu " \
"flags 0x%llx stage 0x%x pipeline 0x%x orig_flags 0x%llx " \
"orig_stage 0x%x orig_pipeline 0x%x reexecute %u " \
"orig_stage 0x%x orig_pipeline 0x%x post %u " \
"txg %llu error %d ena %llu prop { checksum %u compress %u " \
"type %u level %u copies %u dedup %u dedup_verify %u nopwrite %u } }"
@ -102,7 +102,7 @@
__entry->zio_timestamp, __entry->zio_delta, __entry->zio_delay, \
__entry->zio_flags, __entry->zio_stage, __entry->zio_pipeline, \
__entry->zio_orig_flags, __entry->zio_orig_stage, \
__entry->zio_orig_pipeline, __entry->zio_reexecute, \
__entry->zio_orig_pipeline, __entry->zio_post, \
__entry->zio_txg, __entry->zio_error, __entry->zio_ena, \
__entry->zp_checksum, __entry->zp_compress, __entry->zp_type, \
__entry->zp_level, __entry->zp_copies, __entry->zp_dedup, \

View file

@ -157,6 +157,7 @@ struct znode;
extern int zfs_sync(struct super_block *, int, cred_t *);
extern int zfs_inode_alloc(struct super_block *, struct inode **ip);
extern void zfs_inode_free(struct inode *);
extern void zfs_inode_destroy(struct inode *);
extern void zfs_mark_inode_dirty(struct inode *);
extern boolean_t zfs_relatime_need_update(const struct inode *);

View file

@ -954,7 +954,7 @@ typedef struct arc_sums {
wmsum_t arcstat_data_size;
wmsum_t arcstat_metadata_size;
wmsum_t arcstat_dbuf_size;
wmsum_t arcstat_dnode_size;
aggsum_t arcstat_dnode_size;
wmsum_t arcstat_bonus_size;
wmsum_t arcstat_l2_hits;
wmsum_t arcstat_l2_misses;

View file

@ -164,6 +164,7 @@ typedef struct dbuf_dirty_record {
boolean_t dr_nopwrite;
boolean_t dr_brtwrite;
boolean_t dr_diowrite;
boolean_t dr_rewrite;
boolean_t dr_has_raw_params;
/* Override and raw params are mutually exclusive. */

View file

@ -414,6 +414,9 @@ typedef struct dmu_buf {
#define DMU_POOL_ZPOOL_CHECKPOINT "com.delphix:zpool_checkpoint"
#define DMU_POOL_LOG_SPACEMAP_ZAP "com.delphix:log_spacemap_zap"
#define DMU_POOL_DELETED_CLONES "com.delphix:deleted_clones"
#define DMU_POOL_TXG_LOG_TIME_MINUTES "com.klaraystems:txg_log_time:minutes"
#define DMU_POOL_TXG_LOG_TIME_DAYS "com.klaraystems:txg_log_time:days"
#define DMU_POOL_TXG_LOG_TIME_MONTHS "com.klaraystems:txg_log_time:months"
/*
* Allocate an object from this objset. The range of object numbers
@ -822,6 +825,7 @@ struct blkptr *dmu_buf_get_blkptr(dmu_buf_t *db);
*/
void dmu_buf_will_dirty(dmu_buf_t *db, dmu_tx_t *tx);
void dmu_buf_will_dirty_flags(dmu_buf_t *db, dmu_tx_t *tx, dmu_flags_t flags);
void dmu_buf_will_rewrite(dmu_buf_t *db, dmu_tx_t *tx);
boolean_t dmu_buf_is_dirty(dmu_buf_t *db, dmu_tx_t *tx);
void dmu_buf_set_crypt_params(dmu_buf_t *db_fake, boolean_t byteorder,
const uint8_t *salt, const uint8_t *iv, const uint8_t *mac, dmu_tx_t *tx);

View file

@ -152,7 +152,7 @@ struct objset {
* The largest zpl file block allowed in special class.
* cached here instead of zfsvfs for easier access.
*/
int os_zpl_special_smallblock;
uint64_t os_zpl_special_smallblock;
/*
* Pointer is constant; the blkptr it points to is protected by

View file

@ -59,6 +59,13 @@ typedef int (blkptr_cb_t)(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
*/
#define TRAVERSE_NO_DECRYPT (1<<5)
/*
* Always use logical birth time for birth time comparisons. This is useful
* for operations that care about user data changes rather than physical
* block rewrites (e.g., incremental replication).
*/
#define TRAVERSE_LOGICAL (1<<6)
/* Special traverse error return value to indicate skipping of children */
#define TRAVERSE_VISIT_NO_CHILDREN -1

View file

@ -1627,6 +1627,9 @@ typedef struct zfs_rewrite_args {
uint64_t arg;
} zfs_rewrite_args_t;
/* zfs_rewrite_args flags */
#define ZFS_REWRITE_PHYSICAL 0x1 /* Preserve logical birth time. */
#define ZFS_IOC_REWRITE _IOW(0x83, 3, zfs_rewrite_args_t)
/*

View file

@ -110,9 +110,10 @@ void metaslab_class_balance(metaslab_class_t *mc, boolean_t onsync);
void metaslab_class_histogram_verify(metaslab_class_t *);
uint64_t metaslab_class_fragmentation(metaslab_class_t *);
uint64_t metaslab_class_expandable_space(metaslab_class_t *);
boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, zio_t *,
boolean_t, boolean_t *);
boolean_t metaslab_class_throttle_unreserve(metaslab_class_t *, int, zio_t *);
boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, int,
uint64_t, boolean_t, boolean_t *);
boolean_t metaslab_class_throttle_unreserve(metaslab_class_t *, int, int,
uint64_t);
void metaslab_class_evict_old(metaslab_class_t *, uint64_t);
const char *metaslab_class_get_name(metaslab_class_t *);
uint64_t metaslab_class_get_alloc(metaslab_class_t *);

View file

@ -539,6 +539,8 @@ typedef struct metaslab_unflushed_phys {
uint64_t msp_unflushed_txg;
} metaslab_unflushed_phys_t;
char *metaslab_rt_name(metaslab_group_t *, metaslab_t *, const char *);
#ifdef __cplusplus
}
#endif

View file

@ -1,36 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
* Copyright (C) 2007 The Regents of the University of California.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Brian Behlendorf <behlendorf1@llnl.gov>.
* UCRL-CODE-235197
*
* This file is part of the SPL, Solaris Porting Layer.
*
* The SPL is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* The SPL is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with the SPL. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SYS_MOD_H
#define _SYS_MOD_H
#ifdef _KERNEL
#include <sys/mod_os.h>
#else
/*
* Exported symbols
*/
#define EXPORT_SYMBOL(x)
#endif
#endif /* SYS_MOD_H */

View file

@ -49,6 +49,9 @@ typedef enum zfs_range_seg_type {
ZFS_RANGE_SEG_NUM_TYPES,
} zfs_range_seg_type_t;
#define ZFS_RT_NAME(rt) (((rt)->rt_name != NULL) ? (rt)->rt_name : "")
#define ZFS_RT_F_DYN_NAME (1ULL << 0) /* if rt_name must be freed */
/*
* Note: the range_tree may not be accessed concurrently; consumers
* must provide external locking if required.
@ -68,6 +71,9 @@ typedef struct zfs_range_tree {
void *rt_arg;
uint64_t rt_gap; /* allowable inter-segment gap */
uint64_t rt_flags;
const char *rt_name; /* details for debugging */
/*
* The rt_histogram maintains a histogram of ranges. Each bucket,
* rt_histogram[i], contains the number of ranges whose size is:
@ -281,6 +287,9 @@ zfs_range_tree_t *zfs_range_tree_create_gap(const zfs_range_tree_ops_t *ops,
uint64_t gap);
zfs_range_tree_t *zfs_range_tree_create(const zfs_range_tree_ops_t *ops,
zfs_range_seg_type_t type, void *arg, uint64_t start, uint64_t shift);
zfs_range_tree_t *zfs_range_tree_create_flags(const zfs_range_tree_ops_t *ops,
zfs_range_seg_type_t type, void *arg, uint64_t start, uint64_t shift,
uint64_t flags, const char *name);
void zfs_range_tree_destroy(zfs_range_tree_t *rt);
boolean_t zfs_range_tree_contains(zfs_range_tree_t *rt, uint64_t start,
uint64_t size);

View file

@ -140,7 +140,7 @@ typedef struct zio_cksum_salt {
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 6 |BDX|lvl| type | cksum |E| comp| PSIZE | LSIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 7 | padding |
* 7 |R| padding |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 8 | padding |
* +-------+-------+-------+-------+-------+-------+-------+-------+
@ -175,6 +175,7 @@ typedef struct zio_cksum_salt {
* E blkptr_t contains embedded data (see below)
* lvl level of indirection
* type DMU object type
* R rewrite (reallocated/rewritten at phys birth TXG)
* phys birth txg when dva[0] was written; zero if same as logical birth txg
* note that typically all the dva's would be written in this
* txg, but they could be different if they were moved by
@ -190,11 +191,11 @@ typedef struct zio_cksum_salt {
*
* 64 56 48 40 32 24 16 8 0
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 0 | vdev1 | pad | ASIZE |
* 0 | pad | vdev1 | pad | ASIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 1 |G| offset1 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 2 | vdev2 | pad | ASIZE |
* 2 | pad | vdev2 | pad | ASIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 3 |G| offset2 |
* +-------+-------+-------+-------+-------+-------+-------+-------+
@ -204,7 +205,7 @@ typedef struct zio_cksum_salt {
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 6 |BDX|lvl| type | cksum |E| comp| PSIZE | LSIZE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 7 | padding |
* 7 |R| padding |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* 8 | padding |
* +-------+-------+-------+-------+-------+-------+-------+-------+
@ -373,7 +374,8 @@ typedef enum bp_embedded_type {
typedef struct blkptr {
dva_t blk_dva[SPA_DVAS_PER_BP]; /* Data Virtual Addresses */
uint64_t blk_prop; /* size, compression, type, etc */
uint64_t blk_pad[2]; /* Extra space for the future */
uint64_t blk_prop2; /* additional properties */
uint64_t blk_pad; /* Extra space for the future */
uint64_t blk_birth_word[2];
uint64_t blk_fill; /* fill count */
zio_cksum_t blk_cksum; /* 256-bit checksum */
@ -476,32 +478,51 @@ typedef struct blkptr {
#define BP_GET_FREE(bp) BF64_GET((bp)->blk_fill, 0, 1)
#define BP_SET_FREE(bp, x) BF64_SET((bp)->blk_fill, 0, 1, x)
/*
* Block birth time macros for different use cases:
* - BP_GET_LOGICAL_BIRTH(): When the block was logically modified by user.
* To be used with a focus on user data, like incremental replication.
* - BP_GET_PHYSICAL_BIRTH(): When the block was physically written to disks.
* For regular writes is equal to logical birth. For dedup and block cloning
* can be smaller than logical birth. For remapped and rewritten blocks can
* be bigger. To be used with focus on physical disk content: ARC, DDT, scrub.
* - BP_GET_RAW_PHYSICAL_BIRTH(): Raw physical birth value. Zero if equal
* to logical birth. Should only be used for BP copying and debugging.
* - BP_GET_BIRTH(): When the block was allocated, which is a physical birth
* for rewritten blocks (rewrite flag set) or logical birth otherwise.
*/
#define BP_GET_LOGICAL_BIRTH(bp) (bp)->blk_birth_word[1]
#define BP_SET_LOGICAL_BIRTH(bp, x) ((bp)->blk_birth_word[1] = (x))
#define BP_GET_PHYSICAL_BIRTH(bp) (bp)->blk_birth_word[0]
#define BP_GET_RAW_PHYSICAL_BIRTH(bp) (bp)->blk_birth_word[0]
#define BP_SET_PHYSICAL_BIRTH(bp, x) ((bp)->blk_birth_word[0] = (x))
#define BP_GET_BIRTH(bp) \
(BP_IS_EMBEDDED(bp) ? 0 : \
BP_GET_PHYSICAL_BIRTH(bp) ? BP_GET_PHYSICAL_BIRTH(bp) : \
#define BP_GET_PHYSICAL_BIRTH(bp) \
(BP_IS_EMBEDDED(bp) ? 0 : \
BP_GET_RAW_PHYSICAL_BIRTH(bp) ? BP_GET_RAW_PHYSICAL_BIRTH(bp) : \
BP_GET_LOGICAL_BIRTH(bp))
#define BP_SET_BIRTH(bp, logical, physical) \
{ \
ASSERT(!BP_IS_EMBEDDED(bp)); \
BP_SET_LOGICAL_BIRTH(bp, logical); \
BP_SET_PHYSICAL_BIRTH(bp, \
((logical) == (physical) ? 0 : (physical))); \
#define BP_GET_BIRTH(bp) \
((BP_IS_EMBEDDED(bp) || !BP_GET_REWRITE(bp)) ? \
BP_GET_LOGICAL_BIRTH(bp) : BP_GET_PHYSICAL_BIRTH(bp))
#define BP_SET_BIRTH(bp, logical, physical) \
{ \
ASSERT(!BP_IS_EMBEDDED(bp)); \
BP_SET_LOGICAL_BIRTH(bp, logical); \
BP_SET_PHYSICAL_BIRTH(bp, \
((logical) == (physical) ? 0 : (physical))); \
}
#define BP_GET_FILL(bp) \
((BP_IS_ENCRYPTED(bp)) ? BF64_GET((bp)->blk_fill, 0, 32) : \
((BP_IS_EMBEDDED(bp)) ? 1 : (bp)->blk_fill))
(BP_IS_EMBEDDED(bp) ? 1 : \
BP_IS_ENCRYPTED(bp) ? BF64_GET((bp)->blk_fill, 0, 32) : \
(bp)->blk_fill)
#define BP_SET_FILL(bp, fill) \
{ \
if (BP_IS_ENCRYPTED(bp)) \
ASSERT(!BP_IS_EMBEDDED(bp)); \
if (BP_IS_ENCRYPTED(bp)) \
BF64_SET((bp)->blk_fill, 0, 32, fill); \
else \
(bp)->blk_fill = fill; \
@ -516,6 +537,15 @@ typedef struct blkptr {
BF64_SET((bp)->blk_fill, 32, 32, iv2); \
}
#define BP_GET_REWRITE(bp) \
(BP_IS_EMBEDDED(bp) ? 0 : BF64_GET((bp)->blk_prop2, 63, 1))
#define BP_SET_REWRITE(bp, x) \
{ \
ASSERT(!BP_IS_EMBEDDED(bp)); \
BF64_SET((bp)->blk_prop2, 63, 1, x); \
}
#define BP_IS_METADATA(bp) \
(BP_GET_LEVEL(bp) > 0 || DMU_OT_IS_METADATA(BP_GET_TYPE(bp)))
@ -545,7 +575,7 @@ typedef struct blkptr {
(dva1)->dva_word[0] == (dva2)->dva_word[0])
#define BP_EQUAL(bp1, bp2) \
(BP_GET_BIRTH(bp1) == BP_GET_BIRTH(bp2) && \
(BP_GET_PHYSICAL_BIRTH(bp1) == BP_GET_PHYSICAL_BIRTH(bp2) && \
BP_GET_LOGICAL_BIRTH(bp1) == BP_GET_LOGICAL_BIRTH(bp2) && \
DVA_EQUAL(&(bp1)->blk_dva[0], &(bp2)->blk_dva[0]) && \
DVA_EQUAL(&(bp1)->blk_dva[1], &(bp2)->blk_dva[1]) && \
@ -588,8 +618,8 @@ typedef struct blkptr {
{ \
BP_ZERO_DVAS(bp); \
(bp)->blk_prop = 0; \
(bp)->blk_pad[0] = 0; \
(bp)->blk_pad[1] = 0; \
(bp)->blk_prop2 = 0; \
(bp)->blk_pad = 0; \
(bp)->blk_birth_word[0] = 0; \
(bp)->blk_birth_word[1] = 0; \
(bp)->blk_fill = 0; \
@ -696,7 +726,7 @@ typedef struct blkptr {
(u_longlong_t)BP_GET_LSIZE(bp), \
(u_longlong_t)BP_GET_PSIZE(bp), \
(u_longlong_t)BP_GET_LOGICAL_BIRTH(bp), \
(u_longlong_t)BP_GET_BIRTH(bp), \
(u_longlong_t)BP_GET_PHYSICAL_BIRTH(bp), \
(u_longlong_t)BP_GET_FILL(bp), \
ws, \
(u_longlong_t)bp->blk_cksum.zc_word[0], \
@ -1065,6 +1095,7 @@ extern metaslab_class_t *spa_normal_class(spa_t *spa);
extern metaslab_class_t *spa_log_class(spa_t *spa);
extern metaslab_class_t *spa_embedded_log_class(spa_t *spa);
extern metaslab_class_t *spa_special_class(spa_t *spa);
extern metaslab_class_t *spa_special_embedded_log_class(spa_t *spa);
extern metaslab_class_t *spa_dedup_class(spa_t *spa);
extern metaslab_class_t *spa_preferred_class(spa_t *spa, const zio_t *zio);
extern boolean_t spa_special_has_ddt(spa_t *spa);

View file

@ -55,6 +55,8 @@
#include <sys/dsl_deadlist.h>
#include <zfeature_common.h>
#include "zfs_crrd.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -246,6 +248,7 @@ struct spa {
metaslab_class_t *spa_log_class; /* intent log data class */
metaslab_class_t *spa_embedded_log_class; /* log on normal vdevs */
metaslab_class_t *spa_special_class; /* special allocation class */
metaslab_class_t *spa_special_embedded_log_class; /* log on special */
metaslab_class_t *spa_dedup_class; /* dedup allocation class */
uint64_t spa_first_txg; /* first txg after spa_open() */
uint64_t spa_final_txg; /* txg of export/destroy */
@ -343,6 +346,12 @@ struct spa {
spa_checkpoint_info_t spa_checkpoint_info; /* checkpoint accounting */
zthr_t *spa_checkpoint_discard_zthr;
kmutex_t spa_txg_log_time_lock; /* for spa_txg_log_time */
dbrrd_t spa_txg_log_time;
uint64_t spa_last_noted_txg;
uint64_t spa_last_noted_txg_time;
uint64_t spa_last_flush_txg_time;
space_map_t *spa_syncing_log_sm; /* current log space map */
avl_tree_t spa_sm_logs_by_txg;
kmutex_t spa_flushed_ms_lock; /* for metaslabs_by_flushed */

View file

@ -139,6 +139,7 @@ extern uint64_t vdev_asize_to_psize_txg(vdev_t *vd, uint64_t asize,
extern uint64_t vdev_psize_to_asize_txg(vdev_t *vd, uint64_t psize,
uint64_t txg);
extern uint64_t vdev_psize_to_asize(vdev_t *vd, uint64_t psize);
extern uint64_t vdev_get_min_alloc(vdev_t *vd);
/*
* Return the amount of space allocated for a gang block header. Note that
@ -148,7 +149,20 @@ extern uint64_t vdev_psize_to_asize(vdev_t *vd, uint64_t psize);
static inline uint64_t
vdev_gang_header_asize(vdev_t *vd)
{
return (vdev_psize_to_asize_txg(vd, SPA_GANGBLOCKSIZE, 0));
return (vdev_psize_to_asize_txg(vd, SPA_OLD_GANGBLOCKSIZE, 0));
}
/*
* Return the amount of data that can be stored in a gang header. Because we
* need to ensure gang headers can always be allocated (as long as there is
* space available), this is the minimum allocatable size on the vdev. Note that
* since the physical birth txg is not provided, this must be constant for
* a given vdev. (e.g. raidz expansion can't change this)
*/
static inline uint64_t
vdev_gang_header_psize(vdev_t *vd)
{
return (vdev_get_min_alloc(vd));
}
extern int vdev_fault(spa_t *spa, uint64_t guid, vdev_aux_t aux);

View file

@ -621,7 +621,6 @@ extern uint64_t vdev_default_asize(vdev_t *vd, uint64_t psize, uint64_t txg);
extern uint64_t vdev_default_min_asize(vdev_t *vd);
extern uint64_t vdev_get_min_asize(vdev_t *vd);
extern void vdev_set_min_asize(vdev_t *vd);
extern uint64_t vdev_get_min_alloc(vdev_t *vd);
extern uint64_t vdev_get_nparity(vdev_t *vd);
extern uint64_t vdev_get_ndisks(vdev_t *vd);
@ -645,10 +644,11 @@ extern int vdev_obsolete_counts_are_precise(vdev_t *vd, boolean_t *are_precise);
int vdev_checkpoint_sm_object(vdev_t *vd, uint64_t *sm_obj);
void vdev_metaslab_group_create(vdev_t *vd);
uint64_t vdev_best_ashift(uint64_t logical, uint64_t a, uint64_t b);
#if defined(__linux__)
#if defined(__linux__) && defined(_KERNEL)
int param_get_raidz_impl(char *buf, zfs_kernel_param_t *kp);
#endif
int param_set_raidz_impl(ZFS_MODULE_PARAM_ARGS);
char *vdev_rt_name(vdev_t *vd, const char *name);
/*
* Vdev ashift optimization tunables

View file

@ -311,6 +311,7 @@ xva_getxoptattr(xvattr_t *xvap)
*/
#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */
#define V_APPEND 0x2 /* want to do append only check */
#define V_NAMEDATTR 0x4 /* is a named attribute check */
/*
* Structure used on VOP_GETSECATTR and VOP_SETSECATTR operations

View file

@ -204,18 +204,6 @@ extern void vpanic(const char *, va_list)
#endif /* DTRACE_PROBE4 */
#define DTRACE_PROBE4(a, b, c, d, e, f, g, h, i)
/*
* Tunables.
*/
typedef struct zfs_kernel_param {
const char *name; /* unused stub */
} zfs_kernel_param_t;
#define ZFS_MODULE_PARAM(scope_prefix, name_prefix, name, type, perm, desc)
#define ZFS_MODULE_PARAM_ARGS void
#define ZFS_MODULE_PARAM_CALL(scope_prefix, name_prefix, name, setfunc, \
getfunc, perm, desc)
/*
* Threads.
*/
@ -236,6 +224,11 @@ typedef pthread_t kthread_t;
#define thread_join(t) pthread_join((pthread_t)(t), NULL)
#define newproc(f, a, cid, pri, ctp, pid) (ENOSYS)
/*
* Check if the current thread is a memory reclaim thread.
* Always returns false in userspace (no memory reclaim thread).
*/
#define current_is_reclaim_thread() (0)
/* in libzpool, p0 exists only to have its address taken */
typedef struct proc {
@ -673,7 +666,7 @@ extern void random_fini(void);
struct spa;
extern void show_pool_stats(struct spa *);
extern int set_global_var(char const *arg);
extern int handle_tunable_option(const char *, boolean_t);
typedef struct callb_cpr {
kmutex_t *cc_lockp;
@ -778,7 +771,6 @@ typedef int fstrans_cookie_t;
extern fstrans_cookie_t spl_fstrans_mark(void);
extern void spl_fstrans_unmark(fstrans_cookie_t);
extern int __spl_pf_fstrans_check(void);
extern int kmem_cache_reap_active(void);

View file

@ -202,8 +202,6 @@ typedef struct znode {
uint64_t z_size; /* file size (cached) */
uint64_t z_pflags; /* pflags (cached) */
uint32_t z_sync_cnt; /* synchronous open count */
uint32_t z_sync_writes_cnt; /* synchronous write count */
uint32_t z_async_writes_cnt; /* asynchronous write count */
mode_t z_mode; /* mode (cached) */
kmutex_t z_acl_lock; /* acl data lock */
zfs_acl_t *z_acl_cached; /* cached acl */

View file

@ -635,6 +635,8 @@ extern void zil_set_logbias(zilog_t *zilog, uint64_t slogval);
extern uint64_t zil_max_copied_data(zilog_t *zilog);
extern uint64_t zil_max_log_data(zilog_t *zilog, size_t hdrsize);
extern itx_wr_state_t zil_write_state(zilog_t *zilog, uint64_t size,
uint32_t blocksize, boolean_t o_direct, boolean_t commit);
extern void zil_sums_init(zil_sums_t *zs);
extern void zil_sums_fini(zil_sums_t *zs);
@ -642,6 +644,8 @@ extern void zil_kstat_values_update(zil_kstat_values_t *zs,
zil_sums_t *zil_sums);
extern int zil_replay_disable;
extern uint_t zfs_immediate_write_sz;
extern int zil_special_is_slog;
#ifdef __cplusplus
}

View file

@ -59,21 +59,36 @@ typedef struct zio_eck {
/*
* Gang block headers are self-checksumming and contain an array
* of block pointers.
* of block pointers. The old gang block size has enough room for 3 blkptrs,
* while new gang blocks can store more.
*
* Layout:
* +--------+--------+--------+-----+---------+-----------+
* | | | | | | |
* | blkptr | blkptr | blkptr | ... | padding | zio_eck_t |
* | 1 | 2 | 3 | | | |
* +--------+--------+--------+-----+---------+-----------+
* 128B 128B 128B 88B 40B
*/
#define SPA_GANGBLOCKSIZE SPA_MINBLOCKSIZE
#define SPA_GBH_NBLKPTRS ((SPA_GANGBLOCKSIZE - \
sizeof (zio_eck_t)) / sizeof (blkptr_t))
#define SPA_GBH_FILLER ((SPA_GANGBLOCKSIZE - \
sizeof (zio_eck_t) - \
(SPA_GBH_NBLKPTRS * sizeof (blkptr_t))) /\
sizeof (uint64_t))
#define SPA_OLD_GANGBLOCKSIZE SPA_MINBLOCKSIZE
typedef void zio_gbh_phys_t;
typedef struct zio_gbh {
blkptr_t zg_blkptr[SPA_GBH_NBLKPTRS];
uint64_t zg_filler[SPA_GBH_FILLER];
zio_eck_t zg_tail;
} zio_gbh_phys_t;
static inline uint64_t
gbh_nblkptrs(uint64_t size) {
ASSERT(IS_P2ALIGNED(size, sizeof (blkptr_t)));
return ((size - sizeof (zio_eck_t)) / sizeof (blkptr_t));
}
static inline zio_eck_t *
gbh_eck(zio_gbh_phys_t *gbh, uint64_t size) {
ASSERT(IS_P2ALIGNED(size, sizeof (blkptr_t)));
return ((zio_eck_t *)((uintptr_t)gbh + size - sizeof (zio_eck_t)));
}
static inline blkptr_t *
gbh_bp(zio_gbh_phys_t *gbh, int bp) {
return (&((blkptr_t *)gbh)[bp]);
}
enum zio_checksum {
ZIO_CHECKSUM_INHERIT = 0,
@ -196,7 +211,7 @@ typedef uint64_t zio_flag_t;
#define ZIO_FLAG_DONT_RETRY (1ULL << 10)
#define ZIO_FLAG_NODATA (1ULL << 12)
#define ZIO_FLAG_INDUCE_DAMAGE (1ULL << 13)
#define ZIO_FLAG_IO_ALLOCATING (1ULL << 14)
#define ZIO_FLAG_ALLOC_THROTTLED (1ULL << 14)
#define ZIO_FLAG_DDT_INHERIT (ZIO_FLAG_IO_RETRY - 1)
#define ZIO_FLAG_GANG_INHERIT (ZIO_FLAG_IO_RETRY - 1)
@ -226,8 +241,7 @@ typedef uint64_t zio_flag_t;
#define ZIO_FLAG_NOPWRITE (1ULL << 29)
#define ZIO_FLAG_REEXECUTED (1ULL << 30)
#define ZIO_FLAG_DELEGATED (1ULL << 31)
#define ZIO_FLAG_DIO_CHKSUM_ERR (1ULL << 32)
#define ZIO_FLAG_PREALLOCATED (1ULL << 33)
#define ZIO_FLAG_PREALLOCATED (1ULL << 32)
#define ZIO_ALLOCATOR_NONE (-1)
#define ZIO_HAS_ALLOCATOR(zio) ((zio)->io_allocator != ZIO_ALLOCATOR_NONE)
@ -360,6 +374,7 @@ typedef struct zio_prop {
boolean_t zp_encrypt;
boolean_t zp_byteorder;
boolean_t zp_direct_write;
boolean_t zp_rewrite;
uint8_t zp_salt[ZIO_DATA_SALT_LEN];
uint8_t zp_iv[ZIO_DATA_IV_LEN];
uint8_t zp_mac[ZIO_DATA_MAC_LEN];
@ -399,7 +414,9 @@ typedef struct zio_vsd_ops {
typedef struct zio_gang_node {
zio_gbh_phys_t *gn_gbh;
struct zio_gang_node *gn_child[SPA_GBH_NBLKPTRS];
uint64_t gn_gangblocksize;
uint64_t gn_allocsize;
struct zio_gang_node *gn_child[];
} zio_gang_node_t;
typedef zio_t *zio_gang_issue_func_t(zio_t *zio, blkptr_t *bp,
@ -418,14 +435,16 @@ typedef struct zio_transform {
typedef zio_t *zio_pipe_stage_t(zio_t *zio);
/*
* The io_reexecute flags are distinct from io_flags because the child must
* be able to propagate them to the parent. The normal io_flags are local
* to the zio, not protected by any lock, and not modifiable by children;
* the reexecute flags are protected by io_lock, modifiable by children,
* and always propagated -- even when ZIO_FLAG_DONT_PROPAGATE is set.
* The io_post flags describe additional actions that a parent IO should
* consider or perform on behalf of a child. They are distinct from io_flags
* because the child must be able to propagate them to the parent. The normal
* io_flags are local to the zio, not protected by any lock, and not modifiable
* by children; the reexecute flags are protected by io_lock, modifiable by
* children, and always propagated -- even when ZIO_FLAG_DONT_PROPAGATE is set.
*/
#define ZIO_REEXECUTE_NOW 0x01
#define ZIO_REEXECUTE_SUSPEND 0x02
#define ZIO_POST_REEXECUTE (1 << 0)
#define ZIO_POST_SUSPEND (1 << 1)
#define ZIO_POST_DIO_CHKSUM_ERR (1 << 2)
/*
* The io_trim flags are used to specify the type of TRIM to perform. They
@ -461,7 +480,7 @@ struct zio {
enum zio_child io_child_type;
enum trim_flag io_trim_flags;
zio_priority_t io_priority;
uint8_t io_reexecute;
uint8_t io_post;
uint8_t io_state[ZIO_WAIT_TYPES];
uint64_t io_txg;
spa_t *io_spa;

View file

@ -36,8 +36,7 @@
#define SPEC_MAXOFFSET_T ((1LL << ((NBBY * sizeof (daddr32_t)) + \
DEV_BSHIFT - 1)) - 1)
extern void zvol_create_minor(const char *);
extern void zvol_create_minors_recursive(const char *);
extern void zvol_create_minors(const char *);
extern void zvol_remove_minors(spa_t *, const char *, boolean_t);
extern void zvol_rename_minors(spa_t *, const char *, const char *, boolean_t);

View file

@ -108,7 +108,6 @@ zvol_state_t *zvol_find_by_name_hash(const char *name,
uint64_t hash, int mode);
int zvol_first_open(zvol_state_t *zv, boolean_t readonly);
uint64_t zvol_name_hash(const char *name);
void zvol_remove_minors_impl(const char *name);
void zvol_last_close(zvol_state_t *zv);
void zvol_insert(zvol_state_t *zv);
void zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off,
@ -132,7 +131,7 @@ void zv_request_task_free(zv_request_task_t *task);
* platform dependent functions exported to platform independent code
*/
void zvol_os_free(zvol_state_t *zv);
void zvol_os_rename_minor(zvol_state_t *zv, const char *newname);
int zvol_os_rename_minor(zvol_state_t *zv, const char *newname);
int zvol_os_create_minor(const char *name);
int zvol_os_update_volsize(zvol_state_t *zv, uint64_t volsize);
boolean_t zvol_os_is_zvol(const char *path);

View file

@ -87,6 +87,9 @@ typedef enum spa_feature {
SPA_FEATURE_FAST_DEDUP,
SPA_FEATURE_LONGNAME,
SPA_FEATURE_LARGE_MICROZAP,
SPA_FEATURE_DYNAMIC_GANG_HEADER,
SPA_FEATURE_BLOCK_CLONING_ENDIAN,
SPA_FEATURE_PHYSICAL_REWRITE,
SPA_FEATURES
} spa_feature_t;
@ -103,7 +106,15 @@ typedef enum zfeature_flags {
/* Activate this feature at the same time it is enabled. */
ZFEATURE_FLAG_ACTIVATE_ON_ENABLE = (1 << 2),
/* Each dataset has a field set if it has ever used this feature. */
ZFEATURE_FLAG_PER_DATASET = (1 << 3)
ZFEATURE_FLAG_PER_DATASET = (1 << 3),
/*
* This feature isn't enabled by zpool upgrade; it must be explicitly
* listed to be enabled. It will also be applied if listed in an
* explicitly provided compatibility list. This flag can be removed
* from a given feature once support is sufficiently widespread, or
* worries about backwards compatibility are no longer relevant.
*/
ZFEATURE_FLAG_NO_UPGRADE = (1 << 4)
} zfeature_flags_t;
typedef enum zfeature_type {

View file

@ -0,0 +1,75 @@
// 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) 2024 Klara Inc.
*
* This software was developed by
* Mariusz Zaborski <mariusz.zaborski@klarasystems.com>
* Fred Weigel <fred.weigel@klarasystems.com>
* under sponsorship from Wasabi Technology, Inc. and Klara Inc.
*/
#ifndef _CRRD_H_
#define _CRRD_H_
#define RRD_MAX_ENTRIES 256
#define RRD_ENTRY_SIZE sizeof (uint64_t)
#define RRD_STRUCT_ELEM (sizeof (rrd_t) / RRD_ENTRY_SIZE)
typedef enum {
DBRRD_FLOOR,
DBRRD_CEILING
} dbrrd_rounding_t;
typedef struct {
uint64_t rrdd_time;
uint64_t rrdd_txg;
} rrd_data_t;
typedef struct {
uint64_t rrd_head; /* head (beginning) */
uint64_t rrd_tail; /* tail (end) */
uint64_t rrd_length;
rrd_data_t rrd_entries[RRD_MAX_ENTRIES];
} rrd_t;
typedef struct {
rrd_t dbr_minutes;
rrd_t dbr_days;
rrd_t dbr_months;
} dbrrd_t;
size_t rrd_len(rrd_t *rrd);
const rrd_data_t *rrd_entry(rrd_t *r, size_t i);
rrd_data_t *rrd_tail_entry(rrd_t *rrd);
uint64_t rrd_tail(rrd_t *rrd);
uint64_t rrd_get(rrd_t *rrd, size_t i);
void rrd_add(rrd_t *rrd, hrtime_t time, uint64_t txg);
void dbrrd_add(dbrrd_t *db, hrtime_t time, uint64_t txg);
uint64_t dbrrd_query(dbrrd_t *r, hrtime_t tv, dbrrd_rounding_t rouding);
#endif

View file

@ -20,6 +20,7 @@ libspl_la_SOURCES = \
%D%/strlcat.c \
%D%/strlcpy.c \
%D%/timestamp.c \
%D%/tunables.c \
%D%/include/sys/list.h \
%D%/include/sys/list_impl.h

View file

@ -45,6 +45,7 @@ libspl_sys_HEADERS = \
%D%/sys/list_impl.h \
%D%/sys/mhd.h \
%D%/sys/mkdev.h \
%D%/sys/mod.h \
%D%/sys/policy.h \
%D%/sys/poll.h \
%D%/sys/priv.h \
@ -58,6 +59,7 @@ libspl_sys_HEADERS = \
%D%/sys/time.h \
%D%/sys/trace_spl.h \
%D%/sys/trace_zfs.h \
%D%/sys/tunables.h \
%D%/sys/types.h \
%D%/sys/types32.h \
%D%/sys/uio.h \

View file

@ -31,6 +31,11 @@
#include <sys/mount.h> /* for BLKGETSIZE64 */
#ifdef HAVE_STATX
#include <fcntl.h>
#include <linux/stat.h>
#endif
/*
* Emulate Solaris' behavior of returning the block device size in fstat64().
*/

View file

@ -0,0 +1,56 @@
// 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 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2025, Rob Norris <robn@despairlabs.com>
*/
#ifndef _SYS_MOD_H
#define _SYS_MOD_H
#include <sys/tunables.h>
#define ZFS_MODULE_PARAM(scope, prefix, name, type, perm, desc) \
static const zfs_tunable_t _zfs_tunable_##prefix##name = { \
.zt_name = #prefix#name, \
.zt_varp = &prefix##name, \
.zt_varsz = sizeof (prefix##name), \
.zt_type = ZFS_TUNABLE_TYPE_##type, \
.zt_perm = ZFS_TUNABLE_PERM_##perm, \
.zt_desc = desc \
}; \
static const zfs_tunable_t * \
__zfs_tunable_##prefix##name \
__attribute__((__section__("zfs_tunables"))) \
__attribute__((__used__)) \
= &_zfs_tunable_##prefix##name;
#define ZFS_MODULE_PARAM_ARGS void
#define ZFS_MODULE_PARAM_CALL(scope_prefix, name_prefix, name, setfunc, \
getfunc, perm, desc)
#define EXPORT_SYMBOL(x)
#endif

View file

@ -0,0 +1,60 @@
// 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) 2025, Rob Norris <robn@despairlabs.com>
*/
#ifndef _SYS_TUNABLES_H
#define _SYS_TUNABLES_H
typedef enum {
ZFS_TUNABLE_TYPE_INT,
ZFS_TUNABLE_TYPE_UINT,
ZFS_TUNABLE_TYPE_ULONG,
ZFS_TUNABLE_TYPE_U64,
ZFS_TUNABLE_TYPE_STRING,
} zfs_tunable_type_t;
typedef enum {
ZFS_TUNABLE_PERM_ZMOD_RW,
ZFS_TUNABLE_PERM_ZMOD_RD,
} zfs_tunable_perm_t;
typedef struct zfs_tunable {
const char *zt_name;
void *zt_varp;
size_t zt_varsz;
zfs_tunable_type_t zt_type;
zfs_tunable_perm_t zt_perm;
const char *zt_desc;
} zfs_tunable_t;
int zfs_tunable_set(const zfs_tunable_t *tunable, const char *val);
int zfs_tunable_get(const zfs_tunable_t *tunable, char *val, size_t valsz);
const zfs_tunable_t *zfs_tunable_lookup(const char *name);
typedef int (*zfs_tunable_iter_t)(const zfs_tunable_t *tunable, void *arg);
void zfs_tunable_iter(zfs_tunable_iter_t cb, void *arg);
#endif

View file

@ -102,7 +102,7 @@ static inline void *
umem_alloc_aligned(size_t size, size_t align, int flags)
{
void *ptr = NULL;
int rc = EINVAL;
int rc;
do {
rc = posix_memalign(&ptr, align, size);

View file

@ -85,13 +85,21 @@ _sol_getmntent(FILE *fp, struct mnttab *mgetp)
}
static int
getextmntent_impl(FILE *fp, struct extmnttab *mp)
getextmntent_impl(FILE *fp, struct extmnttab *mp, uint64_t *mnt_id)
{
int ret;
struct stat64 st;
*mnt_id = 0;
ret = _sol_getmntent(fp, (struct mnttab *)mp);
if (ret == 0) {
#ifdef HAVE_STATX_MNT_ID
struct statx stx;
if (statx(AT_FDCWD, mp->mnt_mountp,
AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW,
STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID))
*mnt_id = stx.stx_mnt_id;
#endif
if (stat64(mp->mnt_mountp, &st) != 0) {
mp->mnt_major = 0;
mp->mnt_minor = 0;
@ -110,6 +118,12 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
struct stat64 st;
FILE *fp;
int match;
boolean_t have_mnt_id = B_FALSE;
uint64_t target_mnt_id = 0;
uint64_t entry_mnt_id;
#ifdef HAVE_STATX_MNT_ID
struct statx stx;
#endif
if (strlen(path) >= MAXPATHLEN) {
(void) fprintf(stderr, "invalid object; pathname too long\n");
@ -128,6 +142,13 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
return (-1);
}
#ifdef HAVE_STATX_MNT_ID
if (statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW,
STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID)) {
have_mnt_id = B_TRUE;
target_mnt_id = stx.stx_mnt_id;
}
#endif
if ((fp = fopen(MNTTAB, "re")) == NULL) {
(void) fprintf(stderr, "cannot open %s\n", MNTTAB);
@ -139,12 +160,15 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
*/
match = 0;
while (getextmntent_impl(fp, entry) == 0) {
if (makedev(entry->mnt_major, entry->mnt_minor) ==
statbuf->st_dev) {
match = 1;
break;
while (getextmntent_impl(fp, entry, &entry_mnt_id) == 0) {
if (have_mnt_id) {
match = (entry_mnt_id == target_mnt_id);
} else {
match = makedev(entry->mnt_major, entry->mnt_minor) ==
statbuf->st_dev;
}
if (match)
break;
}
(void) fclose(fp);

View file

@ -0,0 +1,319 @@
// 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) 2025, Rob Norris <robn@despairlabs.com>
*/
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <inttypes.h>
#include <sys/tunables.h>
/*
* Userspace tunables.
*
* Tunables are external pointers to global variables that are wired up to the
* host environment in some way that allows the operator to directly change
* their values "under the hood".
*
* In userspace, the "host environment" is the program using libzpool.so. So
* that it can manipulate tunables if it wants, we provide an API to access
* them.
*
* Tunables are declared through the ZFS_MODULE_PARAM* macros, which associate
* a global variable with some metadata we can use to describe and access the
* tunable. This is done by creating a uniquely-named zfs_tunable_t.
*
* At runtime, we need a way to discover these zfs_tunable_t items. Since they
* are declared globally, all over the codebase, there's no central place to
* record or list them. So, we take advantage of the compiler's "linker set"
* feature.
*
* In the ZFS_MODULE_PARAM macro, after we create the zfs_tunable_t, we also
* create a zfs_tunable_t* pointing to it. That pointer is forced into the
* "zfs_tunables" ELF section in compiled object. At link time, the linker will
* collect all these pointers into one single big "zfs_tunable" section, and
* will generate two new symbols in the final object: __start_zfs_tunable and
* __stop_zfs_tunable. These point to the first and last item in that section,
* which allows us to access the pointers in that section like an array, and
* through those pointers access the tunable metadata, and from there the
* actual C variable that the tunable describes.
*/
extern const zfs_tunable_t *__start_zfs_tunables;
extern const zfs_tunable_t *__stop_zfs_tunables;
/*
* Because there are no tunables in libspl itself, the above symbols will not
* be generated, which will stop libspl being linked at all. To work around
* that, we force a symbol into that section, and then when iterating, skip
* any NULL pointers.
*/
static void *__zfs_tunable__placeholder
__attribute__((__section__("zfs_tunables")))
__attribute__((__used__)) = NULL;
/*
* Find the name tunable by walking through the linker set and comparing names,
* as described above. This is not particularly efficient but it's a fairly
* rare task, so it shouldn't be a big deal.
*/
const zfs_tunable_t *
zfs_tunable_lookup(const char *name)
{
for (const zfs_tunable_t **ztp = &__start_zfs_tunables;
ztp != &__stop_zfs_tunables; ztp++) {
const zfs_tunable_t *zt = *ztp;
if (zt == NULL)
continue;
if (strcmp(name, zt->zt_name) == 0)
return (zt);
}
return (NULL);
}
/*
* Like zfs_tunable_lookup, but call the provided callback for each tunable.
*/
void
zfs_tunable_iter(zfs_tunable_iter_t cb, void *arg)
{
for (const zfs_tunable_t **ztp = &__start_zfs_tunables;
ztp != &__stop_zfs_tunables; ztp++) {
const zfs_tunable_t *zt = *ztp;
if (zt == NULL)
continue;
if (cb(zt, arg))
return;
}
}
/*
* Parse a string into an int or uint. It's easier to have a pair of "generic"
* functions that clamp to a given min and max rather than have multiple
* functions for each width of type.
*/
static int
zfs_tunable_parse_int(const char *val, intmax_t *np,
intmax_t min, intmax_t max)
{
intmax_t n;
char *end;
errno = 0;
n = strtoimax(val, &end, 0);
if (errno != 0)
return (errno);
if (*end != '\0')
return (EINVAL);
if (n < min || n > max)
return (ERANGE);
*np = n;
return (0);
}
static int
zfs_tunable_parse_uint(const char *val, uintmax_t *np,
uintmax_t min, uintmax_t max)
{
uintmax_t n;
char *end;
errno = 0;
n = strtoumax(val, &end, 0);
if (errno != 0)
return (errno);
if (*end != '\0')
return (EINVAL);
if (strchr(val, '-'))
return (ERANGE);
if (n < min || n > max)
return (ERANGE);
*np = n;
return (0);
}
/*
* Set helpers for each tunable type. Parses the string, and if produces a
* valid value for the tunable, sets it. No effort is made to make sure the
* tunable is of the right type; that's done in zfs_tunable_set() below.
*/
static int
zfs_tunable_set_int(const zfs_tunable_t *zt, const char *val)
{
intmax_t n;
int err = zfs_tunable_parse_int(val, &n, INT_MIN, INT_MAX);
if (err != 0)
return (err);
*(int *)zt->zt_varp = n;
return (0);
}
static int
zfs_tunable_set_uint(const zfs_tunable_t *zt, const char *val)
{
uintmax_t n;
int err = zfs_tunable_parse_uint(val, &n, 0, UINT_MAX);
if (err != 0)
return (err);
*(unsigned int *)zt->zt_varp = n;
return (0);
}
static int
zfs_tunable_set_ulong(const zfs_tunable_t *zt, const char *val)
{
uintmax_t n;
int err = zfs_tunable_parse_uint(val, &n, 0, ULONG_MAX);
if (err != 0)
return (err);
*(unsigned long *)zt->zt_varp = n;
return (0);
}
static int
zfs_tunable_set_u64(const zfs_tunable_t *zt, const char *val)
{
uintmax_t n;
int err = zfs_tunable_parse_uint(val, &n, 0, UINT64_MAX);
if (err != 0)
return (err);
*(uint64_t *)zt->zt_varp = n;
return (0);
}
static int
zfs_tunable_set_string(const zfs_tunable_t *zt, const char *val)
{
(void) zt, (void) val;
/*
* We can't currently handle strings. String tunables are pointers
* into read-only memory, so we can update the pointer, but not the
* contents. That would mean taking an allocation, but we don't have
* an obvious place to free it.
*
* For now, it's no big deal as there's only a couple of string
* tunables anyway.
*/
return (ENOTSUP);
}
/*
* Get helpers for each tunable type. Converts the value to a string if
* necessary and writes it into the provided buffer. The type is assumed to
* be correct; zfs_tunable_get() below will call the correct function for the
* type.
*/
static int
zfs_tunable_get_int(const zfs_tunable_t *zt, char *val, size_t valsz)
{
snprintf(val, valsz, "%d", *(int *)zt->zt_varp);
return (0);
}
static int
zfs_tunable_get_uint(const zfs_tunable_t *zt, char *val, size_t valsz)
{
snprintf(val, valsz, "%u", *(unsigned int *)zt->zt_varp);
return (0);
}
static int
zfs_tunable_get_ulong(const zfs_tunable_t *zt, char *val, size_t valsz)
{
snprintf(val, valsz, "%lu", *(unsigned long *)zt->zt_varp);
return (0);
}
static int
zfs_tunable_get_u64(const zfs_tunable_t *zt, char *val, size_t valsz)
{
snprintf(val, valsz, "%"PRIu64, *(uint64_t *)zt->zt_varp);
return (0);
}
static int
zfs_tunable_get_string(const zfs_tunable_t *zt, char *val, size_t valsz)
{
strlcpy(val, *(char **)zt->zt_varp, valsz);
return (0);
}
/* The public set function. Delegates to the type-specific version. */
int
zfs_tunable_set(const zfs_tunable_t *zt, const char *val)
{
int err;
switch (zt->zt_type) {
case ZFS_TUNABLE_TYPE_INT:
err = zfs_tunable_set_int(zt, val);
break;
case ZFS_TUNABLE_TYPE_UINT:
err = zfs_tunable_set_uint(zt, val);
break;
case ZFS_TUNABLE_TYPE_ULONG:
err = zfs_tunable_set_ulong(zt, val);
break;
case ZFS_TUNABLE_TYPE_U64:
err = zfs_tunable_set_u64(zt, val);
break;
case ZFS_TUNABLE_TYPE_STRING:
err = zfs_tunable_set_string(zt, val);
break;
default:
err = EOPNOTSUPP;
break;
}
return (err);
}
/* The public get function. Delegates to the type-specific version. */
int
zfs_tunable_get(const zfs_tunable_t *zt, char *val, size_t valsz)
{
int err;
switch (zt->zt_type) {
case ZFS_TUNABLE_TYPE_INT:
err = zfs_tunable_get_int(zt, val, valsz);
break;
case ZFS_TUNABLE_TYPE_UINT:
err = zfs_tunable_get_uint(zt, val, valsz);
break;
case ZFS_TUNABLE_TYPE_ULONG:
err = zfs_tunable_get_ulong(zt, val, valsz);
break;
case ZFS_TUNABLE_TYPE_U64:
err = zfs_tunable_get_u64(zt, val, valsz);
break;
case ZFS_TUNABLE_TYPE_STRING:
err = zfs_tunable_get_string(zt, val, valsz);
break;
default:
err = EOPNOTSUPP;
break;
}
return (err);
}

View file

@ -244,6 +244,10 @@
<elf-symbol name='uu_strerror' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_strndup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_zalloc' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_lookup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/>
@ -612,7 +616,6 @@
<array-type-def dimensions='1' type-id='de572c22' size-in-bits='1472' id='6d3c2f42'>
<subrange length='23' type-id='7359adad' id='fdd0f594'/>
</array-type-def>
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
<array-type-def dimensions='1' type-id='3a47d82b' size-in-bits='256' id='a133ec23'>
<subrange length='4' type-id='7359adad' id='16fe7105'/>
</array-type-def>
@ -978,8 +981,6 @@
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'>
<type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/>
<pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
<qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
<function-decl name='fclose' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='822cd80b'/>
<return type-id='95e97e5e'/>
@ -1019,6 +1020,13 @@
<array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
<subrange length='3' type-id='7359adad' id='56f209d2'/>
</array-type-def>
<array-type-def dimensions='1' type-id='d315442e' size-in-bits='16' id='811205dc'>
<subrange length='1' type-id='7359adad' id='52f813b4'/>
</array-type-def>
<array-type-def dimensions='1' type-id='d3130597' size-in-bits='768' id='f63f23b9'>
<subrange length='12' type-id='7359adad' id='84827bdc'/>
</array-type-def>
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
<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'/>
@ -1053,6 +1061,93 @@
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='__u16' type-id='8efea9e5' id='d315442e'/>
<typedef-decl name='__s32' type-id='95e97e5e' id='3158a266'/>
<typedef-decl name='__u32' type-id='f0981eeb' id='3f1a6b60'/>
<typedef-decl name='__s64' type-id='1eb56b1e' id='49659421'/>
<typedef-decl name='__u64' type-id='3a47d82b' id='d3130597'/>
<class-decl name='statx_timestamp' size-in-bits='128' is-struct='yes' visibility='default' id='94101016'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='tv_sec' type-id='49659421' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='tv_nsec' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='__reserved' type-id='3158a266' visibility='default'/>
</data-member>
</class-decl>
<class-decl name='statx' size-in-bits='2048' is-struct='yes' visibility='default' id='720b04c5'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='stx_mask' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='stx_blksize' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='stx_attributes' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='stx_nlink' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='160'>
<var-decl name='stx_uid' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='stx_gid' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='224'>
<var-decl name='stx_mode' type-id='d315442e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='240'>
<var-decl name='__spare0' type-id='811205dc' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='stx_ino' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
<var-decl name='stx_size' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='384'>
<var-decl name='stx_blocks' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
<var-decl name='stx_attributes_mask' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='512'>
<var-decl name='stx_atime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='640'>
<var-decl name='stx_btime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='768'>
<var-decl name='stx_ctime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='896'>
<var-decl name='stx_mtime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1024'>
<var-decl name='stx_rdev_major' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1056'>
<var-decl name='stx_rdev_minor' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1088'>
<var-decl name='stx_dev_major' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1120'>
<var-decl name='stx_dev_minor' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1152'>
<var-decl name='stx_mnt_id' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1216'>
<var-decl name='__spare2' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1280'>
<var-decl name='__spare3' type-id='f63f23b9' 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'/>
@ -1142,6 +1237,8 @@
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
<pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
<qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/>
<pointer-type-def type-id='720b04c5' size-in-bits='64' id='936b8e35'/>
<qualified-type-def type-id='936b8e35' restrict='yes' id='31d265b7'/>
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='3cad23cd'/>
@ -1157,6 +1254,14 @@
<parameter type-id='95e97e5e'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='statx' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='9d26089a'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='f0981eeb'/>
<parameter type-id='31d265b7'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='95e97e5e'/>
@ -1307,6 +1412,91 @@
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/tunables.c' language='LANG_C99'>
<enum-decl name='zfs_tunable_type_t' naming-typedef-id='f50b1525' id='56905369'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_TUNABLE_TYPE_INT' value='0'/>
<enumerator name='ZFS_TUNABLE_TYPE_UINT' value='1'/>
<enumerator name='ZFS_TUNABLE_TYPE_ULONG' value='2'/>
<enumerator name='ZFS_TUNABLE_TYPE_U64' value='3'/>
<enumerator name='ZFS_TUNABLE_TYPE_STRING' value='4'/>
</enum-decl>
<typedef-decl name='zfs_tunable_type_t' type-id='56905369' id='f50b1525'/>
<enum-decl name='zfs_tunable_perm_t' naming-typedef-id='ada7336b' id='e80e6ebf'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_TUNABLE_PERM_ZMOD_RW' value='0'/>
<enumerator name='ZFS_TUNABLE_PERM_ZMOD_RD' value='1'/>
</enum-decl>
<typedef-decl name='zfs_tunable_perm_t' type-id='e80e6ebf' id='ada7336b'/>
<class-decl name='zfs_tunable' size-in-bits='320' is-struct='yes' visibility='default' id='1a97ee0e'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='zt_name' type-id='80f4b756' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='zt_varp' type-id='eaa32e2f' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='zt_varsz' type-id='b59d7dce' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='zt_type' type-id='f50b1525' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='224'>
<var-decl name='zt_perm' type-id='ada7336b' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='zt_desc' type-id='80f4b756' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='zfs_tunable_t' type-id='1a97ee0e' id='12bf5c5e'/>
<typedef-decl name='zfs_tunable_iter_t' type-id='7ef33f92' id='d8d5f4ab'/>
<typedef-decl name='intmax_t' type-id='5b475db0' id='e104d842'/>
<typedef-decl name='uintmax_t' type-id='04d82f4b' id='f8b828c9'/>
<typedef-decl name='__intmax_t' type-id='bd54fe1a' id='5b475db0'/>
<typedef-decl name='__uintmax_t' type-id='7359adad' id='04d82f4b'/>
<pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
<qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
<qualified-type-def type-id='12bf5c5e' const='yes' id='180e47ee'/>
<pointer-type-def type-id='180e47ee' size-in-bits='64' id='a27af98c'/>
<pointer-type-def type-id='92f86508' size-in-bits='64' id='7ef33f92'/>
<function-decl name='strtoimax' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
<parameter type-id='95e97e5e'/>
<return type-id='e104d842'/>
</function-decl>
<function-decl name='strtoumax' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
<parameter type-id='95e97e5e'/>
<return type-id='f8b828c9'/>
</function-decl>
<function-decl name='zfs_tunable_lookup' mangled-name='zfs_tunable_lookup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_lookup'>
<parameter type-id='80f4b756' name='name'/>
<return type-id='a27af98c'/>
</function-decl>
<function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'>
<parameter type-id='d8d5f4ab' name='cb'/>
<parameter type-id='eaa32e2f' name='arg'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'>
<parameter type-id='a27af98c' name='zt'/>
<parameter type-id='80f4b756' name='val'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zfs_tunable_get' mangled-name='zfs_tunable_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_get'>
<parameter type-id='a27af98c' name='zt'/>
<parameter type-id='26a90f95' name='val'/>
<parameter type-id='b59d7dce' name='valsz'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-type size-in-bits='64' id='92f86508'>
<parameter type-id='a27af98c'/>
<parameter type-id='eaa32e2f'/>
<return type-id='95e97e5e'/>
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libuutil/uu_alloc.c' language='LANG_C99'>
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
<type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>

View file

@ -93,9 +93,9 @@ livelist_compare(const void *larg, const void *rarg)
* 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_LOGICAL_BIRTH(l) < BP_GET_LOGICAL_BIRTH(r)) {
if (BP_GET_BIRTH(l) < BP_GET_BIRTH(r)) {
return (-1);
} else if (BP_GET_LOGICAL_BIRTH(l) > BP_GET_LOGICAL_BIRTH(r)) {
} else if (BP_GET_BIRTH(l) > BP_GET_BIRTH(r)) {
return (+1);
}
return (0);

View file

@ -451,6 +451,10 @@
<elf-symbol name='zfs_strip_partition' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_strip_path' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_truncate_shares' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_lookup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_type_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_unmount' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_unmountall' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -479,6 +483,7 @@
<elf-symbol name='zpool_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_clear_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_close' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_collect_leaves' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_collect_unsup_feat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_ddt_prune' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -528,6 +533,7 @@
<elf-symbol name='zpool_import_status' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_in_use' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_initialize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_initialize_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_initialize_wait' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_is_draid_spare' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -568,6 +574,7 @@
<elf-symbol name='zpool_reguid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_reopen_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_scan' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_scan_range' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_search_import' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_set_bootenv' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_set_guid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -577,6 +584,7 @@
<elf-symbol name='zpool_state_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_sync_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_trim' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_trim_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_upgrade' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_attach' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zpool_vdev_clear' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -631,7 +639,7 @@
<elf-symbol name='fletcher_4_superscalar_ops' size='128' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_config_ops' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='sa_protocol_names' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='spa_feature_table' size='2464' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='spa_feature_table' size='2632' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_deleg_perm_tab' size='528' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_history_event_names' size='328' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -1450,8 +1458,103 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='d315442e' size-in-bits='16' id='811205dc'>
<subrange length='1' type-id='7359adad' id='52f813b4'/>
</array-type-def>
<array-type-def dimensions='1' type-id='d3130597' size-in-bits='768' id='f63f23b9'>
<subrange length='12' type-id='7359adad' id='84827bdc'/>
</array-type-def>
<typedef-decl name='__u16' type-id='8efea9e5' id='d315442e'/>
<typedef-decl name='__s32' type-id='95e97e5e' id='3158a266'/>
<typedef-decl name='__u32' type-id='f0981eeb' id='3f1a6b60'/>
<typedef-decl name='__s64' type-id='1eb56b1e' id='49659421'/>
<typedef-decl name='__u64' type-id='3a47d82b' id='d3130597'/>
<class-decl name='statx_timestamp' size-in-bits='128' is-struct='yes' visibility='default' id='94101016'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='tv_sec' type-id='49659421' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='tv_nsec' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='__reserved' type-id='3158a266' visibility='default'/>
</data-member>
</class-decl>
<class-decl name='statx' size-in-bits='2048' is-struct='yes' visibility='default' id='720b04c5'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='stx_mask' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='stx_blksize' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='stx_attributes' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='stx_nlink' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='160'>
<var-decl name='stx_uid' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='stx_gid' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='224'>
<var-decl name='stx_mode' type-id='d315442e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='240'>
<var-decl name='__spare0' type-id='811205dc' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='stx_ino' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
<var-decl name='stx_size' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='384'>
<var-decl name='stx_blocks' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
<var-decl name='stx_attributes_mask' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='512'>
<var-decl name='stx_atime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='640'>
<var-decl name='stx_btime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='768'>
<var-decl name='stx_ctime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='896'>
<var-decl name='stx_mtime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1024'>
<var-decl name='stx_rdev_major' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1056'>
<var-decl name='stx_rdev_minor' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1088'>
<var-decl name='stx_dev_major' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1120'>
<var-decl name='stx_dev_minor' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1152'>
<var-decl name='stx_mnt_id' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1216'>
<var-decl name='__spare2' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1280'>
<var-decl name='__spare3' type-id='f63f23b9' visibility='default'/>
</data-member>
</class-decl>
<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='720b04c5' size-in-bits='64' id='936b8e35'/>
<qualified-type-def type-id='936b8e35' restrict='yes' id='31d265b7'/>
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='3cad23cd'/>
@ -1463,6 +1566,14 @@
<parameter type-id='822cd80b'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='statx' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='9d26089a'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='f0981eeb'/>
<parameter type-id='31d265b7'/>
<return type-id='95e97e5e'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/timestamp.c' language='LANG_C99'>
<typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
@ -1487,6 +1598,89 @@
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/tunables.c' language='LANG_C99'>
<enum-decl name='zfs_tunable_type_t' naming-typedef-id='f50b1525' id='56905369'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_TUNABLE_TYPE_INT' value='0'/>
<enumerator name='ZFS_TUNABLE_TYPE_UINT' value='1'/>
<enumerator name='ZFS_TUNABLE_TYPE_ULONG' value='2'/>
<enumerator name='ZFS_TUNABLE_TYPE_U64' value='3'/>
<enumerator name='ZFS_TUNABLE_TYPE_STRING' value='4'/>
</enum-decl>
<typedef-decl name='zfs_tunable_type_t' type-id='56905369' id='f50b1525'/>
<enum-decl name='zfs_tunable_perm_t' naming-typedef-id='ada7336b' id='e80e6ebf'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_TUNABLE_PERM_ZMOD_RW' value='0'/>
<enumerator name='ZFS_TUNABLE_PERM_ZMOD_RD' value='1'/>
</enum-decl>
<typedef-decl name='zfs_tunable_perm_t' type-id='e80e6ebf' id='ada7336b'/>
<class-decl name='zfs_tunable' size-in-bits='320' is-struct='yes' visibility='default' id='1a97ee0e'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='zt_name' type-id='80f4b756' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='zt_varp' type-id='eaa32e2f' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='zt_varsz' type-id='b59d7dce' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='zt_type' type-id='f50b1525' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='224'>
<var-decl name='zt_perm' type-id='ada7336b' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='zt_desc' type-id='80f4b756' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='zfs_tunable_t' type-id='1a97ee0e' id='12bf5c5e'/>
<typedef-decl name='zfs_tunable_iter_t' type-id='7ef33f92' id='d8d5f4ab'/>
<typedef-decl name='intmax_t' type-id='5b475db0' id='e104d842'/>
<typedef-decl name='uintmax_t' type-id='04d82f4b' id='f8b828c9'/>
<typedef-decl name='__intmax_t' type-id='bd54fe1a' id='5b475db0'/>
<typedef-decl name='__uintmax_t' type-id='7359adad' id='04d82f4b'/>
<qualified-type-def type-id='12bf5c5e' const='yes' id='180e47ee'/>
<pointer-type-def type-id='180e47ee' size-in-bits='64' id='a27af98c'/>
<pointer-type-def type-id='92f86508' size-in-bits='64' id='7ef33f92'/>
<function-decl name='strtoimax' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
<parameter type-id='95e97e5e'/>
<return type-id='e104d842'/>
</function-decl>
<function-decl name='strtoumax' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
<parameter type-id='95e97e5e'/>
<return type-id='f8b828c9'/>
</function-decl>
<function-decl name='zfs_tunable_lookup' mangled-name='zfs_tunable_lookup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_lookup'>
<parameter type-id='80f4b756' name='name'/>
<return type-id='a27af98c'/>
</function-decl>
<function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'>
<parameter type-id='d8d5f4ab' name='cb'/>
<parameter type-id='eaa32e2f' name='arg'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'>
<parameter type-id='a27af98c' name='zt'/>
<parameter type-id='80f4b756' name='val'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zfs_tunable_get' mangled-name='zfs_tunable_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_get'>
<parameter type-id='a27af98c' name='zt'/>
<parameter type-id='26a90f95' name='val'/>
<parameter type-id='b59d7dce' name='valsz'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-type size-in-bits='64' id='92f86508'>
<parameter type-id='a27af98c'/>
<parameter type-id='eaa32e2f'/>
<return type-id='95e97e5e'/>
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libtpool/thread_pool.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='49ef3ffd' size-in-bits='1024' id='a14403f5'>
<subrange length='16' type-id='7359adad' id='848d0938'/>
@ -4135,13 +4329,6 @@
<parameter type-id='58603c44'/>
<return type-id='9c313c2d'/>
</function-decl>
<function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'>
<parameter type-id='4c81de99'/>
<parameter type-id='80f4b756'/>
<parameter type-id='26a90f95'/>
<parameter type-id='b59d7dce'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zfs_iter_snapshots_v2' mangled-name='zfs_iter_snapshots_v2' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_iter_snapshots_v2'>
<parameter type-id='9200a744'/>
<parameter type-id='95e97e5e'/>
@ -6210,7 +6397,10 @@
<enumerator name='SPA_FEATURE_FAST_DEDUP' value='41'/>
<enumerator name='SPA_FEATURE_LONGNAME' value='42'/>
<enumerator name='SPA_FEATURE_LARGE_MICROZAP' value='43'/>
<enumerator name='SPA_FEATURES' value='44'/>
<enumerator name='SPA_FEATURE_DYNAMIC_GANG_HEADER' value='44'/>
<enumerator name='SPA_FEATURE_BLOCK_CLONING_ENDIAN' value='45'/>
<enumerator name='SPA_FEATURE_PHYSICAL_REWRITE' value='46'/>
<enumerator name='SPA_FEATURES' value='47'/>
</enum-decl>
<typedef-decl name='spa_feature_t' type-id='33ecb627' id='d6618c78'/>
<qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
@ -6629,6 +6819,13 @@
<parameter type-id='e4378506' name='plp'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_prop_get_feature' mangled-name='zpool_prop_get_feature' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_prop_get_feature'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='80f4b756' name='propname'/>
<parameter type-id='26a90f95' name='buf'/>
<parameter type-id='b59d7dce' name='len'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_get_state' mangled-name='zpool_get_state' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_get_state'>
<parameter type-id='4c81de99' name='zhp'/>
<return type-id='95e97e5e'/>
@ -6710,6 +6907,11 @@
<parameter type-id='95e97e5e' name='flags'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_initialize_one' mangled-name='zpool_initialize_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_initialize_one'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='eaa32e2f' name='data'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_initialize' mangled-name='zpool_initialize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_initialize'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='7063e1ab' name='cmd_type'/>
@ -6722,6 +6924,17 @@
<parameter type-id='5ce45b60' name='vds'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_collect_leaves' mangled-name='zpool_collect_leaves' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_collect_leaves'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='5ce45b60' name='nvroot'/>
<parameter type-id='5ce45b60' name='res'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='zpool_trim_one' mangled-name='zpool_trim_one' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_trim_one'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='eaa32e2f' name='data'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_trim' mangled-name='zpool_trim' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_trim'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='b1146b8d' name='cmd_type'/>
@ -6735,6 +6948,14 @@
<parameter type-id='b51cf3c2' name='cmd'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_scan_range' mangled-name='zpool_scan_range' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_scan_range'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='7313fbe2' name='func'/>
<parameter type-id='b51cf3c2' name='cmd'/>
<parameter type-id='c9d12d66' name='date_start'/>
<parameter type-id='c9d12d66' name='date_end'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_find_vdev_by_physpath' mangled-name='zpool_find_vdev_by_physpath' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_vdev_by_physpath'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='80f4b756' name='ppath'/>
@ -9394,8 +9615,8 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/zcommon/zfeature_common.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='19712' id='fd4573e5'>
<subrange length='44' type-id='7359adad' id='cf8ba455'/>
<array-type-def dimensions='1' type-id='83f29ca2' size-in-bits='21056' id='fd43354e'>
<subrange length='47' type-id='7359adad' id='8f8900fe'/>
</array-type-def>
<enum-decl name='zfeature_flags' id='6db816a4'>
<underlying-type type-id='9cac1fee'/>
@ -9403,6 +9624,7 @@
<enumerator name='ZFEATURE_FLAG_MOS' value='2'/>
<enumerator name='ZFEATURE_FLAG_ACTIVATE_ON_ENABLE' value='4'/>
<enumerator name='ZFEATURE_FLAG_PER_DATASET' value='8'/>
<enumerator name='ZFEATURE_FLAG_NO_UPGRADE' value='16'/>
</enum-decl>
<typedef-decl name='zfeature_flags_t' type-id='6db816a4' id='fc329033'/>
<enum-decl name='zfeature_type' id='c4fa2355'>
@ -9472,7 +9694,7 @@
<pointer-type-def type-id='611586a1' size-in-bits='64' id='2e243169'/>
<qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
<pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
<var-decl name='spa_feature_table' type-id='fd4573e5' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
<var-decl name='spa_feature_table' type-id='fd43354e' mangled-name='spa_feature_table' visibility='default' elf-symbol-id='spa_feature_table'/>
<var-decl name='zfeature_checks_disable' type-id='c19b74c3' mangled-name='zfeature_checks_disable' visibility='default' elf-symbol-id='zfeature_checks_disable'/>
<function-decl name='opendir' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>

View file

@ -584,7 +584,7 @@ get_key_material_https(libzfs_handle_t *hdl, const char *uri,
goto end;
}
int kfd = -1;
int kfd;
#ifdef O_TMPFILE
kfd = open(getenv("TMPDIR") ?: "/tmp",
O_RDWR | O_TMPFILE | O_EXCL | O_CLOEXEC, 0600);

View file

@ -1039,7 +1039,6 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
nvlist_t *ret;
int chosen_normal = -1;
int chosen_utf = -1;
int set_maxbs = 0;
if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
(void) no_memory(hdl);
@ -1258,46 +1257,20 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}
/* save the ZFS_PROP_RECORDSIZE during create op */
if (zpool_hdl == NULL && prop == ZFS_PROP_RECORDSIZE) {
set_maxbs = intval;
}
break;
}
case ZFS_PROP_SPECIAL_SMALL_BLOCKS:
{
int maxbs =
set_maxbs == 0 ? SPA_OLD_MAXBLOCKSIZE : set_maxbs;
int maxbs = SPA_MAXBLOCKSIZE;
char buf[64];
if (zpool_hdl != NULL) {
char state[64] = "";
maxbs = zpool_get_prop_int(zpool_hdl,
ZPOOL_PROP_MAXBLOCKSIZE, NULL);
/*
* Issue a warning but do not fail so that
* tests for settable properties succeed.
*/
if (zpool_prop_get_feature(zpool_hdl,
"feature@allocation_classes", state,
sizeof (state)) != 0 ||
strcmp(state, ZFS_FEATURE_ACTIVE) != 0) {
(void) fprintf(stderr, gettext(
"%s: property requires a special "
"device in the pool\n"), propname);
}
}
if (intval != 0 &&
(intval < SPA_MINBLOCKSIZE ||
intval > maxbs || !ISP2(intval))) {
if (intval > SPA_MAXBLOCKSIZE) {
zfs_nicebytes(maxbs, buf, sizeof (buf));
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid '%s=%llu' property: must be zero "
"or a power of 2 from 512B to %s"),
propname, (unsigned long long)intval, buf);
"invalid '%s' property: must be between "
"zero and %s"),
propname, buf);
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}

View file

@ -31,6 +31,7 @@
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
* Copyright (c) 2021, 2023, Klara Inc.
* Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
*/
#include <errno.h>
@ -896,7 +897,7 @@ int
zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval)
{
zfs_cmd_t zc = {"\0"};
int ret = -1;
int ret;
char errbuf[ERRBUFLEN];
nvlist_t *nvl = NULL;
nvlist_t *realprops;
@ -1421,30 +1422,6 @@ zpool_get_state(zpool_handle_t *zhp)
return (zhp->zpool_state);
}
/*
* Check if vdev list contains a special vdev
*/
static boolean_t
zpool_has_special_vdev(nvlist_t *nvroot)
{
nvlist_t **child;
uint_t children;
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &child,
&children) == 0) {
for (uint_t c = 0; c < children; c++) {
const char *bias;
if (nvlist_lookup_string(child[c],
ZPOOL_CONFIG_ALLOCATION_BIAS, &bias) == 0 &&
strcmp(bias, VDEV_ALLOC_BIAS_SPECIAL) == 0) {
return (B_TRUE);
}
}
}
return (B_FALSE);
}
/*
* Check if vdev list contains a dRAID vdev
*/
@ -1548,16 +1525,6 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
goto create_failed;
}
if (nvlist_exists(zc_fsprops,
zfs_prop_to_name(ZFS_PROP_SPECIAL_SMALL_BLOCKS)) &&
!zpool_has_special_vdev(nvroot)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"%s property requires a special vdev"),
zfs_prop_to_name(ZFS_PROP_SPECIAL_SMALL_BLOCKS));
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto create_failed;
}
if (!zc_props &&
(nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) {
goto create_failed;
@ -2470,6 +2437,30 @@ xlate_init_err(int err)
return (err);
}
int
zpool_initialize_one(zpool_handle_t *zhp, void *data)
{
int error;
libzfs_handle_t *hdl = zpool_get_handle(zhp);
const char *pool_name = zpool_get_name(zhp);
if (zpool_open_silent(hdl, pool_name, &zhp) != 0)
return (-1);
initialize_cbdata_t *cb = data;
nvlist_t *vdevs = fnvlist_alloc();
nvlist_t *config = zpool_get_config(zhp, NULL);
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE);
zpool_collect_leaves(zhp, nvroot, vdevs);
if (cb->wait)
error = zpool_initialize_wait(zhp, cb->cmd_type, vdevs);
else
error = zpool_initialize(zhp, cb->cmd_type, vdevs);
fnvlist_free(vdevs);
return (error);
}
/*
* Begin, suspend, cancel, or uninit (clear) the initialization (initializing
* of all free blocks) for the given vdevs in the given pool.
@ -2590,6 +2581,58 @@ xlate_trim_err(int err)
return (err);
}
void
zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
{
libzfs_handle_t *hdl = zhp->zpool_hdl;
uint_t children = 0;
nvlist_t **child;
uint_t i;
(void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&child, &children);
if (children == 0) {
char *path = zpool_vdev_name(hdl, zhp, nvroot,
VDEV_NAME_PATH);
if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
strcmp(path, VDEV_TYPE_HOLE) != 0)
fnvlist_add_boolean(res, path);
free(path);
return;
}
for (i = 0; i < children; i++) {
zpool_collect_leaves(zhp, child[i], res);
}
}
int
zpool_trim_one(zpool_handle_t *zhp, void *data)
{
int error;
libzfs_handle_t *hdl = zpool_get_handle(zhp);
const char *pool_name = zpool_get_name(zhp);
if (zpool_open_silent(hdl, pool_name, &zhp) != 0)
return (-1);
trim_cbdata_t *cb = data;
nvlist_t *vdevs = fnvlist_alloc();
/* no individual leaf vdevs specified, so add them all */
nvlist_t *config = zpool_get_config(zhp, NULL);
nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE);
zpool_collect_leaves(zhp, nvroot, vdevs);
error = zpool_trim(zhp, cb->cmd_type, vdevs, &cb->trim_flags);
fnvlist_free(vdevs);
return (error);
}
static int
zpool_trim_wait(zpool_handle_t *zhp, nvlist_t *vdev_guids)
{
@ -2730,7 +2773,13 @@ out:
* Scan the pool.
*/
int
zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) {
return (zpool_scan_range(zhp, func, cmd, 0, 0));
}
int
zpool_scan_range(zpool_handle_t *zhp, pool_scan_func_t func,
pool_scrub_cmd_t cmd, time_t date_start, time_t date_end)
{
char errbuf[ERRBUFLEN];
int err;
@ -2739,6 +2788,8 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
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);
err = lzc_scrub(ZFS_IOC_POOL_SCRUB, zhp->zpool_name, args, NULL);
fnvlist_free(args);
@ -4344,7 +4395,7 @@ zpool_set_guid(zpool_handle_t *zhp, const uint64_t *guid)
libzfs_handle_t *hdl = zhp->zpool_hdl;
nvlist_t *nvl = NULL;
zfs_cmd_t zc = {"\0"};
int error = -1;
int error;
if (guid != NULL) {
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
@ -5127,9 +5178,10 @@ zpool_load_compat(const char *compat, boolean_t *features, char *report,
/* special cases (unset), "" and "off" => enable all features */
if (compat == NULL || compat[0] == '\0' ||
strcmp(compat, ZPOOL_COMPAT_OFF) == 0) {
if (features != NULL)
if (features != NULL) {
for (uint_t i = 0; i < SPA_FEATURES; i++)
features[i] = B_TRUE;
}
if (report != NULL)
strlcpy(report, gettext("all features enabled"), rlen);
return (ZPOOL_COMPATIBILITY_OK);

View file

@ -484,7 +484,8 @@ check_status(nvlist_t *config, boolean_t isimport,
}
for (i = 0; i < SPA_FEATURES; i++) {
zfeature_info_t *fi = &spa_feature_table[i];
if (!fi->fi_zfs_mod_supported)
if (!fi->fi_zfs_mod_supported ||
(fi->fi_flags & ZFEATURE_FLAG_NO_UPGRADE))
continue;
if (c_features[i] && !nvlist_exists(feat, fi->fi_guid))
return (ZPOOL_STATUS_FEAT_DISABLED);

View file

@ -222,6 +222,10 @@
<elf-symbol name='spl_pagesize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='strlcat' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_get' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_iter' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_lookup' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfs_tunable_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
@ -613,7 +617,6 @@
<array-type-def dimensions='1' type-id='de572c22' size-in-bits='1472' id='6d3c2f42'>
<subrange length='23' type-id='7359adad' id='fdd0f594'/>
</array-type-def>
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
<array-type-def dimensions='1' type-id='3a47d82b' size-in-bits='256' id='a133ec23'>
<subrange length='4' type-id='7359adad' id='16fe7105'/>
</array-type-def>
@ -974,8 +977,6 @@
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/os/linux/gethostid.c' language='LANG_C99'>
<type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/>
<pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
<qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
<function-decl name='strtoull' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
@ -987,6 +988,13 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='d315442e' size-in-bits='16' id='811205dc'>
<subrange length='1' type-id='7359adad' id='52f813b4'/>
</array-type-def>
<array-type-def dimensions='1' type-id='d3130597' size-in-bits='768' id='f63f23b9'>
<subrange length='12' type-id='7359adad' id='84827bdc'/>
</array-type-def>
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
<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'/>
@ -1021,6 +1029,93 @@
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='__u16' type-id='8efea9e5' id='d315442e'/>
<typedef-decl name='__s32' type-id='95e97e5e' id='3158a266'/>
<typedef-decl name='__u32' type-id='f0981eeb' id='3f1a6b60'/>
<typedef-decl name='__s64' type-id='1eb56b1e' id='49659421'/>
<typedef-decl name='__u64' type-id='3a47d82b' id='d3130597'/>
<class-decl name='statx_timestamp' size-in-bits='128' is-struct='yes' visibility='default' id='94101016'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='tv_sec' type-id='49659421' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='tv_nsec' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='__reserved' type-id='3158a266' visibility='default'/>
</data-member>
</class-decl>
<class-decl name='statx' size-in-bits='2048' is-struct='yes' visibility='default' id='720b04c5'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='stx_mask' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='stx_blksize' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='stx_attributes' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='stx_nlink' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='160'>
<var-decl name='stx_uid' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='stx_gid' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='224'>
<var-decl name='stx_mode' type-id='d315442e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='240'>
<var-decl name='__spare0' type-id='811205dc' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='stx_ino' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='320'>
<var-decl name='stx_size' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='384'>
<var-decl name='stx_blocks' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
<var-decl name='stx_attributes_mask' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='512'>
<var-decl name='stx_atime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='640'>
<var-decl name='stx_btime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='768'>
<var-decl name='stx_ctime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='896'>
<var-decl name='stx_mtime' type-id='94101016' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1024'>
<var-decl name='stx_rdev_major' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1056'>
<var-decl name='stx_rdev_minor' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1088'>
<var-decl name='stx_dev_major' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1120'>
<var-decl name='stx_dev_minor' type-id='3f1a6b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1152'>
<var-decl name='stx_mnt_id' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1216'>
<var-decl name='__spare2' type-id='d3130597' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1280'>
<var-decl name='__spare3' type-id='f63f23b9' 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'/>
@ -1096,6 +1191,8 @@
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
<pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
<qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/>
<pointer-type-def type-id='720b04c5' size-in-bits='64' id='936b8e35'/>
<qualified-type-def type-id='936b8e35' restrict='yes' id='31d265b7'/>
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='3cad23cd'/>
@ -1107,15 +1204,18 @@
<parameter type-id='822cd80b'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='statx' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='9d26089a'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='f0981eeb'/>
<parameter type-id='31d265b7'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='f1cadedf'/>
@ -1258,6 +1358,96 @@
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/tunables.c' language='LANG_C99'>
<enum-decl name='zfs_tunable_type_t' naming-typedef-id='f50b1525' id='56905369'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_TUNABLE_TYPE_INT' value='0'/>
<enumerator name='ZFS_TUNABLE_TYPE_UINT' value='1'/>
<enumerator name='ZFS_TUNABLE_TYPE_ULONG' value='2'/>
<enumerator name='ZFS_TUNABLE_TYPE_U64' value='3'/>
<enumerator name='ZFS_TUNABLE_TYPE_STRING' value='4'/>
</enum-decl>
<typedef-decl name='zfs_tunable_type_t' type-id='56905369' id='f50b1525'/>
<enum-decl name='zfs_tunable_perm_t' naming-typedef-id='ada7336b' id='e80e6ebf'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='ZFS_TUNABLE_PERM_ZMOD_RW' value='0'/>
<enumerator name='ZFS_TUNABLE_PERM_ZMOD_RD' value='1'/>
</enum-decl>
<typedef-decl name='zfs_tunable_perm_t' type-id='e80e6ebf' id='ada7336b'/>
<class-decl name='zfs_tunable' size-in-bits='320' is-struct='yes' visibility='default' id='1a97ee0e'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='zt_name' type-id='80f4b756' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='zt_varp' type-id='eaa32e2f' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='zt_varsz' type-id='b59d7dce' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='zt_type' type-id='f50b1525' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='224'>
<var-decl name='zt_perm' type-id='ada7336b' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='256'>
<var-decl name='zt_desc' type-id='80f4b756' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='zfs_tunable_t' type-id='1a97ee0e' id='12bf5c5e'/>
<typedef-decl name='zfs_tunable_iter_t' type-id='7ef33f92' id='d8d5f4ab'/>
<typedef-decl name='intmax_t' type-id='5b475db0' id='e104d842'/>
<typedef-decl name='uintmax_t' type-id='04d82f4b' id='f8b828c9'/>
<typedef-decl name='__intmax_t' type-id='bd54fe1a' id='5b475db0'/>
<typedef-decl name='__uintmax_t' type-id='7359adad' id='04d82f4b'/>
<pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
<qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
<qualified-type-def type-id='12bf5c5e' const='yes' id='180e47ee'/>
<pointer-type-def type-id='180e47ee' size-in-bits='64' id='a27af98c'/>
<pointer-type-def type-id='92f86508' size-in-bits='64' id='7ef33f92'/>
<function-decl name='strtoimax' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
<parameter type-id='95e97e5e'/>
<return type-id='e104d842'/>
</function-decl>
<function-decl name='strtoumax' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
<parameter type-id='95e97e5e'/>
<return type-id='f8b828c9'/>
</function-decl>
<function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zfs_tunable_lookup' mangled-name='zfs_tunable_lookup' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_lookup'>
<parameter type-id='80f4b756' name='name'/>
<return type-id='a27af98c'/>
</function-decl>
<function-decl name='zfs_tunable_iter' mangled-name='zfs_tunable_iter' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_iter'>
<parameter type-id='d8d5f4ab' name='cb'/>
<parameter type-id='eaa32e2f' name='arg'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='zfs_tunable_set' mangled-name='zfs_tunable_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_set'>
<parameter type-id='a27af98c' name='zt'/>
<parameter type-id='80f4b756' name='val'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zfs_tunable_get' mangled-name='zfs_tunable_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_tunable_get'>
<parameter type-id='a27af98c' name='zt'/>
<parameter type-id='26a90f95' name='val'/>
<parameter type-id='b59d7dce' name='valsz'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-type size-in-bits='64' id='92f86508'>
<parameter type-id='a27af98c'/>
<parameter type-id='eaa32e2f'/>
<return type-id='95e97e5e'/>
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libzfs_core/libzfs_core.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
<subrange length='3' type-id='7359adad' id='56f209d2'/>

View file

@ -177,6 +177,7 @@ nodist_libzpool_la_SOURCES = \
module/zfs/zfs_byteswap.c \
module/zfs/zfs_chksum.c \
module/zfs/zfs_debug_common.c \
module/zfs/zfs_crrd.c \
module/zfs/zfs_fm.c \
module/zfs/zfs_fuid.c \
module/zfs/zfs_ratelimit.c \
@ -199,7 +200,7 @@ libzpool_la_LIBADD = \
libzstd.la \
libzutil.la
libzpool_la_LIBADD += $(LIBCLOCK_GETTIME) $(ZLIB_LIBS) -ldl -lm
libzpool_la_LIBADD += $(LIBCLOCK_GETTIME) $(ZLIB_LIBS) -lm
libzpool_la_LDFLAGS = -pthread

View file

@ -1024,12 +1024,6 @@ spl_fstrans_unmark(fstrans_cookie_t cookie)
(void) cookie;
}
int
__spl_pf_fstrans_check(void)
{
return (0);
}
int
kmem_cache_reap_active(void)
{
@ -1037,13 +1031,7 @@ kmem_cache_reap_active(void)
}
void
zvol_create_minor(const char *name)
{
(void) name;
}
void
zvol_create_minors_recursive(const char *name)
zvol_create_minors(const char *name)
{
(void) name;
}
@ -1073,8 +1061,8 @@ zvol_rename_minors(spa_t *spa, const char *oldname, const char *newname,
int
zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp)
{
int fd = -1;
int dump_fd = -1;
int fd;
int dump_fd;
int err;
int old_umask = 0;
zfs_file_t *fp;

View file

@ -36,7 +36,7 @@
#include <sys/fs/zfs.h>
#include <sys/zfs_refcount.h>
#include <sys/zfs_ioctl.h>
#include <dlfcn.h>
#include <sys/tunables.h>
#include <libzutil.h>
/*
@ -151,97 +151,119 @@ show_pool_stats(spa_t *spa)
nvlist_free(config);
}
/* *k_out must be freed by the caller */
static int
set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out)
{
int err;
VERIFY(arg);
char *d = strdup(arg);
char *save = NULL;
char *k = strtok_r(d, "=", &save);
char *v_str = strtok_r(NULL, "=", &save);
char *follow = strtok_r(NULL, "=", &save);
if (k == NULL || v_str == NULL || follow != NULL) {
err = EINVAL;
goto err_free;
}
u_longlong_t val = strtoull(v_str, NULL, 0);
if (val > UINT32_MAX) {
fprintf(stderr, "Value for global variable '%s' must "
"be a 32-bit unsigned integer, got '%s'\n", k, v_str);
err = EOVERFLOW;
goto err_free;
}
*k_out = strdup(k);
*v_out = val;
free(d);
return (0);
err_free:
free(d);
return (err);
}
/*
* Sets given global variable in libzpool to given unsigned 32-bit value.
* arg: "<variable>=<value>"
* Common helper for working with libzpool tunables from the command line.
*
* Valid inputs:
*
* <name> show named tunable and value
* <name>=<value> set tunable value
*
* show show all tunables and values
* show=<name> show named tunable and value
* info show info about all tunables
* info=<name> show info about named tunable
*/
int
set_global_var(char const *arg)
typedef enum { SHOW, INFO, SET } tunable_mode_t;
static int
list_tunables_cb(const zfs_tunable_t *tunable, void *arg)
{
void *zpoolhdl;
char *varname;
u_longlong_t val;
int ret;
const tunable_mode_t *mode = arg;
#ifndef _ZFS_LITTLE_ENDIAN
/*
* On big endian systems changing a 64-bit variable would set the high
* 32 bits instead of the low 32 bits, which could cause unexpected
* results.
*/
fprintf(stderr, "Setting global variables is only supported on "
"little-endian systems\n");
ret = ENOTSUP;
goto out_ret;
#endif
if ((ret = set_global_var_parse_kv(arg, &varname, &val)) != 0) {
goto out_ret;
}
zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
if (zpoolhdl != NULL) {
uint32_t *var;
var = dlsym(zpoolhdl, varname);
if (var == NULL) {
fprintf(stderr, "Global variable '%s' does not exist "
"in libzpool.so\n", varname);
ret = EINVAL;
goto out_dlclose;
}
*var = (uint32_t)val;
static const char *type[] = {
"int", "uint", "ulong", "u64", "str",
};
static const char *perm[] = {
"rw", "rd",
};
if (*mode == SHOW) {
char val[64];
int err = zfs_tunable_get(tunable, val, sizeof (val));
if (err == 0)
printf("%s: %s\n", tunable->zt_name, val);
else
printf("%s: [error getting tunable value: %s]\n",
tunable->zt_name, strerror(err));
} else {
fprintf(stderr, "Failed to open libzpool.so to set global "
"variable\n");
ret = EIO;
goto out_free;
printf("%s [%s %s]: %s\n", tunable->zt_name,
type[tunable->zt_type], perm[tunable->zt_perm],
tunable->zt_desc);
}
ret = 0;
return (0);
}
int
handle_tunable_option(const char *_arg, boolean_t quiet)
{
int err = 0;
char *arg = strdup(_arg);
char *k, *v;
out_dlclose:
dlclose(zpoolhdl);
out_free:
free(varname);
out_ret:
return (ret);
v = arg;
k = strsep(&v, "=");
tunable_mode_t mode;
if (strcmp(k, "show") == 0) {
mode = SHOW;
k = v;
} else if (strcmp(k, "info") == 0) {
mode = INFO;
k = v;
} else if (v == NULL) {
mode = SHOW;
} else {
mode = SET;
}
if (quiet && mode != SET) {
err = EINVAL;
goto out;
}
if (mode == SET) {
const zfs_tunable_t *tunable = zfs_tunable_lookup(k);
if (tunable == NULL) {
err = ENOENT;
goto out;
}
char vold[256], vnew[256];
if (zfs_tunable_get(tunable, vold, sizeof (vold)) != 0)
strcpy(vold, "???");
err = zfs_tunable_set(tunable, v);
if (err != 0)
goto out;
if (zfs_tunable_get(tunable, vnew, sizeof (vnew)) != 0)
strcpy(vnew, "???");
if (!quiet)
printf("%s: %s -> %s\n", k, vold, vnew);
} else if (k != NULL) {
const zfs_tunable_t *tunable = zfs_tunable_lookup(k);
if (tunable == NULL) {
err = ENOENT;
goto out;
}
list_tunables_cb(tunable, &mode);
} else {
zfs_tunable_iter(list_tunables_cb, &mode);
}
out:
if (!quiet) {
if (err == ENOENT)
fprintf(stderr, "no such tunable: %s\n", k);
else if (err != 0)
fprintf(stderr, "couldn't set tunable '%s': %s\n",
k, strerror(err));
}
free(arg);
return (err);
}
static nvlist_t *

View file

@ -188,12 +188,8 @@ i.e. given
will be loaded.
.It Fl C , -vdev-class-state Ns = Ns Sy on Ns | Ns Sy off Ns | Ns Sy random No (default : Sy random )
The vdev allocation class state.
.It Fl o , -option Ns = Ns Ar variable Ns = Ns Ar value
Set global
.Ar variable
to an unsigned 32-bit integer
.Ar value
(little-endian only).
.It Fl o , -option Ns = Ns Ar var Ns = Ns Ar value Ns
Set the given tunable to the provided value.
.It Fl G , -dump-debug
Dump zfs_dbgmsg buffer before exiting due to an error.
.It Fl V , -verbose

View file

@ -1399,14 +1399,15 @@ If this setting is 0, then even if feature@block_cloning is enabled,
using functions and system calls that attempt to clone blocks will act as
though the feature is disabled.
.
.It Sy zfs_bclone_wait_dirty Ns = Ns Sy 0 Ns | Ns 1 Pq int
When set to 1 the FICLONE and FICLONERANGE ioctls wait for dirty data to be
written to disk.
This allows the clone operation to reliably succeed when a file is
.It Sy zfs_bclone_wait_dirty Ns = Ns Sy 1 Ns | Ns 0 Pq int
When set to 1 the FICLONE and FICLONERANGE ioctls will wait for any dirty
data to be written to disk before proceeding.
This ensures that the clone operation reliably succeeds, even if a file is
modified and then immediately cloned.
For small files this may be slower than making a copy of the file.
Therefore, this setting defaults to 0 which causes a clone operation to
immediately fail when encountering a dirty block.
Note that for small files this may be slower than simply copying the file.
When set to 0 the clone operation will immediately fail if it encounters
any dirty blocks.
By default waiting is enabled.
.
.It Sy zfs_blake3_impl Ns = Ns Sy fastest Pq string
Select a BLAKE3 implementation.
@ -1713,10 +1714,19 @@ Similar to
but for cleanup of old indirection records for removed vdevs.
.
.It Sy zfs_immediate_write_sz Ns = Ns Sy 32768 Ns B Po 32 KiB Pc Pq s64
Largest data block to write to the ZIL.
Larger blocks will be treated as if the dataset being written to had the
.Sy logbias Ns = Ns Sy throughput
property set.
Largest write size to store the data directly into the ZIL if
.Sy logbias Ns = Ns Sy latency .
Larger writes may be written indirectly similar to
.Sy logbias Ns = Ns Sy throughput .
In presence of SLOG this parameter is ignored, as if it was set to infinity,
storing all written data into ZIL to not depend on regular vdev latency.
.
.It Sy zil_special_is_slog Ns = Ns Sy 1 Ns | Ns 0 Pq int
When enabled, and written blocks go to normal vdevs, treat present special
vdevs as SLOGs.
Blocks that go to the special vdevs are still written indirectly, as with
.Sy logbias Ns = Ns Sy throughput .
This parameter is ignored if an SLOG is present.
.
.It Sy zfs_initialize_value Ns = Ns Sy 16045690984833335022 Po 0xDEADBEEFDEADBEEE Pc Pq u64
Pattern written to vdev free space by
@ -2237,6 +2247,21 @@ Defer frees starting in this pass.
Maximum memory used for prefetching a checkpoint's space map on each
vdev while discarding the checkpoint.
.
.It Sy zfs_spa_note_txg_time Ns = Ns Sy 600 Pq uint
This parameter defines, in seconds, how often the TXG time database will record
a new TXG if it has changed.
After the specified time interval has passed, and if the TXG number has changed,
the new value is recorded in the database.
These timestamps can later be used for more granular operations, such as
scrubbing.
.
.It Sy zfs_spa_flush_txg_time Ns = Ns Sy 600 Pq uint
This parameter defines, in seconds, how often the ZFS will flush
the TXG time database to disk.
It ensures that the data is actually written to persistent storage, which helps
preserve the database in case of unexpected shutdown.
The database is also automatically flushed during the export sequence.
.
.It Sy zfs_special_class_metadata_reserve_pct Ns = Ns Sy 25 Ns % Pq uint
Only allow small data blocks to be allocated on the special and dedup vdev
types when the available free space percentage on these vdevs exceeds this
@ -2462,8 +2487,8 @@ code for this record type.
The tunable has no effect if the feature is disabled.
.
.It Sy zfs_embedded_slog_min_ms Ns = Ns Sy 64 Pq uint
Usually, one metaslab from each normal-class vdev is dedicated for use by
the ZIL to log synchronous writes.
Usually, one metaslab from each normal and special class vdev is dedicated
for use by the ZIL to log synchronous writes.
However, if there are fewer than
.Sy zfs_embedded_slog_min_ms
metaslabs in the vdev, this functionality is disabled.

View file

@ -541,10 +541,16 @@ The
.Sy blocksize
cannot be changed once the volume has been written, so it should be set at
volume creation time.
The default
.Sy blocksize
for volumes is 16 KiB.
Any power of 2 from 512 bytes to 128 KiB is valid.
The size specified must be a power of two greater than or equal to
.Ar 512 B
and less than or equal to
.Ar 128 KiB .
If the
.Sy large_blocks
feature is enabled on the pool, the size may be up to
.Ar 16 MiB .
The default size is
.Ar 16 KiB .
.Pp
This property can also be referred to by its shortened column name,
.Sy volblock .
@ -1282,10 +1288,12 @@ This feature must be enabled to be used
.It Sy special_small_blocks Ns = Ns Ar size
This value represents the threshold block size for including small file
or zvol blocks into the special allocation class.
Blocks smaller than or equal to this
value will be assigned to the special allocation class while greater blocks
will be assigned to the regular class.
Valid values are zero or a power of two from 512 up to 1048576 (1 MiB).
Blocks smaller than or equal to this value after compression and encryption
will be assigned to the special allocation class, while greater blocks will
be assigned to the regular class.
Valid values are from 0 to maximum block size (
.Ar 16 MiB
).
The default size is 0 which means no small file or zvol blocks
will be allocated in the special class.
.Pp
@ -1569,11 +1577,6 @@ See
.Xr zpool-features 7
for details on ZFS feature flags.
.Pp
However, blocks larger than
.Ar 1 MiB
can have an impact on i/o latency (e.g. tying up a spinning disk for
~300ms), and also potentially on the memory allocator.
.Pp
Note that maximum size is still limited by default to
.Ar 1 MiB
on x86_32, see
@ -1864,7 +1867,8 @@ property is updated with
, the property is set to desired value, but the operation to share, reshare
or unshare the the dataset is not performed.
.It Sy logbias Ns = Ns Sy latency Ns | Ns Sy throughput
Provide a hint to ZFS about handling of synchronous requests in this dataset.
Provide a hint to ZFS about handling of synchronous write requests in this
dataset.
If
.Sy logbias
is set to
@ -1872,12 +1876,12 @@ is set to
.Pq the default ,
ZFS will use pool log devices
.Pq if configured
to handle the requests at low latency.
to handle the write requests at low latency.
If
.Sy logbias
is set to
.Sy throughput ,
ZFS will not use configured pool log devices.
ZFS will not use configured pool log devices to store written data.
ZFS will instead optimize synchronous operations for global pool throughput and
efficient use of resources.
.It Sy snapdev Ns = Ns Sy hidden Ns | Ns Sy visible

View file

@ -401,6 +401,17 @@ This feature becomes
.Sy active
when first block is cloned.
When the last cloned block is freed, it goes back to the enabled state.
.feature com.truenas block_cloning_endian yes
This feature corrects ZAP entry endianness issues in the Block Reference
Table (BRT) used by block cloning.
During the original block cloning implementation, BRT ZAP entries were
mistakenly stored as arrays of 8 single-byte entries instead of single
8-byte entries, making pools non-endian-safe.
.Pp
This feature is activated when the first BRT ZAP is created (that way
ensuring compatibility with existing pools).
When active, new BRT entries are stored in the correct endian-safe format.
The feature becomes inactive when all BRT ZAPs are destroyed.
.feature com.delphix bookmarks yes extensible_dataset
This feature enables use of the
.Nm zfs Cm bookmark
@ -493,6 +504,19 @@ vdev type, or when adding a new
.Sy draid
vdev to an existing pool.
.
.feature com.klarasystems dynamic_gang_header no
This feature enables larger gang headers based on the sector size of the pool.
When enabled, gang headers will use the entire space allocated for them, instead
of always restricting themselves to 512 bytes.
This can reduce the need for nested gang trees in extreme fragmentation
scenarios.
.Pp
This feature becomes active when a gang header is written that is larger than
512 bytes.
This feature is not enabled by
.Xr zpool-upgrade 8 .
Instead, it must be manually enabled, or be part of a compatibility file.
.
.feature org.illumos edonr no extensible_dataset
This feature enables the use of the Edon-R hash algorithm for checksum,
including for nopwrite
@ -829,6 +853,23 @@ when the
command is used on a top-level vdev, and will never return to being
.Sy enabled .
.
.feature com.truenas physical_rewrite yes extensible_dataset
This feature enables physical block rewriting that preserves logical birth
times, avoiding unnecessary inclusion of rewritten blocks in incremental
.Nm zfs Cm send
streams.
When enabled, the
.Nm zfs Cm rewrite Fl P
command can be used.
.Pp
This feature becomes
.Sy active
the first time
.Nm zfs Cm rewrite Fl P
is used on any dataset, and will return to being
.Sy enabled
once all datasets that have ever used physical rewrite are destroyed.
.
.feature org.zfsonlinux project_quota yes extensible_dataset
This feature allows administrators to account the spaces and objects usage
information against the project identifier

View file

@ -390,11 +390,6 @@ Multiple log devices can also be specified, and they can be mirrored.
See the
.Sx EXAMPLES
section for an example of mirroring multiple log devices.
.Pp
Log devices can be added, replaced, attached, detached, and removed.
In addition, log devices are imported and exported as part of the pool
that contains them.
Mirrored devices can be removed by specifying the top-level mirror vdev.
.
.Ss Cache Devices
Devices can be added to a storage pool as
@ -486,8 +481,8 @@ current state of the pool won't be scanned during a scrub.
.
.Ss Special Allocation Class
Allocations in the special class are dedicated to specific block types.
By default, this includes all metadata, the indirect blocks of user data, and
any deduplication tables.
By default, this includes all metadata, the indirect blocks of user data,
intent log (in absence of separate log device), and deduplication tables.
The class can also be provisioned to accept small file blocks or zvol blocks
on a per dataset granularity.
.Pp

View file

@ -474,10 +474,15 @@ as it runs.
Exercise extreme caution when using this option in shared or uncontrolled
environments.
.It Fl o , -option Ns = Ns Ar var Ns = Ns Ar value Ns
Set the given global libzpool variable to the provided value.
The value must be an unsigned 32-bit integer.
Currently only little-endian systems are supported to avoid accidentally setting
the high 32 bits of 64-bit variables.
Set the given tunable to the provided value.
.It Fl o , -option Ns = Ns Ar var Ns
Show the value of the given tunable.
.It Fl o , -option Ns = Ns show
Show all tunables and their values.
.It Fl o , -option Ns = Ns info Ns = Ns Ar value Ns
Show info about a tunable, including their name, type and description.
.It Fl o , -option Ns = Ns info
Show info about all tunables.
.It Fl P , -parseable
Print numbers in an unscaled form more amenable to parsing, e.g.\&
.Sy 1000000

View file

@ -31,7 +31,7 @@
.Sh SYNOPSIS
.Nm zfs
.Cm rewrite
.Oo Fl rvx Ns Oc
.Oo Fl Prvx Ns Oc
.Op Fl l Ar length
.Op Fl o Ar offset
.Ar file Ns | Ns Ar directory Ns
@ -43,6 +43,15 @@ as is without modification at a new location and possibly with new
properties, such as checksum, compression, dedup, copies, etc,
as if they were atomically read and written back.
.Bl -tag -width "-r"
.It Fl P
Perform physical rewrite, preserving logical birth time of blocks.
By default, rewrite updates logical birth times, making blocks appear
as modified in snapshots and incremental send streams.
Physical rewrite preserves logical birth times, avoiding unnecessary
inclusion in incremental streams.
Physical rewrite requires the
.Sy physical_rewrite
feature to be enabled on the pool.
.It Fl l Ar length
Rewrite at most this number of bytes.
.It Fl o Ar offset
@ -60,17 +69,22 @@ same as some property changes may increase pool space usage.
Holes that were never written or were previously zero-compressed are
not rewritten and will remain holes even if compression is disabled.
.Pp
Rewritten blocks will be seen as modified in next snapshot and as such
included into the incremental
.Nm zfs Cm send
stream.
.Pp
If a
.Fl l
or
.Fl o
value request a rewrite to regions past the end of the file, then those
regions are silently ignored, and no error is reported.
.Pp
By default, rewritten blocks update their logical birth time,
meaning they will be included in incremental
.Nm zfs Cm send
streams as modified data.
When the
.Fl P
flag is used, rewritten blocks preserve their logical birth time, since
there are no user data changes.
.
.Sh SEE ALSO
.Xr zfsprops 7
.Xr zfsprops 7 ,
.Xr zpool-features 7

View file

@ -28,7 +28,7 @@
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\" Copyright (c) 2024, 2025, Klara, Inc.
.\"
.Dd May 27, 2025
.Dd July 3, 2025
.Dt ZPOOL-EVENTS 8
.Os
.
@ -465,7 +465,7 @@ ZIO_FLAG_DONT_RETRY:0x00000400
ZIO_FLAG_NODATA:0x00001000
ZIO_FLAG_INDUCE_DAMAGE:0x00002000
ZIO_FLAG_IO_ALLOCATING:0x00004000
ZIO_FLAG_ALLOC_THROTTLED:0x00004000
ZIO_FLAG_IO_RETRY:0x00008000
ZIO_FLAG_PROBE:0x00010000
ZIO_FLAG_TRYHARD:0x00020000

View file

@ -26,6 +26,7 @@
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\" Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
.\"
.Dd May 27, 2021
.Dt ZPOOL-INITIALIZE 8
@ -39,7 +40,7 @@
.Cm initialize
.Op Fl c Ns | Ns Fl s | Ns Fl u
.Op Fl w
.Ar pool
.Fl a Ns | Ns Ar pool
.Oo Ar device Oc Ns
.
.Sh DESCRIPTION
@ -48,6 +49,10 @@ devices, or all eligible devices in the pool if no individual devices are
specified.
Only leaf data or log devices may be initialized.
.Bl -tag -width Ds
.It Fl a , -all
Begin, cancel, suspend initializing on
all
pools.
.It Fl c , -cancel
Cancel initializing on the specified devices, or all eligible devices if none
are specified.

View file

@ -26,8 +26,9 @@
.\" Copyright (c) 2018, 2021 George Melikov. All Rights Reserved.
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\" Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
.\"
.Dd November 18, 2024
.Dd December 11, 2024
.Dt ZPOOL-SCRUB 8
.Os
.
@ -39,7 +40,9 @@
.Cm scrub
.Op Ns Fl e | Ns Fl p | Fl s Ns | Fl C Ns
.Op Fl w
.Ar pool Ns
.Op Fl S Ar date
.Op Fl E Ar date
.Fl a Ns | Ns Ar pool Ns
.
.Sh DESCRIPTION
Begins a scrub or resumes a paused scrub.
@ -89,6 +92,12 @@ During this period, no completion time estimate will be provided.
.
.Sh OPTIONS
.Bl -tag -width "-s"
.It Fl a , -all
Begin, pause, stop scrub on
all
pools.
Initiating scrubs on multiple pools can put considerable load and memory
pressure on the system, so this operation should be performed with caution.
.It Fl s
Stop scrubbing.
.It Fl p
@ -118,6 +127,44 @@ resilvering, nor can it be run when a regular scrub is paused.
Continue scrub from last saved txg (see zpool
.Sy last_scrubbed_txg
property).
.It Fl S Ar date , Fl E Ar date
Allows specifying the date range for blocks created between these dates.
.Bl -bullet -compact -offset indent
.It
.Fl S
Defines a start date.
If not specified, scrubbing begins from the start of the pool's
existence.
.It
.Fl E
Defines an end date.
If not specified, scrubbing continues up to the most recent data.
.El
The provided date should be in the format:
.Dq YYYY-MM-DD HH:MM .
Where:
.Bl -bullet -compact -offset indent
.It
.Dq YYYY
is the year.
.It
.Dq MM
is the numeric representation of the month.
.It
.Dq DD
is the day of the month.
.It
.Dq HH
is the hour.
.It
.Dq MM
is the minutes.
.El
The hour and minutes parameters can be omitted.
The time should be provided in machine local time zone.
Specifying dates prior to enabling this feature will result in scrubbing
starting from the date the pool was created.
If the time was moved backward manually the data range may become inaccurate.
.El
.Sh EXAMPLES
.Ss Example 1

View file

@ -26,6 +26,7 @@
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
.\" Copyright 2017 Nexenta Systems, Inc.
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
.\" Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
.\"
.Dd May 27, 2021
.Dt ZPOOL-TRIM 8
@ -40,7 +41,7 @@
.Op Fl dw
.Op Fl r Ar rate
.Op Fl c Ns | Ns Fl s
.Ar pool
.Fl a Ns | Ns Ar pool
.Oo Ar device Ns Oc Ns
.
.Sh DESCRIPTION
@ -57,6 +58,10 @@ See the documentation for the
.Sy autotrim
property above for the types of vdev devices which can be trimmed.
.Bl -tag -width Ds
.It Fl a , -all
Perform TRIM operation on
all
pools.
.It Fl d , -secure
Causes a secure TRIM to be initiated.
When performing a secure TRIM, the

View file

@ -406,6 +406,7 @@ ZFS_OBJS := \
zfs_byteswap.o \
zfs_chksum.o \
zfs_debug_common.o \
zfs_crrd.o \
zfs_fm.o \
zfs_fuid.o \
zfs_impl.o \
@ -494,3 +495,34 @@ UBSAN_SANITIZE_zfs/sa.o := n
ifeq ($(CONFIG_ALTIVEC),y)
$(obj)/zfs/vdev_raidz_math_powerpc_altivec.o : c_flags += -maltivec
endif
# The following recipes attempt to fix out of src-tree builds, where $(src) != $(obj), so that the
# subdir %.c/%.S -> %.o targets will work as expected. The in-kernel pattern targets do not seem to
# be working on subdirs since about ~6.10
zobjdirs = $(dir $(zfs-objs)) $(dir $(spl-objs)) \
$(dir $(zfs-$(CONFIG_X86))) $(dir $(zfs-$(CONFIG_UML_X86))) $(dir $(zfs-$(CONFIG_ARM64))) \
$(dir $(zfs-$(CONFIG_PPC64))) $(dir $(zfs-$(CONFIG_PPC)))
z_cdirs = $(sort $(filter-out lua/setjmp/ $(addprefix icp/asm-aarch64/, aes/ blake3/ modes/ sha2/) \
$(addprefix icp/asm-x86_64/, aes/ blake3/ modes/ sha2/) \
$(addprefix icp/asm-ppc/, aes/ blake3/ modes/ sha2/) \
$(addprefix icp/asm-ppc64/, aes/ blake3/ modes/ sha2/), $(zobjdirs)))
z_sdirs = $(sort $(filter lua/setjmp/ $(addprefix icp/asm-aarch64/, aes/ blake3/ modes/ sha2/) \
$(addprefix icp/asm-x86_64/, aes/ blake3/ modes/ sha2/) \
$(addprefix icp/asm-ppc/, aes/ blake3/ modes/ sha2/) \
$(addprefix icp/asm-ppc64/, aes/ blake3/ modes/ sha2/), $(zobjdirs)))
define ZKMOD_C_O_MAKE_TARGET
$1%.o: $(src)/$1%.c FORCE
$$(call if_changed_rule,cc_o_c)
$$(call cmd,force_checksrc)
endef
define ZKMOD_S_O_MAKE_TARGET
$1%.o: $(src)/$1%.S FORCE
$$(call if_changed_rule,as_o_S)
$$(call cmd,force_checksrc)
endef
$(foreach target,$(z_cdirs), $(eval $(call ZKMOD_C_O_MAKE_TARGET,$(target))))
$(foreach target,$(z_sdirs), $(eval $(call ZKMOD_S_O_MAKE_TARGET,$(target))))

View file

@ -217,6 +217,7 @@ SRCS+= abd_os.c \
vdev_label_os.c \
zfs_acl.c \
zfs_ctldir.c \
zfs_crrd.c \
zfs_debug.c \
zfs_dir.c \
zfs_file_os.c \

Some files were not shown because too many files have changed in this diff Show more