xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
- python3 python3-dev python3-setuptools python3-cffi python3-packaging
+ python3 python3-dev python3-setuptools python3-cffi python3-packaging \
+ libcurl4-openssl-dev
- name: Autogen.sh
run: |
sh autogen.sh
- name: Tests
run: |
/usr/share/zfs/zfs-tests.sh -vR -s 3G
+ timeout-minutes: 330
- name: Prepare artifacts
if: failure()
run: |
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
- python3 python3-dev python3-setuptools python3-cffi python3-packaging
+ python3 python3-dev python3-setuptools python3-cffi python3-packaging \
+ libcurl4-openssl-dev
- name: Autogen.sh
run: |
sh autogen.sh
- name: Tests
run: |
/usr/share/zfs/zfs-tests.sh -vR -s 3G -r sanity
+ timeout-minutes: 330
- name: Prepare artifacts
if: failure()
run: |
Meta: 1
Name: zfs
Branch: 1.0
-Version: 2.1.2
+Version: 2.1.3
Release: 1
Release-Tags: relext
License: CDDL
Author: OpenZFS
-Linux-Maximum: 5.15
+Linux-Maximum: 5.16
Linux-Minimum: 3.10
* [Documentation](https://openzfs.github.io/openzfs-docs/) - for using and developing this repo
* [ZoL Site](https://zfsonlinux.org) - Linux release info & links
* [Mailing lists](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html)
- * [OpenZFS site](http://open-zfs.org/) - for conference videos and info on other platforms (illumos, OSX, Windows, etc)
+ * [OpenZFS site](https://openzfs.org/) - for conference videos and info on other platforms (illumos, OSX, Windows, etc)
# Installation
}
}
- if (verbose)
- (void) fprintf(stdout, gettext("mount.zfs:\n"
- " dataset: \"%s\"\n mountpoint: \"%s\"\n"
- " mountflags: 0x%lx\n zfsflags: 0x%lx\n"
- " mountopts: \"%s\"\n mtabopts: \"%s\"\n"),
- dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt);
-
if (mntflags & MS_REMOUNT) {
nomtab = 1;
remount = 1;
return (MOUNT_USAGE);
}
- zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt);
+ if (!zfsutil || sloppy ||
+ libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
+ zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt);
+ }
/* treat all snapshots as legacy mount points */
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT)
if (zfs_version == 0) {
fprintf(stderr, gettext("unable to fetch "
"ZFS version for filesystem '%s'\n"), dataset);
+ zfs_close(zhp);
+ libzfs_fini(g_zfs);
return (MOUNT_SYSERR);
}
- zfs_close(zhp);
- libzfs_fini(g_zfs);
-
/*
* Legacy mount points may only be mounted using 'mount', never using
* 'zfs mount'. However, since 'zfs mount' actually invokes 'mount'
"Use 'zfs set mountpoint=%s' or 'mount -t zfs %s %s'.\n"
"See zfs(8) for more information.\n"),
dataset, mntpoint, dataset, mntpoint);
+ zfs_close(zhp);
+ libzfs_fini(g_zfs);
return (MOUNT_USAGE);
}
"Use 'zfs set mountpoint=%s' or 'zfs mount %s'.\n"
"See zfs(8) for more information.\n"),
dataset, "legacy", dataset);
+ zfs_close(zhp);
+ libzfs_fini(g_zfs);
return (MOUNT_USAGE);
}
+ if (verbose)
+ (void) fprintf(stdout, gettext("mount.zfs:\n"
+ " dataset: \"%s\"\n mountpoint: \"%s\"\n"
+ " mountflags: 0x%lx\n zfsflags: 0x%lx\n"
+ " mountopts: \"%s\"\n mtabopts: \"%s\"\n"),
+ dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt);
+
if (!fake) {
- error = mount(dataset, mntpoint, MNTTYPE_ZFS,
- mntflags, mntopts);
+ if (zfsutil && !sloppy &&
+ !libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
+ error = zfs_mount_at(zhp, mntopts, mntflags, mntpoint);
+ if (error) {
+ (void) fprintf(stderr, "zfs_mount_at() failed: "
+ "%s", libzfs_error_description(g_zfs));
+ zfs_close(zhp);
+ libzfs_fini(g_zfs);
+ return (MOUNT_SYSERR);
+ }
+ } else {
+ error = mount(dataset, mntpoint, MNTTYPE_ZFS,
+ mntflags, mntopts);
+ }
}
+ zfs_close(zhp);
+ libzfs_fini(g_zfs);
+
if (error) {
switch (errno) {
case ENOENT:
# DEVPATH=/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/subsystem/devices/0:0:0:0/scsi_generic/sg0
# Get the enclosure ID ("0:0:0:0")
- ENC=$(basename $(readlink -m "/sys/$DEVPATH/../.."))
+ ENC="${DEVPATH%/*}"
+ ENC="${ENC%/*}"
+ ENC="${ENC##*/}"
if [ ! -d "/sys/class/enclosure/$ENC" ] ; then
# Not an enclosure, bail out
return
# The PCI directory is two directories up from the port directory
# /sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0
- PCI_ID_LONG=$(basename $(readlink -m "/sys/$PORT_DIR/../.."))
+ PCI_ID_LONG="$(readlink -m "/sys/$PORT_DIR/../..")"
+ PCI_ID_LONG="${PCI_ID_LONG##*/}"
# Strip down the PCI address from 0000:05:00.0 to 05:00.0
- PCI_ID=$(echo "$PCI_ID_LONG" | sed -r 's/^[0-9]+://g')
+ PCI_ID="${PCI_ID_LONG#[0-9]*:}"
# Name our device according to vdev_id.conf (like "L0" or "U1").
NAME=$(awk "/channel/{if (\$1 == \"channel\" && \$2 == \"$PCI_ID\" && \
link=$(echo "$link" | sed 's/p[0-9][0-9]*$//')
fi
# Check both the fully qualified and the base name of link.
- for l in $link $(basename "$link") ; do
+ for l in $link ${link##*/} ; do
if [ ! -z "$l" ]; then
alias=$(awk -v var="$l" '($1 == "alias") && \
($3 == var) \
#include <sys/fm/fs/zfs.h>
#include <libzfs.h>
#include <string.h>
+#include <libgen.h>
#include "zfs_agents.h"
#include "fmd_api.h"
rv = zed_event_service(&zcp);
/* ENODEV: When kernel module is unloaded (osx) */
- if (rv == ENODEV)
+ if (rv != 0)
break;
}
[ -n "${ZEVENT_VDEV_GUID}" ] && msg="${msg} vdev_guid=${ZEVENT_VDEV_GUID}"
else
[ -n "${ZEVENT_POOL}" ] && msg="${msg} pool='${ZEVENT_POOL}'"
- [ -n "${ZEVENT_VDEV_PATH}" ] && msg="${msg} vdev=$(basename "${ZEVENT_VDEV_PATH}")"
+ [ -n "${ZEVENT_VDEV_PATH}" ] && msg="${msg} vdev=${ZEVENT_VDEV_PATH##*/}"
fi
# log pool state if state is anything other than 'ACTIVE'
# Rate-limit the notification based in part on the filename.
#
-rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};$(basename -- "$0")"
+rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};${0##*/}"
rate_limit_interval="${ZED_NOTIFY_INTERVAL_SECS}"
zed_rate_limit "${rate_limit_tag}" "${rate_limit_interval}" || exit 3
# Send notification in response to a fault induced statechange
#
# ZEVENT_SUBCLASS: 'statechange'
-# ZEVENT_VDEV_STATE_STR: 'DEGRADED', 'FAULTED' or 'REMOVED'
+# ZEVENT_VDEV_STATE_STR: 'DEGRADED', 'FAULTED', 'REMOVED', or 'UNAVAIL'
#
# Exit codes:
# 0: notification sent
if [ "${ZEVENT_VDEV_STATE_STR}" != "FAULTED" ] \
&& [ "${ZEVENT_VDEV_STATE_STR}" != "DEGRADED" ] \
- && [ "${ZEVENT_VDEV_STATE_STR}" != "REMOVED" ]; then
+ && [ "${ZEVENT_VDEV_STATE_STR}" != "REMOVED" ] \
+ && [ "${ZEVENT_VDEV_STATE_STR}" != "UNAVAIL" ]; then
exit 3
fi
zed_log_err()
{
logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "error:" \
- "$(basename -- "$0"):""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"
+ "${0##*/}:""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"
}
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
+ zed_notify_pushover "${subject}" "${pathname}"; rv=$?
+ [ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
+ [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
+
[ "${num_success}" -gt 0 ] && return 0
[ "${num_failure}" -gt 0 ] && return 1
return 2
[ -n "${subject}" ] || return 1
if [ ! -r "${pathname}" ]; then
zed_log_err \
- "$(basename "${ZED_EMAIL_PROG}") cannot read \"${pathname}\""
+ "${ZED_EMAIL_PROG##*/} cannot read \"${pathname}\""
return 1
fi
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS} < "${pathname}" >/dev/null 2>&1
rv=$?
if [ "${rv}" -ne 0 ]; then
- zed_log_err "$(basename "${ZED_EMAIL_PROG}") exit=${rv}"
+ zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}"
return 1
fi
return 0
# Construct the JSON message for posting.
#
- msg_json="$(printf '{"text": "*%s*\n%s"}' "${subject}" "${msg_body}" )"
+ msg_json="$(printf '{"text": "*%s*\\n%s"}' "${subject}" "${msg_body}" )"
# Send the POST request and check for errors.
#
return 0
}
+# zed_notify_pushover (subject, pathname)
+#
+# Send a notification via Pushover <https://pushover.net/>.
+# The access token (ZED_PUSHOVER_TOKEN) identifies this client to the
+# Pushover server. The user token (ZED_PUSHOVER_USER) defines the user or
+# group to which the notification will be sent.
+#
+# Requires curl and sed executables to be installed in the standard PATH.
+#
+# References
+# https://pushover.net/api
+#
+# Arguments
+# subject: notification subject
+# pathname: pathname containing the notification message (OPTIONAL)
+#
+# Globals
+# ZED_PUSHOVER_TOKEN
+# ZED_PUSHOVER_USER
+#
+# Return
+# 0: notification sent
+# 1: notification failed
+# 2: not configured
+#
+zed_notify_pushover()
+{
+ local subject="$1"
+ local pathname="${2:-"/dev/null"}"
+ local msg_body
+ local msg_out
+ local msg_err
+ local url="https://api.pushover.net/1/messages.json"
+
+ [ -n "${ZED_PUSHOVER_TOKEN}" ] && [ -n "${ZED_PUSHOVER_USER}" ] || return 2
+
+ if [ ! -r "${pathname}" ]; then
+ zed_log_err "pushover cannot read \"${pathname}\""
+ return 1
+ fi
+
+ zed_check_cmd "curl" "sed" || return 1
+
+ # Read the message body in.
+ #
+ msg_body="$(cat "${pathname}")"
+
+ if [ -z "${msg_body}" ]
+ then
+ msg_body=$subject
+ subject=""
+ fi
+
+ # Send the POST request and check for errors.
+ #
+ msg_out="$( \
+ curl \
+ --form-string "token=${ZED_PUSHOVER_TOKEN}" \
+ --form-string "user=${ZED_PUSHOVER_USER}" \
+ --form-string "message=${msg_body}" \
+ --form-string "title=${subject}" \
+ "${url}" \
+ 2>/dev/null \
+ )"; rv=$?
+ if [ "${rv}" -ne 0 ]; then
+ zed_log_err "curl exit=${rv}"
+ return 1
+ fi
+ msg_err="$(echo "${msg_out}" \
+ | sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"
+ if [ -n "${msg_err}" ]; then
+ zed_log_err "pushover \"${msg_err}"\"
+ return 1
+ fi
+ return 0
+}
+
+
# zed_rate_limit (tag, [interval])
#
# Check whether an event of a given type [tag] has already occurred within the
# Email address of the zpool administrator for receipt of notifications;
# multiple addresses can be specified if they are delimited by whitespace.
# Email will only be sent if ZED_EMAIL_ADDR is defined.
-# Disabled by default; uncomment to enable.
+# Enabled by default; comment to disable.
#
-#ZED_EMAIL_ADDR="root"
+ZED_EMAIL_ADDR="root"
##
# Name or path of executable responsible for sending notifications via email;
#
#ZED_SLACK_WEBHOOK_URL=""
+##
+# Pushover token.
+# This defines the application from which the notification will be sent.
+# <https://pushover.net/api#registration>
+# Disabled by default; uncomment to enable.
+# ZED_PUSHOVER_USER, below, must also be configured.
+#
+#ZED_PUSHOVER_TOKEN=""
+
+##
+# Pushover user key.
+# This defines which user or group will receive Pushover notifications.
+# <https://pushover.net/api#identifiers>
+# Disabled by default; uncomment to enable.
+# ZED_PUSHOVER_TOKEN, above, must also be configured.
+#ZED_PUSHOVER_USER=""
+
##
# Default directory for zed state files.
#
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
+#include <signal.h>
+
#include "zed_exec.h"
#include "zed_log.h"
#include "zed_strings.h"
dev=$(readlink "$dev")
fi
-dev=$(basename "$dev")
+dev="${dev##*/}"
val=""
if [ -d "/sys/class/block/$dev/slaves" ] ; then
- # ls -C: output in columns, no newlines
- val=$(ls -C "/sys/class/block/$dev/slaves")
-
- # ls -C will print two spaces between files; change to one space.
- val=$(echo "$val" | sed -r 's/[[:blank:]]+/ /g')
+ # ls -C: output in columns, no newlines, two spaces (change to one)
+ # shellcheck disable=SC2012
+ val=$(ls -C "/sys/class/block/$dev/slaves" | tr -s '[:space:]' ' ')
fi
echo "dm-deps=$val"
iostat-1s: Do a single 1-second iostat sample and show values.
iostat-10s: Do a single 10-second iostat sample and show values."
-script=$(basename "$0")
+script="${0##*/}"
if [ "$1" = "-h" ] ; then
echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2-
exit
${brief:+"-y"} \
${interval:+"$interval"} \
${interval:+"1"} \
- "$VDEV_UPATH" | awk NF | tail -n 2)
+ "$VDEV_UPATH" | grep -v '^$' | tail -n 2)
fi
cols=$(echo "$out" | head -n 1)
# Get the values and tab separate them to make them cut-able.
-vals=$(echo "$out" | tail -n 1 | sed -r 's/[[:blank:]]+/\t/g')
+vals=$(echo "$out" | tail -n 1 | tr -s '[:space:]' '\t')
i=0
for col in $cols ; do
vendor: Show the disk vendor.
lsblk: Show the disk size, vendor, and model number."
-script=$(basename "$0")
+script="${0##*/}"
if [ "$1" = "-h" ] ; then
echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2-
fi
if [ -b "$VDEV_UPATH" ]; then
- device=$(basename "$VDEV_UPATH")
- val=$(cat "/sys/block/$device/queue/rotational" 2>/dev/null)
- if [ "$val" = "0" ]; then
- MEDIA="ssd"
- fi
-
- if [ "$val" = "1" ]; then
- MEDIA="hdd"
- fi
+ device="${VDEV_UPATH##*/}"
+ read -r val 2>/dev/null < "/sys/block/$device/queue/rotational"
+ case "$val" in
+ 0) MEDIA="ssd" ;;
+ 1) MEDIA="hdd" ;;
+ esac
vpd_pg83="/sys/block/$device/device/vpd_pg83"
if [ -f "$vpd_pg83" ]; then
locate_led: Show value of the disk enclosure slot locate LED.
ses: Show disk's enc, enc device, slot, and fault/locate LED values."
-script=$(basename "$0")
+script="${0##*/}"
if [ "$1" = "-h" ] ; then
echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2-
exit
continue;
vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
- cb->cb_name_flags);
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID);
ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
newchild[c], cb, depth + 2);
free(vname);
}
vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
- cb->cb_name_flags);
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID);
ret += print_vdev_stats(zhp, vname, oldnv ?
oldchild[c] : NULL, newchild[c], cb, depth + 2);
free(vname);
continue;
vname = zpool_vdev_name(g_zfs, zhp, child[c],
- cb->cb_name_flags);
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID);
print_list_stats(zhp, vname, child[c], cb, depth + 2, B_FALSE);
free(vname);
}
printed = B_TRUE;
}
vname = zpool_vdev_name(g_zfs, zhp, child[c],
- cb->cb_name_flags);
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID);
print_list_stats(zhp, vname, child[c], cb, depth + 2,
B_FALSE);
free(vname);
fletcher_4_init();
while (read_hdr(drr, &zc)) {
+ uint64_t featureflags = 0;
/*
* If this is the first DMU record being processed, check for
BSWAP_64(drrb->drr_fromguid);
}
+ featureflags =
+ DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
+
(void) printf("BEGIN record\n");
(void) printf("\thdrtype = %lld\n",
DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo));
BSWAP_64(drro->drr_maxblkid);
}
+ if (featureflags & DMU_BACKUP_FEATURE_RAW &&
+ drro->drr_bonuslen > drro->drr_raw_bonuslen) {
+ (void) fprintf(stderr,
+ "Warning: Object %llu has bonuslen = "
+ "%u > raw_bonuslen = %u\n\n",
+ (u_longlong_t)drro->drr_object,
+ drro->drr_bonuslen, drro->drr_raw_bonuslen);
+ }
+
payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
if (verbose) {
-e 's|@PYTHON[@]|$(PYTHON)|g' \
-e 's|@PYTHON_SHEBANG[@]|$(PYTHON_SHEBANG)|g' \
-e 's|@DEFAULT_INIT_NFS_SERVER[@]|$(DEFAULT_INIT_NFS_SERVER)|g' \
- -e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g'
+ -e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g' \
+ -e 's|@LIBFETCH_DYNAMIC[@]|$(LIBFETCH_DYNAMIC)|g' \
+ -e 's|@LIBFETCH_SONAME[@]|$(LIBFETCH_SONAME)|g'
SUBSTFILES =
CLEANFILES = $(SUBSTFILES)
dnl #
AM_PATH_PYTHON([], [], [:])
AS_IF([test -z "$PYTHON_VERSION"], [
- PYTHON_VERSION=$(basename $PYTHON | tr -cd 0-9.)
+ PYTHON_VERSION=$(echo ${PYTHON##*/} | tr -cd 0-9.)
])
PYTHON_MINOR=${PYTHON_VERSION#*\.}
dnl # Required by ZFS_AC_CONFIG_ALWAYS_PYZFS.
dnl #
AC_DEFUN([ZFS_AC_PYTHON_MODULE], [
- PYTHON_NAME=$(basename $PYTHON)
+ PYTHON_NAME=${PYTHON##*/}
AC_MSG_CHECKING([for $PYTHON_NAME module: $1])
AS_IF([$PYTHON -c "import $1" 2>/dev/null], [
AC_MSG_RESULT(yes)
--- /dev/null
+dnl #
+dnl # 5.16 API change
+dnl # add_disk grew a must-check return code
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_ADD_DISK], [
+
+ ZFS_LINUX_TEST_SRC([add_disk_ret], [
+ #include <linux/genhd.h>
+ ], [
+ struct gendisk *disk = NULL;
+ int err = add_disk(disk);
+ err = err;
+ ])
+
+])
+AC_DEFUN([ZFS_AC_KERNEL_ADD_DISK], [
+ AC_MSG_CHECKING([whether add_disk() returns int])
+ ZFS_LINUX_TEST_RESULT([add_disk_ret],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_ADD_DISK_RET, 1,
+ [add_disk() returns int])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
dnl # The fallocate callback was moved from the inode_operations
dnl # structure to the file_operations structure.
dnl #
+dnl #
+dnl # Linux 3.15+
+dnl # fallocate learned a new flag, FALLOC_FL_ZERO_RANGE
+dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_FALLOCATE], [
ZFS_LINUX_TEST_SRC([file_fallocate], [
#include <linux/fs.h>
.fallocate = test_fallocate,
};
], [])
+ ZFS_LINUX_TEST_SRC([falloc_fl_zero_range], [
+ #include <linux/falloc.h>
+ ],[
+ int flags __attribute__ ((unused));
+ flags = FALLOC_FL_ZERO_RANGE;
+ ])
])
AC_DEFUN([ZFS_AC_KERNEL_FALLOCATE], [
AC_MSG_CHECKING([whether fops->fallocate() exists])
ZFS_LINUX_TEST_RESULT([file_fallocate], [
AC_MSG_RESULT(yes)
+ AC_MSG_CHECKING([whether FALLOC_FL_ZERO_RANGE exists])
+ ZFS_LINUX_TEST_RESULT([falloc_fl_zero_range], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FALLOC_FL_ZERO_RANGE, 1, [FALLOC_FL_ZERO_RANGE is defined])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
],[
ZFS_LINUX_TEST_ERROR([file_fallocate])
])
-dnl #
+dnl #
dnl # Handle differences in kernel FPU code.
dnl #
dnl # Kernel
dnl # 5.16: XCR code put into asm/fpu/xcr.h
-dnl # HAVE_KERNEL_FPU_XCR_HEADER
+dnl # HAVE_KERNEL_FPU_XCR_HEADER
+dnl #
+dnl # XSTATE_XSAVE and XSTATE_XRESTORE aren't accessible any more
+dnl # HAVE_KERNEL_FPU_XSAVE_INTERNAL
+dnl #
+dnl # 5.11: kernel_fpu_begin() is an inlined function now, so don't check
+dnl # for it inside the kernel symbols.
dnl #
dnl # 5.0: Wrappers have been introduced to save/restore the FPU state.
dnl # This change was made to the 4.19.38 and 4.14.120 LTS kernels.
struct fxregs_state *fxr __attribute__ ((unused)) = &st->fxsave;
struct xregs_state *xr __attribute__ ((unused)) = &st->xsave;
])
+
+ ZFS_LINUX_TEST_SRC([fpu_xsave_internal], [
+ #include <linux/sched.h>
+ #if defined(__x86_64) || defined(__x86_64__) || \
+ defined(__i386) || defined(__i386__)
+ #if !defined(__x86)
+ #define __x86
+ #endif
+ #endif
+
+ #if !defined(__x86)
+ #error Unsupported architecture
+ #endif
+
+ #include <linux/types.h>
+ #ifdef HAVE_KERNEL_FPU_API_HEADER
+ #include <asm/fpu/api.h>
+ #include <asm/fpu/internal.h>
+ #else
+ #include <asm/i387.h>
+ #include <asm/xcr.h>
+ #endif
+
+ ],[
+ struct fpu *fpu = ¤t->thread.fpu;
+ union fpregs_state *st = &fpu->fpstate->regs;
+ struct fregs_state *fr __attribute__ ((unused)) = &st->fsave;
+ struct fxregs_state *fxr __attribute__ ((unused)) = &st->fxsave;
+ struct xregs_state *xr __attribute__ ((unused)) = &st->xsave;
+ ])
])
AC_DEFUN([ZFS_AC_KERNEL_FPU], [
dnl # Legacy kernel
dnl #
AC_MSG_CHECKING([whether kernel fpu is available])
- ZFS_LINUX_TEST_RESULT_SYMBOL([kernel_fpu_license],
- [kernel_fpu_begin], [arch/x86/kernel/fpu/core.c], [
+ ZFS_LINUX_TEST_RESULT([kernel_fpu_license], [
AC_MSG_RESULT(kernel_fpu_*)
AC_DEFINE(HAVE_KERNEL_FPU, 1,
[kernel has kernel_fpu_* functions])
AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1,
[kernel fpu internal])
],[
+ ZFS_LINUX_TEST_RESULT([fpu_xsave_internal], [
+ AC_MSG_RESULT(internal with internal XSAVE)
+ AC_DEFINE(HAVE_KERNEL_FPU_XSAVE_INTERNAL, 1,
+ [kernel fpu and XSAVE internal])
+ ],[
AC_MSG_RESULT(unavailable)
+ ])
])
])
])
AC_DEFUN([ZFS_AC_KERNEL_SRC_KVMALLOC], [
ZFS_LINUX_TEST_SRC([kvmalloc], [
#include <linux/mm.h>
+ #include <linux/slab.h>
],[
void *p __attribute__ ((unused));
--- /dev/null
+AC_DEFUN([ZFS_AC_KERNEL_KTHREAD_COMPLETE_AND_EXIT], [
+ dnl #
+ dnl # 5.17 API,
+ dnl # cead18552660702a4a46f58e65188fe5f36e9dfe ("exit: Rename complete_and_exit to kthread_complete_and_exit")
+ dnl #
+ dnl # Also moves the definition from include/linux/kernel.h to include/linux/kthread.h
+ dnl #
+ AC_MSG_CHECKING([whether kthread_complete_and_exit() is available])
+ ZFS_LINUX_TEST_RESULT([kthread_complete_and_exit], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(SPL_KTHREAD_COMPLETE_AND_EXIT, kthread_complete_and_exit, [kthread_complete_and_exit() available])
+ ], [
+ AC_MSG_RESULT(no)
+ AC_DEFINE(SPL_KTHREAD_COMPLETE_AND_EXIT, complete_and_exit, [using complete_and_exit() instead])
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_KTHREAD_DEQUEUE_SIGNAL_4ARG], [
+ dnl #
+ dnl # 5.17 API: enum pid_type * as new 4th dequeue_signal() argument,
+ dnl # 5768d8906bc23d512b1a736c1e198aa833a6daa4 ("signal: Requeue signals in the appropriate queue")
+ dnl #
+ dnl # int dequeue_signal(struct task_struct *task, sigset_t *mask, kernel_siginfo_t *info);
+ dnl # int dequeue_signal(struct task_struct *task, sigset_t *mask, kernel_siginfo_t *info, enum pid_type *type);
+ dnl #
+ AC_MSG_CHECKING([whether dequeue_signal() takes 4 arguments])
+ ZFS_LINUX_TEST_RESULT([kthread_dequeue_signal], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_DEQUEUE_SIGNAL_4ARG, 1, [dequeue_signal() takes 4 arguments])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_KTHREAD_COMPLETE_AND_EXIT], [
+ ZFS_LINUX_TEST_SRC([kthread_complete_and_exit], [
+ #include <linux/kthread.h>
+ ], [
+ struct completion *completion = NULL;
+ long code = 0;
+
+ kthread_complete_and_exit(completion, code);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_KTHREAD_DEQUEUE_SIGNAL_4ARG], [
+ ZFS_LINUX_TEST_SRC([kthread_dequeue_signal], [
+ #include <linux/sched/signal.h>
+ ], [
+ struct task_struct *task = NULL;
+ sigset_t *mask = NULL;
+ kernel_siginfo_t *info = NULL;
+ enum pid_type *type = NULL;
+ int error __attribute__ ((unused));
+
+ error = dequeue_signal(task, mask, info, type);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_KTHREAD], [
+ ZFS_AC_KERNEL_KTHREAD_COMPLETE_AND_EXIT
+ ZFS_AC_KERNEL_KTHREAD_DEQUEUE_SIGNAL_4ARG
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_SRC_KTHREAD], [
+ ZFS_AC_KERNEL_SRC_KTHREAD_COMPLETE_AND_EXIT
+ ZFS_AC_KERNEL_SRC_KTHREAD_DEQUEUE_SIGNAL_4ARG
+])
dnl #
-dnl # 3.10 API change,
-dnl # PDE is replaced by PDE_DATA
+dnl # 5.17 API: PDE_DATA() renamed to pde_data(),
+dnl # 359745d78351c6f5442435f81549f0207ece28aa ("proc: remove PDE_DATA() completely")
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_PDE_DATA], [
ZFS_LINUX_TEST_SRC([pde_data], [
#include <linux/proc_fs.h>
], [
- PDE_DATA(NULL);
+ pde_data(NULL);
])
])
AC_DEFUN([ZFS_AC_KERNEL_PDE_DATA], [
- AC_MSG_CHECKING([whether PDE_DATA() is available])
- ZFS_LINUX_TEST_RESULT_SYMBOL([pde_data], [PDE_DATA], [], [
+ AC_MSG_CHECKING([whether pde_data() is lowercase])
+ ZFS_LINUX_TEST_RESULT([pde_data], [
AC_MSG_RESULT(yes)
- ],[
- ZFS_LINUX_TEST_ERROR([PDE_DATA])
+ AC_DEFINE(SPL_PDE_DATA, pde_data, [pde_data() is pde_data()])
+ ], [
+ AC_MSG_RESULT(no)
+ AC_DEFINE(SPL_PDE_DATA, PDE_DATA, [pde_data() is PDE_DATA()])
])
])
error = iov_iter_fault_in_readable(&iter, size);
])
+ ZFS_LINUX_TEST_SRC([fault_in_iov_iter_readable], [
+ #include <linux/fs.h>
+ #include <linux/uio.h>
+ ],[
+ struct iov_iter iter = { 0 };
+ size_t size = 512;
+ int error __attribute__ ((unused));
+
+ error = fault_in_iov_iter_readable(&iter, size);
+ ])
+
ZFS_LINUX_TEST_SRC([iov_iter_count], [
#include <linux/fs.h>
#include <linux/uio.h>
AC_DEFINE(HAVE_IOV_ITER_FAULT_IN_READABLE, 1,
[iov_iter_fault_in_readable() is available])
],[
- AC_MSG_RESULT(no)
- enable_vfs_iov_iter="no"
+ AC_MSG_CHECKING([whether fault_in_iov_iter_readable() is available])
+ ZFS_LINUX_TEST_RESULT([fault_in_iov_iter_readable], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FAULT_IN_IOV_ITER_READABLE, 1,
+ [fault_in_iov_iter_readable() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ enable_vfs_iov_iter="no"
+ ])
])
AC_MSG_CHECKING([whether iov_iter_count() is available])
ZFS_AC_KERNEL_SRC_VFS_SET_PAGE_DIRTY_NOBUFFERS
ZFS_AC_KERNEL_SRC_STANDALONE_LINUX_STDARG
ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT
+ ZFS_AC_KERNEL_SRC_ADD_DISK
+ ZFS_AC_KERNEL_SRC_KTHREAD
AC_MSG_CHECKING([for available kernel interfaces])
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
ZFS_AC_KERNEL_VFS_SET_PAGE_DIRTY_NOBUFFERS
ZFS_AC_KERNEL_STANDALONE_LINUX_STDARG
ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT
+ ZFS_AC_KERNEL_ADD_DISK
+ ZFS_AC_KERNEL_KTHREAD
])
dnl #
dnl #
dnl # Detect the kernel to be built against
dnl #
+dnl # Most modern Linux distributions have separate locations for bare
+dnl # source (source) and prebuilt (build) files. Additionally, there are
+dnl # `source` and `build` symlinks in `/lib/modules/$(KERNEL_VERSION)`
+dnl # pointing to them. The directory search order is now:
+dnl #
+dnl # - `configure` command line values if both `--with-linux` and
+dnl # `--with-linux-obj` were defined
+dnl #
+dnl # - If only `--with-linux` was defined, `--with-linux-obj` is assumed
+dnl # to have the same value as `--with-linux`
+dnl #
+dnl # - If neither `--with-linux` nor `--with-linux-obj` were defined
+dnl # autodetection is used:
+dnl #
+dnl # - `/lib/modules/$(uname -r)/{source,build}` respectively, if exist.
+dnl #
+dnl # - If only `/lib/modules/$(uname -r)/build` exists, it is assumed
+dnl # to be both source and build directory.
+dnl #
+dnl # - The first directory in `/lib/modules` with the highest version
+dnl # number according to `sort -V` which contains both `source` and
+dnl # `build` symlinks/directories. If module directory contains only
+dnl # `build` component, it is assumed to be both source and build
+dnl # directory.
+dnl #
+dnl # - Last resort: the first directory matching `/usr/src/kernels/*`
+dnl # and `/usr/src/linux-*` with the highest version number according
+dnl # to `sort -V` is assumed to be both source and build directory.
+dnl #
AC_DEFUN([ZFS_AC_KERNEL], [
AC_ARG_WITH([linux],
AS_HELP_STRING([--with-linux=PATH],
[Path to kernel build objects]),
[kernelbuild="$withval"])
- AC_MSG_CHECKING([kernel source directory])
- AS_IF([test -z "$kernelsrc"], [
- AS_IF([test -e "/lib/modules/$(uname -r)/source"], [
- headersdir="/lib/modules/$(uname -r)/source"
- sourcelink=$(readlink -f "$headersdir")
+ AC_MSG_CHECKING([kernel source and build directories])
+ AS_IF([test -n "$kernelsrc" && test -z "$kernelbuild"], [
+ kernelbuild="$kernelsrc"
+ ], [test -z "$kernelsrc"], [
+ AS_IF([test -e "/lib/modules/$(uname -r)/source" && \
+ test -e "/lib/modules/$(uname -r)/build"], [
+ src="/lib/modules/$(uname -r)/source"
+ build="/lib/modules/$(uname -r)/build"
], [test -e "/lib/modules/$(uname -r)/build"], [
- headersdir="/lib/modules/$(uname -r)/build"
- sourcelink=$(readlink -f "$headersdir")
+ build="/lib/modules/$(uname -r)/build"
+ src="$build"
], [
- sourcelink=$(ls -1d /usr/src/kernels/* \
- /usr/src/linux-* \
- 2>/dev/null | grep -v obj | tail -1)
+ src=
+
+ for d in $(ls -1d /lib/modules/* 2>/dev/null | sort -Vr); do
+ if test -e "$d/source" && test -e "$d/build"; then
+ src="$d/source"
+ build="$d/build"
+ break
+ fi
+
+ if test -e "$d/build"; then
+ src="$d/build"
+ build="$d/build"
+ break
+ fi
+ done
+
+ # the least reliable method
+ if test -z "$src"; then
+ src=$(ls -1d /usr/src/kernels/* /usr/src/linux-* \
+ 2>/dev/null | grep -v obj | sort -Vr | head -1)
+ build="$src"
+ fi
])
- AS_IF([test -n "$sourcelink" && test -e ${sourcelink}], [
- kernelsrc=`readlink -f ${sourcelink}`
+ AS_IF([test -n "$src" && test -e "$src"], [
+ kernelsrc=$(readlink -e "$src")
], [
kernelsrc="[Not found]"
])
+ AS_IF([test -n "$build" && test -e "$build"], [
+ kernelbuild=$(readlink -e "$build")
+ ], [
+ kernelbuild="[Not found]"
+ ])
], [
AS_IF([test "$kernelsrc" = "NONE"], [
kernsrcver=NONE
withlinux=yes
])
+ AC_MSG_RESULT([done])
+ AC_MSG_CHECKING([kernel source directory])
AC_MSG_RESULT([$kernelsrc])
- AS_IF([test ! -d "$kernelsrc"], [
+ AC_MSG_CHECKING([kernel build directory])
+ AC_MSG_RESULT([$kernelbuild])
+ AS_IF([test ! -d "$kernelsrc" || test ! -d "$kernelbuild"], [
AC_MSG_ERROR([
*** Please make sure the kernel devel package for your distribution
*** is installed and then try again. If that fails, you can specify the
- *** location of the kernel source with the '--with-linux=PATH' option.])
+ *** location of the kernel source and build with the '--with-linux=PATH' and
+ *** '--with-linux-obj=PATH' options respectively.])
])
- AC_MSG_CHECKING([kernel build directory])
- AS_IF([test -z "$kernelbuild"], [
- AS_IF([test x$withlinux != xyes -a -e "/lib/modules/$(uname -r)/build"], [
- kernelbuild=`readlink -f /lib/modules/$(uname -r)/build`
- ], [test -d ${kernelsrc}-obj/${target_cpu}/${target_cpu}], [
- kernelbuild=${kernelsrc}-obj/${target_cpu}/${target_cpu}
- ], [test -d ${kernelsrc}-obj/${target_cpu}/default], [
- kernelbuild=${kernelsrc}-obj/${target_cpu}/default
- ], [test -d `dirname ${kernelsrc}`/build-${target_cpu}], [
- kernelbuild=`dirname ${kernelsrc}`/build-${target_cpu}
- ], [
- kernelbuild=${kernelsrc}
- ])
- ])
- AC_MSG_RESULT([$kernelbuild])
-
AC_MSG_CHECKING([kernel source version])
utsrelease1=$kernelbuild/include/linux/version.h
utsrelease2=$kernelbuild/include/linux/utsrelease.h
dnl # Used internally by ZFS_LINUX_TEST_{COMPILE,MODPOST}
dnl #
AC_DEFUN([ZFS_LINUX_COMPILE], [
+ AC_ARG_VAR([KERNEL_CC], [C compiler for
+ building kernel modules])
+ AC_ARG_VAR([KERNEL_LD], [Linker for
+ building kernel modules])
+ AC_ARG_VAR([KERNEL_LLVM], [Binary option to
+ build kernel modules with LLVM/CLANG toolchain])
AC_TRY_COMMAND([
KBUILD_MODPOST_NOFINAL="$5" KBUILD_MODPOST_WARN="$6"
- make modules -k -j$TEST_JOBS -C $LINUX_OBJ $ARCH_UM
+ make modules -k -j$TEST_JOBS ${KERNEL_CC:+CC=$KERNEL_CC} ${KERNEL_LD:+LD=$KERNEL_LD} ${KERNEL_LLVM:+LLVM=$KERNEL_LLVM} -C $LINUX_OBJ $ARCH_UM
M=$PWD/$1 >$1/build.log 2>&1])
AS_IF([AC_TRY_COMMAND([$2])], [$3], [$4])
])
ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_AES
ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_PCLMULQDQ
ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_MOVBE
+ ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVE
+ ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVEOPT
+ ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVES
;;
esac
])
AC_MSG_RESULT([no])
])
])
+
+dnl #
+dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVE
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVE], [
+ AC_MSG_CHECKING([whether host toolchain supports XSAVE])
+
+ AC_LINK_IFELSE([AC_LANG_SOURCE([
+ [
+ void main()
+ {
+ char b[4096] __attribute__ ((aligned (64)));
+ __asm__ __volatile__("xsave %[b]\n" : : [b] "m" (*b) : "memory");
+ }
+ ]])], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_XSAVE], 1, [Define if host toolchain supports XSAVE])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+
+dnl #
+dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVEOPT
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVEOPT], [
+ AC_MSG_CHECKING([whether host toolchain supports XSAVEOPT])
+
+ AC_LINK_IFELSE([AC_LANG_SOURCE([
+ [
+ void main()
+ {
+ char b[4096] __attribute__ ((aligned (64)));
+ __asm__ __volatile__("xsaveopt %[b]\n" : : [b] "m" (*b) : "memory");
+ }
+ ]])], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_XSAVEOPT], 1, [Define if host toolchain supports XSAVEOPT])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+
+dnl #
+dnl # ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVES
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_TOOLCHAIN_CAN_BUILD_XSAVES], [
+ AC_MSG_CHECKING([whether host toolchain supports XSAVES])
+
+ AC_LINK_IFELSE([AC_LANG_SOURCE([
+ [
+ void main()
+ {
+ char b[4096] __attribute__ ((aligned (64)));
+ __asm__ __volatile__("xsaves %[b]\n" : : [b] "m" (*b) : "memory");
+ }
+ ]])], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_XSAVES], 1, [Define if host toolchain supports XSAVES])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
--- /dev/null
+dnl #
+dnl # Check for a libfetch - either fetch(3) or libcurl.
+dnl #
+dnl # There are two configuration dimensions:
+dnl # * fetch(3) vs libcurl
+dnl # * static vs dynamic
+dnl #
+dnl # fetch(3) is only dynamic.
+dnl # We use sover 6, which first appeared in FreeBSD 8.0-RELEASE.
+dnl #
+dnl # libcurl development packages include curl-config(1) – we want:
+dnl # * HTTPS support
+dnl # * version at least 7.16 (October 2006), for sover 4
+dnl # * to decide if it's static or not
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_USER_LIBFETCH], [
+ AC_MSG_CHECKING([for libfetch])
+ LIBFETCH_LIBS=
+ LIBFETCH_IS_FETCH=0
+ LIBFETCH_IS_LIBCURL=0
+ LIBFETCH_DYNAMIC=0
+ LIBFETCH_SONAME=
+ have_libfetch=
+
+ saved_libs="$LIBS"
+ LIBS="$LIBS -lfetch"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #include <sys/param.h>
+ #include <stdio.h>
+ #include <fetch.h>
+ ]], [fetchGetURL("", "");])], [
+ have_libfetch=1
+ LIBFETCH_IS_FETCH=1
+ LIBFETCH_DYNAMIC=1
+ LIBFETCH_SONAME="libfetch.so.6"
+ LIBFETCH_LIBS="-ldl"
+ AC_MSG_RESULT([fetch(3)])
+ ], [])
+ LIBS="$saved_libs"
+
+ if test -z "$have_libfetch"; then
+ if curl-config --protocols 2>/dev/null | grep -q HTTPS &&
+ test "$(printf "%u" "0x$(curl-config --vernum)")" -ge "$(printf "%u" "0x071000")"; then
+ have_libfetch=1
+ LIBFETCH_IS_LIBCURL=1
+ if test "$(curl-config --built-shared)" = "yes"; then
+ LIBFETCH_DYNAMIC=1
+ LIBFETCH_SONAME="libcurl.so.4"
+ LIBFETCH_LIBS="-ldl"
+ AC_MSG_RESULT([libcurl])
+ else
+ LIBFETCH_LIBS="$(curl-config --libs)"
+ AC_MSG_RESULT([libcurl (static)])
+ fi
+
+ CCFLAGS="$CCFLAGS $(curl-config --cflags)"
+ fi
+ fi
+
+ if test -z "$have_libfetch"; then
+ AC_MSG_RESULT([none])
+ fi
+
+ AC_SUBST([LIBFETCH_LIBS])
+ AC_SUBST([LIBFETCH_DYNAMIC])
+ AC_SUBST([LIBFETCH_SONAME])
+ AC_DEFINE_UNQUOTED([LIBFETCH_IS_FETCH], [$LIBFETCH_IS_FETCH], [libfetch is fetch(3)])
+ AC_DEFINE_UNQUOTED([LIBFETCH_IS_LIBCURL], [$LIBFETCH_IS_LIBCURL], [libfetch is libcurl])
+ AC_DEFINE_UNQUOTED([LIBFETCH_DYNAMIC], [$LIBFETCH_DYNAMIC], [whether the chosen libfetch is to be loaded at run-time])
+ AC_DEFINE_UNQUOTED([LIBFETCH_SONAME], ["$LIBFETCH_SONAME"], [soname of chosen libfetch])
+])
ZFS_AC_CONFIG_USER_LIBCRYPTO
ZFS_AC_CONFIG_USER_LIBAIO
ZFS_AC_CONFIG_USER_LIBATOMIC
+ ZFS_AC_CONFIG_USER_LIBFETCH
ZFS_AC_CONFIG_USER_CLOCK_GETTIME
ZFS_AC_CONFIG_USER_PAM
ZFS_AC_CONFIG_USER_RUNSTATEDIR
RPM_DEFINE_KMOD=${RPM_DEFINE_KMOD}' --define "kernels $(LINUX_VERSION)"'
RPM_DEFINE_KMOD=${RPM_DEFINE_KMOD}' --define "ksrc $(LINUX)"'
RPM_DEFINE_KMOD=${RPM_DEFINE_KMOD}' --define "kobj $(LINUX_OBJ)"'
+ RPM_DEFINE_KMOD=${RPM_DEFINE_KMOD}' --define "kernel_cc KERNEL_CC=$(KERNEL_CC)"'
+ RPM_DEFINE_KMOD=${RPM_DEFINE_KMOD}' --define "kernel_ld KERNEL_LD=$(KERNEL_LD)"'
+ RPM_DEFINE_KMOD=${RPM_DEFINE_KMOD}' --define "kernel_llvm KERNEL_LLVM=$(KERNEL_LLVM)"'
])
RPM_DEFINE_DKMS=''
if test ! -f ".nogitrelease" && git rev-parse --git-dir > /dev/null 2>&1; then
_match="${ZFS_META_NAME}-${ZFS_META_VERSION}"
_alias=$(git describe --match=${_match} 2>/dev/null)
- _release=$(echo ${_alias}|cut -f3- -d'-'|sed 's/-/_/g')
+ _release=$(echo ${_alias}|sed "s/${ZFS_META_NAME}//"|cut -f3- -d'-'|tr - _)
if test -n "${_release}"; then
ZFS_META_RELEASE=${_release}
_zfs_ac_meta_type="git describe"
else
_match="${ZFS_META_NAME}-${ZFS_META_VERSION}-${ZFS_META_RELEASE}"
_alias=$(git describe --match=${_match} 2>/dev/null)
- _release=$(echo ${_alias}|cut -f3- -d'-'|sed 's/-/_/g')
+ _release=$(echo ${_alias}|sed 's/${ZFS_META_NAME}//'|cut -f3- -d'-'|tr - _)
if test -n "${_release}"; then
ZFS_META_RELEASE=${_release}
_zfs_ac_meta_type="git describe"
tests/zfs-tests/tests/functional/rootpool/Makefile
tests/zfs-tests/tests/functional/rsend/Makefile
tests/zfs-tests/tests/functional/scrub_mirror/Makefile
+ tests/zfs-tests/tests/functional/simd/Makefile
tests/zfs-tests/tests/functional/slog/Makefile
tests/zfs-tests/tests/functional/snapshot/Makefile
tests/zfs-tests/tests/functional/snapused/Makefile
#!/bin/sh
-ZVER=$(cut -f 1 -d '-' /sys/module/zfs/version)
+read -r ZVER < /sys/module/zfs/version
+ZVER="${ZVER%%-*}"
KVER=$(uname -r)
exec bpftrace \
get_devtype() {
local typ
- typ=$(udevadm info --query=property --name="$1" | grep "^ID_FS_TYPE=" | sed 's|^ID_FS_TYPE=||')
- if [ "$typ" = "" ] ; then
+ typ=$(udevadm info --query=property --name="$1" | sed -n 's|^ID_FS_TYPE=||p')
+ if [ -z "$typ" ] ; then
typ=$(blkid -c /dev/null "$1" -o value -s TYPE)
fi
echo "$typ"
local dev
local mp
local fstype
- local pool
local _
numfields="$(awk '{print NF; exit}' /proc/self/mountinfo)"
if [ "$numfields" = "10" ] ; then
# shellcheck disable=SC2086
while read -r ${fields?} ; do
[ "$fstype" = "zfs" ] || continue
- if [ "$mp" = "$1" ]; then
- pool=$(echo "$dev" | cut -d / -f 1)
- get_pool_devices "$pool"
- fi
+ [ "$mp" = "$1" ] && get_pool_devices "${dev%%/*}"
done < /proc/self/mountinfo
}
majmin=$(get_maj_min "$dev")
if [ -d "/sys/dev/block/$majmin/slaves" ] ; then
for _depdev in "/sys/dev/block/$majmin/slaves"/*; do
- [[ -f $_depdev/dev ]] || continue
- _depdev=/dev/$(basename "$_depdev")
- _depdevname=$(udevadm info --query=property --name="$_depdev" | grep "^DEVNAME=" | sed 's|^DEVNAME=||')
+ [ -f "$_depdev/dev" ] || continue
+ _depdev="/dev/${_depdev##*/}"
+ _depdevname=$(udevadm info --query=property --name="$_depdev" | sed -n 's|^DEVNAME=||p')
_depdevtype=$(get_devtype "$_depdevname")
dinfo "zfsexpandknowledge: underlying block device backing ZFS dataset $mp: ${_depdevname//$'\n'/ }"
array_contains "$_depdevname" "${host_devs[@]}" || host_devs+=("$_depdevname")
# Fallback: Guess the path and include all matches
dracut_install /usr/lib*/gcc/**/libgcc_s.so*
fi
+ # shellcheck disable=SC2050
+ if [ @LIBFETCH_DYNAMIC@ -gt 0 ]; then
+ for d in $libdirs; do
+ [ -e "$d/@LIBFETCH_SONAME@" ] && dracut_install "$d/@LIBFETCH_SONAME@"
+ done
+ fi
dracut_install @mounthelperdir@/mount.zfs
dracut_install @udevdir@/vdev_id
dracut_install awk
- dracut_install basename
dracut_install cut
+ dracut_install tr
dracut_install head
dracut_install @udevdir@/zvol_id
inst_hook cmdline 95 "${moddir}/parse-zfs.sh"
root="${root#FILESYSTEM=}"
root="zfs:${root#ZFS=}"
# switch + with spaces because kernel cmdline does not allow us to quote parameters
- root=$(printf '%s\n' "$root" | sed "s/+/ /g")
+ root=$(echo "$root" | tr '+' ' ')
rootok=1
wait_for_zfs=1
[Service]
Type=oneshot
-ExecStart=/bin/sh -c "systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')"
+ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')"
[Install]
WantedBy=zfs-import.target
_zfs_generator_cb() {
dset="${1}"
mpnt="${2}"
- unit="sysroot$(echo "$mpnt" | sed 's;/;-;g').mount"
+ unit="sysroot$(echo "$mpnt" | tr '/' '-').mount"
{
echo "[Unit]"
[ "$KEYSTATUS" = "unavailable" ] || exit 0
KEYLOCATION="$(zfs get -H -o value keylocation "${ENCRYPTIONROOT}")"
- if ! [ "${KEYLOCATION}" = "prompt" ]; then
- zfs load-key "${ENCRYPTIONROOT}"
- else
- # decrypt them
- TRY_COUNT=5
- while [ $TRY_COUNT -gt 0 ]; do
- systemd-ask-password "Encrypted ZFS password for ${BOOTFS}" --no-tty | zfs load-key "${ENCRYPTIONROOT}" && break
- TRY_COUNT=$((TRY_COUNT - 1))
- done
- fi
+ case "${KEYLOCATION%%://*}" in
+ prompt)
+ for _ in 1 2 3; do
+ systemd-ask-password --no-tty "Encrypted ZFS password for ${BOOTFS}" | zfs load-key "${ENCRYPTIONROOT}" && break
+ done
+ ;;
+ http*)
+ systemctl start network-online.target
+ zfs load-key "${ENCRYPTIONROOT}"
+ ;;
+ file)
+ KEYFILE="${KEYLOCATION#file://}"
+ [ -r "${KEYFILE}" ] || udevadm settle
+ [ -r "${KEYFILE}" ] || {
+ info "Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..."
+ for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
+ sleep 0.5s
+ [ -r "${KEYFILE}" ] && break
+ done
+ }
+ [ -r "${KEYFILE}" ] || warn "Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway."
+ zfs load-key "${ENCRYPTIONROOT}"
+ ;;
+ *)
+ zfs load-key "${ENCRYPTIONROOT}"
+ ;;
+ esac
fi
fi
# ${BOOTFS} should have been set by zfs-env-bootfs.service
Type=oneshot
ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
-ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; @sbindir@/zfs rollback -Rf "${BOOTFS}@${SNAPNAME:-%v}"'
+ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "${BOOTFS}@${SNAPNAME:-%v}"'
RemainAfterExit=yes
# ${BOOTFS} should have been set by zfs-env-bootfs.service
Type=oneshot
ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
-ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; @sbindir@/zfs snapshot "${BOOTFS}@${SNAPNAME:-%v}"'
+ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "${BOOTFS}@${SNAPNAME:-%v}"'
RemainAfterExit=yes
copy_exec "$libgcc"
done
+# shellcheck disable=SC2050
+if [ @LIBFETCH_DYNAMIC@ -gt 0 ]; then
+ find /lib/ -name "@LIBFETCH_SONAME@" | while read -r libfetch; do
+ copy_exec "$libfetch"
+ done
+fi
+
copy_file config "/etc/hostid"
copy_file cache "@sysconfdir@/zfs/zpool.cache"
copy_file config "@initconfdir@/zfs"
find_pools()
{
pools=$("$@" 2> /dev/null | \
- grep -E "pool:|^[a-zA-Z0-9]" | \
- sed 's@.*: @@' | \
+ sed -Ee '/pool:|^[a-zA-Z0-9]/!d' -e 's@.*: @@' | \
tr '\n' ';')
echo "${pools%%;}" # Return without the last ';'.
KEYSTATUS="$(get_fs_value "${ENCRYPTIONROOT}" keystatus)"
# Continue only if the key needs to be loaded
[ "$KEYSTATUS" = "unavailable" ] || return 0
- TRY_COUNT=3
- # If key is stored in a file, do not prompt
+ # Do not prompt if key is stored noninteractively,
if ! [ "${KEYLOCATION}" = "prompt" ]; then
$ZFS load-key "${ENCRYPTIONROOT}"
# Prompt with plymouth, if active
- elif [ -e /bin/plymouth ] && /bin/plymouth --ping 2>/dev/null; then
+ elif /bin/plymouth --ping 2>/dev/null; then
echo "plymouth" > /run/zfs_console_askpwd_cmd
- while [ $TRY_COUNT -gt 0 ]; do
+ for _ in 1 2 3; do
plymouth ask-for-password --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}" | \
$ZFS load-key "${ENCRYPTIONROOT}" && break
- TRY_COUNT=$((TRY_COUNT - 1))
done
# Prompt with systemd, if active
elif [ -e /run/systemd/system ]; then
echo "systemd-ask-password" > /run/zfs_console_askpwd_cmd
- while [ $TRY_COUNT -gt 0 ]; do
- systemd-ask-password "Encrypted ZFS password for ${ENCRYPTIONROOT}" --no-tty | \
+ for _ in 1 2 3; do
+ systemd-ask-password --no-tty "Encrypted ZFS password for ${ENCRYPTIONROOT}" | \
$ZFS load-key "${ENCRYPTIONROOT}" && break
- TRY_COUNT=$((TRY_COUNT - 1))
done
# Prompt with ZFS tty, otherwise
else
# Temporarily setting "printk" to "7" allows the prompt to appear even when the "quiet" kernel option has been used
echo "load-key" > /run/zfs_console_askpwd_cmd
- storeprintk="$(awk '{print $1}' /proc/sys/kernel/printk)"
+ read -r storeprintk _ < /proc/sys/kernel/printk
echo 7 > /proc/sys/kernel/printk
$ZFS load-key "${ENCRYPTIONROOT}"
echo "$storeprintk" > /proc/sys/kernel/printk
-# ZoL userland configuration.
+# OpenZFS userland configuration.
# NOTE: This file is intended for sysv init and initramfs.
# Changing some of these settings may not make any difference on
# To enable a boolean setting, set it to yes, on, true, or 1.
# Anything else will be interpreted as unset.
+# Run `zfs load-key` during system start?
+ZFS_LOAD_KEY='yes'
+
+# Run `zfs unload-key` during system stop?
+ZFS_UNLOAD_KEY='no'
+
# Run `zfs mount -a` during system start?
ZFS_MOUNT='yes'
zfs-import
+zfs-load-key
zfs-mount
zfs-share
zfs-zed
EXTRA_DIST += README.md
-init_SCRIPTS = zfs-import zfs-mount zfs-share zfs-zed
+init_SCRIPTS = zfs-import zfs-load-key zfs-mount zfs-share zfs-zed
SUBSTFILES += $(init_SCRIPTS)
To setup the init script links in /etc/rc?.d manually on a Debian GNU/Linux
(or derived) system, run the following commands (the order is important!):
- update-rc.d zfs-import start 07 S . stop 07 0 1 6 .
- update-rc.d zfs-mount start 02 2 3 4 5 . stop 06 0 1 6 .
- update-rc.d zfs-zed start 07 2 3 4 5 . stop 08 0 1 6 .
- update-rc.d zfs-share start 27 2 3 4 5 . stop 05 0 1 6 .
+ update-rc.d zfs-import start 07 S . stop 07 0 1 6 .
+ update-rc.d zfs-load-key start 02 2 3 4 5 . stop 06 0 1 6 .
+ update-rc.d zfs-mount start 02 2 3 4 5 . stop 06 0 1 6 .
+ update-rc.d zfs-zed start 07 2 3 4 5 . stop 08 0 1 6 .
+ update-rc.d zfs-share start 27 2 3 4 5 . stop 05 0 1 6 .
To do the same on RedHat, Fedora and/or CentOS:
chkconfig zfs-import
+ chkconfig zfs-load-key
chkconfig zfs-mount
chkconfig zfs-zed
chkconfig zfs-share
On Gentoo:
rc-update add zfs-import boot
+ rc-update add zfs-load-key boot
rc-update add zfs-mount boot
rc-update add zfs-zed default
rc-update add zfs-share default
local pools
pools=$("$@" 2> /dev/null | \
- grep -E "pool:|^[a-zA-Z0-9]" | \
- sed 's@.*: @@' | \
+ sed -Ee '/pool:|^[a-zA-Z0-9]/!d' -e 's@.*: @@' | \
sort | \
tr '\n' ';')
--- /dev/null
+#!@DEFAULT_INIT_SHELL@
+#
+# zfs-load-key This script will load/unload the zfs filesystems keys.
+#
+# chkconfig: 2345 06 99
+# description: This script will load or unload the zfs filesystems keys during
+# system boot/shutdown. Only filesystems with key path set
+# in keylocation property. See the zfs(8) man page for details.
+# probe: true
+#
+### BEGIN INIT INFO
+# Provides: zfs-load-key
+# Required-Start: $local_fs zfs-import
+# Required-Stop: $local_fs zfs-import
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# X-Start-Before: zfs-mount
+# X-Stop-After: zfs-zed
+# Short-Description: Load ZFS keys for filesystems and volumes
+# Description: Run the `zfs load-key` or `zfs unload-key` commands.
+### END INIT INFO
+#
+# Released under the 2-clause BSD license.
+#
+# This script is based on debian/zfsutils.zfs.init from the
+# Debian GNU/kFreeBSD zfsutils 8.1-3 package, written by Aurelien Jarno.
+
+# Source the common init script
+. @sysconfdir@/zfs/zfs-functions
+
+# ----------------------------------------------------
+
+do_depend()
+{
+ # bootmisc will log to /var which may be a different zfs than root.
+ before bootmisc logger zfs-mount
+
+ after zfs-import sysfs
+ keyword -lxc -openvz -prefix -vserver
+}
+
+# Load keys for all datasets/filesystems
+do_load_keys()
+{
+ zfs_log_begin_msg "Load ZFS filesystem(s) keys"
+
+ "$ZFS" list -Ho name,encryptionroot,keystatus,keylocation |
+ while IFS=" " read -r name encryptionroot keystatus keylocation; do
+ if [ "$encryptionroot" != "-" ] &&
+ [ "$name" = "$encryptionroot" ] &&
+ [ "$keystatus" = "unavailable" ] &&
+ [ "$keylocation" != "prompt" ] &&
+ [ "$keylocation" != "none" ]
+ then
+ zfs_action "Load key for $encryptionroot" \
+ "$ZFS" load-key "$encryptionroot"
+ fi
+ done
+
+ zfs_log_end_msg 0
+
+ return 0
+}
+
+# Unload keys for all datasets/filesystems
+do_unload_keys()
+{
+ zfs_log_begin_msg "Unload ZFS filesystem(s) key"
+
+ "$ZFS" list -Ho name,encryptionroot,keystatus | sed '1!G;h;$!d' |
+ while IFS=" " read -r name encryptionroot keystatus; do
+ if [ "$encryptionroot" != "-" ] &&
+ [ "$name" = "$encryptionroot" ] &&
+ [ "$keystatus" = "available" ]
+ then
+ zfs_action "Unload key for $encryptionroot" \
+ "$ZFS" unload-key "$encryptionroot"
+ fi
+ done
+
+ zfs_log_end_msg 0
+
+ return 0
+}
+
+do_start()
+{
+ check_boolean "$ZFS_LOAD_KEY" || exit 0
+
+ check_module_loaded "zfs" || exit 0
+
+ do_load_keys
+}
+
+do_stop()
+{
+ check_boolean "$ZFS_UNLOAD_KEY" || exit 0
+
+ check_module_loaded "zfs" || exit 0
+
+ do_unload_keys
+}
+
+# ----------------------------------------------------
+
+if [ ! -e /sbin/openrc-run ]
+then
+ case "$1" in
+ start)
+ do_start
+ ;;
+ stop)
+ do_stop
+ ;;
+ force-reload|condrestart|reload|restart|status)
+ # no-op
+ ;;
+ *)
+ [ -n "$1" ] && echo "Error: Unknown command $1."
+ echo "Usage: $0 {start|stop}"
+ exit 3
+ ;;
+ esac
+
+ exit $?
+else
+ # Create wrapper functions since Gentoo don't use the case part.
+ depend() { do_depend; }
+ start() { do_start; }
+ stop() { do_stop; }
+fi
*.service
*.target
*.preset
+*.timer
zfs-volume-wait.service \
zfs-import.target \
zfs-volumes.target \
- zfs.target
+ zfs.target \
+ zfs-scrub-monthly@.timer \
+ zfs-scrub-weekly@.timer \
+ zfs-scrub@.service
SUBSTFILES += $(systemdpreset_DATA) $(systemdunit_DATA)
--- /dev/null
+[Unit]
+Description=Monthly zpool scrub timer for %i
+Documentation=man:zpool-scrub(8)
+
+[Timer]
+OnCalendar=monthly
+Persistent=true
+RandomizedDelaySec=1h
+Unit=zfs-scrub@%i.service
+
+[Install]
+WantedBy=timers.target
--- /dev/null
+[Unit]
+Description=Weekly zpool scrub timer for %i
+Documentation=man:zpool-scrub(8)
+
+[Timer]
+OnCalendar=weekly
+Persistent=true
+RandomizedDelaySec=1h
+Unit=zfs-scrub@%i.service
+
+[Install]
+WantedBy=timers.target
--- /dev/null
+[Unit]
+Description=zpool scrub on %i
+Documentation=man:zpool-scrub(8)
+Requires=zfs.target
+After=zfs.target
+ConditionACPower=true
+ConditionPathIsDirectory=/sys/module/zfs
+
+[Service]
+ExecStart=/bin/sh -c '\
+if @sbindir@/zpool status %i | grep "scrub in progress"; then\
+exec @sbindir@/zpool wait -t scrub %i;\
+else exec @sbindir@/zpool scrub -w %i; fi'
+ExecStop=-/bin/sh -c '@sbindir@/zpool scrub -p %i 2>/dev/null || true'
-# This is a script with common functions etc used by zfs-import, zfs-mount,
-# zfs-share and zfs-zed.
+# This is a script with common functions etc used by zfs-import, zfs-load-key,
+# zfs-mount, zfs-share and zfs-zed.
#
# It is _NOT_ to be called independently
#
ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache"
# Sensible defaults
+ZFS_LOAD_KEY='yes'
+ZFS_UNLOAD_KEY='no'
ZFS_MOUNT='yes'
ZFS_UNMOUNT='yes'
ZFS_SHARE='yes'
# ----------------------------------------------------
-export ZFS ZED ZPOOL ZPOOL_CACHE ZFS_MOUNT ZFS_UNMOUNT ZFS_SHARE ZFS_UNSHARE
+export ZFS ZED ZPOOL ZPOOL_CACHE ZFS_LOAD_KEY ZFS_UNLOAD_KEY ZFS_MOUNT ZFS_UNMOUNT \
+ ZFS_SHARE ZFS_UNSHARE
zfs_action()
{
# Unset all MTAB_* variables
# shellcheck disable=SC2046
- unset $(env | grep ^MTAB_ | sed 's,=.*,,')
+ unset $(env | sed -e '/^MTAB_/!d' -e 's,=.*,,')
while read -r fs mntpnt fstype opts rest; do
if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then
fs=$(/bin/echo "$fs" | sed 's,\\0,\\00,')
# Remove 'unwanted' characters.
- mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,,g' \
- -e 's,-,,g' -e 's,\.,,g' -e 's, ,,g')
- fs=$(printf '%b\n' "$fs")
+ mntpnt=$(printf '%b' "$mntpnt" | tr -d '/. -')
+ fs=$(printf '%b' "$fs")
# Set the variable.
eval export "MTAB_$mntpnt=\"$fs\""
{
local mntpnt="$1"
# Remove 'unwanted' characters.
- mntpnt=$(printf '%b\n' "$mntpnt" | sed -e 's,/,,g' \
- -e 's,-,,g' -e 's,\.,,g' -e 's, ,,g')
+ mntpnt=$(printf '%b' "$mntpnt" | tr -d '/. -')
local var
var="$(eval echo "MTAB_$mntpnt")"
# Unset all FSTAB_* variables
# shellcheck disable=SC2046
- unset $(env | grep ^FSTAB_ | sed 's,=.*,,')
+ unset $(env | sed -e '/^FSTAB_/!d' -e 's,=.*,,')
i=0
while read -r fs mntpnt fstype opts; do
if echo "$fs $mntpnt $fstype $opts" | grep -qE "$match"; then
eval export "FSTAB_dev_$i=$fs"
- fs=$(printf '%b\n' "$fs" | sed 's,/,_,g')
+ fs=$(printf '%b' "$fs" | tr '/' '_')
eval export "FSTAB_$i=$mntpnt"
i=$((i + 1))
boolean_t libzfs_prop_debug;
regex_t libzfs_urire;
uint64_t libzfs_max_nvlist;
+ void *libfetch;
+ char *libfetch_load_error;
};
struct zfs_handle {
/* TODO: This field needs conversion! */
#define va_nblocks va_bytes
#define va_blksize va_blocksize
-#define va_seq va_gen
#define MAXOFFSET_T OFF_MAX
#define EXCL 0
* When the kernel_fpu_* symbols are unavailable then provide our own
* versions which allow the FPU to be safely used.
*/
+#if defined(HAVE_KERNEL_FPU_INTERNAL) || defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL)
+
+#if defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL)
+/*
+ * Some sanity checks.
+ * HAVE_KERNEL_FPU_INTERNAL and HAVE_KERNEL_FPU_XSAVE_INTERNAL are exclusive.
+ */
#if defined(HAVE_KERNEL_FPU_INTERNAL)
+#error "HAVE_KERNEL_FPU_INTERNAL and HAVE_KERNEL_FPU_XSAVE_INTERNAL defined"
+#endif
+/*
+ * For kernels >= 5.16 we have to use inline assembly with the XSAVE{,OPT,S}
+ * instructions, so we need the toolchain to support at least XSAVE.
+ */
+#if !defined(HAVE_XSAVE)
+#error "Toolchain needs to support the XSAVE assembler instruction"
+#endif
+#endif
#include <linux/mm.h>
+#include <linux/slab.h>
extern union fpregs_state **zfs_kfpu_fpregs;
}
#define kfpu_allowed() 1
+#if defined(HAVE_KERNEL_FPU_INTERNAL)
#define ex_handler_fprestore ex_handler_default
+#endif
/*
* FPU save and restore instructions.
#define kfpu_fxsr_clean(rval) __asm("fnclex; emms; fildl %P[addr]" \
: : [addr] "m" (rval));
+#if defined(HAVE_KERNEL_FPU_INTERNAL)
static inline void
kfpu_save_xsave(struct xregs_state *addr, uint64_t mask)
{
XSTATE_XSAVE(addr, low, hi, err);
WARN_ON_ONCE(err);
}
+#endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */
+
+#if defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL)
+#define kfpu_do_xsave(instruction, addr, mask) \
+{ \
+ uint32_t low, hi; \
+ \
+ low = mask; \
+ hi = (uint64_t)(mask) >> 32; \
+ __asm(instruction " %[dst]\n\t" \
+ : \
+ : [dst] "m" (*(addr)), "a" (low), "d" (hi) \
+ : "memory"); \
+}
+#endif /* defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL) */
static inline void
kfpu_save_fxsr(struct fxregs_state *addr)
kfpu_fnsave(addr);
}
+#if defined(HAVE_KERNEL_FPU_INTERNAL)
static inline void
kfpu_begin(void)
{
* FPU state to be correctly preserved and restored.
*/
union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()];
-
if (static_cpu_has(X86_FEATURE_XSAVE)) {
kfpu_save_xsave(&state->xsave, ~0);
} else if (static_cpu_has(X86_FEATURE_FXSR)) {
kfpu_save_fsave(&state->fsave);
}
}
+#endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */
+
+#if defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL)
+static inline void
+kfpu_begin(void)
+{
+ /*
+ * Preemption and interrupts must be disabled for the critical
+ * region where the FPU state is being modified.
+ */
+ preempt_disable();
+ local_irq_disable();
+
+ /*
+ * The current FPU registers need to be preserved by kfpu_begin()
+ * and restored by kfpu_end(). They are stored in a dedicated
+ * per-cpu variable, not in the task struct, this allows any user
+ * FPU state to be correctly preserved and restored.
+ */
+ union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()];
+#if defined(HAVE_XSAVES)
+ if (static_cpu_has(X86_FEATURE_XSAVES)) {
+ kfpu_do_xsave("xsaves", &state->xsave, ~0);
+ return;
+ }
+#endif
+#if defined(HAVE_XSAVEOPT)
+ if (static_cpu_has(X86_FEATURE_XSAVEOPT)) {
+ kfpu_do_xsave("xsaveopt", &state->xsave, ~0);
+ return;
+ }
+#endif
+ if (static_cpu_has(X86_FEATURE_XSAVE)) {
+ kfpu_do_xsave("xsave", &state->xsave, ~0);
+ } else if (static_cpu_has(X86_FEATURE_FXSR)) {
+ kfpu_save_fxsr(&state->fxsave);
+ } else {
+ kfpu_save_fsave(&state->fsave);
+ }
+}
+#endif /* defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL) */
+#if defined(HAVE_KERNEL_FPU_INTERNAL)
static inline void
kfpu_restore_xsave(struct xregs_state *addr, uint64_t mask)
{
hi = mask >> 32;
XSTATE_XRESTORE(addr, low, hi);
}
+#endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */
+
+#if defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL)
+#define kfpu_do_xrstor(instruction, addr, mask) \
+{ \
+ uint32_t low, hi; \
+ \
+ low = mask; \
+ hi = (uint64_t)(mask) >> 32; \
+ __asm(instruction " %[src]" \
+ : \
+ : [src] "m" (*(addr)), "a" (low), "d" (hi) \
+ : "memory"); \
+}
+#endif /* defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL) */
static inline void
kfpu_restore_fxsr(struct fxregs_state *addr)
kfpu_frstor(addr);
}
+#if defined(HAVE_KERNEL_FPU_INTERNAL)
static inline void
kfpu_end(void)
{
local_irq_enable();
preempt_enable();
}
+#endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */
+
+#if defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL)
+static inline void
+kfpu_end(void)
+{
+ union fpregs_state *state = zfs_kfpu_fpregs[smp_processor_id()];
+#if defined(HAVE_XSAVES)
+ if (static_cpu_has(X86_FEATURE_XSAVES)) {
+ kfpu_do_xrstor("xrstors", &state->xsave, ~0);
+ goto out;
+ }
+#endif
+ if (static_cpu_has(X86_FEATURE_XSAVE)) {
+ kfpu_do_xrstor("xrstor", &state->xsave, ~0);
+ } else if (static_cpu_has(X86_FEATURE_FXSR)) {
+ kfpu_save_fxsr(&state->fxsave);
+ } else {
+ kfpu_save_fsave(&state->fsave);
+ }
+out:
+ local_irq_enable();
+ preempt_enable();
+
+}
+#endif /* defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL) */
#else
#define kfpu_init() 0
#define kfpu_fini() ((void) 0)
-#endif /* defined(HAVE_KERNEL_FPU_INTERNAL) */
+#endif /* defined(HAVE_KERNEL_FPU_INTERNAL || HAVE_KERNEL_FPU_XSAVE_INTERNAL) */
#endif /* defined(KERNEL_EXPORTS_X86_FPU) */
/*
#include <asm/uaccess.h>
#include <sys/types.h>
+#if defined(HAVE_VFS_IOV_ITER) && defined(HAVE_FAULT_IN_IOV_ITER_READABLE)
+#define iov_iter_fault_in_readable(a, b) fault_in_iov_iter_readable(a, b)
+#endif
+
typedef struct iovec iovec_t;
typedef enum zfs_uio_rw {
uint64_t dsl_pool_adjustedsize(dsl_pool_t *dp, zfs_space_check_t slop_policy);
uint64_t dsl_pool_unreserved_space(dsl_pool_t *dp,
zfs_space_check_t slop_policy);
+uint64_t dsl_pool_deferred_space(dsl_pool_t *dp);
void dsl_pool_dirty_space(dsl_pool_t *dp, int64_t space, dmu_tx_t *tx);
void dsl_pool_undirty_space(dsl_pool_t *dp, int64_t space, uint64_t txg);
void dsl_free(dsl_pool_t *dp, uint64_t txg, const blkptr_t *bpp);
#define FM_EREPORT_PAYLOAD_ZFS_BAD_CLEARED_BITS "bad_cleared_bits"
#define FM_EREPORT_PAYLOAD_ZFS_BAD_SET_HISTOGRAM "bad_set_histogram"
#define FM_EREPORT_PAYLOAD_ZFS_BAD_CLEARED_HISTOGRAM "bad_cleared_histogram"
+#define FM_EREPORT_PAYLOAD_ZFS_SNAPSHOT_NAME "snapshot_name"
+#define FM_EREPORT_PAYLOAD_ZFS_DEVICE_NAME "device_name"
+#define FM_EREPORT_PAYLOAD_ZFS_RAW_DEVICE_NAME "raw_name"
+#define FM_EREPORT_PAYLOAD_ZFS_VOLUME "volume"
#define FM_EREPORT_FAILMODE_WAIT "wait"
#define FM_EREPORT_FAILMODE_CONTINUE "continue"
#define FM_RESOURCE_AUTOREPLACE "autoreplace"
#define FM_RESOURCE_STATECHANGE "statechange"
+#define FM_RESOURCE_ZFS_SNAPSHOT_MOUNT "snapshot_mount"
+#define FM_RESOURCE_ZFS_SNAPSHOT_UNMOUNT "snapshot_unmount"
+#define FM_RESOURCE_ZVOL_CREATE_SYMLINK "zvol_create"
+#define FM_RESOURCE_ZVOL_REMOVE_SYMLINK "zvol_remove"
+
#ifdef __cplusplus
}
#endif
/* asynchronous event notification */
extern void spa_event_notify(spa_t *spa, vdev_t *vdev, nvlist_t *hist_nvl,
const char *name);
+extern void zfs_ereport_zvol_post(const char *subclass, const char *name,
+ const char *device_name, const char *raw_name);
/* waiting for pool activities to complete */
extern int spa_wait(const char *pool, zpool_wait_activity_t activity,
extern boolean_t vdev_draid_missing(vdev_t *, uint64_t, uint64_t, uint64_t);
extern uint64_t vdev_draid_asize_to_psize(vdev_t *, uint64_t);
extern void vdev_draid_map_alloc_empty(zio_t *, struct raidz_row *);
+extern int vdev_draid_map_verify_empty(zio_t *, struct raidz_row *);
extern nvlist_t *vdev_draid_read_config_spare(vdev_t *);
/* Functions for dRAID distributed spares. */
#endif
struct zio;
+struct raidz_col;
struct raidz_row;
struct raidz_map;
#if !defined(_KERNEL)
void vdev_raidz_reconstruct(struct raidz_map *, const int *, int);
void vdev_raidz_child_done(zio_t *);
void vdev_raidz_io_done(zio_t *);
+void vdev_raidz_checksum_error(zio_t *, struct raidz_col *, abd_t *);
extern const zio_vsd_ops_t vdev_raidz_vsd_ops;
struct zio_bad_cksum *info);
void zio_vsd_default_cksum_report(zio_t *zio, zio_cksum_report_t *zcr);
+extern void zfs_ereport_snapshot_post(const char *subclass, spa_t *spa,
+ const char *name);
/* Called from spa_sync(), but primarily an injection handler */
extern void spa_handle_ignored_writes(spa_t *spa);
struct pidfh *pfh;
pid_t mountdpid;
+start:
pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid);
if (pfh != NULL) {
- /* Mountd is not running. */
+ /* mountd(8) is not running. */
pidfile_remove(pfh);
return (SA_OK);
}
/* Cannot open pidfile for some reason. */
return (SA_SYSTEM_ERR);
}
+ if (mountdpid == -1) {
+ /* mountd(8) exists, but didn't write the PID yet */
+ usleep(500);
+ goto start;
+ }
/* We have mountd(8) PID in mountdpid variable. */
kill(mountdpid, SIGHUP);
return (SA_OK);
strlcat(mntopts, opt, size);
}
+static __thread char gfstypename[MFSNAMELEN];
+static __thread char gmntfromname[MNAMELEN];
+static __thread char gmntonname[MNAMELEN];
+static __thread char gmntopts[MNTMAXSTR];
+
void
statfs2mnttab(struct statfs *sfs, struct mnttab *mp)
{
- static char mntopts[MNTMAXSTR];
long flags;
- mntopts[0] = '\0';
+ strlcpy(gfstypename, sfs->f_fstypename, sizeof (gfstypename));
+ mp->mnt_fstype = gfstypename;
+
+ strlcpy(gmntfromname, sfs->f_mntfromname, sizeof (gmntfromname));
+ mp->mnt_special = gmntfromname;
+
+ strlcpy(gmntonname, sfs->f_mntonname, sizeof (gmntonname));
+ mp->mnt_mountp = gmntonname;
flags = sfs->f_flags;
-#define OPTADD(opt) optadd(mntopts, sizeof (mntopts), (opt))
+ gmntopts[0] = '\0';
+#define OPTADD(opt) optadd(gmntopts, sizeof (gmntopts), (opt))
if (flags & MNT_RDONLY)
OPTADD(MNTOPT_RO);
else
else
OPTADD(MNTOPT_EXEC);
#undef OPTADD
- mp->mnt_special = strdup(sfs->f_mntfromname);
- mp->mnt_mountp = strdup(sfs->f_mntonname);
- mp->mnt_fstype = strdup(sfs->f_fstypename);
- mp->mnt_mntopts = strdup(mntopts);
+ mp->mnt_mntopts = gmntopts;
}
static struct statfs *gsfs = NULL;
int
getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
{
- // struct statfs *sfs;
int i, error;
error = statfs_init();
int
getmntent(FILE *fp, struct mnttab *mp)
{
- // struct statfs *sfs;
int error, nfs;
nfs = (int)lseek(fileno(fp), 0, SEEK_CUR);
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
$(abs_top_builddir)/lib/libuutil/libuutil.la
-libzfs_la_LIBADD += -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LTLIBINTL)
+libzfs_la_LIBADD += -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LIBFETCH_LIBS) $(LTLIBINTL)
libzfs_la_LDFLAGS = -pthread
<parameter type-id='e1c52942'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='unlink' visibility='default' binding='global' size-in-bits='64'>
- <parameter type-id='80f4b756'/>
- <return type-id='95e97e5e'/>
- </function-decl>
</abi-instr>
<abi-instr address-size='64' path='os/linux/smb.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='2040' id='11641789'>
<typedef-decl name='zpool_handle_t' type-id='67002a8a' id='b1efc708'/>
<typedef-decl name='libzfs_handle_t' type-id='c8a9d9d8' id='95942d0c'/>
<typedef-decl name='zfs_iter_f' type-id='5571cde4' id='d8e49ab9'/>
- <class-decl name='libzfs_handle' size-in-bits='20224' is-struct='yes' visibility='default' id='c8a9d9d8'>
+ <class-decl name='libzfs_handle' size-in-bits='20352' is-struct='yes' visibility='default' id='c8a9d9d8'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='libzfs_error' type-id='95e97e5e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='20160'>
<var-decl name='libzfs_max_nvlist' type-id='9c313c2d' visibility='default'/>
</data-member>
+ <data-member access='public' layout-offset-in-bits='20224'>
+ <var-decl name='libfetch' type-id='eaa32e2f' visibility='default'/>
+ </data-member>
+ <data-member access='public' layout-offset-in-bits='20288'>
+ <var-decl name='libfetch_load_error' type-id='26a90f95' visibility='default'/>
+ </data-member>
</class-decl>
<class-decl name='zfs_handle' size-in-bits='4928' is-struct='yes' visibility='default' id='f6ee4445'>
<data-member access='public' layout-offset-in-bits='0'>
<function-decl name='__ctype_b_loc' visibility='default' binding='global' size-in-bits='64'>
<return type-id='c59e1ef0'/>
</function-decl>
+ <function-decl name='dlopen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <parameter type-id='95e97e5e'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='dlsym' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='1b7446cd'/>
+ <parameter type-id='9d26089a'/>
+ <return type-id='eaa32e2f'/>
+ </function-decl>
+ <function-decl name='dlerror' visibility='default' binding='global' size-in-bits='64'>
+ <return type-id='26a90f95'/>
+ </function-decl>
<function-decl name='PKCS5_PBKDF2_HMAC_SHA1' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='822cd80b'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='fdopen' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='95e97e5e'/>
+ <parameter type-id='80f4b756'/>
+ <return type-id='822cd80b'/>
+ </function-decl>
<function-decl name='printf' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter is-variadic='yes'/>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='asprintf' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='8c85230f'/>
+ <parameter type-id='9d26089a'/>
+ <parameter is-variadic='yes'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='fputc' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='822cd80b'/>
<parameter type-id='e75a27e9'/>
<return type-id='b59d7dce'/>
</function-decl>
+ <function-decl name='rewind' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='822cd80b'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
<function-decl name='ferror' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='822cd80b'/>
<return type-id='95e97e5e'/>
<parameter type-id='b59d7dce'/>
<return type-id='eaa32e2f'/>
</function-decl>
+ <function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='26a90f95'/>
+ </function-decl>
<function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<return type-id='26a90f95'/>
<parameter type-id='95e97e5e'/>
<return type-id='95e97e5e'/>
</function-decl>
+ <function-decl name='unlink' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='80f4b756'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-type size-in-bits='64' id='ee076206'>
<return type-id='48b5725f'/>
</function-type>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='asprintf' visibility='default' binding='global' size-in-bits='64'>
- <parameter type-id='8c85230f'/>
- <parameter type-id='9d26089a'/>
- <parameter is-variadic='yes'/>
- <return type-id='95e97e5e'/>
- </function-decl>
<function-decl name='strtol' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='8c85230f'/>
<parameter type-id='b59d7dce'/>
<return type-id='26a90f95'/>
</function-decl>
- <function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
- <parameter type-id='80f4b756'/>
- <return type-id='26a90f95'/>
- </function-decl>
<function-decl name='strrchr' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='4051f5e7'/>
<return type-id='95e97e5e'/>
</function-decl>
- <function-decl name='fdopen' visibility='default' binding='global' size-in-bits='64'>
- <parameter type-id='95e97e5e'/>
- <parameter type-id='80f4b756'/>
- <return type-id='822cd80b'/>
- </function-decl>
<function-decl name='pipe2' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='7292109c'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
+ <function-decl name='avl_insert' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='a3681dea'/>
+ <parameter type-id='eaa32e2f'/>
+ <parameter type-id='fba6cb51'/>
+ <return type-id='48b5725f'/>
+ </function-decl>
<function-decl name='nvlist_lookup_boolean' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='5ce45b60'/>
<parameter type-id='80f4b756'/>
<function-decl name='__ctype_toupper_loc' visibility='default' binding='global' size-in-bits='64'>
<return type-id='24f95ba5'/>
</function-decl>
+ <function-decl name='dlclose' visibility='default' binding='global' size-in-bits='64'>
+ <parameter type-id='eaa32e2f'/>
+ <return type-id='95e97e5e'/>
+ </function-decl>
<function-decl name='regcomp' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='5c53ba29'/>
<parameter type-id='9d26089a'/>
#include <signal.h>
#include <errno.h>
#include <openssl/evp.h>
+#if LIBFETCH_DYNAMIC
+#include <dlfcn.h>
+#endif
+#if LIBFETCH_IS_FETCH
+#include <sys/param.h>
+#include <stdio.h>
+#include <fetch.h>
+#elif LIBFETCH_IS_LIBCURL
+#include <curl/curl.h>
+#endif
#include <libzfs.h>
#include "libzfs_impl.h"
#include "zfeature_common.h"
static int get_key_material_file(libzfs_handle_t *, const char *, const char *,
zfs_keyformat_t, boolean_t, uint8_t **, size_t *);
+static int get_key_material_https(libzfs_handle_t *, const char *, const char *,
+ zfs_keyformat_t, boolean_t, uint8_t **, size_t *);
static zfs_uri_handler_t uri_handlers[] = {
{ "file", get_key_material_file },
+ { "https", get_key_material_https },
+ { "http", get_key_material_https },
{ NULL, NULL }
};
return (ret);
}
+static int
+get_key_material_https(libzfs_handle_t *hdl, const char *uri,
+ const char *fsname, zfs_keyformat_t keyformat, boolean_t newkey,
+ uint8_t **restrict buf, size_t *restrict len_out)
+{
+ int ret = 0;
+ FILE *key = NULL;
+ boolean_t is_http = strncmp(uri, "http:", strlen("http:")) == 0;
+
+ if (strlen(uri) < (is_http ? 7 : 8)) {
+ ret = EINVAL;
+ goto end;
+ }
+
+#if LIBFETCH_DYNAMIC
+#define LOAD_FUNCTION(func) \
+ __typeof__(func) *func = dlsym(hdl->libfetch, #func);
+
+ if (hdl->libfetch == NULL)
+ hdl->libfetch = dlopen(LIBFETCH_SONAME, RTLD_LAZY);
+
+ if (hdl->libfetch == NULL) {
+ hdl->libfetch = (void *)-1;
+ char *err = dlerror();
+ if (err)
+ hdl->libfetch_load_error = strdup(err);
+ }
+
+ if (hdl->libfetch == (void *)-1) {
+ ret = ENOSYS;
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Couldn't load %s: %s"),
+ LIBFETCH_SONAME, hdl->libfetch_load_error ?: "(?)");
+ goto end;
+ }
+
+ boolean_t ok;
+#if LIBFETCH_IS_FETCH
+ LOAD_FUNCTION(fetchGetURL);
+ char *fetchLastErrString = dlsym(hdl->libfetch, "fetchLastErrString");
+
+ ok = fetchGetURL && fetchLastErrString;
+#elif LIBFETCH_IS_LIBCURL
+ LOAD_FUNCTION(curl_easy_init);
+ LOAD_FUNCTION(curl_easy_setopt);
+ LOAD_FUNCTION(curl_easy_perform);
+ LOAD_FUNCTION(curl_easy_cleanup);
+ LOAD_FUNCTION(curl_easy_strerror);
+ LOAD_FUNCTION(curl_easy_getinfo);
+
+ ok = curl_easy_init && curl_easy_setopt && curl_easy_perform &&
+ curl_easy_cleanup && curl_easy_strerror && curl_easy_getinfo;
+#endif
+ if (!ok) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "keylocation=%s back-end %s missing symbols."),
+ is_http ? "http://" : "https://", LIBFETCH_SONAME);
+ ret = ENOSYS;
+ goto end;
+ }
+#endif
+
+#if LIBFETCH_IS_FETCH
+ key = fetchGetURL(uri, "");
+ if (key == NULL) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Couldn't GET %s: %s"),
+ uri, fetchLastErrString);
+ ret = ENETDOWN;
+ }
+#elif LIBFETCH_IS_LIBCURL
+ CURL *curl = curl_easy_init();
+ if (curl == NULL) {
+ ret = ENOTSUP;
+ goto end;
+ }
+
+ int kfd = -1;
+#ifdef O_TMPFILE
+ kfd = open(getenv("TMPDIR") ?: "/tmp",
+ O_RDWR | O_TMPFILE | O_EXCL | O_CLOEXEC, 0600);
+ if (kfd != -1)
+ goto kfdok;
+#endif
+
+ char *path;
+ if (asprintf(&path,
+ "%s/libzfs-XXXXXXXX.https", getenv("TMPDIR") ?: "/tmp") == -1) {
+ ret = ENOMEM;
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s"),
+ strerror(ret));
+ goto end;
+ }
+
+ kfd = mkostemps(path, strlen(".https"), O_CLOEXEC);
+ if (kfd == -1) {
+ ret = errno;
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Couldn't create temporary file %s: %s"),
+ path, strerror(ret));
+ free(path);
+ goto end;
+ }
+ (void) unlink(path);
+ free(path);
+
+kfdok:
+ if ((key = fdopen(kfd, "r+")) == NULL) {
+ ret = errno;
+ free(path);
+ (void) close(kfd);
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Couldn't reopen temporary file: %s"), strerror(ret));
+ goto end;
+ }
+
+ char errbuf[CURL_ERROR_SIZE] = "";
+ char *cainfo = getenv("SSL_CA_CERT_FILE"); /* matches fetch(3) */
+ char *capath = getenv("SSL_CA_CERT_PATH"); /* matches fetch(3) */
+ char *clcert = getenv("SSL_CLIENT_CERT_FILE"); /* matches fetch(3) */
+ char *clkey = getenv("SSL_CLIENT_KEY_FILE"); /* matches fetch(3) */
+ (void) curl_easy_setopt(curl, CURLOPT_URL, uri);
+ (void) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ (void) curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 30000L);
+ (void) curl_easy_setopt(curl, CURLOPT_WRITEDATA, key);
+ (void) curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
+ if (cainfo != NULL)
+ (void) curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo);
+ if (capath != NULL)
+ (void) curl_easy_setopt(curl, CURLOPT_CAPATH, capath);
+ if (clcert != NULL)
+ (void) curl_easy_setopt(curl, CURLOPT_SSLCERT, clcert);
+ if (clkey != NULL)
+ (void) curl_easy_setopt(curl, CURLOPT_SSLKEY, clkey);
+
+ CURLcode res = curl_easy_perform(curl);
+
+ if (res != CURLE_OK) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Failed to connect to %s: %s"),
+ uri, strlen(errbuf) ? errbuf : curl_easy_strerror(res));
+ ret = ENETDOWN;
+ } else {
+ long resp = 200;
+ (void) curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp);
+
+ if (resp < 200 || resp >= 300) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "Couldn't GET %s: %ld"),
+ uri, resp);
+ ret = ENOENT;
+ } else
+ rewind(key);
+ }
+
+ curl_easy_cleanup(curl);
+#else
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "No keylocation=%s back-end."), is_http ? "http://" : "https://");
+ ret = ENOSYS;
+#endif
+
+end:
+ if (ret == 0)
+ ret = get_key_material_raw(key, keyformat, buf, len_out);
+
+ if (key != NULL)
+ fclose(key);
+
+ return (ret);
+}
+
/*
* Attempts to fetch key material, no matter where it might live. The key
* material is allocated and returned in km_out. *can_retry_out will be set
* Note: if there are multiple snaps with the
* same GUID, we ignore all but one.
*/
- if (avl_find(fsavl, fn, NULL) == NULL)
- avl_add(fsavl, fn);
+ avl_index_t where = 0;
+ if (avl_find(fsavl, fn, &where) == NULL)
+ avl_insert(fsavl, fn, where);
else
free(fn);
}
fnvlist_add_nvlist(sd->snapprops, snapname, nv);
fnvlist_free(nv);
if (sd->holds) {
- nvlist_t *holds = fnvlist_alloc();
- int err = lzc_get_holds(zhp->zfs_name, &holds);
- if (err == 0) {
+ nvlist_t *holds;
+ if (lzc_get_holds(zhp->zfs_name, &holds) == 0) {
fnvlist_add_nvlist(sd->snapholds, snapname, holds);
+ fnvlist_free(holds);
}
- fnvlist_free(holds);
}
zfs_close(zhp);
"progress thread exited nonzero")));
}
- if (flags->props || flags->holds || flags->backup) {
+ if (err == 0 && (flags->props || flags->holds || flags->backup)) {
/* Write the final end record. */
err = send_conclusion_record(fd, NULL);
if (err != 0)
#include <strings.h>
#include <unistd.h>
#include <math.h>
+#if LIBFETCH_DYNAMIC
+#include <dlfcn.h>
+#endif
#include <sys/stat.h>
#include <sys/mnttab.h>
#include <sys/mntent.h>
libzfs_core_fini();
regfree(&hdl->libzfs_urire);
fletcher_4_fini();
+#if LIBFETCH_DYNAMIC
+ if (hdl->libfetch != (void *)-1 && hdl->libfetch != NULL)
+ (void) dlclose(hdl->libfetch);
+ free(hdl->libfetch_load_error);
+#endif
free(hdl);
}
if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
char badopt[MNT_LINE_MAX] = {0};
- unsigned long mntflags = flags, zfsflags;
+ unsigned long mntflags = flags, zfsflags = 0;
char myopts[MNT_LINE_MAX] = {0};
if (zfs_parse_mount_options(opts, &mntflags,
These blocks are meant to be prefetched fairly aggressively ahead of
the code that may use them.
.
+.It Sy zfs_arc_prune_task_threads Ns = Ns Sy 1 Pq int
+Number of arc_prune threads.
+.Fx
+does not need more than one.
+Linux may theoretically use one per mount point up to number of CPUs,
+but that was not proven to be useful.
+.
.It Sy zfs_max_missing_tvds Ns = Ns Sy 0 Pq int
Number of missing top-level vdevs which will be allowed during
pool import (only in read-only mode).
or less of their original size.
.It Xo
.Sy context Ns = Ns Sy none Ns | Ns
-.Ar SELinux-User : Ns Ar SElinux-Role : Ns Ar Selinux-Type : Ns Ar Sensitivity-Level
+.Ar SELinux-User : Ns Ar SELinux-Role : Ns Ar SELinux-Type : Ns Ar Sensitivity-Level
.Xc
This flag sets the SELinux context for all files in the file system under
a mount point for that file system.
for more information.
.It Xo
.Sy fscontext Ns = Ns Sy none Ns | Ns
-.Ar SELinux-User : Ns Ar SElinux-Role : Ns Ar Selinux-Type : Ns Ar Sensitivity-Level
+.Ar SELinux-User : Ns Ar SELinux-Role : Ns Ar SELinux-Type : Ns Ar Sensitivity-Level
.Xc
This flag sets the SELinux context for the file system file system being
mounted.
for more information.
.It Xo
.Sy defcontext Ns = Ns Sy none Ns | Ns
-.Ar SELinux-User : Ns Ar SElinux-Role : Ns Ar Selinux-Type : Ns Ar Sensitivity-Level
+.Ar SELinux-User : Ns Ar SELinux-Role : Ns Ar SELinux-Type : Ns Ar Sensitivity-Level
.Xc
This flag sets the SELinux default context for unlabeled files.
See
for more information.
.It Xo
.Sy rootcontext Ns = Ns Sy none Ns | Ns
-.Ar SELinux-User : Ns Ar SElinux-Role : Ns Ar Selinux-Type : Ns Ar Sensitivity-Level
+.Ar SELinux-User : Ns Ar SELinux-Role : Ns Ar SELinux-Type : Ns Ar Sensitivity-Level
.Xc
This flag sets the SELinux context for the root inode of the file system.
See
the keyformat can be with
.Nm zfs Cm change-key .
.It Xo
-.Sy keylocation Ns = Ns Sy prompt Ns | Ns Sy file:// Ns Em </absolute/file/path>
+.Sy keylocation Ns = Ns Sy prompt Ns | Ns Sy file:// Ns Em </absolute/file/path> Ns | Ns Sy https:// Ns Em <address> | Ns Sy http:// Ns Em <address>
.Xc
Controls where the user's encryption key will be loaded from by default for
commands such as
the command line.
If a file URI is selected, the key will be loaded from the
specified absolute file path.
+If an HTTPS or HTTP URL is selected, it will be GETted using
+.Xr fetch 3 ,
+libcurl, or nothing, depending on compile-time configuration and run-time
+availability.
+The
+.Ev SSL_CA_CERT_FILE
+environment variable can be set to set the location
+of the concatenated certificate store.
+The
+.Ev SSL_CA_CERT_PATH
+environment variable can be set to override the location
+of the directory containing the certificate authority bundle.
+The
+.Ev SSL_CLIENT_CERT_FILE
+and
+.Ev SSL_CLIENT_KEY_FILE
+environment variables can be set to configure the path
+to the client certificate and its key.
.It Sy pbkdf2iters Ns = Ns Ar iterations
Controls the number of PBKDF2 iterations that a
.Sy passphrase
the dataset is shared using the default options:
.Dl sec=sys,rw,crossmnt,no_subtree_check
.Pp
+Please note that the options are comma-separated, unlike those found in
+.Xr exports 5 .
+This is done to negate the need for quoting, as well as to make parsing
+with scripts easier.
+.Pp
See
.Xr exports 5
for the meaning of the default options.
will decrease while
.Sy free
increases.
+.It Sy leaked
+Space not released while
+.Sy freeing
+due to corruption, now permanently leaked into the pool.
.It Sy health
The current health of the pool.
Health can be one of
.Bl -tag -width "continue"
.It Sy wait
Blocks all I/O access until the device connectivity is recovered and the errors
-are cleared.
+are cleared with
+.Nm zpool Cm clear .
This is the default behavior.
.It Sy continue
Returns
.Bl -tag -width "-r"
.It Fl l
Ensures the key is loaded before attempting to change the key.
-This is effectively equivalent to runnin
+This is effectively equivalent to running
.Nm zfs Cm load-key Ar filesystem ; Nm zfs Cm change-key Ar filesystem
.It Fl o Ar property Ns = Ns Ar value
Allows the user to set encryption key properties
manner as is required for
.Nm zfs Cm create .
For instance:
-.Dl # Nm zfs Cm send Pa tank/test@snap1 | Nm zfs Cm recv Fl o Sy encryption Ns = Ns Sy on Fl o keyformat=passphrase Fl o Sy keylocation Ns = Ns Pa file:///path/to/keyfile
+.Dl # Nm zfs Cm send Pa tank/test@snap1 | Nm zfs Cm recv Fl o Sy encryption Ns = Ns Sy on Fl o Sy keyformat Ns = Ns Sy passphrase Fl o Sy keylocation Ns = Ns Pa file:///path/to/keyfile
.Pp
Note that
.Fl o Sy keylocation Ns = Ns Sy prompt
.Nm zfs Cm set
to change this setting after the fact.
Similarly, you can receive a dataset as an encrypted child by specifying
-.Op Fl x Ar encryption
+.Fl x Sy encryption
to force the property to be inherited.
Overriding encryption properties (except for
.Sy keylocation )
.\" Copyright 2018 Nexenta Systems, Inc.
.\" Copyright 2019 Joyent, Inc.
.\"
-.Dd June 30, 2019
+.Dd May 17, 2021
.Dt ZFS-SHARE 8
.Os
.
.Sh SYNOPSIS
.Nm zfs
.Cm share
+.Op Fl l
.Fl a Ns | Ns Ar filesystem
.Nm zfs
.Cm unshare
.It Xo
.Nm zfs
.Cm share
+.Op Fl l
.Fl a Ns | Ns Ar filesystem
.Xc
Shares available ZFS file systems.
.Bl -tag -width "-a"
+.It Fl l
+Load keys for encrypted filesystems as they are being mounted.
+This is equivalent to executing
+.Nm zfs Cm load-key
+on each encryption root before mounting it.
+Note that if a filesystem has
+.Sy keylocation Ns = Ns Sy prompt ,
+this will cause the terminal to interactively block after asking for the key.
.It Fl a
Share all available ZFS file systems.
Invoked automatically as part of the boot process.
.Dl # Nm Qq $ Ns Pq Nm hostid
.It Record a custom hostid Po Ar 0xdeadbeef Pc in Pa /etc/hostid
.Dl # Nm Ar deadbeef
-.It Record a custom hostid Po Ar 0x01234567 Pc in Pa /tmp/hostid No and ovewrite the file if it exists
+.It Record a custom hostid Po Ar 0x01234567 Pc in Pa /tmp/hostid No and overwrite the file if it exists
.Dl # Nm Fl f o Ar /tmp/hostid 0x01234567
.El
.
The
.Ar new_device
is reconstructed sequentially to restore redundancy as quickly as possible.
-Checksums are not verfied during sequential reconstruction so a scrub is
+Checksums are not verified during sequential reconstruction so a scrub is
started when the resilver completes.
Sequential reconstruction is not supported for raidz configurations.
.It Fl w
If no arguments are specified, all device errors within the pool are cleared.
If one or more devices is specified, only those errors associated with the
specified device or devices are cleared.
-If
+.Pp
+If the pool was suspended it will be brought back online provided the
+devices can be accessed.
+Pools with
.Sy multihost
-is enabled and the pool has been suspended, this will not resume I/O.
+enabled which have been suspended cannot be resumed.
While the pool was suspended, it may have been imported on
another host, and resuming I/O could result in pool damage.
.
.El
.
.Sh EVENTS
-Theese are the different event subclasses.
+These are the different event subclasses.
The full event name would be
.Sy ereport.fs.zfs.\& Ns Em SUBCLASS ,
but only the last part is listed here.
.It Sy vdev.remove
Issued when a vdev is detached from a mirror (or a spare detached from a
vdev where it have been used to replace a failed drive - only works if
-the original drive have been readded).
+the original drive have been re-added).
.It Sy vdev.clear
Issued when clearing device errors in a pool.
Such as running
about pool recovery mode, see the
.Fl X
option, above.
-WARNING: This option can be extremely hazardous to the
+.Em WARNING :
+This option can be extremely hazardous to the
health of your pool and should only be used as a last resort.
.It Fl t
Used with
-.Sy newpool .
+.Ar newpool .
Specifies that
-.Sy newpool
+.Ar newpool
is temporary.
Temporary pool names last until export.
Ensures that the original pool name will be used
The
.Ar new-device
is reconstructed sequentially to restore redundancy as quickly as possible.
-Checksums are not verfied during sequential reconstruction so a scrub is
+Checksums are not verified during sequential reconstruction so a scrub is
started when the resilver completes.
Sequential reconstruction is not supported for raidz configurations.
.It Fl w
scrubbed sequentially at 10.0M/s.
.El
.El
+.Sh PERIODIC SCRUB
+On machines using systemd, scrub timers can be enabled on per-pool basis.
+.Nm weekly
+and
+.Nm monthly
+timer units are provided.
+.Bl -tag -width Ds
+.It Xo
+.Xc
+.Nm systemctl
+.Cm enable
+.Cm zfs-scrub-\fIweekly\fB@\fIrpool\fB.timer
+.Cm --now
+.It Xo
+.Xc
+.Nm systemctl
+.Cm enable
+.Cm zfs-scrub-\fImonthly\fB@\fIotherpool\fB.timer
+.Cm --now
+.El
.
.Sh SEE ALSO
+.Xr systemd.timer 5 ,
.Xr zpool-iostat 8 ,
.Xr zpool-resilver 8 ,
.Xr zpool-status 8
include Kbuild
INSTALL_MOD_DIR ?= extra
+INSTALL_MOD_PATH ?= $(DESTDIR)
SUBDIR_TARGETS = icp lua zstd
FMAKE = env -u MAKEFLAGS make $(FMAKEFLAGS)
modules-Linux:
- list='$(SUBDIR_TARGETS)'; for targetdir in $$list; do \
- $(MAKE) -C $$targetdir; \
- done
- $(MAKE) -C @LINUX_OBJ@ M=`pwd` @KERNEL_MAKE@ CONFIG_ZFS=m modules
+ list='$(SUBDIR_TARGETS)'; for td in $$list; do $(MAKE) -C $$td; done
+ $(MAKE) -C @LINUX_OBJ@ $(if @KERNEL_CC@,CC=@KERNEL_CC@) \
+ $(if @KERNEL_LD@,LD=@KERNEL_LD@) $(if @KERNEL_LLVM@,LLVM=@KERNEL_LLVM@) \
+ M="$$PWD" @KERNEL_MAKE@ CONFIG_ZFS=m modules
modules-FreeBSD:
+$(FMAKE)
clean-Linux:
@# Only cleanup the kernel build directories when CONFIG_KERNEL
@# is defined. This indicates that kernel modules should be built.
-@CONFIG_KERNEL_TRUE@ $(MAKE) -C @LINUX_OBJ@ M=`pwd` @KERNEL_MAKE@ clean
-
- if [ -f @LINUX_SYMBOLS@ ]; then $(RM) @LINUX_SYMBOLS@; fi
- if [ -f Module.markers ]; then $(RM) Module.markers; fi
+@CONFIG_KERNEL_TRUE@ $(MAKE) -C @LINUX_OBJ@ M="$$PWD" @KERNEL_MAKE@ clean
- find . -name '*.ur-safe' -type f -print | xargs $(RM)
+ $(RM) @LINUX_SYMBOLS@ Module.markers
+ find . -name '*.ur-safe' -type f -delete
clean-FreeBSD:
+$(FMAKE) clean
modules_install-Linux:
@# Install the kernel modules
- $(MAKE) -C @LINUX_OBJ@ M=`pwd` modules_install \
- INSTALL_MOD_PATH=$(DESTDIR)$(INSTALL_MOD_PATH) \
+ $(MAKE) -C @LINUX_OBJ@ M="$$PWD" modules_install \
+ INSTALL_MOD_PATH=$(INSTALL_MOD_PATH) \
INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \
KERNELRELEASE=@LINUX_VERSION@
@# Remove extraneous build products when packaging
- kmoddir=$(DESTDIR)$(INSTALL_MOD_PATH)/lib/modules/@LINUX_VERSION@; \
+ kmoddir=$(INSTALL_MOD_PATH)/lib/modules/@LINUX_VERSION@; \
if [ -n "$(DESTDIR)" ]; then \
- find $$kmoddir -name 'modules.*' | xargs $(RM); \
+ find $$kmoddir -name 'modules.*' -delete; \
fi
- sysmap=$(DESTDIR)$(INSTALL_MOD_PATH)/boot/System.map-@LINUX_VERSION@; \
+ @# Debian ships tiny fake System.map files that are
+ @# syntactically valid but just say
+ @# "if you want system.map go install this package"
+ @# Naturally, depmod is less than amused by this.
+ @# So if we find it missing or with one of these present,
+ @# we check for the alternate path for the System.map
+ sysmap=$(INSTALL_MOD_PATH)/boot/System.map-@LINUX_VERSION@; \
+ { [ -f "$$sysmap" ] && [ $$(wc -l < "$$sysmap") -ge 100 ]; } || \
+ sysmap=$(INSTALL_MOD_PATH)/usr/lib/debug/boot/System.map-@LINUX_VERSION@; \
if [ -f $$sysmap ]; then \
depmod -ae -F $$sysmap @LINUX_VERSION@; \
fi
modules_uninstall-Linux:
@# Uninstall the kernel modules
- kmoddir=$(DESTDIR)$(INSTALL_MOD_PATH)/lib/modules/@LINUX_VERSION@; \
+ kmoddir=$(INSTALL_MOD_PATH)/lib/modules/@LINUX_VERSION@; \
for objdir in $(ZFS_MODULES); do \
$(RM) -R $$kmoddir/$(INSTALL_MOD_DIR)/$$objdir; \
done
n = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
abd_zero_buf = kmem_cache_alloc(abd_chunk_cache, KM_PUSHPAGE);
+ bzero(abd_zero_buf, PAGE_SIZE);
abd_zero_scatter = abd_alloc_struct(SPA_MAXBLOCKSIZE);
abd_zero_scatter->abd_flags |= ABD_FLAG_OWNER | ABD_FLAG_ZEROS;
err = zfs_file_pwrite(vf->vf_file, buf, size, off, &resid);
abd_return_buf(zio->io_abd, buf, size);
}
+ zio->io_error = err;
if (resid != 0 && zio->io_error == 0)
zio->io_error = ENOSPC;
TQ_SLEEP), !=, 0);
}
-/* ARGSUSED */
static void
vdev_file_io_done(zio_t *zio)
{
+ (void) zio;
}
vdev_ops_t vdev_file_ops = {
*/
vap->va_blksize = 0;
vap->va_nblocks = 0;
- vap->va_seq = 0;
+ vap->va_gen = 0;
vn_fsid(vp, vap);
vap->va_mode = zfsctl_ctldir_mode;
vap->va_type = VDIR;
racct_add_force(curproc, RACCT_READIOPS, iops);
PROC_UNLOCK(curproc);
}
+#else
+ (void) size;
#endif /* RACCT */
}
racct_add_force(curproc, RACCT_WRITEIOPS, iops);
PROC_UNLOCK(curproc);
}
+#else
+ (void) size;
#endif /* RACCT */
}
vnode_t *dvp;
uint64_t object = 0;
uint64_t fid_gen = 0;
+ uint64_t setgen = 0;
uint64_t gen_mask;
uint64_t zp_gen;
int i, err;
if (zfsvfs->z_parent == zfsvfs && fidp->fid_len == LONG_FID_LEN) {
zfid_long_t *zlfid = (zfid_long_t *)fidp;
uint64_t objsetid = 0;
- uint64_t setgen = 0;
for (i = 0; i < sizeof (zlfid->zf_setid); i++)
objsetid |= ((uint64_t)zlfid->zf_setid[i]) << (8 * i);
return (SET_ERROR(EINVAL));
}
+ if (fidp->fid_len == LONG_FID_LEN && (fid_gen > 1 || setgen != 0)) {
+ dprintf("snapdir fid: fid_gen (%llu) and setgen (%llu)\n",
+ (u_longlong_t)fid_gen, (u_longlong_t)setgen);
+ return (SET_ERROR(EINVAL));
+ }
+
/*
* A zero fid_gen means we are in .zfs or the .zfs/snapshot
* directory tree. If the object == zfsvfs->z_shares_dir, then
#define VNCHECKREF(vp)
#endif
+#if __FreeBSD_version >= 1400045
+typedef uint64_t cookie_t;
+#else
+typedef ulong_t cookie_t;
+#endif
+
/*
* Programming rules.
*
/* ARGSUSED */
static int
zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
- int *ncookies, ulong_t **cookies)
+ int *ncookies, cookie_t **cookies)
{
znode_t *zp = VTOZ(vp);
iovec_t *iovp;
boolean_t check_sysattrs;
uint8_t type;
int ncooks;
- ulong_t *cooks = NULL;
+ cookie_t *cooks = NULL;
int flags = 0;
ZFS_ENTER(zfsvfs);
*/
ncooks = zfs_uio_resid(uio) / (sizeof (struct dirent) -
sizeof (((struct dirent *)NULL)->d_name) + 1);
- cooks = malloc(ncooks * sizeof (ulong_t), M_TEMP, M_WAITOK);
+ cooks = malloc(ncooks * sizeof (*cooks), M_TEMP, M_WAITOK);
*cookies = cooks;
*ncookies = ncooks;
}
vap->va_size = zp->z_size;
if (vp->v_type == VBLK || vp->v_type == VCHR)
vap->va_rdev = zfs_cmpldev(rdev);
- vap->va_seq = zp->z_seq;
+ vap->va_gen = zp->z_gen;
vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */
vap->va_filerev = zp->z_seq;
if (lr != NULL)
zfs_rangelock_exit(lr);
ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
+
+ dataset_kstats_update_read_kstats(&zfsvfs->z_kstat, count*PAGE_SIZE);
+
ZFS_EXIT(zfsvfs);
if (error != 0)
if ((flags & (zfs_vm_pagerput_sync | zfs_vm_pagerput_inval)) != 0 ||
zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zfsvfs->z_log, zp->z_id);
+
+ dataset_kstats_update_write_kstats(&zfsvfs->z_kstat, len);
+
ZFS_EXIT(zfsvfs);
return (rtvals[0]);
}
struct ucred *a_cred;
int *a_eofflag;
int *a_ncookies;
- ulong_t **a_cookies;
+ cookie_t **a_cookies;
};
#endif
* and le_bswap indicates whether a byteswap is needed to get this block
* into little endian format.
*/
-/* ARGSUSED */
int
zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
boolean_t should_bswap, uint8_t *portable_mac, uint8_t *local_mac)
bcopy(raw_portable_mac, portable_mac, ZIO_OBJSET_MAC_LEN);
+ /*
+ * This is necessary here as we check next whether
+ * OBJSET_FLAG_USERACCOUNTING_COMPLETE is set in order to
+ * decide if the local_mac should be zeroed out. That flag will always
+ * be set by dmu_objset_id_quota_upgrade_cb() and
+ * dmu_objset_userspace_upgrade_cb() if useraccounting has been
+ * completed.
+ */
+ intval = osp->os_flags;
+ if (should_bswap)
+ intval = BSWAP_64(intval);
+ boolean_t uacct_incomplete =
+ !(intval & OBJSET_FLAG_USERACCOUNTING_COMPLETE);
+
/*
* The local MAC protects the user, group and project accounting.
* If these objects are not present, the local MAC is zeroed out.
*/
- if ((datalen >= OBJSET_PHYS_SIZE_V3 &&
+ if (uacct_incomplete ||
+ (datalen >= OBJSET_PHYS_SIZE_V3 &&
osp->os_userused_dnode.dn_type == DMU_OT_NONE &&
osp->os_groupused_dnode.dn_type == DMU_OT_NONE &&
osp->os_projectused_dnode.dn_type == DMU_OT_NONE) ||
* It also means we'll only return one zfs_uio_t.
*/
-/* ARGSUSED */
static int
zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
uint8_t *cipherbuf, uint_t datalen, boolean_t byteswap, zfs_uio_t *puio,
zfs_uio_t *out_uio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len,
boolean_t *no_crypt)
{
+ (void) puio;
uint8_t *aadbuf = zio_buf_alloc(datalen);
uint8_t *src, *dst, *slrp, *dlrp, *blkend, *aadp;
iovec_t *dst_iovecs;
return (0);
}
-/* ARGSUSED */
static int
zio_crypt_init_uios_normal(boolean_t encrypt, uint8_t *plainbuf,
uint8_t *cipherbuf, uint_t datalen, zfs_uio_t *puio, zfs_uio_t *out_uio,
uint_t *enc_len)
{
+ (void) puio;
int ret;
uint_t nr_plain = 1, nr_cipher = 2;
iovec_t *plain_iovecs = NULL, *cipher_iovecs = NULL;
zvol_state_t *zv;
int err = 0;
boolean_t drop_suspend = B_FALSE;
- boolean_t drop_namespace = B_FALSE;
if (!zpool_on_zvol && tsd_get(zfs_geom_probe_vdev_key) != NULL) {
/*
retry:
rw_enter(&zvol_state_lock, ZVOL_RW_READER);
+ /*
+ * Obtain a copy of private under zvol_state_lock to make sure either
+ * the result of zvol free code setting private to NULL is observed,
+ * or the zv is protected from being freed because of the positive
+ * zv_open_count.
+ */
zv = pp->private;
if (zv == NULL) {
rw_exit(&zvol_state_lock);
goto out_locked;
}
- if (zv->zv_open_count == 0 && !mutex_owned(&spa_namespace_lock)) {
- /*
- * We need to guarantee that the namespace lock is held
- * to avoid spurious failures in zvol_first_open.
- */
- drop_namespace = B_TRUE;
- if (!mutex_tryenter(&spa_namespace_lock)) {
- rw_exit(&zvol_state_lock);
- mutex_enter(&spa_namespace_lock);
- goto retry;
- }
- }
mutex_enter(&zv->zv_state_lock);
if (zv->zv_zso->zso_dying) {
rw_exit(&zvol_state_lock);
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
if (zv->zv_open_count == 0) {
+ boolean_t drop_namespace = B_FALSE;
+
ASSERT(ZVOL_RW_READ_HELD(&zv->zv_suspend_lock));
+
+ /*
+ * Take spa_namespace_lock to prevent lock inversion when
+ * zvols from one pool are opened as vdevs in another.
+ */
+ if (!mutex_owned(&spa_namespace_lock)) {
+ if (!mutex_tryenter(&spa_namespace_lock)) {
+ mutex_exit(&zv->zv_state_lock);
+ rw_exit(&zv->zv_suspend_lock);
+ kern_yield(PRI_USER);
+ goto retry;
+ } else {
+ drop_namespace = B_TRUE;
+ }
+ }
err = zvol_first_open(zv, !(flag & FWRITE));
+ if (drop_namespace)
+ mutex_exit(&spa_namespace_lock);
if (err)
goto out_zv_locked;
pp->mediasize = zv->zv_volsize;
pp->stripesize = zv->zv_volblocksize;
}
+ ASSERT(MUTEX_HELD(&zv->zv_state_lock));
+
/*
* Check for a bad on-disk format version now since we
* lied about owning the dataset readonly before.
out_zv_locked:
mutex_exit(&zv->zv_state_lock);
out_locked:
- if (drop_namespace)
- mutex_exit(&spa_namespace_lock);
if (drop_suspend)
rw_exit(&zv->zv_suspend_lock);
return (err);
struct zvol_state_dev *zsd;
int err = 0;
boolean_t drop_suspend = B_FALSE;
- boolean_t drop_namespace = B_FALSE;
retry:
rw_enter(&zvol_state_lock, ZVOL_RW_READER);
+ /*
+ * Obtain a copy of si_drv2 under zvol_state_lock to make sure either
+ * the result of zvol free code setting si_drv2 to NULL is observed,
+ * or the zv is protected from being freed because of the positive
+ * zv_open_count.
+ */
zv = dev->si_drv2;
if (zv == NULL) {
rw_exit(&zvol_state_lock);
goto out_locked;
}
- if (zv->zv_open_count == 0 && !mutex_owned(&spa_namespace_lock)) {
- /*
- * We need to guarantee that the namespace lock is held
- * to avoid spurious failures in zvol_first_open.
- */
- drop_namespace = B_TRUE;
- if (!mutex_tryenter(&spa_namespace_lock)) {
- rw_exit(&zvol_state_lock);
- mutex_enter(&spa_namespace_lock);
- goto retry;
- }
- }
mutex_enter(&zv->zv_state_lock);
-
+ if (zv->zv_zso->zso_dying) {
+ rw_exit(&zvol_state_lock);
+ err = SET_ERROR(ENXIO);
+ goto out_zv_locked;
+ }
ASSERT3S(zv->zv_volmode, ==, ZFS_VOLMODE_DEV);
/*
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
if (zv->zv_open_count == 0) {
+ boolean_t drop_namespace = B_FALSE;
+
ASSERT(ZVOL_RW_READ_HELD(&zv->zv_suspend_lock));
+
+ /*
+ * Take spa_namespace_lock to prevent lock inversion when
+ * zvols from one pool are opened as vdevs in another.
+ */
+ if (!mutex_owned(&spa_namespace_lock)) {
+ if (!mutex_tryenter(&spa_namespace_lock)) {
+ mutex_exit(&zv->zv_state_lock);
+ rw_exit(&zv->zv_suspend_lock);
+ kern_yield(PRI_USER);
+ goto retry;
+ } else {
+ drop_namespace = B_TRUE;
+ }
+ }
err = zvol_first_open(zv, !(flags & FWRITE));
+ if (drop_namespace)
+ mutex_exit(&spa_namespace_lock);
if (err)
goto out_zv_locked;
}
+ ASSERT(MUTEX_HELD(&zv->zv_state_lock));
+
if ((flags & FWRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
err = SET_ERROR(EROFS);
goto out_opened;
out_zv_locked:
mutex_exit(&zv->zv_state_lock);
out_locked:
- if (drop_namespace)
- mutex_exit(&spa_namespace_lock);
if (drop_suspend)
rw_exit(&zv->zv_suspend_lock);
return (err);
return (rc);
f = filp->private_data;
- f->private = PDE_DATA(inode);
+ f->private = SPL_PDE_DATA(inode);
return (0);
}
struct seq_file *f = filp->private_data;
procfs_list_cursor_t *cursor = f->private;
- cursor->procfs_list = PDE_DATA(inode);
+ cursor->procfs_list = SPL_PDE_DATA(inode);
cursor->cached_node = NULL;
cursor->cached_pos = 0;
ASSERT(tq);
spin_lock_irqsave_nested(&tq->tq_lock, flags, tq->tq_lock_class);
- if (!(tq->tq_flags & TASKQ_ACTIVE))
- goto out;
+ if (!(tq->tq_flags & TASKQ_ACTIVE)) {
+ spin_unlock_irqrestore(&tq->tq_lock, flags);
+ return (err);
+ }
ASSERT(tq->tq_flags & TASKQ_THREADS_CPU_PCT);
int nthreads = MIN(tq->tq_cpu_pct, 100);
if (!((tq->tq_flags & TASKQ_DYNAMIC) && spl_taskq_thread_dynamic) &&
tq->tq_maxthreads > tq->tq_nthreads) {
- ASSERT3U(tq->tq_maxthreads, ==, tq->tq_nthreads + 1);
+ spin_unlock_irqrestore(&tq->tq_lock, flags);
taskq_thread_t *tqt = taskq_thread_create(tq);
if (tqt == NULL)
err = -1;
+ return (err);
}
-
-out:
spin_unlock_irqrestore(&tq->tq_lock, flags);
return (err);
}
__thread_exit(void)
{
tsd_exit();
- complete_and_exit(NULL, 0);
+ SPL_KTHREAD_COMPLETE_AND_EXIT(NULL, 0);
/* Unreachable */
}
EXPORT_SYMBOL(__thread_exit);
spin_lock_irq(&task->sighand->siglock);
int ret;
+#ifdef HAVE_DEQUEUE_SIGNAL_4ARG
+ enum pid_type __type;
+ if ((ret = dequeue_signal(task, &set, &__info, &__type)) != 0) {
+#else
if ((ret = dequeue_signal(task, &set, &__info)) != 0) {
+#endif
#ifdef HAVE_SIGNAL_STOP
spin_unlock_irq(&task->sighand->siglock);
kernel_signal_stop();
#ifdef HAVE_1ARG_SUBMIT_BIO
(void) submit_bio(bio);
#else
- (void) submit_bio(0, bio);
+ (void) submit_bio(bio_data_dir(bio), bio);
#endif
}
TQ_SLEEP), !=, TASKQID_INVALID);
}
-/* ARGSUSED */
static void
vdev_file_io_done(zio_t *zio)
{
+ (void) zio;
}
vdev_ops_t vdev_file_ops = {
void
zfs_racct_read(uint64_t size, uint64_t iops)
{
+ (void) size, (void) iops;
}
void
zfs_racct_write(uint64_t size, uint64_t iops)
{
+ (void) size, (void) iops;
}
*objects = 0;
for_each_online_node(sc.nid) {
*objects += (*shrinker->scan_objects)(shrinker, &sc);
+ /*
+ * reset sc.nr_to_scan, modified by
+ * scan_objects == super_cache_scan
+ */
+ sc.nr_to_scan = nr_to_scan;
}
} else {
*objects = (*shrinker->scan_objects)(shrinker, &sc);
zil_commit(zfsvfs->z_log, zp->z_id);
}
+ dataset_kstats_update_write_kstats(&zfsvfs->z_kstat, pglen);
+
ZFS_EXIT(zfsvfs);
return (err);
}
err = zfs_fillpage(ip, pl, nr_pages);
+ dataset_kstats_update_read_kstats(&zfsvfs->z_kstat, nr_pages*PAGESIZE);
+
ZFS_EXIT(zfsvfs);
return (err);
}
bcopy(raw_portable_mac, portable_mac, ZIO_OBJSET_MAC_LEN);
+ /*
+ * This is necessary here as we check next whether
+ * OBJSET_FLAG_USERACCOUNTING_COMPLETE is set in order to
+ * decide if the local_mac should be zeroed out. That flag will always
+ * be set by dmu_objset_id_quota_upgrade_cb() and
+ * dmu_objset_userspace_upgrade_cb() if useraccounting has been
+ * completed.
+ */
+ intval = osp->os_flags;
+ if (should_bswap)
+ intval = BSWAP_64(intval);
+ boolean_t uacct_incomplete =
+ !(intval & OBJSET_FLAG_USERACCOUNTING_COMPLETE);
+
/*
* The local MAC protects the user, group and project accounting.
* If these objects are not present, the local MAC is zeroed out.
*/
- if ((datalen >= OBJSET_PHYS_SIZE_V3 &&
+ if (uacct_incomplete ||
+ (datalen >= OBJSET_PHYS_SIZE_V3 &&
osp->os_userused_dnode.dn_type == DMU_OT_NONE &&
osp->os_groupused_dnode.dn_type == DMU_OT_NONE &&
osp->os_projectused_dnode.dn_type == DMU_OT_NONE) ||
uint8_t *cipherbuf, uint_t datalen, zfs_uio_t *puio, zfs_uio_t *cuio,
uint_t *enc_len)
{
+ (void) encrypt;
int ret;
uint_t nr_plain = 1, nr_cipher = 2;
iovec_t *plain_iovecs = NULL, *cipher_iovecs = NULL;
fstrans_cookie_t cookie;
int error = 0;
- if ((mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) != 0)
+ int test_mode = FALLOC_FL_PUNCH_HOLE;
+#ifdef HAVE_FALLOC_FL_ZERO_RANGE
+ test_mode |= FALLOC_FL_ZERO_RANGE;
+#endif
+
+ if ((mode & ~(FALLOC_FL_KEEP_SIZE | test_mode)) != 0)
return (-EOPNOTSUPP);
if (offset < 0 || len <= 0)
crhold(cr);
cookie = spl_fstrans_mark();
- if (mode & FALLOC_FL_PUNCH_HOLE) {
+ if (mode & (test_mode)) {
flock64_t bf;
if (offset > olen)
{
zvol_state_t *zv;
int error = 0;
- boolean_t drop_suspend = B_TRUE;
- boolean_t drop_namespace = B_FALSE;
+ boolean_t drop_suspend = B_FALSE;
#ifndef HAVE_BLKDEV_GET_ERESTARTSYS
hrtime_t timeout = MSEC2NSEC(zvol_open_timeout_ms);
hrtime_t start = gethrtime();
return (SET_ERROR(-ENXIO));
}
- if (zv->zv_open_count == 0 && !mutex_owned(&spa_namespace_lock)) {
+ mutex_enter(&zv->zv_state_lock);
+ /*
+ * Make sure zvol is not suspended during first open
+ * (hold zv_suspend_lock) and respect proper lock acquisition
+ * ordering - zv_suspend_lock before zv_state_lock
+ */
+ if (zv->zv_open_count == 0) {
+ if (!rw_tryenter(&zv->zv_suspend_lock, RW_READER)) {
+ mutex_exit(&zv->zv_state_lock);
+ rw_enter(&zv->zv_suspend_lock, RW_READER);
+ mutex_enter(&zv->zv_state_lock);
+ /* check to see if zv_suspend_lock is needed */
+ if (zv->zv_open_count != 0) {
+ rw_exit(&zv->zv_suspend_lock);
+ } else {
+ drop_suspend = B_TRUE;
+ }
+ } else {
+ drop_suspend = B_TRUE;
+ }
+ }
+ rw_exit(&zvol_state_lock);
+
+ ASSERT(MUTEX_HELD(&zv->zv_state_lock));
+
+ if (zv->zv_open_count == 0) {
+ boolean_t drop_namespace = B_FALSE;
+
+ ASSERT(RW_READ_HELD(&zv->zv_suspend_lock));
+
/*
* In all other call paths the spa_namespace_lock is taken
* before the bdev->bd_mutex lock. However, on open(2)
* the kernel so the only option is to return the error for
* the caller to handle it.
*/
- if (!mutex_tryenter(&spa_namespace_lock)) {
- rw_exit(&zvol_state_lock);
+ if (!mutex_owned(&spa_namespace_lock)) {
+ if (!mutex_tryenter(&spa_namespace_lock)) {
+ mutex_exit(&zv->zv_state_lock);
+ rw_exit(&zv->zv_suspend_lock);
#ifdef HAVE_BLKDEV_GET_ERESTARTSYS
- schedule();
- return (SET_ERROR(-ERESTARTSYS));
-#else
- if ((gethrtime() - start) > timeout)
+ schedule();
return (SET_ERROR(-ERESTARTSYS));
+#else
+ if ((gethrtime() - start) > timeout)
+ return (SET_ERROR(-ERESTARTSYS));
- schedule_timeout(MSEC_TO_TICK(10));
- goto retry;
+ schedule_timeout(MSEC_TO_TICK(10));
+ goto retry;
#endif
- } else {
- drop_namespace = B_TRUE;
- }
- }
-
- mutex_enter(&zv->zv_state_lock);
- /*
- * make sure zvol is not suspended during first open
- * (hold zv_suspend_lock) and respect proper lock acquisition
- * ordering - zv_suspend_lock before zv_state_lock
- */
- if (zv->zv_open_count == 0) {
- if (!rw_tryenter(&zv->zv_suspend_lock, RW_READER)) {
- mutex_exit(&zv->zv_state_lock);
- rw_enter(&zv->zv_suspend_lock, RW_READER);
- mutex_enter(&zv->zv_state_lock);
- /* check to see if zv_suspend_lock is needed */
- if (zv->zv_open_count != 0) {
- rw_exit(&zv->zv_suspend_lock);
- drop_suspend = B_FALSE;
+ } else {
+ drop_namespace = B_TRUE;
}
}
- } else {
- drop_suspend = B_FALSE;
- }
- rw_exit(&zvol_state_lock);
- ASSERT(MUTEX_HELD(&zv->zv_state_lock));
-
- if (zv->zv_open_count == 0) {
- ASSERT(RW_READ_HELD(&zv->zv_suspend_lock));
error = -zvol_first_open(zv, !(flag & FMODE_WRITE));
- if (error)
- goto out_mutex;
- }
- if ((flag & FMODE_WRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
- error = -EROFS;
- goto out_open_count;
+ if (drop_namespace)
+ mutex_exit(&spa_namespace_lock);
}
- zv->zv_open_count++;
-
- mutex_exit(&zv->zv_state_lock);
- if (drop_namespace)
- mutex_exit(&spa_namespace_lock);
- if (drop_suspend)
- rw_exit(&zv->zv_suspend_lock);
-
- zfs_check_media_change(bdev);
-
- return (0);
+ if (error == 0) {
+ if ((flag & FMODE_WRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
+ if (zv->zv_open_count == 0)
+ zvol_last_close(zv);
-out_open_count:
- if (zv->zv_open_count == 0)
- zvol_last_close(zv);
+ error = SET_ERROR(-EROFS);
+ } else {
+ zv->zv_open_count++;
+ }
+ }
-out_mutex:
mutex_exit(&zv->zv_state_lock);
- if (drop_namespace)
- mutex_exit(&spa_namespace_lock);
if (drop_suspend)
rw_exit(&zv->zv_suspend_lock);
- return (SET_ERROR(error));
+ if (error == 0)
+ zfs_check_media_change(bdev);
+
+ return (error);
}
static void
rw_enter(&zvol_state_lock, RW_WRITER);
zvol_insert(zv);
rw_exit(&zvol_state_lock);
+#ifdef HAVE_ADD_DISK_RET
+ error = add_disk(zv->zv_zso->zvo_disk);
+#else
add_disk(zv->zv_zso->zvo_disk);
+#endif
} else {
ida_simple_remove(&zvol_ida, idx);
}
"ENCROOT");
zprop_register_string(ZFS_PROP_KEYLOCATION, "keylocation",
"none", PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
- "prompt | <file URI>", "KEYLOCATION");
+ "prompt | <file URI> | <https URL> | <http URL>", "KEYLOCATION");
zprop_register_string(ZFS_PROP_REDACT_SNAPS,
"redact_snaps", NULL, PROP_READONLY,
ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "<snapshot>[,...]",
return (B_TRUE);
else if (strlen(str) > 8 && strncmp("file:///", str, 8) == 0)
return (B_TRUE);
+ else if (strlen(str) > 8 && strncmp("https://", str, 8) == 0)
+ return (B_TRUE);
+ else if (strlen(str) > 7 && strncmp("http://", str, 7) == 0)
+ return (B_TRUE);
return (B_FALSE);
}
#include <sys/simd.h>
-#if defined(HAVE_KERNEL_FPU_INTERNAL)
+#if defined(HAVE_KERNEL_FPU_INTERNAL) || defined(HAVE_KERNEL_FPU_XSAVE_INTERNAL)
union fpregs_state **zfs_kfpu_fpregs;
EXPORT_SYMBOL(zfs_kfpu_fpregs);
-#endif /* HAVE_KERNEL_FPU_INTERNAL */
+#endif /* HAVE_KERNEL_FPU_INTERNAL || HAVE_KERNEL_FPU_XSAVE_INTERNAL */
static int __init
zcommon_init(void)
&ba_ptr);
}
-/*ARGSUSED*/
static int
abd_zero_off_cb(void *buf, size_t size, void *private)
{
+ (void) private;
(void) memset(buf, 0, size);
return (0);
}
return (ret);
}
-/*ARGSUSED*/
static int
abd_copy_off_cb(void *dbuf, void *sbuf, size_t size, void *private)
{
+ (void) private;
(void) memcpy(dbuf, sbuf, size);
return (0);
}
abd_copy_off_cb, NULL);
}
-/*ARGSUSED*/
static int
abd_cmp_cb(void *bufa, void *bufb, size_t size, void *private)
{
+ (void) private;
return (memcmp(bufa, bufb, size));
}
int zfs_arc_meta_adjust_restarts = 4096;
int zfs_arc_lotsfree_percent = 10;
+/*
+ * Number of arc_prune threads
+ */
+static int zfs_arc_prune_task_threads = 1;
+
/* The 6 states: */
arc_state_t ARC_anon;
arc_state_t ARC_mru;
static void
buf_fini(void)
{
- int i;
-
#if defined(_KERNEL)
/*
* Large allocations which do not require contiguous pages
kmem_free(buf_hash_table.ht_table,
(buf_hash_table.ht_mask + 1) * sizeof (void *));
#endif
- for (i = 0; i < BUF_LOCKS; i++)
+ for (int i = 0; i < BUF_LOCKS; i++)
mutex_destroy(BUF_HASH_LOCK(i));
kmem_cache_destroy(hdr_full_cache);
kmem_cache_destroy(hdr_full_crypt_cache);
* Constructor callback - called when the cache is empty
* and a new buf is requested.
*/
-/* ARGSUSED */
static int
hdr_full_cons(void *vbuf, void *unused, int kmflag)
{
+ (void) unused, (void) kmflag;
arc_buf_hdr_t *hdr = vbuf;
bzero(hdr, HDR_FULL_SIZE);
return (0);
}
-/* ARGSUSED */
static int
hdr_full_crypt_cons(void *vbuf, void *unused, int kmflag)
{
+ (void) unused;
arc_buf_hdr_t *hdr = vbuf;
hdr_full_cons(vbuf, unused, kmflag);
return (0);
}
-/* ARGSUSED */
static int
hdr_l2only_cons(void *vbuf, void *unused, int kmflag)
{
+ (void) unused, (void) kmflag;
arc_buf_hdr_t *hdr = vbuf;
bzero(hdr, HDR_L2ONLY_SIZE);
return (0);
}
-/* ARGSUSED */
static int
buf_cons(void *vbuf, void *unused, int kmflag)
{
+ (void) unused, (void) kmflag;
arc_buf_t *buf = vbuf;
bzero(buf, sizeof (arc_buf_t));
* Destructor callback - called when a cached buf is
* no longer required.
*/
-/* ARGSUSED */
static void
hdr_full_dest(void *vbuf, void *unused)
{
+ (void) unused;
arc_buf_hdr_t *hdr = vbuf;
ASSERT(HDR_EMPTY(hdr));
arc_space_return(HDR_FULL_SIZE, ARC_SPACE_HDRS);
}
-/* ARGSUSED */
static void
hdr_full_crypt_dest(void *vbuf, void *unused)
{
+ (void) unused;
arc_buf_hdr_t *hdr = vbuf;
hdr_full_dest(vbuf, unused);
arc_space_return(sizeof (hdr->b_crypt_hdr), ARC_SPACE_HDRS);
}
-/* ARGSUSED */
static void
hdr_l2only_dest(void *vbuf, void *unused)
{
- arc_buf_hdr_t *hdr __maybe_unused = vbuf;
+ (void) unused;
+ arc_buf_hdr_t *hdr = vbuf;
ASSERT(HDR_EMPTY(hdr));
arc_space_return(HDR_L2ONLY_SIZE, ARC_SPACE_L2HDRS);
}
-/* ARGSUSED */
static void
buf_dest(void *vbuf, void *unused)
{
+ (void) unused;
arc_buf_t *buf = vbuf;
mutex_destroy(&buf->b_evict_lock);
void
arc_buf_sigsegv(int sig, siginfo_t *si, void *unused)
{
+ (void) sig, (void) unused;
panic("Got SIGSEGV at address: 0x%lx\n", (long)si->si_addr);
}
#endif
-/* ARGSUSED */
static void
arc_buf_unwatch(arc_buf_t *buf)
{
ASSERT0(mprotect(buf->b_data, arc_buf_size(buf),
PROT_READ | PROT_WRITE));
}
+#else
+ (void) buf;
#endif
}
-/* ARGSUSED */
static void
arc_buf_watch(arc_buf_t *buf)
{
if (arc_watch)
ASSERT0(mprotect(buf->b_data, arc_buf_size(buf),
PROT_READ));
+#else
+ (void) buf;
#endif
}
* arc_buf_fill().
*/
static void
-arc_buf_untransform_in_place(arc_buf_t *buf, kmutex_t *hash_lock)
+arc_buf_untransform_in_place(arc_buf_t *buf)
{
arc_buf_hdr_t *hdr = buf->b_hdr;
if (hash_lock != NULL)
mutex_enter(hash_lock);
- arc_buf_untransform_in_place(buf, hash_lock);
+ arc_buf_untransform_in_place(buf);
if (hash_lock != NULL)
mutex_exit(hash_lock);
void
arc_buf_info(arc_buf_t *ab, arc_buf_info_t *abi, int state_index)
{
+ (void) state_index;
arc_buf_hdr_t *hdr = ab->b_hdr;
l1arc_buf_hdr_t *l1hdr = NULL;
l2arc_buf_hdr_t *l2hdr = NULL;
abd_cache_reap_now();
}
-/* ARGSUSED */
static boolean_t
arc_evict_cb_check(void *arg, zthr_t *zthr)
{
+ (void) arg, (void) zthr;
+
#ifdef ZFS_DEBUG
/*
* This is necessary in order to keep the kstat information
* Keep arc_size under arc_c by running arc_evict which evicts data
* from the ARC.
*/
-/* ARGSUSED */
static void
arc_evict_cb(void *arg, zthr_t *zthr)
{
+ (void) arg, (void) zthr;
+
uint64_t evicted = 0;
fstrans_cookie_t cookie = spl_fstrans_mark();
spl_fstrans_unmark(cookie);
}
-/* ARGSUSED */
static boolean_t
arc_reap_cb_check(void *arg, zthr_t *zthr)
{
+ (void) arg, (void) zthr;
+
int64_t free_memory = arc_available_memory();
static int reap_cb_check_counter = 0;
* target size of the cache (arc_c), causing the arc_evict_cb()
* to free more buffers.
*/
-/* ARGSUSED */
static void
arc_reap_cb(void *arg, zthr_t *zthr)
{
+ (void) arg, (void) zthr;
+
int64_t free_memory;
fstrans_cookie_t cookie = spl_fstrans_mark();
}
/* a generic arc_read_done_func_t which you can use */
-/* ARGSUSED */
void
arc_bcopy_func(zio_t *zio, const zbookmark_phys_t *zb, const blkptr_t *bp,
arc_buf_t *buf, void *arg)
{
+ (void) zio, (void) zb, (void) bp;
+
if (buf == NULL)
return;
}
/* a generic arc_read_done_func_t */
-/* ARGSUSED */
void
arc_getbuf_func(zio_t *zio, const zbookmark_phys_t *zb, const blkptr_t *bp,
arc_buf_t *buf, void *arg)
{
+ (void) zb, (void) bp;
arc_buf_t **bufp = arg;
if (buf == NULL) {
offsetof(arc_prune_t, p_node));
mutex_init(&arc_prune_mtx, NULL, MUTEX_DEFAULT, NULL);
- arc_prune_taskq = taskq_create("arc_prune", 100, defclsyspri,
- boot_ncpus, INT_MAX, TASKQ_PREPOPULATE | TASKQ_DYNAMIC |
- TASKQ_THREADS_CPU_PCT);
+ arc_prune_taskq = taskq_create("arc_prune", zfs_arc_prune_task_threads,
+ defclsyspri, 100, INT_MAX, TASKQ_PREPOPULATE | TASKQ_DYNAMIC);
arc_ksp = kstat_create("zfs", 0, "arcstats", "misc", KSTAT_TYPE_NAMED,
sizeof (arc_stats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL);
* This thread feeds the L2ARC at regular intervals. This is the beating
* heart of the L2ARC.
*/
-/* ARGSUSED */
static void
l2arc_feed_thread(void *unused)
{
+ (void) unused;
callb_cpr_t cpr;
l2arc_dev_t *dev;
spa_t *spa;
ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, evict_batch_limit, INT, ZMOD_RW,
"The number of headers to evict per sublist before moving to the next");
+
+ZFS_MODULE_PARAM(zfs_arc, zfs_arc_, prune_task_threads, INT, ZMOD_RW,
+ "Number of arc_prune threads");
/* END CSTYLED */
uint64_t uncomp;
};
-/* ARGSUSED */
static int
space_range_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed, dmu_tx_t *tx)
{
+ (void) bp_freed, (void) tx;
struct space_range_arg *sra = arg;
if (bp->blk_birth > sra->mintxg && bp->blk_birth <= sra->maxtxg) {
* bpobj are designated as free or allocated that information is not preserved
* in bplists.
*/
-/* ARGSUSED */
int
bplist_append_cb(void *arg, const blkptr_t *bp, boolean_t bp_freed,
dmu_tx_t *tx)
{
+ (void) bp_freed, (void) tx;
bplist_t *bpl = arg;
bplist_append(bpl, bp);
return (0);
dmu_buf_rele(db, FTAG);
}
-/* ARGSUSED */
static int
bptree_visit_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
{
+ (void) zilog, (void) dnp;
int err;
struct bptree_args *ba = arg;
static void dbuf_sync_leaf_verify_bonus_dnode(dbuf_dirty_record_t *dr);
static int dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, uint32_t flags);
-extern inline void dmu_buf_init_user(dmu_buf_user_t *dbu,
- dmu_buf_evict_func_t *evict_func_sync,
- dmu_buf_evict_func_t *evict_func_async,
- dmu_buf_t **clear_on_evict_dbufp);
-
/*
* Global data structures and functions for the dbuf cache.
*/
uint_t dbuf_cache_hiwater_pct = 10;
uint_t dbuf_cache_lowater_pct = 10;
-/* ARGSUSED */
static int
dbuf_cons(void *vdb, void *unused, int kmflag)
{
+ (void) unused, (void) kmflag;
dmu_buf_impl_t *db = vdb;
bzero(db, sizeof (dmu_buf_impl_t));
return (0);
}
-/* ARGSUSED */
static void
dbuf_dest(void *vdb, void *unused)
{
+ (void) unused;
dmu_buf_impl_t *db = vdb;
mutex_destroy(&db->db_mtx);
rw_destroy(&db->db_rwlock);
* of the dbuf cache is at or below the maximum size. Once the dbuf is aged
* out of the cache it is destroyed and becomes eligible for arc eviction.
*/
-/* ARGSUSED */
static void
dbuf_evict_thread(void *unused)
{
+ (void) unused;
callb_cpr_t cpr;
CALLB_CPR_INIT(&cpr, &dbuf_evict_lock, callb_generic_cpr, FTAG);
dbuf_read_done(zio_t *zio, const zbookmark_phys_t *zb, const blkptr_t *bp,
arc_buf_t *buf, void *vdb)
{
+ (void) zb, (void) bp;
dmu_buf_impl_t *db = vdb;
mutex_enter(&db->db_mtx);
* was taken, ENOENT if no action was taken.
*/
static int
-dbuf_read_hole(dmu_buf_impl_t *db, dnode_t *dn, uint32_t flags)
+dbuf_read_hole(dmu_buf_impl_t *db, dnode_t *dn)
{
ASSERT(MUTEX_HELD(&db->db_mtx));
goto early_unlock;
}
- err = dbuf_read_hole(db, dn, flags);
+ err = dbuf_read_hole(db, dn);
if (err == 0)
goto early_unlock;
dl->dr_overridden_by.blk_birth = dr->dr_txg;
}
-/* ARGSUSED */
void
dmu_buf_fill_done(dmu_buf_t *dbuf, dmu_tx_t *tx)
{
+ (void) tx;
dmu_buf_impl_t *db = (dmu_buf_impl_t *)dbuf;
dbuf_states_t old_state;
mutex_enter(&db->db_mtx);
dbuf_issue_final_prefetch_done(zio_t *zio, const zbookmark_phys_t *zb,
const blkptr_t *iobp, arc_buf_t *abuf, void *private)
{
+ (void) zio, (void) zb, (void) iobp;
dbuf_prefetch_arg_t *dpa = private;
dbuf_prefetch_fini(dpa, B_TRUE);
dbuf_prefetch_indirect_done(zio_t *zio, const zbookmark_phys_t *zb,
const blkptr_t *iobp, arc_buf_t *abuf, void *private)
{
+ (void) zb, (void) iobp;
dbuf_prefetch_arg_t *dpa = private;
ASSERT3S(dpa->dpa_zb.zb_level, <, dpa->dpa_curlevel);
}
}
-/* ARGSUSED */
static void
dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
{
+ (void) buf;
dmu_buf_impl_t *db = vdb;
dnode_t *dn;
blkptr_t *bp = zio->io_bp;
dmu_buf_unlock_parent(db, dblt, FTAG);
}
-/* ARGSUSED */
/*
* This function gets called just prior to running through the compression
* stage of the zio pipeline. If we're an indirect block comprised of only
static void
dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
{
+ (void) zio, (void) buf;
dmu_buf_impl_t *db = vdb;
dnode_t *dn;
blkptr_t *bp;
* so this callback allows us to retire dirty space gradually, as the physical
* i/os complete.
*/
-/* ARGSUSED */
static void
dbuf_write_physdone(zio_t *zio, arc_buf_t *buf, void *arg)
{
+ (void) buf;
dmu_buf_impl_t *db = arg;
objset_t *os = db->db_objset;
dsl_pool_t *dp = dmu_objset_pool(os);
dsl_pool_undirty_space(dp, delta, zio->io_txg);
}
-/* ARGSUSED */
static void
dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb)
{
+ (void) buf;
dmu_buf_impl_t *db = vdb;
blkptr_t *bp_orig = &zio->io_bp_orig;
blkptr_t *bp = db->db_blkptr;
* otherwise return false.
* Used below in dmu_free_long_range_impl() to enable abort when unmounting
*/
-/*ARGSUSED*/
static boolean_t
dmu_objset_zfs_unmounting(objset_t *os)
{
#ifdef _KERNEL
if (dmu_objset_type(os) == DMU_OST_ZFS)
return (zfs_get_vfs_flag_unmounted(os));
+#else
+ (void) os;
#endif
return (B_FALSE);
}
dmu_tx_t *dsa_tx;
} dmu_sync_arg_t;
-/* ARGSUSED */
static void
dmu_sync_ready(zio_t *zio, arc_buf_t *buf, void *varg)
{
+ (void) buf;
dmu_sync_arg_t *dsa = varg;
dmu_buf_t *db = dsa->dsa_zgd->zgd_db;
blkptr_t *bp = zio->io_bp;
dmu_sync_ready(zio, NULL, zio->io_private);
}
-/* ARGSUSED */
static void
dmu_sync_done(zio_t *zio, arc_buf_t *buf, void *varg)
{
+ (void) buf;
dmu_sync_arg_t *dsa = varg;
dbuf_dirty_record_t *dr = dsa->dsa_dr;
dmu_buf_impl_t *db = dr->dr_dbuf;
buf[i] = BSWAP_16(buf[i]);
}
-/* ARGSUSED */
void
byteswap_uint8_array(void *vbuf, size_t size)
{
+ (void) vbuf, (void) size;
}
void
(((uint64_t)dnp->dn_datablkszsec) << (SPA_MINBLOCKSHIFT + \
(level) * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT)))
-/* ARGSUSED */
static int
diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
{
+ (void) zilog;
dmu_diffarg_t *da = arg;
int err = 0;
dmu_objset_own_impl(dsl_dataset_t *ds, dmu_objset_type_t type,
boolean_t readonly, boolean_t decrypt, void *tag, objset_t **osp)
{
- int err;
+ (void) tag;
- err = dmu_objset_from_ds(ds, osp);
+ int err = dmu_objset_from_ds(ds, osp);
if (err != 0) {
return (err);
} else if (type != DMU_OST_ANY && type != (*osp)->os_phys->os_type) {
dsl_crypto_params_t *doca_dcp;
} dmu_objset_create_arg_t;
-/*ARGSUSED*/
static int
dmu_objset_create_check(void *arg, dmu_tx_t *tx)
{
proc_t *doca_proc;
} dmu_objset_clone_arg_t;
-/*ARGSUSED*/
static int
dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
{
}
}
-/* ARGSUSED */
static void
dmu_objset_write_ready(zio_t *zio, arc_buf_t *abuf, void *arg)
{
+ (void) abuf;
blkptr_t *bp = zio->io_bp;
objset_t *os = arg;
dnode_phys_t *dnp = &os->os_phys->os_meta_dnode;
rrw_exit(&os->os_dsl_dataset->ds_bp_rwlock, FTAG);
}
-/* ARGSUSED */
static void
dmu_objset_write_done(zio_t *zio, arc_buf_t *abuf, void *arg)
{
+ (void) abuf;
blkptr_t *bp = zio->io_bp;
blkptr_t *bp_orig = &zio->io_bp_orig;
objset_t *os = arg;
if (!(flags & DRR_FLAG_SPILL_BLOCK))
return (SET_ERROR(ZFS_ERR_SPILL_BLOCK_FLAG_MISSING));
} else {
- dsflags |= DS_HOLD_FLAG_DECRYPT;
+ /*
+ * We support unencrypted datasets below encrypted ones now,
+ * so add the DS_HOLD_FLAG_DECRYPT flag only if we are dealing
+ * with a dataset we may encrypt.
+ */
+ if (drba->drba_dcp != NULL &&
+ drba->drba_dcp->cp_crypt != ZIO_CRYPT_OFF) {
+ dsflags |= DS_HOLD_FLAG_DECRYPT;
+ }
}
error = dsl_dataset_hold_flags(dp, tofs, dsflags, FTAG, &ds);
* Third, if there is a deleted object, we need to create a redaction record for
* all of the blocks in that object.
*/
-/*ARGSUSED*/
static int
redact_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const struct dnode_phys *dnp, void *arg)
{
+ (void) spa, (void) zilog;
struct redact_thread_arg *rta = arg;
struct redact_record *record;
* to send it.
*/
if (bonuslen != 0) {
+ if (drro->drr_bonuslen > DN_MAX_BONUS_LEN(dnp))
+ return (SET_ERROR(EINVAL));
drro->drr_raw_bonuslen = DN_MAX_BONUS_LEN(dnp);
bonuslen = drro->drr_raw_bonuslen;
}
* This is the callback function to traverse_dataset that acts as a worker
* thread for dmu_send_impl.
*/
-/*ARGSUSED*/
static int
send_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const struct dnode_phys *dnp, void *arg)
{
+ (void) zilog;
struct send_thread_arg *sta = arg;
struct send_range *record;
struct send_merge_thread_arg *smt_arg, boolean_t resuming, objset_t *os,
redaction_list_t *redact_rl, nvlist_t *nvl)
{
+ (void) smt_arg;
dsl_dataset_t *to_ds = dspp->to_ds;
int err = 0;
return (err);
}
-/* ARGSUSED */
static int
traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
{
+ (void) zilog, (void) dnp;
prefetch_data_t *pfd = arg;
int zio_flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE;
arc_flags_t aflags = ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH |
static void
dmu_zfetch_stream_done(void *arg, boolean_t io_issued)
{
+ (void) io_issued;
zstream_t *zs = arg;
if (zfs_refcount_remove(&zs->zs_refs, NULL) == 0)
return (TREE_PCMP(d1, d2));
}
-/* ARGSUSED */
static int
dnode_cons(void *arg, void *unused, int kmflag)
{
+ (void) unused, (void) kmflag;
dnode_t *dn = arg;
- int i;
rw_init(&dn->dn_struct_rwlock, NULL, RW_NOLOCKDEP, NULL);
mutex_init(&dn->dn_mtx, NULL, MUTEX_DEFAULT, NULL);
bzero(&dn->dn_next_blksz[0], sizeof (dn->dn_next_blksz));
bzero(&dn->dn_next_maxblkid[0], sizeof (dn->dn_next_maxblkid));
- for (i = 0; i < TXG_SIZE; i++) {
+ for (int i = 0; i < TXG_SIZE; i++) {
multilist_link_init(&dn->dn_dirty_link[i]);
dn->dn_free_ranges[i] = NULL;
list_create(&dn->dn_dirty_records[i],
return (0);
}
-/* ARGSUSED */
static void
dnode_dest(void *arg, void *unused)
{
- int i;
+ (void) unused;
dnode_t *dn = arg;
rw_destroy(&dn->dn_struct_rwlock);
zfs_refcount_destroy(&dn->dn_tx_holds);
ASSERT(!list_link_active(&dn->dn_link));
- for (i = 0; i < TXG_SIZE; i++) {
+ for (int i = 0; i < TXG_SIZE; i++) {
ASSERT(!multilist_link_active(&dn->dn_dirty_link[i]));
ASSERT3P(dn->dn_free_ranges[i], ==, NULL);
list_destroy(&dn->dn_dirty_records[i]);
odn->dn_moved = (uint8_t)-1;
}
-/*ARGSUSED*/
static kmem_cbrc_t
dnode_move(void *buf, void *newbuf, size_t size, void *arg)
{
DNODE_FLAG_USEROBJUSED_ACCOUNTED;
mutex_exit(&dn->dn_mtx);
dmu_objset_userquota_get_ids(dn, B_FALSE, tx);
- } else {
- /* Once we account for it, we should always account for it */
+ } else if (!(os->os_encrypted && dmu_objset_is_receiving(os))) {
+ /*
+ * Once we account for it, we should always account for it,
+ * except for the case of a raw receive. We will not be able
+ * to account for it until the receiving dataset has been
+ * mounted.
+ */
ASSERT(!(dn->dn_phys->dn_flags &
DNODE_FLAG_USERUSED_ACCOUNTED));
ASSERT(!(dn->dn_phys->dn_flags &
dnode_rele(dn, (void *)(uintptr_t)tx->tx_txg);
}
+ ASSERT3U(dnp->dn_bonuslen, <=, DN_MAX_BONUS_LEN(dnp));
+
/*
* Although we have dropped our reference to the dnode, it
* can't be evicted until its written, and we haven't yet
(void) zfs_refcount_remove(&rl->rl_longholds, tag);
}
-/* ARGSUSED */
static void
redaction_list_evict_sync(void *rlu)
{
* Adjust the FBN of any bookmarks that reference this block, whose "next"
* is the head dataset.
*/
-/* ARGSUSED */
void
dsl_bookmark_block_killed(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
{
+ (void) tx;
+
/*
* Iterate over bookmarks whose "next" is the head dataset.
*/
if (ret != 0)
return (ret);
- /*
- * Useraccounting is not portable and must be done with the keys loaded.
- * Therefore, whenever we do any kind of receive the useraccounting
- * must not be present.
- */
- ASSERT0(os->os_flags & OBJSET_FLAG_USERACCOUNTING_COMPLETE);
- ASSERT0(os->os_flags & OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE);
-
mdn = DMU_META_DNODE(os);
/*
arc_release(os->os_phys_buf, &os->os_phys_buf);
bcopy(portable_mac, os->os_phys->os_portable_mac, ZIO_OBJSET_MAC_LEN);
bzero(os->os_phys->os_local_mac, ZIO_OBJSET_MAC_LEN);
+ os->os_flags &= ~OBJSET_FLAG_USERACCOUNTING_COMPLETE;
os->os_next_write_raw[tx->tx_txg & TXG_MASK] = B_TRUE;
/* set metadnode compression and checksum */
#define DS_REF_MAX (1ULL << 62)
-extern inline dsl_dataset_phys_t *dsl_dataset_phys(dsl_dataset_t *ds);
-
static void dsl_dataset_set_remap_deadlist_object(dsl_dataset_t *ds,
uint64_t obj, dmu_tx_t *tx);
static void dsl_dataset_unset_remap_deadlist_object(dsl_dataset_t *ds,
dmu_tx_t *ddrsa_tx;
} dsl_dataset_rename_snapshot_arg_t;
-/* ARGSUSED */
static int
dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
dsl_dataset_t *hds, void *arg)
{
+ (void) dp;
dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
int error;
uint64_t val;
} dsl_dataset_set_qr_arg_t;
-/* ARGSUSED */
static int
dsl_dataset_set_refquota_check(void *arg, dmu_tx_t *tx)
{
uint64_t ddsca_value;
} dsl_dataset_set_compression_arg_t;
-/* ARGSUSED */
static int
dsl_dataset_set_compression_check(void *arg, dmu_tx_t *tx)
{
dmu_tx_t *tx;
};
-/* ARGSUSED */
static int
kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
{
+ (void) spa, (void) dnp;
struct killarg *ka = arg;
dmu_tx_t *tx = ka->tx;
* inconsistent datasets, even if we encounter an error trying to
* process one of them.
*/
-/* ARGSUSED */
int
dsl_destroy_inconsistent(const char *dsname, void *arg)
{
+ (void) arg;
objset_t *os;
if (dmu_objset_hold(dsname, FTAG, &os) == 0) {
* dsl_dir_init_fs_ss_count().
*/
-extern inline dsl_dir_phys_t *dsl_dir_phys(dsl_dir_t *dd);
-
static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
typedef struct ddulrt_arg {
*/
if (secpolicy_zfs_proc(cr, proc) == 0)
return (ENFORCE_NEVER);
+#else
+ (void) proc;
#endif
if ((obj = dsl_dir_phys(dd)->dd_head_dataset_obj) == 0)
* we're very close to full, this will allow a steady trickle of
* removes to get through.
*/
- uint64_t deferred = 0;
if (dd->dd_parent == NULL) {
uint64_t avail = dsl_pool_unreserved_space(dd->dd_pool,
(netfree) ?
/*
* If they are requesting more space, and our current estimate
* is over quota, they get to try again unless the actual
- * on-disk is over quota and there are no pending changes (which
- * may free up space for us).
+ * on-disk is over quota and there are no pending changes
+ * or deferred frees (which may free up space for us).
*/
if (used_on_disk + est_inflight >= quota) {
- if (est_inflight > 0 || used_on_disk < quota ||
- (retval == ENOSPC && used_on_disk < quota + deferred))
- retval = ERESTART;
+ if (est_inflight > 0 || used_on_disk < quota) {
+ retval = SET_ERROR(ERESTART);
+ } else {
+ ASSERT3U(used_on_disk, >=, quota);
+
+ if (retval == ENOSPC && (used_on_disk - quota) <
+ dsl_pool_deferred_space(dd->dd_pool)) {
+ retval = SET_ERROR(ERESTART);
+ }
+ }
+
dprintf_dd(dd, "failing: used=%lluK inflight = %lluK "
"quota=%lluK tr=%lluK err=%d\n",
(u_longlong_t)used_on_disk>>10,
(u_longlong_t)quota>>10, (u_longlong_t)asize>>10, retval);
mutex_exit(&dd->dd_lock);
DMU_TX_STAT_BUMP(dmu_tx_quota);
- return (SET_ERROR(retval));
+ return (retval);
}
/* We need to up our estimated delta before dropping dd_lock */
int nest_delta;
} dsl_valid_rename_arg_t;
-/* ARGSUSED */
static int
dsl_valid_rename(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
{
+ (void) dp;
dsl_valid_rename_arg_t *dvra = arg;
char namebuf[ZFS_MAX_DATASET_NAME_LEN];
* The delete queue is ZPL specific, and libzpool doesn't have
* it. It doesn't make sense to wait for it.
*/
+ (void) ds;
*in_progress = B_FALSE;
break;
#endif
}
dsl_pool_t *
-dsl_pool_create(spa_t *spa, nvlist_t *zplprops, dsl_crypto_params_t *dcp,
- uint64_t txg)
+dsl_pool_create(spa_t *spa, nvlist_t *zplprops __attribute__((unused)),
+ dsl_crypto_params_t *dcp, uint64_t txg)
{
int err;
dsl_pool_t *dp = dsl_pool_open_impl(spa, txg);
return (quota);
}
+uint64_t
+dsl_pool_deferred_space(dsl_pool_t *dp)
+{
+ return (metaslab_class_get_deferred(spa_normal_class(dp->dp_spa)));
+}
+
boolean_t
dsl_pool_need_dirty_delay(dsl_pool_t *dp)
{
return (!list_is_empty(&ds->ds_prop_cbs));
}
-/* ARGSUSED */
static int
dsl_prop_notify_all_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
{
+ (void) arg;
dsl_dir_t *dd = ds->ds_dir;
dsl_prop_record_t *pr;
dsl_prop_cb_record_t *cbr;
}
}
-/* ARGSUSED */
int
dsl_scan_setup_check(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
vdev_t *rvd = scn->scn_dp->dp_spa->spa_root_vdev;
dsl_scan_setup_sync, &func, 0, ZFS_SPACE_CHECK_EXTRA_RESERVED));
}
-/* ARGSUSED */
static void
dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
{
ASSERT(!dsl_scan_is_running(scn));
}
-/* ARGSUSED */
static int
dsl_scan_cancel_check(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
if (!dsl_scan_is_running(scn))
return (0);
}
-/* ARGSUSED */
static void
dsl_scan_cancel_sync(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
dsl_scan_done(scn, B_FALSE, tx);
zil_header_t *zsa_zh;
} zil_scan_arg_t;
-/* ARGSUSED */
static int
dsl_scan_zil_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
uint64_t claim_txg)
{
+ (void) zilog;
zil_scan_arg_t *zsa = arg;
dsl_pool_t *dp = zsa->zsa_dp;
dsl_scan_t *scn = dp->dp_scan;
return (0);
}
-/* ARGSUSED */
static int
dsl_scan_zil_record(zilog_t *zilog, const lr_t *lrc, void *arg,
uint64_t claim_txg)
{
+ (void) zilog;
if (lrc->lrc_txtype == TX_WRITE) {
zil_scan_arg_t *zsa = arg;
dsl_pool_t *dp = zsa->zsa_dp;
dsl_scan_prefetch_cb(zio_t *zio, const zbookmark_phys_t *zb, const blkptr_t *bp,
arc_buf_t *buf, void *private)
{
+ (void) zio;
scan_prefetch_ctx_t *spc = private;
dsl_scan_t *scn = spc->spc_scn;
spa_t *spa = scn->scn_dp->dp_spa;
scan_prefetch_ctx_rele(spc, scn);
}
-/* ARGSUSED */
static void
dsl_scan_prefetch_thread(void *arg)
{
ASSERT(!BP_IS_REDACTED(bp));
+ /*
+ * There is an unlikely case of encountering dnodes with contradicting
+ * dn_bonuslen and DNODE_FLAG_SPILL_BLKPTR flag before in files created
+ * or modified before commit 4254acb was merged. As it is not possible
+ * to know which of the two is correct, report an error.
+ */
+ if (dnp != NULL &&
+ dnp->dn_bonuslen > DN_MAX_BONUS_LEN(dnp)) {
+ scn->scn_phys.scn_errors++;
+ spa_log_error(dp->dp_spa, zb);
+ return (SET_ERROR(EINVAL));
+ }
+
if (BP_GET_LEVEL(bp) > 0) {
arc_flags_t flags = ARC_FLAG_WAIT;
int i;
dsl_scan_sync_state(scn, tx, SYNC_CACHED);
}
-/* ARGSUSED */
static int
enqueue_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg)
{
dsl_dataset_rele(ds, FTAG);
}
-/* ARGSUSED */
static int
enqueue_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg)
{
+ (void) arg;
dsl_dataset_t *ds;
int err;
dsl_scan_t *scn = dp->dp_scan;
return (0);
}
-/* ARGSUSED */
void
dsl_scan_ddt_entry(dsl_scan_t *scn, enum zio_checksum checksum,
ddt_entry_t *dde, dmu_tx_t *tx)
{
+ (void) tx;
const ddt_key_t *ddk = &dde->dde_key;
ddt_phys_t *ddp = dde->dde_phys;
blkptr_t bp;
zbookmark_phys_t zb = { 0 };
- int p;
if (!dsl_scan_is_running(scn))
return;
if (scn->scn_done_txg != 0)
return;
- for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
+ for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
if (ddp->ddp_phys_birth == 0 ||
ddp->ddp_phys_birth > scn->scn_phys.scn_max_txg)
continue;
#define DST_AVG_BLKSHIFT 14
-/* ARGSUSED */
static int
dsl_null_checkfunc(void *arg, dmu_tx_t *tx)
{
+ (void) arg, (void) tx;
return (0);
}
/*
* Wrappers for FM nvlist allocators
*/
-/* ARGSUSED */
static void *
i_fm_alloc(nv_alloc_t *nva, size_t size)
{
+ (void) nva;
return (kmem_zalloc(size, KM_SLEEP));
}
-/* ARGSUSED */
static void
i_fm_free(nv_alloc_t *nva, void *buf, size_t size)
{
+ (void) nva;
kmem_free(buf, size);
}
return ((size_t)dstlen);
}
-/*ARGSUSED*/
int
gzip_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
{
+ (void) n;
zlen_t dstlen = d_len;
ASSERT(d_len >= s_len);
static void *lz4_alloc(int flags);
static void lz4_free(void *ctx);
-/*ARGSUSED*/
size_t
lz4_compress_zfs(void *s_start, void *d_start, size_t s_len,
size_t d_len, int n)
{
+ (void) n;
uint32_t bufsiz;
char *dest = d_start;
return (bufsiz + sizeof (bufsiz));
}
-/*ARGSUSED*/
int
lz4_decompress_zfs(void *s_start, void *d_start, size_t s_len,
size_t d_len, int n)
{
+ (void) n;
const char *src = s_start;
uint32_t bufsiz = BE_IN32(src);
/* Compression functions */
-/*ARGSUSED*/
static int
LZ4_compressCtx(void *ctx, const char *source, char *dest, int isize,
int osize)
HASHLOG64K))
#define LZ4_HASH64K_VALUE(p) LZ4_HASH64K_FUNCTION(A32(p))
-/*ARGSUSED*/
static int
LZ4_compress64kCtx(void *ctx, const char *source, char *dest, int isize,
int osize)
#define OFFSET_MASK ((1 << (16 - MATCH_BITS)) - 1)
#define LEMPEL_SIZE 1024
-/*ARGSUSED*/
size_t
lzjb_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
{
+ (void) n;
uchar_t *src = s_start;
uchar_t *dst = d_start;
uchar_t *cpy;
return (dst - (uchar_t *)d_start);
}
-/*ARGSUSED*/
int
lzjb_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
{
+ (void) s_len, (void) n;
uchar_t *src = s_start;
uchar_t *dst = d_start;
uchar_t *d_end = (uchar_t *)d_start + d_len;
* Create any block allocator specific components. The current allocators
* rely on using both a size-ordered range_tree_t and an array of uint64_t's.
*/
-/* ARGSUSED */
static void
metaslab_rt_create(range_tree_t *rt, void *arg)
{
mrap->mra_floor_shift = metaslab_by_size_min_shift;
}
-/* ARGSUSED */
static void
metaslab_rt_destroy(range_tree_t *rt, void *arg)
{
+ (void) rt;
metaslab_rt_arg_t *mrap = arg;
zfs_btree_t *size_tree = mrap->mra_bt;
kmem_free(mrap, sizeof (*mrap));
}
-/* ARGSUSED */
static void
metaslab_rt_add(range_tree_t *rt, range_seg_t *rs, void *arg)
{
zfs_btree_add(size_tree, rs);
}
-/* ARGSUSED */
static void
metaslab_rt_remove(range_tree_t *rt, range_seg_t *rs, void *arg)
{
zfs_btree_remove(size_tree, rs);
}
-/* ARGSUSED */
static void
metaslab_rt_vacate(range_tree_t *rt, void *arg)
{
inuse = spl_kmem_cache_inuse(zfs_btree_leaf_cache);
}
}
+#else
+ (void) mc;
#endif
}
}
}
-/* ARGSUSED */
static uint64_t
metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal,
uint64_t asize, uint64_t txg, boolean_t want_unique, dva_t *dva, int d,
mutex_exit(&msp->ms_lock);
}
-/* ARGSUSED */
void
metaslab_free_impl_cb(uint64_t inner_offset, vdev_t *vd, uint64_t offset,
uint64_t size, void *arg)
{
+ (void) inner_offset;
boolean_t *checkpoint = arg;
ASSERT3P(checkpoint, !=, NULL);
int mcca_error;
} metaslab_claim_cb_arg_t;
-/* ARGSUSED */
static void
metaslab_claim_impl_cb(uint64_t inner_offset, vdev_t *vd, uint64_t offset,
uint64_t size, void *arg)
{
+ (void) inner_offset;
metaslab_claim_cb_arg_t *mcca_arg = arg;
if (mcca_arg->mcca_error == 0) {
spa_config_exit(spa, SCL_VDEV, FTAG);
}
-/* ARGSUSED */
static void
metaslab_check_free_impl_cb(uint64_t inner, vdev_t *vd, uint64_t offset,
uint64_t size, void *arg)
{
+ (void) inner, (void) arg;
+
if (vd->vdev_ops == &vdev_indirect_ops)
return;
return (range_tree_space(rt) == 0);
}
-/* ARGSUSED */
void
rt_btree_create(range_tree_t *rt, void *arg)
{
zfs_btree_create(size_tree, rt->rt_btree_compare, size);
}
-/* ARGSUSED */
void
rt_btree_destroy(range_tree_t *rt, void *arg)
{
+ (void) rt;
zfs_btree_t *size_tree = arg;
ASSERT0(zfs_btree_numnodes(size_tree));
zfs_btree_destroy(size_tree);
}
-/* ARGSUSED */
void
rt_btree_add(range_tree_t *rt, range_seg_t *rs, void *arg)
{
+ (void) rt;
zfs_btree_t *size_tree = arg;
zfs_btree_add(size_tree, rs);
}
-/* ARGSUSED */
void
rt_btree_remove(range_tree_t *rt, range_seg_t *rs, void *arg)
{
+ (void) rt;
zfs_btree_t *size_tree = arg;
zfs_btree_remove(size_tree, rs);
}
-/* ARGSUSED */
void
rt_btree_vacate(range_tree_t *rt, void *arg)
{
static int sa_legacy_attr_count = ARRAY_SIZE(sa_legacy_attrs);
static kmem_cache_t *sa_cache = NULL;
-/*ARGSUSED*/
static int
sa_cache_constructor(void *buf, void *unused, int kmflag)
{
+ (void) unused, (void) kmflag;
sa_handle_t *hdl = buf;
mutex_init(&hdl->sa_lock, NULL, MUTEX_DEFAULT, NULL);
return (0);
}
-/*ARGSUSED*/
static void
sa_cache_destructor(void *buf, void *unused)
{
+ (void) unused;
sa_handle_t *hdl = buf;
mutex_destroy(&hdl->sa_lock);
}
}
}
-/*ARGSUSED*/
static void
sa_byteswap_cb(void *hdr, void *attr_addr, sa_attr_type_t attr,
uint16_t length, int length_idx, boolean_t variable_length, void *userp)
{
+ (void) hdr, (void) length_idx, (void) variable_length;
sa_handle_t *hdl = userp;
sa_os_t *sa = hdl->sa_os->os_sa;
return (0);
}
-/*ARGSUSED*/
static void
sa_evict_sync(void *dbu)
{
+ (void) dbu;
panic("evicting sa dbuf\n");
}
return (0);
}
-/*ARGSUSED*/
void
abd_checksum_SHA256(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
+ (void) ctx_template;
int ret;
SHA2_CTX ctx;
zio_cksum_t tmp;
zcp->zc_word[3] = BE_64(tmp.zc_word[3]);
}
-/*ARGSUSED*/
void
abd_checksum_SHA512_native(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
+ (void) ctx_template;
SHA2_CTX ctx;
SHA2Init(SHA512_256, &ctx);
SHA2Final(zcp, &ctx);
}
-/*ARGSUSED*/
void
abd_checksum_SHA512_byteswap(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
}
}
-/*ARGSUSED*/
static int
spa_change_guid_check(void *arg, dmu_tx_t *tx)
{
spa_wake_waiters(spa);
/*
- * If the log space map feature is enabled and the pool is getting
- * exported (but not destroyed), we want to spend some time flushing
- * as many metaslabs as we can in an attempt to destroy log space
- * maps and save import time.
+ * If we have set the spa_final_txg, we have already performed the
+ * tasks below in spa_export_common(). We should not redo it here since
+ * we delay the final TXGs beyond what spa_final_txg is set at.
*/
- if (spa_should_flush_logs_on_unload(spa))
- spa_unload_log_sm_flush_all(spa);
+ if (spa->spa_final_txg == UINT64_MAX) {
+ /*
+ * If the log space map feature is enabled and the pool is
+ * getting exported (but not destroyed), we want to spend some
+ * time flushing as many metaslabs as we can in an attempt to
+ * destroy log space maps and save import time.
+ */
+ if (spa_should_flush_logs_on_unload(spa))
+ spa_unload_log_sm_flush_all(spa);
- /*
- * Stop async tasks.
- */
- spa_async_suspend(spa);
+ /*
+ * Stop async tasks.
+ */
+ spa_async_suspend(spa);
- if (spa->spa_root_vdev) {
- vdev_t *root_vdev = spa->spa_root_vdev;
- vdev_initialize_stop_all(root_vdev, VDEV_INITIALIZE_ACTIVE);
- vdev_trim_stop_all(root_vdev, VDEV_TRIM_ACTIVE);
- vdev_autotrim_stop_all(spa);
- vdev_rebuild_stop_all(spa);
+ if (spa->spa_root_vdev) {
+ vdev_t *root_vdev = spa->spa_root_vdev;
+ vdev_initialize_stop_all(root_vdev,
+ VDEV_INITIALIZE_ACTIVE);
+ vdev_trim_stop_all(root_vdev, VDEV_TRIM_ACTIVE);
+ vdev_autotrim_stop_all(spa);
+ vdev_rebuild_stop_all(spa);
+ }
}
/*
int spa_load_verify_metadata = B_TRUE;
int spa_load_verify_data = B_TRUE;
-/*ARGSUSED*/
static int
spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
{
+ (void) zilog, (void) dnp;
+
if (zb->zb_level == ZB_DNODE_LEVEL || BP_IS_HOLE(bp) ||
BP_IS_EMBEDDED(bp) || BP_IS_REDACTED(bp))
return (0);
return (0);
}
-/* ARGSUSED */
static int
verify_dataset_name_len(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
{
+ (void) dp, (void) arg;
+
if (dsl_dataset_namelen(ds) >= ZFS_MAX_DATASET_NAME_LEN)
return (SET_ERROR(ENAMETOOLONG));
return (spa->spa_livelists_to_delete != 0);
}
-/* ARGSUSED */
static boolean_t
spa_livelist_delete_cb_check(void *arg, zthr_t *z)
{
+ (void) z;
spa_t *spa = arg;
return (spa_livelist_delete_check(spa));
}
* be freed. Then, call a synctask which performs the actual frees and updates
* the pool-wide livelist data.
*/
-/* ARGSUSED */
static void
spa_livelist_delete_cb(void *arg, zthr_t *z)
{
zfs_livelist_condense_zthr_cancel++;
}
-/* ARGSUSED */
/*
* Check that there is something to condense but that a condense is not
* already in progress and that condensing has not been cancelled.
static boolean_t
spa_livelist_condense_cb_check(void *arg, zthr_t *z)
{
+ (void) z;
spa_t *spa = arg;
if ((spa->spa_to_condense.ds != NULL) &&
(spa->spa_to_condense.syncing == B_FALSE) &&
if (new_state != POOL_STATE_UNINITIALIZED && !hardforce) {
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa->spa_state = new_state;
+ vdev_config_dirty(spa->spa_root_vdev);
+ spa_config_exit(spa, SCL_ALL, FTAG);
+ }
+
+ /*
+ * If the log space map feature is enabled and the pool is
+ * getting exported (but not destroyed), we want to spend some
+ * time flushing as many metaslabs as we can in an attempt to
+ * destroy log space maps and save import time. This has to be
+ * done before we set the spa_final_txg, otherwise
+ * spa_sync() -> spa_flush_metaslabs() may dirty the final TXGs.
+ * spa_should_flush_logs_on_unload() should be called after
+ * spa_state has been set to the new_state.
+ */
+ if (spa_should_flush_logs_on_unload(spa))
+ spa_unload_log_sm_flush_all(spa);
+
+ if (new_state != POOL_STATE_UNINITIALIZED && !hardforce) {
+ spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa->spa_final_txg = spa_last_synced_txg(spa) +
TXG_DEFER_SIZE + 1;
- vdev_config_dirty(spa->spa_root_vdev);
spa_config_exit(spa, SCL_ALL, FTAG);
}
}
boolean_t
spa_has_spare(spa_t *spa, uint64_t guid)
{
+ (void) spa;
int i;
uint64_t spareguid;
spa_aux_vdev_t *sav = &spa->spa_spares;
ev = kmem_alloc(sizeof (sysevent_t), KM_SLEEP);
ev->resource = resource;
}
+#else
+ (void) spa, (void) vd, (void) hist_nvl, (void) name;
#endif
return (ev);
}
zfs_zevent_post(ev->resource, NULL, zfs_zevent_post_cb);
kmem_free(ev, sizeof (*ev));
}
+#else
+ (void) ev;
#endif
}
return (B_TRUE);
}
-/* ARGSUSED */
boolean_t
spa_checkpoint_discard_thread_check(void *arg, zthr_t *zthr)
{
+ (void) zthr;
spa_t *spa = arg;
if (!spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT))
}
-/* ARGSUSED */
static int
spa_checkpoint_check(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
if (!spa_feature_is_enabled(spa, SPA_FEATURE_POOL_CHECKPOINT))
return (0);
}
-/* ARGSUSED */
static void
spa_checkpoint_sync(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
spa_t *spa = dp->dp_spa;
uberblock_t checkpoint = spa->spa_ubsync;
return (error);
}
-/* ARGSUSED */
static int
spa_checkpoint_discard_check(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
if (!spa_feature_is_active(spa, SPA_FEATURE_POOL_CHECKPOINT))
return (0);
}
-/* ARGSUSED */
static void
spa_checkpoint_discard_sync(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
VERIFY0(zap_remove(spa_meta_objset(spa), DMU_POOL_DIRECTORY_OBJECT,
mutex_exit(&spa->spa_errlist_lock);
mutex_exit(&spa->spa_errlog_lock);
+#else
+ (void) spa, (void) uaddr, (void) count;
#endif
return (ret);
void
spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
{
+ (void) tag;
int wlocks_held = 0;
ASSERT3U(SCL_LOCKS, <, sizeof (wlocks_held) * NBBY);
void
spa_config_exit(spa_t *spa, int locks, const void *tag)
{
+ (void) tag;
for (int i = SCL_LOCKS - 1; i >= 0; i--) {
spa_config_lock_t *scl = &spa->spa_config_lock[i];
if (!(locks & (1 << i)))
return (vd->vdev_mg);
}
-/* ARGSUSED */
void
vdev_default_xlate(vdev_t *vd, const range_seg64_t *logical_rs,
range_seg64_t *physical_rs, range_seg64_t *remain_rs)
{
+ (void) vd, (void) remain_rs;
+
physical_rs->rs_start = logical_rs->rs_start;
physical_rs->rs_end = logical_rs->rs_end;
}
static boolean_t
vdev_default_open_children_func(vdev_t *vd)
{
+ (void) vd;
return (B_TRUE);
}
vdev_default_need_resilver(vdev_t *vd, const dva_t *dva, size_t psize,
uint64_t phys_birth)
{
+ (void) dva, (void) psize;
+
/* Set by sequential resilver. */
if (phys_birth == TXG_UNKNOWN)
return (B_TRUE);
static void
vdev_get_child_stat_ex(vdev_t *cvd, vdev_stat_ex_t *vsx, vdev_stat_ex_t *cvsx)
{
+ (void) cvd;
+
int t, b;
for (t = 0; t < ZIO_TYPES; t++) {
for (b = 0; b < ARRAY_SIZE(vsx->vsx_disk_histo[0]); b++)
vdev_space_update(vdev_t *vd, int64_t alloc_delta, int64_t defer_delta,
int64_t space_delta)
{
+ (void) defer_delta;
int64_t dspace_delta;
spa_t *spa = vd->vdev_spa;
vdev_t *rvd = spa->spa_root_vdev;
ASSERT3U(skip_off, ==, rr->rr_nempty * skip_size);
}
+/*
+ * Verify that all empty sectors are zero filled before using them to
+ * calculate parity. Otherwise, silent corruption in an empty sector will
+ * result in bad parity being generated. That bad parity will then be
+ * considered authoritative and overwrite the good parity on disk. This
+ * is possible because the checksum is only calculated over the data,
+ * thus it cannot be used to detect damage in empty sectors.
+ */
+int
+vdev_draid_map_verify_empty(zio_t *zio, raidz_row_t *rr)
+{
+ uint64_t skip_size = 1ULL << zio->io_vd->vdev_top->vdev_ashift;
+ uint64_t parity_size = rr->rr_col[0].rc_size;
+ uint64_t skip_off = parity_size - skip_size;
+ uint64_t empty_off = 0;
+ int ret = 0;
+
+ ASSERT3U(zio->io_type, ==, ZIO_TYPE_READ);
+ ASSERT3P(rr->rr_abd_empty, !=, NULL);
+ ASSERT3U(rr->rr_bigcols, >, 0);
+
+ void *zero_buf = kmem_zalloc(skip_size, KM_SLEEP);
+
+ for (int c = rr->rr_bigcols; c < rr->rr_cols; c++) {
+ raidz_col_t *rc = &rr->rr_col[c];
+
+ ASSERT3P(rc->rc_abd, !=, NULL);
+ ASSERT3U(rc->rc_size, ==, parity_size);
+
+ if (abd_cmp_buf_off(rc->rc_abd, zero_buf, skip_off,
+ skip_size) != 0) {
+ vdev_raidz_checksum_error(zio, rc, rc->rc_abd);
+ abd_zero_off(rc->rc_abd, skip_off, skip_size);
+ rc->rc_error = SET_ERROR(ECKSUM);
+ ret++;
+ }
+
+ empty_off += skip_size;
+ }
+
+ ASSERT3U(empty_off, ==, abd_get_size(rr->rr_abd_empty));
+
+ kmem_free(zero_buf, skip_size);
+
+ return (ret);
+}
+
/*
* Given a logical address within a dRAID configuration, return the physical
* address on the first drive in the group that this address maps to
static int
vdev_draid_init(spa_t *spa, nvlist_t *nv, void **tsd)
{
+ (void) spa;
uint64_t ndata, nparity, nspares, ngroups;
int error;
return (cvd);
}
-/* ARGSUSED */
static void
vdev_draid_spare_close(vdev_t *vd)
{
zio_execute(zio);
}
-/* ARGSUSED */
static void
vdev_draid_spare_io_done(zio_t *zio)
{
+ (void) zio;
}
/*
}
}
-/* ARGSUSED */
static boolean_t
spa_condense_indirect_thread_check(void *arg, zthr_t *zthr)
{
+ (void) zthr;
spa_t *spa = arg;
return (spa->spa_condensing_indirect != NULL);
}
-/* ARGSUSED */
static void
spa_condense_indirect_thread(void *arg, zthr_t *zthr)
{
return (error);
}
-/* ARGSUSED */
static void
vdev_indirect_close(vdev_t *vd)
{
+ (void) vd;
}
-/* ARGSUSED */
static int
vdev_indirect_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
uint64_t *logical_ashift, uint64_t *physical_ashift)
* divisible by sizeof (uint64_t), and buf must be 8-byte aligned. The ABD
* allocation will guarantee these for us.
*/
-/* ARGSUSED */
static int
vdev_initialize_block_fill(void *buf, size_t len, void *unused)
{
+ (void) unused;
+
ASSERT0(len % sizeof (uint64_t));
#ifdef _ILP32
for (uint64_t i = 0; i < len; i += sizeof (uint32_t)) {
void
vdev_initialize_stop_wait(spa_t *spa, list_t *vd_list)
{
+ (void) spa;
vdev_t *vd;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
vdev_mirror_rebuild_asize(vdev_t *vd, uint64_t start, uint64_t asize,
uint64_t max_segment)
{
+ (void) start;
+
uint64_t psize = MIN(P2ROUNDUP(max_segment, 1 << vd->vdev_ashift),
SPA_MAXBLOCKSIZE);
#include <sys/fs/zfs.h>
#include <sys/zio.h>
-/* ARGSUSED */
static int
vdev_missing_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
uint64_t *ashift, uint64_t *pshift)
* VDEV_AUX_BAD_GUID_SUM. So we pretend to succeed, knowing that we
* will fail the GUID sum check before ever trying to open the pool.
*/
+ (void) vd;
*psize = 0;
*max_psize = 0;
*ashift = 0;
return (0);
}
-/* ARGSUSED */
static void
vdev_missing_close(vdev_t *vd)
{
+ (void) vd;
}
-/* ARGSUSED */
static void
vdev_missing_io_start(zio_t *zio)
{
zio_execute(zio);
}
-/* ARGSUSED */
static void
vdev_missing_io_done(zio_t *zio)
{
+ (void) zio;
}
vdev_ops_t vdev_missing_ops = {
}
}
-/* ARGSUSED */
static int
vdev_raidz_reconst_p_func(void *dbuf, void *sbuf, size_t size, void *private)
{
+ (void) private;
uint64_t *dst = dbuf;
uint64_t *src = sbuf;
int cnt = size / sizeof (src[0]);
return (0);
}
-/* ARGSUSED */
static int
vdev_raidz_reconst_q_pre_func(void *dbuf, void *sbuf, size_t size,
void *private)
{
+ (void) private;
uint64_t *dst = dbuf;
uint64_t *src = sbuf;
uint64_t mask;
return (0);
}
-/* ARGSUSED */
static int
vdev_raidz_reconst_q_pre_tail_func(void *buf, size_t size, void *private)
{
+ (void) private;
uint64_t *dst = buf;
uint64_t mask;
int cnt = size / sizeof (dst[0]);
/*
* Report a checksum error for a child of a RAID-Z device.
*/
-static void
-raidz_checksum_error(zio_t *zio, raidz_col_t *rc, abd_t *bad_data)
+void
+vdev_raidz_checksum_error(zio_t *zio, raidz_col_t *rc, abd_t *bad_data)
{
vdev_t *vd = zio->io_vd->vdev_child[rc->rc_devidx];
abd_copy(orig[c], rc->rc_abd, rc->rc_size);
}
+ /*
+ * Verify any empty sectors are zero filled to ensure the parity
+ * is calculated correctly even if these non-data sectors are damaged.
+ */
+ if (rr->rr_nempty && rr->rr_abd_empty != NULL)
+ ret += vdev_draid_map_verify_empty(zio, rr);
+
/*
* Regenerates parity even for !tried||rc_error!=0 columns. This
* isn't harmful but it does have the side effect of fixing stuff
continue;
if (abd_cmp(orig[c], rc->rc_abd) != 0) {
- raidz_checksum_error(zio, rc, orig[c]);
+ vdev_raidz_checksum_error(zio, rc, orig[c]);
rc->rc_error = SET_ERROR(ECKSUM);
ret++;
}
(zio->io_flags & ZIO_FLAG_RESILVER)) {
int n = raidz_parity_verify(zio, rr);
unexpected_errors += n;
- ASSERT3U(parity_errors + n, <=, rr->rr_firstdatacol);
}
if (zio->io_error == 0 && spa_writeable(zio->io_spa) &&
*/
if (rc->rc_error == 0 &&
c >= rr->rr_firstdatacol) {
- raidz_checksum_error(zio,
+ vdev_raidz_checksum_error(zio,
rc, rc->rc_orig_data);
rc->rc_error =
SET_ERROR(ECKSUM);
vdev_raidz_xlate(vdev_t *cvd, const range_seg64_t *logical_rs,
range_seg64_t *physical_rs, range_seg64_t *remain_rs)
{
+ (void) remain_rs;
+
vdev_t *raidvd = cvd->vdev_parent;
ASSERT(raidvd->vdev_ops == &vdev_raidz_ops);
mutex_exit(&svr->svr_lock);
}
-/* ARGSUSED */
static int
spa_vdev_remove_cancel_check(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
if (spa->spa_vdev_removal == NULL)
* Cancel a removal by freeing all entries from the partial mapping
* and marking the vdev as no longer being removing.
*/
-/* ARGSUSED */
static void
spa_vdev_remove_cancel_sync(void *arg, dmu_tx_t *tx)
{
+ (void) arg;
spa_t *spa = dmu_tx_pool(tx)->dp_spa;
spa_vdev_removal_t *svr = spa->spa_vdev_removal;
vdev_t *vd = vdev_lookup_top(spa, svr->svr_vdev_id);
void
vdev_trim_stop_wait(spa_t *spa, list_t *vd_list)
{
+ (void) spa;
vdev_t *vd;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
int fzap_default_block_shift = 14; /* 16k blocksize */
-extern inline zap_phys_t *zap_f_phys(zap_t *zap);
-
static uint64_t zap_allocate_blocks(zap_t *zap, int nblocks);
void
#define LEAF_HASH_ENTPTR(l, h) (&zap_leaf_phys(l)->l_hash[LEAF_HASH(l, h)])
-extern inline zap_leaf_phys_t *zap_leaf_phys(zap_leaf_t *l);
-
static void
zap_memset(void *a, int c, size_t n)
{
#include <sys/sunddi.h>
#endif
-extern inline mzap_phys_t *zap_m_phys(zap_t *zap);
-
static int mzap_upgrade(zap_t **zapp,
void *tag, dmu_tx_t *tx, zap_flags_t flags);
}
}
-/* ARGSUSED */
static void
zcp_lua_counthook(lua_State *state, lua_Debug *ar)
{
+ (void) ar;
lua_getfield(state, LUA_REGISTRYINDEX, ZCP_RUN_INFO_KEY);
zcp_run_info_t *ri = lua_touserdata(state, -1);
* The txg_wait_synced_sig will continue to wait for the txg to complete
* after calling this callback.
*/
-/* ARGSUSED */
static void
zcp_eval_sig(void *arg, dmu_tx_t *tx)
{
+ (void) tx;
zcp_run_info_t *ri = arg;
ri->zri_canceled = B_TRUE;
.blocks_modified = 0
};
-/* ARGSUSED */
static int
zcp_synctask_destroy(lua_State *state, boolean_t sync, nvlist_t *err_details)
{
+ (void) err_details;
int err;
const char *dsname = lua_tostring(state, 1);
.blocks_modified = 3
};
-/* ARGSUSED */
static int
zcp_synctask_snapshot(lua_State *state, boolean_t sync, nvlist_t *err_details)
{
+ (void) err_details;
int err;
dsl_dataset_snapshot_arg_t ddsa = { 0 };
const char *dsname = lua_tostring(state, 1);
zcp_synctask_inherit_prop(lua_State *state, boolean_t sync,
nvlist_t *err_details)
{
+ (void) err_details;
int err;
zcp_inherit_prop_arg_t zipa = { 0 };
dsl_props_set_arg_t *dpsa = &zipa.zipa_dpsa;
.blocks_modified = 1,
};
-/* ARGSUSED */
static int
zcp_synctask_bookmark(lua_State *state, boolean_t sync, nvlist_t *err_details)
{
+ (void) err_details;
int err;
const char *source = lua_tostring(state, 1);
const char *new = lua_tostring(state, 2);
static int
zcp_synctask_set_prop(lua_State *state, boolean_t sync, nvlist_t *err_details)
{
+ (void) err_details;
int err;
zcp_set_prop_arg_t args = { 0 };
* read I/Os, there are basically three 'types' of I/O, which form a roughly
* layered diagram:
*
- * +---------------+
+ * +---------------+
* | Aggregate I/O | No associated logical data or device
* +---------------+
* |
/*
* background task to clean stale recent event nodes.
*/
-/*ARGSUSED*/
static void
zfs_ereport_cleaner(void *arg)
{
return (eip);
}
#else
-/*ARGSUSED*/
void
zfs_ereport_clear(spa_t *spa, vdev_t *vd)
{
+ (void) spa, (void) vd;
}
#endif
(zio != NULL) && (!zio->io_timestamp)) {
return (B_FALSE);
}
+#else
+ (void) subclass, (void) spa, (void) vd, (void) zio;
#endif
return (B_TRUE);
}
/* Cleanup is handled by the callback function */
rc = zfs_zevent_post(ereport, detector, zfs_zevent_post_cb);
+#else
+ (void) subclass, (void) spa, (void) vd, (void) zb, (void) zio,
+ (void) state;
#endif
return (rc);
}
if (zfs_is_ratelimiting_event(FM_EREPORT_ZFS_CHECKSUM, vd))
return (SET_ERROR(EBUSY));
+#else
+ (void) zb, (void) offset;
#endif
report = kmem_zalloc(sizeof (*report), KM_SLEEP);
report->zcr_ereport = report->zcr_detector = NULL;
if (info != NULL)
kmem_free(info, sizeof (*info));
+#else
+ (void) report, (void) good_data, (void) bad_data,
+ (void) drop_if_identical;
#endif
}
rc = zfs_zevent_post(ereport, detector, zfs_zevent_post_cb);
kmem_free(info, sizeof (*info));
}
+#else
+ (void) spa, (void) vd, (void) zb, (void) zio, (void) offset,
+ (void) length, (void) good_data, (void) bad_data, (void) zbc;
#endif
return (rc);
}
while ((elem = nvlist_next_nvpair(aux, elem)) != NULL)
(void) nvlist_add_nvpair(resource, elem);
}
-
+#else
+ (void) spa, (void) vd, (void) type, (void) name, (void) aux;
#endif
return (resource);
}
resource = zfs_event_create(spa, vd, type, name, aux);
if (resource)
zfs_zevent_post(resource, NULL, zfs_zevent_post_cb);
+#else
+ (void) spa, (void) vd, (void) type, (void) name, (void) aux;
#endif
}
if (aux)
fm_nvlist_destroy(aux, FM_NVA_FREE);
+#else
+ (void) spa, (void) vd, (void) laststate;
#endif
}
mutex_destroy(&recent_events_lock);
}
+void
+zfs_ereport_snapshot_post(const char *subclass, spa_t *spa, const char *name)
+{
+ nvlist_t *aux;
+
+ aux = fm_nvlist_create(NULL);
+ nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_SNAPSHOT_NAME, name);
+
+ zfs_post_common(spa, NULL, FM_RSRC_CLASS, subclass, aux);
+ fm_nvlist_destroy(aux, FM_NVA_FREE);
+}
+
+/*
+ * Post when a event when a zvol is created or removed
+ *
+ * This is currently only used by macOS, since it uses the event to create
+ * symlinks between the volume name (mypool/myvol) and the actual /dev
+ * device (/dev/disk3). For example:
+ *
+ * /var/run/zfs/dsk/mypool/myvol -> /dev/disk3
+ *
+ * name: The full name of the zvol ("mypool/myvol")
+ * dev_name: The full /dev name for the zvol ("/dev/disk3")
+ * raw_name: The raw /dev name for the zvol ("/dev/rdisk3")
+ */
+void
+zfs_ereport_zvol_post(const char *subclass, const char *name,
+ const char *dev_name, const char *raw_name)
+{
+ nvlist_t *aux;
+ char *r;
+
+ boolean_t locked = mutex_owned(&spa_namespace_lock);
+ if (!locked) mutex_enter(&spa_namespace_lock);
+ spa_t *spa = spa_lookup(name);
+ if (!locked) mutex_exit(&spa_namespace_lock);
+
+ if (spa == NULL)
+ return;
+
+ aux = fm_nvlist_create(NULL);
+ nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_DEVICE_NAME, dev_name);
+ nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_RAW_DEVICE_NAME,
+ raw_name);
+ r = strchr(name, '/');
+ if (r && r[1])
+ nvlist_add_string(aux, FM_EREPORT_PAYLOAD_ZFS_VOLUME, &r[1]);
+
+ zfs_post_common(spa, NULL, FM_RSRC_CLASS, subclass, aux);
+ fm_nvlist_destroy(aux, FM_NVA_FREE);
+}
+
EXPORT_SYMBOL(zfs_ereport_post);
EXPORT_SYMBOL(zfs_ereport_is_valid);
EXPORT_SYMBOL(zfs_ereport_post_checksum);
return (error);
}
+static void
+zfs_clear_setid_bits_if_necessary(zfsvfs_t *zfsvfs, znode_t *zp, cred_t *cr,
+ uint64_t *clear_setid_bits_txgp, dmu_tx_t *tx)
+{
+ zilog_t *zilog = zfsvfs->z_log;
+ const uint64_t uid = KUID_TO_SUID(ZTOUID(zp));
+
+ ASSERT(clear_setid_bits_txgp != NULL);
+ ASSERT(tx != NULL);
+
+ /*
+ * Clear Set-UID/Set-GID bits on successful write if not
+ * privileged and at least one of the execute bits is set.
+ *
+ * It would be nice to do this after all writes have
+ * been done, but that would still expose the ISUID/ISGID
+ * to another app after the partial write is committed.
+ *
+ * Note: we don't call zfs_fuid_map_id() here because
+ * user 0 is not an ephemeral uid.
+ */
+ mutex_enter(&zp->z_acl_lock);
+ if ((zp->z_mode & (S_IXUSR | (S_IXUSR >> 3) | (S_IXUSR >> 6))) != 0 &&
+ (zp->z_mode & (S_ISUID | S_ISGID)) != 0 &&
+ secpolicy_vnode_setid_retain(zp, cr,
+ ((zp->z_mode & S_ISUID) != 0 && uid == 0)) != 0) {
+ uint64_t newmode;
+
+ zp->z_mode &= ~(S_ISUID | S_ISGID);
+ newmode = zp->z_mode;
+ (void) sa_update(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs),
+ (void *)&newmode, sizeof (uint64_t), tx);
+
+ mutex_exit(&zp->z_acl_lock);
+
+ /*
+ * Make sure SUID/SGID bits will be removed when we replay the
+ * log. If the setid bits are keep coming back, don't log more
+ * than one TX_SETATTR per transaction group.
+ */
+ if (*clear_setid_bits_txgp != dmu_tx_get_txg(tx)) {
+ vattr_t va;
+
+ bzero(&va, sizeof (va));
+ va.va_mask = AT_MODE;
+ va.va_nodeid = zp->z_id;
+ va.va_mode = newmode;
+ zfs_log_setattr(zilog, tx, TX_SETATTR, zp, &va, AT_MODE,
+ NULL);
+ *clear_setid_bits_txgp = dmu_tx_get_txg(tx);
+ }
+ } else {
+ mutex_exit(&zp->z_acl_lock);
+ }
+}
+
/*
* Write the bytes to a file.
*
{
int error = 0, error1;
ssize_t start_resid = zfs_uio_resid(uio);
+ uint64_t clear_setid_bits_txg = 0;
/*
* Fasttrack empty write
break;
}
+ /*
+ * NB: We must call zfs_clear_setid_bits_if_necessary before
+ * committing the transaction!
+ */
+
/*
* If rangelock_enter() over-locked we grow the blocksize
* and then reduce the lock range. This will only happen
zfs_uio_fault_disable(uio, B_FALSE);
#ifdef __linux__
if (error == EFAULT) {
+ zfs_clear_setid_bits_if_necessary(zfsvfs, zp,
+ cr, &clear_setid_bits_txg, tx);
dmu_tx_commit(tx);
/*
* Account for partial writes before
* VFS, which will handle faulting and will retry.
*/
if (error != 0 && error != EFAULT) {
+ zfs_clear_setid_bits_if_necessary(zfsvfs, zp,
+ cr, &clear_setid_bits_txg, tx);
dmu_tx_commit(tx);
break;
}
error = dmu_assign_arcbuf_by_dbuf(
sa_get_db(zp->z_sa_hdl), woff, abuf, tx);
if (error != 0) {
+ /*
+ * XXX This might not be necessary if
+ * dmu_assign_arcbuf_by_dbuf is guaranteed
+ * to be atomic.
+ */
+ zfs_clear_setid_bits_if_necessary(zfsvfs, zp,
+ cr, &clear_setid_bits_txg, tx);
dmu_return_arcbuf(abuf);
dmu_tx_commit(tx);
break;
break;
}
- /*
- * Clear Set-UID/Set-GID bits on successful write if not
- * privileged and at least one of the execute bits is set.
- *
- * It would be nice to do this after all writes have
- * been done, but that would still expose the ISUID/ISGID
- * to another app after the partial write is committed.
- *
- * Note: we don't call zfs_fuid_map_id() here because
- * user 0 is not an ephemeral uid.
- */
- mutex_enter(&zp->z_acl_lock);
- if ((zp->z_mode & (S_IXUSR | (S_IXUSR >> 3) |
- (S_IXUSR >> 6))) != 0 &&
- (zp->z_mode & (S_ISUID | S_ISGID)) != 0 &&
- secpolicy_vnode_setid_retain(zp, cr,
- ((zp->z_mode & S_ISUID) != 0 && uid == 0)) != 0) {
- uint64_t newmode;
- zp->z_mode &= ~(S_ISUID | S_ISGID);
- newmode = zp->z_mode;
- (void) sa_update(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs),
- (void *)&newmode, sizeof (uint64_t), tx);
- }
- mutex_exit(&zp->z_acl_lock);
+ zfs_clear_setid_bits_if_necessary(zfsvfs, zp, cr,
+ &clear_setid_bits_txg, tx);
zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime);
/* Avoid clobbering EFAULT. */
error = error1;
+ /*
+ * NB: During replay, the TX_SETATTR record logged by
+ * zfs_clear_setid_bits_if_necessary must precede any of
+ * the TX_WRITE records logged here.
+ */
zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag,
NULL, NULL);
+
dmu_tx_commit(tx);
if (error != 0)
return (error);
}
-/* ARGSUSED */
static int
zil_clear_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
uint64_t first_txg)
{
+ (void) tx;
ASSERT(!BP_IS_HOLE(bp));
/*
return (0);
}
-/* ARGSUSED */
static int
zil_noop_log_record(zilog_t *zilog, const lr_t *lrc, void *tx,
uint64_t first_txg)
{
+ (void) zilog, (void) lrc, (void) tx, (void) first_txg;
return (0);
}
return (zil_claim_log_block(zilog, &lr->lr_blkptr, tx, first_txg));
}
-/* ARGSUSED */
static int
zil_free_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
uint64_t claim_txg)
{
+ (void) claim_txg;
+
zio_free(zilog->zl_spa, dmu_tx_get_txg(tx), bp);
return (0);
* Checksum errors are ok as they indicate the end of the chain.
* Any other error (no device or read failure) returns an error.
*/
-/* ARGSUSED */
int
zil_check_log_chain(dsl_pool_t *dp, dsl_dataset_t *ds, void *tx)
{
+ (void) dp;
zilog_t *zilog;
objset_t *os;
blkptr_t *bp;
mutex_exit(&zilog->zl_lock);
}
-/* ARGSUSED */
static int
zil_lwb_cons(void *vbuf, void *unused, int kmflag)
{
+ (void) unused, (void) kmflag;
lwb_t *lwb = vbuf;
list_create(&lwb->lwb_itxs, sizeof (itx_t), offsetof(itx_t, itx_node));
list_create(&lwb->lwb_waiters, sizeof (zil_commit_waiter_t),
return (0);
}
-/* ARGSUSED */
static void
zil_lwb_dest(void *vbuf, void *unused)
{
+ (void) unused;
lwb_t *lwb = vbuf;
mutex_destroy(&lwb->lwb_vdev_lock);
avl_destroy(&lwb->lwb_vdev_tree);
return (0);
}
-/* ARGSUSED */
static int
zil_incr_blks(zilog_t *zilog, const blkptr_t *bp, void *arg, uint64_t claim_txg)
{
+ (void) bp, (void) arg, (void) claim_txg;
+
zilog->zl_replay_blks++;
return (0);
return (B_FALSE);
}
-/* ARGSUSED */
int
zil_reset(const char *osname, void *arg)
{
- int error;
+ (void) arg;
- error = zil_suspend(osname, NULL);
+ int error = zil_suspend(osname, NULL);
/* EACCES means crypto key not loaded */
if ((error == EACCES) || (error == EBUSY))
return (SET_ERROR(error));
static void
zio_abd_free(void *abd, size_t size)
{
+ (void) size;
abd_free((abd_t *)abd);
}
boolean_t
zfs_dva_valid(spa_t *spa, const dva_t *dva, const blkptr_t *bp)
{
+ (void) bp;
uint64_t vdevid = DVA_GET_VDEV(dva);
if (vdevid >= spa->spa_root_vdev->vdev_children)
zio->io_abd, NULL, lsize, zp->zp_complevel);
if (psize == 0 || psize >= lsize)
compress = ZIO_COMPRESS_OFF;
- } else if (zio->io_flags & ZIO_FLAG_RAW_COMPRESS) {
+ } else if (zio->io_flags & ZIO_FLAG_RAW_COMPRESS &&
+ !(zio->io_flags & ZIO_FLAG_RAW_ENCRYPT)) {
+ /*
+ * If we are raw receiving an encrypted dataset we should not
+ * take this codepath because it will change the on-disk block
+ * and decryption will fail.
+ */
size_t rounded = MIN((size_t)roundup(psize,
spa->spa_min_alloc), lsize);
!zio_taskq_member(zio, ZIO_TASKQ_ISSUE) &&
!zio_taskq_member(zio, ZIO_TASKQ_ISSUE_HIGH))
return (B_TRUE);
+#else
+ (void) zio;
#endif /* HAVE_LARGE_STACKS */
return (B_FALSE);
return (zio);
}
-/* ARGSUSED */
static zio_t *
zio_free_gang(zio_t *pio, blkptr_t *bp, zio_gang_node_t *gn, abd_t *data,
uint64_t offset)
{
+ (void) gn, (void) data, (void) offset;
+
zio_t *zio = zio_free_sync(pio, pio->io_spa, pio->io_txg, bp,
ZIO_GANG_CHILD_FLAGS(pio));
if (zio == NULL) {
return (zio);
}
-/* ARGSUSED */
static zio_t *
zio_claim_gang(zio_t *pio, blkptr_t *bp, zio_gang_node_t *gn, abd_t *data,
uint64_t offset)
{
+ (void) gn, (void) data, (void) offset;
return (zio_claim(pio, pio->io_spa, pio->io_txg, bp,
NULL, NULL, ZIO_GANG_CHILD_FLAGS(pio)));
}
zfs_ereport_finish_checksum(zcr, good_buf, zcr->zcr_cbdata, B_FALSE);
}
-/*ARGSUSED*/
void
zio_vsd_default_cksum_report(zio_t *zio, zio_cksum_report_t *zcr)
{
* invocation and passed to the checksum function.
*/
-/*ARGSUSED*/
static void
abd_checksum_off(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
+ (void) abd, (void) size, (void) ctx_template;
ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0);
}
-/*ARGSUSED*/
static void
abd_fletcher_2_native(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
+ (void) ctx_template;
fletcher_init(zcp);
(void) abd_iterate_func(abd, 0, size,
fletcher_2_incremental_native, zcp);
}
-/*ARGSUSED*/
static void
abd_fletcher_2_byteswap(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
+ (void) ctx_template;
fletcher_init(zcp);
(void) abd_iterate_func(abd, 0, size,
fletcher_2_incremental_byteswap, zcp);
fletcher_4_abd_ops.acf_fini(acdp);
}
-/*ARGSUSED*/
void
abd_fletcher_4_native(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
+ (void) ctx_template;
fletcher_4_ctx_t ctx;
zio_abd_checksum_data_t acd = {
}
-/*ARGSUSED*/
void
abd_fletcher_4_byteswap(abd_t *abd, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
+ (void) ctx_template;
fletcher_4_ctx_t ctx;
zio_abd_checksum_data_t acd = {
zio_complevel_select(spa_t *spa, enum zio_compress compress, uint8_t child,
uint8_t parent)
{
+ (void) spa;
uint8_t result;
if (!ZIO_COMPRESS_HASLEVEL(compress))
return (result);
}
-/*ARGSUSED*/
static int
zio_compress_zeroed_cb(void *data, size_t len, void *private)
{
+ (void) private;
+
uint64_t *end = (uint64_t *)((char *)data + len);
for (uint64_t *word = (uint64_t *)data; word < end; word++)
if (*word != 0)
# Are we doing an upgrade?
if [ "$1" = "1" -o "$1" = "upgrade" ] ; then
# Yes we are. Are we upgrading to a new ZFS version?
- NEWEST_VER=$(dkms status zfs | sed 's/,//g' | sort -r -V | awk '/installed/{print $2; exit}')
+ NEWEST_VER=$(dkms status zfs | tr -d , | sort -r -V | awk '/installed/{print $2; exit}')
if [ "$NEWEST_VER" != "%{version}" ] ; then
# Yes, it's a new ZFS version. We'll uninstall the old module
# later on in this script.
--with-linux=%{ksrc} \
--with-linux-obj=%{kobj} \
%{debug} \
- %{debuginfo}
+ %{debuginfo} \
+ %{?kernel_cc} \
+ %{?kernel_ld} \
+ %{?kernel_llvm}
make %{?_smp_mflags}
cd ..
done
BuildRequires: libtirpc-devel
%endif
+%if %{with pam}
+BuildRequires: pam-devel
+%endif
+
Requires: openssl
%if 0%{?_systemd}
BuildRequires: systemd
%endif
+
%endif
%if 0%{?_systemd}
%else
if [ -x /sbin/chkconfig ]; then
/sbin/chkconfig --add zfs-import
+ /sbin/chkconfig --add zfs-load-key
/sbin/chkconfig --add zfs-mount
/sbin/chkconfig --add zfs-share
/sbin/chkconfig --add zfs-zed
%else
if [ "$1" = "0" -o "$1" = "remove" ] && [ -x /sbin/chkconfig ]; then
/sbin/chkconfig --del zfs-import
+ /sbin/chkconfig --del zfs-load-key
/sbin/chkconfig --del zfs-mount
/sbin/chkconfig --del zfs-share
/sbin/chkconfig --del zfs-zed
--with-linux=%{ksrc} \
--with-linux-obj=%{kobj} \
%{debug} \
- %{debuginfo}
+ %{debuginfo} \
+ %{?kernel_cc} \
+ %{?kernel_ld} \
+ %{?kernel_llvm}
make %{?_smp_mflags}
%install
--prefix=/usr
--with-config=kernel
--with-linux=\$(
- case \`lsb_release -is\` in
- (Debian|Devuan)
- if [[ -e \${kernel_source_dir/%build/source} ]]
- then
- echo \${kernel_source_dir/%build/source}
- else
- # A kpkg exception for Proxmox 2.0
- echo \${kernel_source_dir}
- fi
- ;;
- (*)
- echo \${kernel_source_dir}
- ;;
- esac
+ if [ -e "\${kernel_source_dir/%build/source}" ]
+ then
+ echo "\${kernel_source_dir/%build/source}"
+ else
+ echo "\${kernel_source_dir}"
+ fi
)
- --with-linux-obj=\${kernel_source_dir}
+ --with-linux-obj="\${kernel_source_dir}"
\$(
[[ -n \"\${ICP_ROOT}\" ]] && \\
{
myprog_help ()
{
- echo "Usage: $(basename ${0}) [OPTIONS]"
+ echo "Usage: ${0##*/} [OPTIONS]"
echo $'\n'"Creates a template to be used during kmod building"
echo $'\n'"Available options:"
echo " --filterfile <file> -- filter the results with grep --file <file>"
cleanup_linux_loopback() {
for TEST_LOOPBACK in ${LOOPBACKS}; do
- LOOP_DEV=$(basename "$TEST_LOOPBACK")
+ LOOP_DEV="${TEST_LOOPBACK##*/}"
DM_DEV=$(sudo "${DMSETUP}" ls 2>/dev/null | \
grep "${LOOP_DEV}" | cut -f1)
TEST_LOOPBACK=$(sudo "${LOSETUP}" -f)
sudo "${LOSETUP}" "${TEST_LOOPBACK}" "${TEST_FILE}" ||
fail "Failed: ${TEST_FILE} -> ${TEST_LOOPBACK}"
- BASELOOPBACK=$(basename "$TEST_LOOPBACK")
+ BASELOOPBACK="${TEST_LOOPBACK##*/}"
DISKS="$DISKS $BASELOOPBACK"
LOOPBACKS="$LOOPBACKS $TEST_LOOPBACK"
fi
export TESTFAIL_CALLBACKS
export PATH=$STF_PATH
-if [ "$UNAME" = "FreeBSD" ] ; then
- mkdir -p "$FILEDIR" || true
- RESULTS_FILE=$(mktemp -u "${FILEDIR}/zts-results.XXXXXX")
- REPORT_FILE=$(mktemp -u "${FILEDIR}/zts-report.XXXXXX")
-else
- RESULTS_FILE=$(mktemp -u -t zts-results.XXXXXX -p "$FILEDIR")
- REPORT_FILE=$(mktemp -u -t zts-report.XXXXXX -p "$FILEDIR")
-fi
+mktemp_file() {
+ if [ "$UNAME" = "FreeBSD" ]; then
+ mktemp -u "${FILEDIR}/$1.XXXXXX"
+ else
+ mktemp -ut "$1.XXXXXX" -p "$FILEDIR"
+ fi
+}
+mkdir -p "$FILEDIR" || :
+RESULTS_FILE=$(mktemp_file zts-results)
+REPORT_FILE=$(mktemp_file zts-report)
#
# Run all the tests as specified.
if [ "$RESULT" -eq "2" ] && [ -n "$RERUN" ]; then
MAYBES="$($ZTS_REPORT --list-maybes)"
- TEMP_RESULTS_FILE=$(mktemp -u -t zts-results-tmp.XXXXX -p "$FILEDIR")
- TEST_LIST=$(mktemp -u -t test-list.XXXXX -p "$FILEDIR")
+ TEMP_RESULTS_FILE=$(mktemp_file zts-results-tmp)
+ TEST_LIST=$(mktemp_file test-list)
grep "^Test:.*\[FAIL\]" "$RESULTS_FILE" >"$TEMP_RESULTS_FILE"
for test_name in $MAYBES; do
grep "$test_name " "$TEMP_RESULTS_FILE" >>"$TEST_LIST"
for KMOD in $KMOD_SPL $KMOD_ZAVL $KMOD_ZNVPAIR $KMOD_ZUNICODE $KMOD_ZCOMMON \
$KMOD_ZLUA $KMOD_ZZSTD $KMOD_ICP $KMOD_ZFS; do
- NAME=$(basename "$KMOD" .ko)
+ NAME="${KMOD##*/}"
+ NAME="${NAME%.ko}"
if lsmod | grep -E -q "^${NAME}"; then
LOADED_MODULES="$LOADED_MODULES\t$NAME\n"
unload_module_linux() {
KMOD=$1
- NAME=$(basename "$KMOD" .ko)
+ NAME="${KMOD##*/}"
+ NAME="${NAME%.ko}"
FILE=$(modinfo "$KMOD" | awk '/^filename:/ {print $2}')
VERSION=$(modinfo "$KMOD" | awk '/^version:/ {print $2}')
unload_modules_linux() {
for KMOD in $KMOD_ZFS $KMOD_ICP $KMOD_ZZSTD $KMOD_ZLUA $KMOD_ZCOMMON \
$KMOD_ZUNICODE $KMOD_ZNVPAIR $KMOD_ZAVL $KMOD_SPL; do
- NAME=$(basename "$KMOD" .ko)
- USE_COUNT=$(lsmod | grep -E "^${NAME} " | awk '{print $3}')
+ NAME="${KMOD##*/}"
+ NAME="${NAME%.ko}"
+ USE_COUNT=$(lsmod | awk '/^'"${NAME}"'/ {print $3}')
if [ "$USE_COUNT" = "0" ] ; then
unload_module_linux "$KMOD" || return 1
"$POOL_DIR_COPY" || \
fail "Failed to copy $POOL_DIR_PRISTINE to $POOL_DIR_COPY"
POOL_NAME=$($ZPOOL_CMD import -d "$POOL_DIR_COPY" | \
- awk '/pool:/ { print $2; exit 0 }')
+ awk '/pool:/ { print $2; exit }')
if ! $ZPOOL_CMD import -N -d "$POOL_DIR_COPY"
"$POOL_NAME" &>/dev/null; then
[tests/functional/cli_root/zfs_load-key]
tests = ['zfs_load-key', 'zfs_load-key_all', 'zfs_load-key_file',
- 'zfs_load-key_location', 'zfs_load-key_noop', 'zfs_load-key_recursive']
+ 'zfs_load-key_https', 'zfs_load-key_location', 'zfs_load-key_noop',
+ 'zfs_load-key_recursive']
tags = ['functional', 'cli_root', 'zfs_load-key']
[tests/functional/cli_root/zfs_mount]
'zfs_receive_016_pos', 'receive-o-x_props_override',
'zfs_receive_from_encrypted', 'zfs_receive_to_encrypted',
'zfs_receive_raw', 'zfs_receive_raw_incremental', 'zfs_receive_-e',
- 'zfs_receive_raw_-d', 'zfs_receive_from_zstd', 'zfs_receive_new_props']
+ 'zfs_receive_raw_-d', 'zfs_receive_from_zstd', 'zfs_receive_new_props',
+ 'zfs_receive_-wR-encrypted-mix']
tags = ['functional', 'cli_root', 'zfs_receive']
[tests/functional/cli_root/zfs_rename]
tests = ['exec_001_pos', 'exec_002_neg']
tags = ['functional', 'exec']
+[tests/functional/fallocate]
+tests = ['fallocate_punch-hole']
+tags = ['functional', 'fallocate']
+
[tests/functional/features/async_destroy]
tests = ['async_destroy_001_pos']
tags = ['functional', 'features', 'async_destroy']
tests = ['large_files_001_pos', 'large_files_002_pos']
tags = ['functional', 'large_files']
-[tests/functional/largest_pool]
-tests = ['largest_pool_001_pos']
-pre =
-post =
-tags = ['functional', 'largest_pool']
-
[tests/functional/limits]
tests = ['filesystem_count', 'filesystem_limit', 'snapshot_count',
'snapshot_limit']
[tests/functional/no_space]
tests = ['enospc_001_pos', 'enospc_002_pos', 'enospc_003_pos',
- 'enospc_df']
+ 'enospc_df', 'enospc_rm']
tags = ['functional', 'no_space']
[tests/functional/nopwrite]
'send_freeobjects', 'send_realloc_files',
'send_realloc_encrypted_files', 'send_spill_block', 'send_holds',
'send_hole_birth', 'send_mixed_raw', 'send-wR_encrypted_zvol',
- 'send_partial_dataset', 'send_invalid', 'send_doall']
+ 'send_partial_dataset', 'send_invalid', 'send_doall',
+ 'send_raw_spill_block', 'send_raw_ashift']
tags = ['functional', 'rsend']
[tests/functional/scrub_mirror]
[tests/functional/suid]
tests = ['suid_write_to_suid', 'suid_write_to_sgid', 'suid_write_to_suid_sgid',
- 'suid_write_to_none']
+ 'suid_write_to_none', 'suid_write_zil_replay']
tags = ['functional', 'suid']
[tests/functional/threadsappend]
'userquota_004_pos', 'userquota_005_neg', 'userquota_006_pos',
'userquota_007_pos', 'userquota_008_pos', 'userquota_009_pos',
'userquota_010_pos', 'userquota_011_pos', 'userquota_012_neg',
- 'userspace_001_pos', 'userspace_002_pos', 'userspace_encrypted']
+ 'userspace_001_pos', 'userspace_002_pos', 'userspace_encrypted',
+ 'userspace_send_encrypted']
tags = ['functional', 'userquota']
[tests/functional/vdev_zaps]
tags = ['functional', 'events']
[tests/functional/fallocate:Linux]
-tests = ['fallocate_prealloc', 'fallocate_punch-hole']
+tests = ['fallocate_prealloc']
tags = ['functional', 'fallocate']
[tests/functional/fault:Linux]
tests = ['libaio', 'io_uring']
tags = ['functional', 'io']
+[tests/functional/largest_pool:Linux]
+tests = ['largest_pool_001_pos']
+pre =
+post =
+tags = ['functional', 'largest_pool']
+
[tests/functional/mmap:Linux]
tests = ['mmap_libaio_001_pos']
tags = ['functional', 'mmap']
tests = ['send_realloc_dnode_size', 'send_encrypted_files']
tags = ['functional', 'rsend']
+[tests/functional/simd:Linux]
+pre =
+post =
+tests = ['simd_supported']
+tags = ['functional', 'simd']
+
[tests/functional/snapshot:Linux]
tests = ['snapshot_015_pos', 'snapshot_016_pos']
tags = ['functional', 'snapshot']
[tests/functional/cli_root/zfs_load-key]
tests = ['zfs_load-key', 'zfs_load-key_all', 'zfs_load-key_file',
- 'zfs_load-key_location', 'zfs_load-key_noop', 'zfs_load-key_recursive']
+ 'zfs_load-key_https', 'zfs_load-key_location', 'zfs_load-key_noop',
+ 'zfs_load-key_recursive']
tags = ['functional', 'cli_root', 'zfs_load-key']
[tests/functional/cli_root/zfs_mount]
#
trim_reason = 'DISKS must support discard (TRIM/UNMAP)'
+#
+# Some tests on FreeBSD require the fspacectl(2) system call and the
+# truncate(1) utility supporting the -d option. The system call was first
+# introduced in FreeBSD version 1400032.
+#
+fspacectl_reason = 'fspacectl(2) and truncate -d support required'
+
#
# Some tests are not applicable to a platform or need to be updated to operate
# in the manor required by the platform. Any tests which are skipped for this
if sys.platform.startswith('freebsd'):
known.update({
+ 'cli_root/zfs_receive/receive-o-x_props_override':
+ ['FAIL', known_reason],
'cli_root/zpool_wait/zpool_wait_trim_basic': ['SKIP', trim_reason],
'cli_root/zpool_wait/zpool_wait_trim_cancel': ['SKIP', trim_reason],
'cli_root/zpool_wait/zpool_wait_trim_flag': ['SKIP', trim_reason],
'cli_root/zfs_unshare/setup': ['SKIP', share_reason],
'cli_root/zpool_add/zpool_add_004_pos': ['FAIL', known_reason],
'cli_root/zpool_destroy/zpool_destroy_001_pos': ['SKIP', '6145'],
- 'cli_root/zpool_import/import_rewind_config_changed':
- ['FAIL', rewind_reason],
'cli_root/zpool_import/zpool_import_missing_003_pos': ['SKIP', '6839'],
'cli_root/zpool_initialize/zpool_initialize_import_export':
['FAIL', '11948'],
'cli_root/zpool_trim/setup': ['SKIP', trim_reason],
'cli_root/zpool_upgrade/zpool_upgrade_004_pos': ['FAIL', '6141'],
'delegate/setup': ['SKIP', exec_reason],
+ 'fallocate/fallocate_punch-hole': ['SKIP', fspacectl_reason],
'history/history_004_pos': ['FAIL', '7026'],
'history/history_005_neg': ['FAIL', '6680'],
'history/history_006_neg': ['FAIL', '5657'],
'largest_pool/largest_pool_001_pos': ['FAIL', known_reason],
'mmp/mmp_on_uberblocks': ['FAIL', known_reason],
'pyzfs/pyzfs_unittest': ['SKIP', python_deps_reason],
- 'no_space/enospc_002_pos': ['FAIL', enospc_reason],
'pool_checkpoint/checkpoint_discard_busy': ['FAIL', '11946'],
'projectquota/setup': ['SKIP', exec_reason],
'redundancy/redundancy_004_neg': ['FAIL', '7290'],
'removal/removal_condense_export': ['FAIL', known_reason],
'reservation/reservation_008_pos': ['FAIL', '7741'],
'reservation/reservation_018_pos': ['FAIL', '5642'],
- 'rsend/rsend_019_pos': ['FAIL', '6086'],
- 'rsend/rsend_020_pos': ['FAIL', '6446'],
- 'rsend/rsend_021_pos': ['FAIL', '6446'],
- 'rsend/rsend_024_pos': ['FAIL', '5665'],
- 'rsend/send-c_volume': ['FAIL', '6087'],
- 'rsend/send_partial_dataset': ['FAIL', known_reason],
'snapshot/clone_001_pos': ['FAIL', known_reason],
'snapshot/snapshot_009_pos': ['FAIL', '7961'],
'snapshot/snapshot_010_pos': ['FAIL', '7961'],
maybe.update({
'cli_root/zfs_copies/zfs_copies_002_pos': ['FAIL', known_reason],
'cli_root/zfs_inherit/zfs_inherit_001_neg': ['FAIL', known_reason],
- 'cli_root/zfs_receive/receive-o-x_props_override':
- ['FAIL', known_reason],
'cli_root/zfs_share/zfs_share_011_pos': ['FAIL', known_reason],
'cli_root/zfs_share/zfs_share_concurrent_shares':
['FAIL', known_reason],
'delegate/zfs_allow_003_pos': ['FAIL', known_reason],
'inheritance/inherit_001_pos': ['FAIL', '11829'],
'resilver/resilver_restart_001': ['FAIL', known_reason],
- 'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason],
+ 'pool_checkpoint/checkpoint_big_rewind': ['FAIL', '12622'],
+ 'pool_checkpoint/checkpoint_indirect': ['FAIL', '12623'],
})
elif sys.platform.startswith('linux'):
maybe.update({
- 'alloc_class/alloc_class_009_pos': ['FAIL', known_reason],
- 'alloc_class/alloc_class_010_pos': ['FAIL', known_reason],
- 'alloc_class/alloc_class_011_neg': ['FAIL', known_reason],
- 'alloc_class/alloc_class_012_pos': ['FAIL', known_reason],
- 'alloc_class/alloc_class_013_pos': ['FAIL', '11888'],
'cli_root/zfs_rename/zfs_rename_002_pos': ['FAIL', known_reason],
- 'cli_root/zpool_expand/zpool_expand_001_pos': ['FAIL', known_reason],
- 'cli_root/zpool_expand/zpool_expand_005_pos': ['FAIL', known_reason],
'cli_root/zpool_reopen/zpool_reopen_003_pos': ['FAIL', known_reason],
'fault/auto_spare_shared': ['FAIL', '11889'],
'io/io_uring': ['SKIP', 'io_uring support required'],
'mmp/mmp_active_import': ['FAIL', known_reason],
'mmp/mmp_exported_import': ['FAIL', known_reason],
'mmp/mmp_inactive_import': ['FAIL', known_reason],
- 'refreserv/refreserv_raidz': ['FAIL', known_reason],
- 'rsend/rsend_007_pos': ['FAIL', known_reason],
- 'rsend/rsend_010_pos': ['FAIL', known_reason],
- 'rsend/rsend_011_pos': ['FAIL', known_reason],
- 'snapshot/rollback_003_pos': ['FAIL', known_reason],
+ 'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', '12621'],
+ 'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason],
})
maybe.update({
'events/events_002_pos': ['FAIL', '11546'],
})
+elif sys.platform.startswith('linux'):
+ maybe.update({
+ 'alloc_class/alloc_class_009_pos': ['FAIL', known_reason],
+ 'alloc_class/alloc_class_010_pos': ['FAIL', known_reason],
+ 'cli_root/zfs_rename/zfs_rename_002_pos': ['FAIL', known_reason],
+ 'cli_root/zpool_expand/zpool_expand_001_pos': ['FAIL', known_reason],
+ 'cli_root/zpool_expand/zpool_expand_005_pos': ['FAIL', known_reason],
+ 'cli_root/zpool_reopen/zpool_reopen_003_pos': ['FAIL', known_reason],
+ 'refreserv/refreserv_raidz': ['FAIL', known_reason],
+ 'rsend/rsend_007_pos': ['FAIL', known_reason],
+ 'rsend/rsend_010_pos': ['FAIL', known_reason],
+ 'rsend/rsend_011_pos': ['FAIL', known_reason],
+ 'snapshot/rollback_003_pos': ['FAIL', known_reason],
+ })
def usage(s):
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/sysmacros.h>
#include <errno.h>
+#ifdef __linux__
+#include <linux/fs.h>
+#endif
static void
seek_data(int fd, off_t offset, off_t expected)
function block_device_wait
{
if is_linux; then
- udevadm trigger $*
+ udevadm trigger $* 2>/dev/null
typeset start=$SECONDS
udevadm settle
typeset elapsed=$((SECONDS - start))
# Copyright (c) 2017, Lawrence Livermore National Security LLC.
# Copyright (c) 2017, Datto Inc. All rights reserved.
# Copyright (c) 2017, Open-E Inc. All rights reserved.
+# Copyright (c) 2021, The FreeBSD Foundation.
# Use is subject to license terms.
#
function splitline
{
- echo $1 | sed "s/,/ /g"
+ echo $1 | tr ',' ' '
}
function default_setup
case "$(uname)" in
Linux)
endcyl=$(parted -s $DEV_DSKDIR/$disk -- unit cyl print | \
- grep "part${slice}" | \
- awk '{print $3}' | \
- sed 's,cyl,,')
+ awk "/part${slice}/"' {sub(/cyl/, "", $3); print $3}')
((endcyl = (endcyl + 1)))
;;
FreeBSD)
if datasetnonexists "$fs" ; then
return 1
else
- fs=$(echo $fs | sed 's@/@_@g')
+ fs=$(echo $fs | tr / _)
fi
if is_linux; then
disklist=$(zpool iostat -v $1 | nawk '(NR >4) {print $1}' | \
grep -v "\-\-\-\-\-" | \
- egrep -v -e "^(mirror|raidz[1-3]|spare|log|cache|special|dedup)$")
+ egrep -v -e "^(mirror|raidz[1-3]|draid[1-3]|spare|log|cache|special|dedup)|\-[0-9]$")
echo $disklist
}
esac
}
+function punch_hole # offset length file
+{
+ typeset offset=$1
+ typeset length=$2
+ typeset file=$3
+
+ case $(uname) in
+ FreeBSD)
+ truncate -d -o $offset -l $length "$file"
+ ;;
+ Linux)
+ fallocate --punch-hole --offset $offset --length $length "$file"
+ ;;
+ *)
+ false
+ ;;
+ esac
+}
+
#
# Wait for the specified arcstat to reach non-zero quiescence.
# If echo is 1 echo the value after reaching quiescence, otherwise
if BUILD_LINUX
SUBDIRS += \
+ simd \
tmpfile
endif
((ret |= $?))
kill -9 $pid
+ wait $pid 2> /dev/null
return $ret
}
--- /dev/null
+000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
zfs_load-key.ksh \
zfs_load-key_all.ksh \
zfs_load-key_file.ksh \
+ zfs_load-key_https.ksh \
zfs_load-key_location.ksh \
zfs_load-key_noop.ksh \
zfs_load-key_recursive.ksh
dist_pkgdata_DATA = \
zfs_load-key.cfg \
- zfs_load-key_common.kshlib
+ zfs_load-key_common.kshlib \
+ PASSPHRASE \
+ HEXKEY \
+ RAWKEY
--- /dev/null
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
#
. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+cleanup_https
default_cleanup
#
. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
DISK=${DISKS%% *}
-default_setup $DISK
+default_setup_noexit $DISK
+setup_https
+log_pass
# Copyright (c) 2017 Datto, Inc. All rights reserved.
#
+# $PASSPHRASE, $HEXKEY, and $RAWKEY must be kept in sync
+# with the corresponding files in this directory
+
export PASSPHRASE="password"
export PASSPHRASE1="password1"
export PASSPHRASE2="password2"
export HEXKEY1="201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A090807060504030201"
export RAWKEY="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
export RAWKEY1="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+
+export SSL_CA_CERT_FILE="/$TESTPOOL/snakeoil.crt"
+export HTTPS_PORT_FILE="/$TESTPOOL/snakeoil.port"
+export HTTPS_HOSTNAME="localhost"
+export HTTPS_PORT=
+export HTTPS_BASE_URL=
+
+function get_https_port
+{
+ if [ -z "$HTTPS_PORT" ]; then
+ read -r HTTPS_PORT < "$HTTPS_PORT_FILE" || return
+ fi
+
+ echo "$HTTPS_PORT"
+}
+
+function get_https_base_url
+{
+ if [ -z "$HTTPS_BASE_URL" ]; then
+ HTTPS_BASE_URL="https://$HTTPS_HOSTNAME:$(get_https_port)" || {
+ typeset ret=$?
+ HTTPS_BASE_URL=
+ return $ret
+ }
+ fi
+
+ echo "$HTTPS_BASE_URL"
+}
function cleanup
{
datasetexists $TESTPOOL/$TESTFS1 && destroy_dataset $TESTPOOL/$TESTFS1
+ datasetexists $TESTPOOL/$TESTFS2 && destroy_dataset $TESTPOOL/$TESTFS2
datasetexists $TESTPOOL/zvol && destroy_dataset $TESTPOOL/zvol
poolexists $TESTPOOL1 && log_must destroy_pool $TESTPOOL1
}
log_must zfs create -o encryption=on -o keyformat=passphrase \
-o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=$(get_https_base_url)/PASSPHRASE $TESTPOOL/$TESTFS2
+
log_must zfs create -V 64M -o encryption=on -o keyformat=passphrase \
-o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/zvol
log_must zfs unmount $TESTPOOL/$TESTFS1
log_must_busy zfs unload-key $TESTPOOL/$TESTFS1
+log_must zfs unmount $TESTPOOL/$TESTFS2
+log_must_busy zfs unload-key $TESTPOOL/$TESTFS2
+
log_must_busy zfs unload-key $TESTPOOL/zvol
log_must zfs unmount $TESTPOOL1
log_must key_available $TESTPOOL1
log_must key_available $TESTPOOL/zvol
log_must key_available $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS2
log_must zfs mount $TESTPOOL1
log_must zfs mount $TESTPOOL/$TESTFS1
+log_must zfs mount $TESTPOOL/$TESTFS2
log_pass "'zfs load-key -a' loads keys for all datasets"
return 0
}
+
+function setup_https
+{
+ log_must openssl req -x509 -newkey rsa:4096 -sha256 -days 1 -nodes -keyout "/$TESTPOOL/snakeoil.key" -out "$SSL_CA_CERT_FILE" -subj "/CN=$HTTPS_HOSTNAME"
+
+ python3 -uc "
+import http.server, ssl, sys, os, time, random
+
+sys.stdin.close()
+
+httpd, err, port = None, None, None
+for i in range(1, 100):
+ port = random.randint(0xC000, 0xFFFF) # ephemeral range
+ try:
+ httpd = http.server.HTTPServer(('$HTTPS_HOSTNAME', port), http.server.SimpleHTTPRequestHandler)
+ break
+ except:
+ err = sys.exc_info()[1]
+ time.sleep(i / 100)
+if not httpd:
+ raise err
+
+with open('$HTTPS_PORT_FILE', 'w') as portf:
+ print(port, file=portf)
+
+httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, keyfile='/$TESTPOOL/snakeoil.key', certfile='$SSL_CA_CERT_FILE', ssl_version=ssl.PROTOCOL_TLS)
+
+os.chdir('$STF_SUITE/tests/functional/cli_root/zfs_load-key')
+
+with open('/$TESTPOOL/snakeoil.pid', 'w') as pidf:
+ if os.fork() != 0:
+ os._exit(0)
+ print(os.getpid(), file=pidf)
+
+sys.stdout.close()
+sys.stderr.close()
+try:
+ sys.stdout = sys.stderr = open('/tmp/ZTS-snakeoil.log', 'w', buffering=1) # line
+except:
+ sys.stdout = sys.stderr = open('/dev/null', 'w')
+
+print('{} start on {}'.format(os.getpid(), port))
+httpd.serve_forever()
+" || log_fail
+
+ typeset https_pid=
+ for d in $(seq 0 0.1 5); do
+ read -r https_pid 2>/dev/null < "/$TESTPOOL/snakeoil.pid" && [ -n "$https_pid" ] && break
+ sleep "$d"
+ done
+ [ -z "$https_pid" ] && log_fail "Couldn't start HTTPS server"
+ log_note "Started HTTPS server as $https_pid on port $(get_https_port)"
+}
+
+function cleanup_https
+{
+ typeset https_pid=
+ read -r https_pid 2>/dev/null < "/$TESTPOOL/snakeoil.pid" || return 0
+
+ log_must kill "$https_pid"
+ cat /tmp/ZTS-snakeoil.log
+ rm -f "/$TESTPOOL/snakeoil.pid" "/tmp/ZTS-snakeoil.log"
+}
--- /dev/null
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs load-key' should load a dataset's key from an https:// URL,
+# but fail to do so if the domain doesn't exist or the file 404s.
+#
+# STRATEGY:
+# 1. Try to create a dataset pointing to an RFC6761-guaranteed unresolvable domain,
+# one to the sshd port (which will be either unoccupied (ECONNREFUSED)
+# or have sshd on it ("wrong version number")).
+# and one pointing to an URL that will always 404.
+# 2. Create encrypted datasets with keylocation=https://address
+# 3. Unmount the datasets and unload their keys
+# 4. Attempt to load the keys
+# 5. Verify the keys are loaded
+# 6. Attempt to mount the datasets
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for fs in "$TESTFS1" "$TESTFS2" "$TESTFS3"; do
+ datasetexists $TESTPOOL/$fs && \
+ log_must zfs destroy $TESTPOOL/$fs
+ done
+}
+log_onexit cleanup
+
+log_assert "'zfs load-key' should load a key from a file"
+
+log_mustnot zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=https://invalid./where-ever $TESTPOOL/$TESTFS1
+
+log_mustnot zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=https://$HTTPS_HOSTNAME:22 $TESTPOOL/$TESTFS1
+
+log_mustnot zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=$(get_https_base_url)/ENOENT $TESTPOOL/$TESTFS1
+
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=$(get_https_base_url)/PASSPHRASE $TESTPOOL/$TESTFS1
+
+log_must zfs create -o encryption=on -o keyformat=hex \
+ -o keylocation=$(get_https_base_url)/HEXKEY $TESTPOOL/$TESTFS2
+
+log_must zfs create -o encryption=on -o keyformat=raw \
+ -o keylocation=$(get_https_base_url)/RAWKEY $TESTPOOL/$TESTFS3
+
+for fs in "$TESTFS1" "$TESTFS2" "$TESTFS3"; do
+ log_must zfs unmount $TESTPOOL/$fs
+ log_must zfs unload-key $TESTPOOL/$fs
+done
+for fs in "$TESTFS1" "$TESTFS2" "$TESTFS3"; do
+ log_must zfs load-key $TESTPOOL/$fs
+ log_must key_available $TESTPOOL/$fs
+ log_must zfs mount $TESTPOOL/$fs
+done
+
+log_pass "'zfs load-key' loads a key from a file"
log_must key_available $TESTPOOL/$TESTFS1
log_must verify_keylocation $TESTPOOL/$TESTFS1 "file://$key_location"
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+log_must zfs load-key -L $(get_https_base_url)/PASSPHRASE $TESTPOOL/$TESTFS1
+log_must key_available $TESTPOOL/$TESTFS1
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "file://$key_location"
+
log_pass "'zfs load-key -L' overrides keylocation with provided value"
log_must zfs create -o keyformat=passphrase \
-o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1/child
+log_must zfs create -o keyformat=passphrase \
+ -o keylocation=$(get_https_base_url)/PASSPHRASE $TESTPOOL/$TESTFS1/child/child
+
log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1/child/child
log_must zfs unload-key $TESTPOOL/$TESTFS1/child
log_must zfs unload-key $TESTPOOL/$TESTFS1
log_must zfs load-key -r $TESTPOOL
log_must key_available $TESTPOOL/$TESTFS1
log_must key_available $TESTPOOL/$TESTFS1/child
+log_must key_available $TESTPOOL/$TESTFS1/child/child
log_must zfs mount $TESTPOOL/$TESTFS1
log_must zfs mount $TESTPOOL/$TESTFS1/child
+log_must zfs mount $TESTPOOL/$TESTFS1/child/child
log_pass "'zfs load-key -r' recursively loads keys"
zfs_receive_raw.ksh \
zfs_receive_raw_incremental.ksh \
zfs_receive_raw_-d.ksh \
- zfs_receive_-e.ksh
+ zfs_receive_-e.ksh \
+ zfs_receive_-wR-encrypted-mix.ksh
dist_pkgdata_DATA = \
zstd_test_data.txt
--- /dev/null
+#!/bin/ksh -p
+#
+# 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 http://www.opensolaris.org/os/licensing.
+# 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) 2022 by Attila Fülöp <attila@fueloep.org>
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS should receive a raw send of a mix of unencrypted and encrypted
+# child datasets
+#
+# The layout of the datasets is: enc/unenc/enc/unenc
+#
+# STRATEGY:
+# 1. Create the dataset hierarchy
+# 2. Snapshot the dataset hierarchy
+# 3. Send -Rw the dataset hierarchy and receive into a top-level dataset
+# 4. Check the encryption property of the received datasets
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists "$TESTPOOL/$TESTFS1" && \
+ destroy_dataset "$TESTPOOL/$TESTFS1" -r
+
+ datasetexists "$TESTPOOL/$TESTFS2" && \
+ destroy_dataset "$TESTPOOL/$TESTFS2" -r
+}
+
+log_onexit cleanup
+
+log_assert "ZFS should receive a mix of un/encrypted childs"
+
+typeset src="$TESTPOOL/$TESTFS1"
+typeset dst="$TESTPOOL/$TESTFS2"
+typeset snap="snap"
+
+echo "password" | \
+ create_dataset "$src" -o encryption=on -o keyformat=passphrase
+create_dataset "$src/u" "-o encryption=off"
+echo "password" | \
+ create_dataset "$src/u/e" -o encryption=on -o keyformat=passphrase
+create_dataset "$src/u/e/u" -o encryption=off
+
+log_must zfs snapshot -r "$src@$snap"
+log_must eval "zfs send -Rw $src@$snap | zfs receive -u $dst"
+log_must test "$(get_prop 'encryption' $dst)" != "off"
+log_must test "$(get_prop 'encryption' $dst/u)" == "off"
+log_must test "$(get_prop 'encryption' $dst/u/e)" != "off"
+log_must test "$(get_prop 'encryption' $dst/u/e/u)" == "off"
+
+log_pass "ZFS can receive a mix of un/encrypted childs"
log_note "Verifying ZFS will receive to an encrypted child"
log_must eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c1"
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c1)" != "off"
-log_note "Verifying 'send -p' will receive to an encrypted child"
+# Unload the key, the following tests won't require it and we will test
+# the receive checks as well.
+log_must zfs unmount $TESTPOOL/$TESTFS1
+log_must zfs unload-key $TESTPOOL/$TESTFS1
+
+log_note "Verifying 'send -p' will receive to an unencrypted child"
log_must eval "zfs send -p $snap | zfs receive $TESTPOOL/$TESTFS1/c2"
log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c2)" == "off"
-log_note "Verifying 'send -R' will receive to an encrypted child"
+# For completeness add the property override case.
+log_note "Verifying recv -o encyption=off' will receive to an unencrypted child"
+log_must eval "zfs send $snap | \
+ zfs receive -o encryption=off $TESTPOOL/$TESTFS1/c2o"
+log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c2o)" == "off"
+
+log_note "Verifying 'send -R' will receive to an unencrypted child"
log_must eval "zfs send -R $snap | zfs receive $TESTPOOL/$TESTFS1/c3"
log_must test "$(get_prop 'encryption' $TESTPOOL/$TESTFS1/c3)" == "off"
log_note "Verifying ZFS will not receive to an encrypted child when the" \
"parent key is unloaded"
-log_must zfs unmount $TESTPOOL/$TESTFS1
-log_must zfs unload-key $TESTPOOL/$TESTFS1
log_mustnot eval "zfs send $snap | zfs receive $TESTPOOL/$TESTFS1/c4"
log_pass "ZFS can receive encrypted filesystems into child dataset"
}
log_onexit cleanup
-log_assert "Key location can only be 'prompt' or a file path for encryption" \
- "roots, and 'none' for unencrypted volumes"
+log_assert "Key location can only be 'prompt', 'file://', or 'https://'" \
+ "for encryption roots, and 'none' for unencrypted volumes"
log_must eval "echo $PASSPHRASE > /$TESTPOOL/pkey"
-o keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
log_mustnot zfs set keylocation=none $TESTPOOL/$TESTFS1
-if true; then
- log_mustnot zfs set keylocation=/$TESTPOOL/pkey $TESTPOOL/$TESTFS1
-else
- ### SOON: ###
- # file:///$TESTPOOL/pkey and /$TESTPOOL/pkey are equivalent on FreeBSD
- # thanks to libfetch. Eventually we want to make the other platforms
- # work this way as well, either by porting libfetch or by other means.
- log_must zfs set keylocation=/$TESTPOOL/pkey $TESTPOOL/$TESTFS1
-fi
+log_mustnot zfs set keylocation=/$TESTPOOL/pkey $TESTPOOL/$TESTFS1
log_must zfs set keylocation=file:///$TESTPOOL/pkey $TESTPOOL/$TESTFS1
log_must verify_keylocation $TESTPOOL/$TESTFS1 "file:///$TESTPOOL/pkey"
+setup_https
+log_must zfs set keylocation=$(get_https_base_url)/PASSPHRASE $TESTPOOL/$TESTFS1
+log_must verify_keylocation $TESTPOOL/$TESTFS1 "$(get_https_base_url)/PASSPHRASE"
+
log_must zfs set keylocation=prompt $TESTPOOL/$TESTFS1
log_must verify_keylocation $TESTPOOL/$TESTFS1 "prompt"
log_must verify_keylocation $TESTPOOL/$TESTFS1/child "none"
-log_pass "Key location can only be 'prompt' or a file path for encryption" \
- "roots, and 'none' for unencrypted volumes"
+log_pass "Key location can only be 'prompt', 'file://', or 'https://'" \
+ "for encryption roots, and 'none' for unencrypted volumes"
# in zpool status.
#
# STRATEGY:
-# 1. Create a raidz or mirror pool
+# 1. Create a mirror, raidz, or draid pool
# 2. Inject read/write IO errors or checksum errors
# 3. Verify the number of errors in zpool status match the corresponding
# number of error events.
-# 4. Repeat for all combinations of raidz/mirror and io/checksum errors.
+# 4. Repeat for all combinations of mirror/raidz/draid and io/checksum
+# errors.
#
. $STF_SUITE/include/libtest.shlib
# Run error test on a specific type of pool
#
-# $1: pool - raidz, mirror
+# $1: pool - mirror, raidz, draid
# $2: test type - corrupt (checksum error), io
# $3: read, write
function do_test
log_must zpool destroy $POOL
}
-# Test all types of errors on mirror and raidz pools
-for pooltype in mirror raidz ; do
+# Test all types of errors on mirror, raidz, and draid pools
+for pooltype in mirror raidz draid; do
do_test $pooltype corrupt read
do_test $pooltype io read
do_test $pooltype io write
log_assert "zpool can be autoexpanded after set autoexpand=on on vdev expansion"
-for type in " " mirror raidz draid; do
+for type in " " mirror raidz draid:1s; do
log_note "Setting up loopback, scsi_debug, and file vdevs"
log_must truncate -s $org_size $FILE_LO
DEV1=$(losetup -f)
if [[ $? -ne 0 ]] ; then
log_fail "pool $TESTPOOL1 has not expanded"
fi
- elif [[ $type == "draid" ]]; then
+ elif [[ $type == "draid:1s" ]]; then
typeset expansion_size=$((2*($exp_size-$org_size)))
zpool history -il $TESTPOOL1 | \
grep "pool '$TESTPOOL1' size:" | \
log_must generate_data $TESTPOOL1 $MD5FILE2 "second"
- log_must zpool export $TESTPOOL1
+ log_must_busy zpool export $TESTPOOL1
log_must mv $missingvdevs $BACKUP_DEVICE_DIR
"get suspended."
verify_data_md5sums $MD5FILE >/dev/null 2>&1
- log_must zpool export $TESTPOOL1
+ log_must_busy zpool export $TESTPOOL1
typeset newpaths=$(echo "$missingvdevs" | \
sed "s:$DEVICE_DIR:$BACKUP_DEVICE_DIR:g")
typeset detachvdev="${4:-}"
typeset removevdev="${5:-}"
typeset finalpool="${6:-}"
+ typeset retval=1
typeset poolcheck="$poolcreate"
# while having a checkpoint, we take it after the
# operation that changes the config.
#
+ # However, it is possible the MOS data was overwritten
+ # in which case the pool will either be unimportable, or
+ # may have been rewound prior to the data being written.
+ # In which case an error is returned and test_common()
+ # is retried by the caller to minimize false positives.
+ #
log_must zpool checkpoint $TESTPOOL1
log_must overwrite_data $TESTPOOL1 ""
log_must zpool export $TESTPOOL1
- log_must zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1
- log_must check_pool_config $TESTPOOL1 "$poolcheck"
+ zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1
+ if (( $? == 0 )); then
+ verify_data_md5sums $MD5FILE
+ if (( $? == 0 )); then
+ retval=0
+ fi
- log_must verify_data_md5sums $MD5FILE
+ log_must check_pool_config $TESTPOOL1 "$poolcheck"
+ log_must zpool destroy $TESTPOOL1
+ fi
# Cleanup
- log_must zpool destroy $TESTPOOL1
if [[ -n $pathstochange ]]; then
for dev in $pathstochange; do
log_must mv "${dev}_new" $dev
log_must zpool destroy $TESTPOOL2
log_note ""
+ return $retval
}
function test_add_vdevs
log_note "$0: pool '$poolcreate', add $addvdevs."
- test_common "$poolcreate" "$addvdevs"
+ for retry in $(seq 1 5); do
+ test_common "$poolcreate" "$addvdevs" && return
+ log_note "Retry $retry / 5 for test_add_vdevs()"
+ done
+
+ log_fail "Exhausted all 5 retries for test_add_vdevs()"
}
function test_attach_vdev
log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto."
- test_common "$poolcreate" "" "$attachto $attachvdev"
+ for retry in $(seq 1 5); do
+ test_common "$poolcreate" "" "$attachto $attachvdev" && return
+ log_note "Retry $retry / 5 for test_attach_vdev()"
+ done
+
+ log_fail "Exhausted all 5 retries for test_attach_vdev()"
}
function test_detach_vdev
log_note "$0: pool '$poolcreate', detach $detachvdev."
- test_common "$poolcreate" "" "" "$detachvdev"
+ for retry in $(seq 1 5); do
+ test_common "$poolcreate" "" "" "$detachvdev" && return
+ log_note "Retry $retry / 5 for test_detach_vdev()"
+ done
+
+ log_fail "Exhausted all 5 retries for test_detach_vdev()"
}
function test_attach_detach_vdev
log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto," \
"then detach $detachvdev."
- test_common "$poolcreate" "" "$attachto $attachvdev" "$detachvdev"
+ for retry in $(seq 1 5); do
+ test_common "$poolcreate" "" "$attachto $attachvdev" \
+ "$detachvdev" && return
+ log_note "Retry $retry / 5 for test_attach_detach_vdev()"
+ done
+
+ log_fail "Exhausted all 5 retries for test_attach_detach_vdev()"
}
function test_remove_vdev
log_note "$0: pool '$poolcreate', remove $removevdev."
- test_common "$poolcreate" "" "" "" "$removevdev" "$finalpool"
+ for retry in $(seq 1 5); do
+ test_common "$poolcreate" "" "" "" "$removevdev" \
+ "$finalpool" && return
+ log_note "Retry $retry / 5 for test_remove_vdev()"
+ done
+
+ log_fail "Exhausted all 5 retries for test_remove_vdev()"
}
# Record txg history
{
typeset pool=$1
typeset -i timeout=$2
- typeset func=$3
+ typeset funct=$3
while [ $timeout -gt 0 ]; do
(( --timeout ))
- if ( $func $pool ); then
+ if ( $funct $pool ); then
return 0
fi
sleep 1
fi
log_must zpool events
-# Verify at least 5 deadman events were logged. The first after 5 seconds,
+# Verify at least 4 deadman events were logged. The first after 5 seconds,
# and another each second thereafter until the delay is clearer.
events=$(zpool events | grep -c ereport.fs.zfs.deadman)
-if [ "$events" -lt 5 ]; then
+if [ "$events" -lt 4 ]; then
log_fail "Expect >=5 deadman events, $events found"
fi
#
# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+# Copyright (c) 2021 by The FreeBSD Foundation.
#
. $STF_SUITE/include/libtest.shlib
#
# DESCRIPTION:
-# Test `fallocate --punch-hole`
+# Test hole-punching functionality
#
# STRATEGY:
# 1. Create a dense file
verify_runnable "global"
+#
+# Prior to __FreeBSD_version 1400032 there are no mechanism to punch hole in a
+# file on FreeBSD. truncate -d support is required to call fspacectl(2) on
+# behalf of the script.
+#
+if is_freebsd; then
+ if [[ $(uname -K) -lt 1400032 ]]; then
+ log_unsupported "Requires fspacectl(2) support on FreeBSD"
+ fi
+ if truncate -d 2>&1 | grep "illegal option" > /dev/null; then
+ log_unsupported "Requires truncate(1) -d support on FreeBSD"
+ fi
+fi
+
FILE=$TESTDIR/$TESTFILE0
BLKSZ=$(get_prop recordsize $TESTPOOL)
log_must check_disk_size $((131072 * 8))
# Punch a hole for the first full block.
-log_must fallocate --punch-hole --offset 0 --length $BLKSZ $FILE
+log_must punch_hole 0 $BLKSZ $FILE
log_must check_disk_size $((131072 * 7))
# Partially punch a hole in the second block.
-log_must fallocate --punch-hole --offset $BLKSZ --length $((BLKSZ / 2)) $FILE
+log_must punch_hole $BLKSZ $((BLKSZ / 2)) $FILE
log_must check_disk_size $((131072 * 7))
# Punch a hole which overlaps the third and forth block.
-log_must fallocate --punch-hole --offset $(((BLKSZ * 2) + (BLKSZ / 2))) \
- --length $((BLKSZ)) $FILE
+log_must punch_hole $(((BLKSZ * 2) + (BLKSZ / 2))) $((BLKSZ)) $FILE
log_must check_disk_size $((131072 * 7))
# Punch a hole from the fifth block past the end of file. The apparent
# file size should not change since --keep-size is implied.
apparent_size=$(stat_size $FILE)
-log_must fallocate --punch-hole --offset $((BLKSZ * 4)) \
- --length $((BLKSZ * 10)) $FILE
+log_must punch_hole $((BLKSZ * 4)) $((BLKSZ * 10)) $FILE
log_must check_disk_size $((131072 * 4))
log_must check_apparent_size $apparent_size
log_must zfs share $fs
log_must zfs unshare $fs
fi
-log_must zfs send -i $snap1 $snap2 > /dev/null
+# https://github.com/openzfs/zfs/issues/11445
+set -o pipefail
+log_must zfs send -i $snap1 $snap2 | cat > /dev/null
log_must zfs holds $snap1
log_must eval "zpool history $TESTPOOL > $NEW_HISTORY"
enospc_001_pos.ksh \
enospc_002_pos.ksh \
enospc_003_pos.ksh \
- enospc_df.ksh
+ enospc_df.ksh \
+ enospc_rm.ksh
dist_pkgdata_DATA = \
enospc.cfg
#
log_note "Writing files until ENOSPC."
-for i in $(seq 30); do
+for i in $(seq 100); do
file_write -o create -f $TESTDIR/file.$i -b $BLOCKSZ \
-c $NUM_WRITES -d $DATA
ret=$?
log_mustnot_expect space zfs create $TESTPOOL/$TESTFS/subfs
log_mustnot_expect space zfs clone $TESTPOOL/$TESTFS@snap $TESTPOOL/clone
-log_mustnot_expect space zfs snapshot $TESTPOOL/$TESTFS@snap2
-log_mustnot_expect space zfs bookmark \
- $TESTPOOL/$TESTFS@snap $TESTPOOL/$TESTFS#bookmark
log_must zfs send $TESTPOOL/$TESTFS@snap > $TEST_BASE_DIR/stream.$$
log_mustnot_expect space zfs receive $TESTPOOL/$TESTFS/recvd < $TEST_BASE_DIR/stream.$$
--- /dev/null
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2022 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/no_space/enospc.cfg
+
+#
+# DESCRIPTION:
+# After filling a filesystem, verify the contents can be removed
+# without encountering an ENOSPC error.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ log_must rm -f $all_vdevs
+}
+
+log_onexit cleanup
+
+log_assert "Files can be removed from full file system."
+
+all_vdevs=$(echo $TEST_BASE_DIR/file.{01..12})
+
+log_must truncate -s $MINVDEVSIZE $all_vdevs
+
+log_must zpool create -f $TESTPOOL draid2:8d:2s $all_vdevs
+log_must zfs create $TESTPOOL/$TESTFS
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+log_note "Writing files until ENOSPC."
+log_mustnot_expect "No space left on device" fio --name=test \
+ --fallocate=none --rw=write --bs=1M --size=1G --numjobs=4 \
+ --sync=1 --directory=$TESTDIR/ --group_reporting
+
+log_must rm $TESTDIR/test.*
+log_must test -z "$(ls -A $TESTDIR)"
+
+log_pass "All files removed without error"
log_must zpool checkpoint $TESTPOOL
test_change_state_after_checkpoint
-log_must zpool export $TESTPOOL
+log_must_busy zpool export $TESTPOOL
log_must zpool import -o readonly=on --rewind-to-checkpoint $TESTPOOL
test_verify_pre_checkpoint_state "ro-check"
-log_must zpool export $TESTPOOL
+log_must_busy zpool export $TESTPOOL
log_must zpool import $TESTPOOL
test_verify_post_checkpoint_state
typeset -i cnt=$2
typeset all_devs=$(zpool iostat -v $pool | awk '{print $1}'| \
- egrep -v "^pool$|^capacity$|^mirror$|^raidz1$|^raidz2$|^raidz3$|^draid1.*|^draid2.*|^draid3.*|---" | \
+ egrep -v "^pool$|^capacity$|^mirror\-[0-9]$|^raidz[1-3]\-[0-9]$|^draid[1-3].*\-[0-9]$|---" | \
egrep -v "/old$|^$pool$")
typeset -i i=0
typeset vdevs
block_device_wait "/dev/zvol/$vol"
log_must dd if=/dev/zero of=/dev/zvol/$vol \
bs=1024k count=$volsize
- sync
+ sync_pool $TESTPOOL
ref=$(zfs get -Hpo value referenced "$vol")
refres=$(zfs get -Hpo value refreservation "$vol")
verify_runnable "both"
-fs=$TESTPOOL/$TESTFS/$(basename $0).$$
+fs=$TESTPOOL/$TESTFS/${0##*/}.$$
function cleanup
{
send_realloc_files.ksh \
send_realloc_encrypted_files.ksh \
send_spill_block.ksh \
+ send_raw_spill_block.ksh \
+ send_raw_ashift.ksh \
send_holds.ksh \
send_hole_birth.ksh \
send_invalid.ksh \
log_must rm -rf $BACKDIR/*
if is_global_zone ; then
+ #
+ # Linux: Issuing a `df` seems to properly force any negative
+ # dcache entries to be invalidated preventing failures when
+ # accessing the mount point. Additional investigation required.
+ #
+ # https://github.com/openzfs/zfs/issues/6143
+ #
+ log_must df >/dev/null
log_must_busy zfs destroy -Rf $pool
else
typeset list=$(zfs list -H -r -t all -o name $pool)
log_onexit cleanup_pool $POOL2
typeset sendfs=$POOL2/$FS
-typeset megs=128
+typeset megs=64
for prop in "${compress_prop_vals[@]}"; do
for compressible in 'yes' 'no'; do
--- /dev/null
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2019, Lawrence Livermore National Security, LLC.
+# Copyright (c) 2021, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify encrypted raw sending to pools with greater ashift succeeds.
+#
+# Strategy:
+# 1) Create a set of files each containing some file data in an
+# encrypted filesystem.
+# 2) Snapshot and raw send these files to a pool with greater ashift
+# 3) Verify that all the xattrs (and thus the spill block) were
+# preserved when receiving the incremental stream.
+# 4) Repeat the test for a non-encrypted filesystem using raw send
+#
+
+verify_runnable "both"
+
+log_assert "Verify raw sending to pools with greater ashift succeeds"
+
+function cleanup
+{
+ rm -f $BACKDIR/fs@*
+ poolexists pool9 && destroy_pool pool9
+ poolexists pool12 && destroy_pool pool12
+ log_must rm -f $TESTDIR/vdev_a $TESTDIR/vdev_b
+}
+
+function xattr_test
+{
+ log_must zfs set xattr=sa pool9/$1
+ log_must zfs set dnodesize=legacy pool9/$1
+ log_must zfs set recordsize=128k pool9/$1
+ rand_set_prop pool9/$1 compression "${compress_prop_vals[@]}"
+
+ # Create 40 files each with a spill block containing xattrs. Each file
+ # will be modified in a different way to validate the incremental receive.
+ for i in {1..40}; do
+ file="/pool9/$1/file$i"
+
+ log_must mkfile 16384 $file
+ for j in {1..20}; do
+ log_must set_xattr "testattr$j" "$attrvalue" $file
+ done
+ done
+
+ # Snapshot the pool and send it to the new dataset.
+ log_must zfs snapshot pool9/$1@snap1
+ log_must eval "zfs send -w pool9/$1@snap1 >$BACKDIR/$1@snap1"
+ log_must eval "zfs recv pool12/$1 < $BACKDIR/$1@snap1"
+
+ #
+ # Modify file[1-6]'s contents but not the spill blocks.
+ #
+ # file1 - Increase record size; single block
+ # file2 - Increase record size; multiple blocks
+ # file3 - Truncate file to zero size; single block
+ # file4 - Truncate file to smaller size; single block
+ # file5 - Truncate file to much larger size; add holes
+ # file6 - Truncate file to embedded size; embedded data
+ #
+ log_must mkfile 32768 /pool9/$1/file1
+ log_must mkfile 1048576 /pool9/$1/file2
+ log_must truncate -s 0 /pool9/$1/file3
+ log_must truncate -s 8192 /pool9/$1/file4
+ log_must truncate -s 1073741824 /pool9/$1/file5
+ log_must truncate -s 50 /pool9/$1/file6
+
+ #
+ # Modify file[11-16]'s contents and their spill blocks.
+ #
+ # file11 - Increase record size; single block
+ # file12 - Increase record size; multiple blocks
+ # file13 - Truncate file to zero size; single block
+ # file14 - Truncate file to smaller size; single block
+ # file15 - Truncate file to much larger size; add holes
+ # file16 - Truncate file to embedded size; embedded data
+ #
+ log_must mkfile 32768 /pool9/$1/file11
+ log_must mkfile 1048576 /pool9/$1/file12
+ log_must truncate -s 0 /pool9/$1/file13
+ log_must truncate -s 8192 /pool9/$1/file14
+ log_must truncate -s 1073741824 /pool9/$1/file15
+ log_must truncate -s 50 /pool9/$1/file16
+
+ for i in {11..20}; do
+ log_must rm_xattr testattr1 /pool9/$1/file$i
+ done
+
+ #
+ # Modify file[21-26]'s contents and remove their spill blocks.
+ #
+ # file21 - Increase record size; single block
+ # file22 - Increase record size; multiple blocks
+ # file23 - Truncate file to zero size; single block
+ # file24 - Truncate file to smaller size; single block
+ # file25 - Truncate file to much larger size; add holes
+ # file26 - Truncate file to embedded size; embedded data
+ #
+ log_must mkfile 32768 /pool9/$1/file21
+ log_must mkfile 1048576 /pool9/$1/file22
+ log_must truncate -s 0 /pool9/$1/file23
+ log_must truncate -s 8192 /pool9/$1/file24
+ log_must truncate -s 1073741824 /pool9/$1/file25
+ log_must truncate -s 50 /pool9/$1/file26
+
+ for i in {21..30}; do
+ for j in {1..20}; do
+ log_must rm_xattr testattr$j /pool9/$1/file$i
+ done
+ done
+
+ #
+ # Modify file[31-40]'s spill blocks but not the file contents.
+ #
+ for i in {31..40}; do
+ file="/pool9/$1/file$i"
+ log_must rm_xattr testattr$(((RANDOM % 20) + 1)) $file
+ log_must set_xattr testattr$(((RANDOM % 20) + 1)) "$attrvalue" $file
+ done
+
+ # Snapshot the pool and send the incremental snapshot.
+ log_must zfs snapshot pool9/$1@snap2
+ log_must eval "zfs send -w -i pool9/$1@snap1 pool9/$1@snap2 >$BACKDIR/$1@snap2"
+ log_must eval "zfs recv pool12/$1 < $BACKDIR/$1@snap2"
+}
+
+attrvalue="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+
+log_onexit cleanup
+
+# Create pools
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
+truncate -s $MINVDEVSIZE $TESTDIR/vdev_b
+log_must zpool create -f -o ashift=9 pool9 $TESTDIR/vdev_a
+log_must zpool create -f -o ashift=12 pool12 $TESTDIR/vdev_b
+
+# Create encrypted fs
+log_must eval "echo 'password' | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt " \
+ "pool9/encfs"
+
+# Run xattr tests for encrypted fs
+xattr_test encfs
+
+# Calculate the expected recursive checksum for source encrypted fs
+expected_cksum=$(recursive_cksum /pool9/encfs)
+
+# Mount target encrypted fs
+log_must eval "echo 'password' | zfs load-key pool12/encfs"
+log_must zfs mount pool12/encfs
+
+# Validate the received copy using the received recursive checksum
+actual_cksum=$(recursive_cksum /pool12/encfs)
+if [[ "$expected_cksum" != "$actual_cksum" ]]; then
+ log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
+fi
+
+# Perform the same test but without encryption (send -w)
+log_must zfs create pool9/fs
+
+# Run xattr tests for non-encrypted fs
+xattr_test fs
+
+# Calculate the expected recursive checksum for source non-encrypted fs
+expected_cksum=$(recursive_cksum /pool9/fs)
+
+# Validate the received copy using the received recursive checksum
+actual_cksum=$(recursive_cksum /pool12/fs)
+if [[ "$expected_cksum" != "$actual_cksum" ]]; then
+ log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
+fi
+
+log_pass "Verify raw sending to pools with greater ashift succeeds"
--- /dev/null
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2019, Lawrence Livermore National Security, LLC.
+# Copyright (c) 2021, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify spill blocks are correctly preserved in raw sends.
+#
+# Strategy:
+# 1) Create a set of files each containing some file data in an
+# encrypted filesystem.
+# 2) Add enough xattrs to the file to require a spill block.
+# 3) Snapshot and raw send these files to a new dataset.
+# 4) Modify the files and spill blocks in a variety of ways.
+# 5) Send the changes using an raw incremental send stream.
+# 6) Verify that all the xattrs (and thus the spill block) were
+# preserved when receiving the incremental stream.
+#
+
+verify_runnable "both"
+
+log_assert "Verify spill blocks are correctly preserved in raw sends"
+
+function cleanup
+{
+ rm -f $BACKDIR/fs@*
+ destroy_dataset $POOL/fs "-rR"
+ destroy_dataset $POOL/newfs "-rR"
+}
+
+attrvalue="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+
+log_onexit cleanup
+
+log_must eval "echo 'password' | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt " \
+ "$POOL/fs"
+log_must zfs set xattr=sa $POOL/fs
+log_must zfs set dnodesize=legacy $POOL/fs
+log_must zfs set recordsize=128k $POOL/fs
+
+# Create 40 files each with a spill block containing xattrs. Each file
+# will be modified in a different way to validate the incremental receive.
+for i in {1..40}; do
+ file="/$POOL/fs/file$i"
+
+ log_must mkfile 16384 $file
+ for j in {1..20}; do
+ log_must set_xattr "testattr$j" "$attrvalue" $file
+ done
+done
+
+# Snapshot the pool and send it to the new dataset.
+log_must zfs snapshot $POOL/fs@snap1
+log_must eval "zfs send -w $POOL/fs@snap1 >$BACKDIR/fs@snap1"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap1"
+
+#
+# Modify file[1-6]'s contents but not the spill blocks.
+#
+# file1 - Increase record size; single block
+# file2 - Increase record size; multiple blocks
+# file3 - Truncate file to zero size; single block
+# file4 - Truncate file to smaller size; single block
+# file5 - Truncate file to much larger size; add holes
+# file6 - Truncate file to embedded size; embedded data
+#
+log_must mkfile 32768 /$POOL/fs/file1
+log_must mkfile 1048576 /$POOL/fs/file2
+log_must truncate -s 0 /$POOL/fs/file3
+log_must truncate -s 8192 /$POOL/fs/file4
+log_must truncate -s 1073741824 /$POOL/fs/file5
+log_must truncate -s 50 /$POOL/fs/file6
+
+#
+# Modify file[11-16]'s contents and their spill blocks.
+#
+# file11 - Increase record size; single block
+# file12 - Increase record size; multiple blocks
+# file13 - Truncate file to zero size; single block
+# file14 - Truncate file to smaller size; single block
+# file15 - Truncate file to much larger size; add holes
+# file16 - Truncate file to embedded size; embedded data
+#
+log_must mkfile 32768 /$POOL/fs/file11
+log_must mkfile 1048576 /$POOL/fs/file12
+log_must truncate -s 0 /$POOL/fs/file13
+log_must truncate -s 8192 /$POOL/fs/file14
+log_must truncate -s 1073741824 /$POOL/fs/file15
+log_must truncate -s 50 /$POOL/fs/file16
+
+for i in {11..20}; do
+ log_must rm_xattr testattr1 /$POOL/fs/file$i
+done
+
+#
+# Modify file[21-26]'s contents and remove their spill blocks.
+#
+# file21 - Increase record size; single block
+# file22 - Increase record size; multiple blocks
+# file23 - Truncate file to zero size; single block
+# file24 - Truncate file to smaller size; single block
+# file25 - Truncate file to much larger size; add holes
+# file26 - Truncate file to embedded size; embedded data
+#
+log_must mkfile 32768 /$POOL/fs/file21
+log_must mkfile 1048576 /$POOL/fs/file22
+log_must truncate -s 0 /$POOL/fs/file23
+log_must truncate -s 8192 /$POOL/fs/file24
+log_must truncate -s 1073741824 /$POOL/fs/file25
+log_must truncate -s 50 /$POOL/fs/file26
+
+for i in {21..30}; do
+ for j in {1..20}; do
+ log_must rm_xattr testattr$j /$POOL/fs/file$i
+ done
+done
+
+#
+# Modify file[31-40]'s spill blocks but not the file contents.
+#
+for i in {31..40}; do
+ file="/$POOL/fs/file$i"
+ log_must rm_xattr testattr$(((RANDOM % 20) + 1)) $file
+ log_must set_xattr testattr$(((RANDOM % 20) + 1)) "$attrvalue" $file
+done
+
+# Calculate the expected recursive checksum for the source.
+expected_cksum=$(recursive_cksum /$POOL/fs)
+
+# Snapshot the pool and send the incremental snapshot.
+log_must zfs snapshot $POOL/fs@snap2
+log_must eval "zfs send -w -i $POOL/fs@snap1 $POOL/fs@snap2 >$BACKDIR/fs@snap2"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap2"
+log_must eval "echo 'password' | zfs load-key $POOL/newfs"
+log_must zfs mount $POOL/newfs
+
+# Validate the received copy using the received recursive checksum.
+actual_cksum=$(recursive_cksum /$POOL/newfs)
+if [[ "$expected_cksum" != "$actual_cksum" ]]; then
+ log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
+fi
+
+log_pass "Verify spill blocks are correctly preserved in raw sends"
# to avoid timeout due to reduced performance.
nr_files=100
passes=2
-elif is_freebsd; then
- # Use fewer files and passes on FreeBSD to avoid timeout.
- nr_files=500
- passes=2
else
- nr_files=1000
+ nr_files=300
passes=3
fi
# to avoid timeout due to reduced performance.
nr_files=100
passes=2
-elif is_freebsd; then
- # Use fewer passes and files on FreeBSD to avoid timeout.
- nr_files=500
- passes=2
else
- nr_files=1000
+ nr_files=300
passes=3
fi
--- /dev/null
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/simd
+dist_pkgdata_SCRIPTS = simd_supported.ksh
--- /dev/null
+#!/bin/ksh -p
+#
+# 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 http://www.opensolaris.org/os/licensing.
+# 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) 2022 by Attila Fülöp <attila@fueloep.org>
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Make sure we have SIMD support, so it will not go away without notice
+#
+# STRATEGY:
+# 1. Test if we are running on a Linux x86 system with SSE support
+# 2. If so, check if the zfs_fletcher_4_impl module parameter contains
+# a sse implementation
+# 3. If not fail the test, otherwise pass it
+
+log_note "Testing if we support SIMD instructions (Linux x86 only)"
+
+if !is_linux; then
+ log_unsupported "Not a Linux System"
+fi
+
+case "$(uname -m)" in
+i386|i686|x86_64)
+ typeset -R modparam="/sys/module/zcommon/parameters/zfs_fletcher_4_impl"
+ if cat /proc/cpuinfo | awk '/^flags/ {print; exit;}' | grep -q sse; then
+ log_must grep -q sse "$modparam"
+ log_pass "SIMD instructions supported"
+ else
+ log_unsupported "No FPU present"
+ fi
+ ;;
+*)
+ log_unsupported "Not a x86 CPU"
+ ;;
+esac
log_must zfs snapshot $TESTPOOL/$TESTFILE@$TESTSNAP
log_must zfs snapshot $SNAPPOOL.1
+#
+# Linux: Issuing a `df` seems to properly force any negative dcache entries to
+# be invalidated preventing failures when accessing the mount point. Additional
+# investigation required.
+#
+# https://github.com/openzfs/zfs/issues/6143
+#
+log_must df >/dev/null
+
export __ZFS_POOL_RESTRICT="$TESTPOOL"
log_must zfs unmount -a
log_must zfs mount -a
log_must touch /$TESTPOOL/$TESTFILE/$TESTFILE.1
log_must zfs rollback $SNAPPOOL.1
-
-#
-# Workaround for issue #6143. Issuing a `df` seems to properly force any
-# negative dcache entries to be invalidated preventing subsequent failures
-# when accessing the mount point. Additional investigation required.
-#
-log_must df
+log_must df >/dev/null
log_pass "Rollbacks succeed when nested file systems are present."
suid_write_to_sgid.ksh \
suid_write_to_suid_sgid.ksh \
suid_write_to_none.ksh \
+ suid_write_zil_replay.ksh \
cleanup.ksh \
setup.ksh
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
-
-static void
-test_stat_mode(mode_t extra)
-{
- struct stat st;
- int i, fd;
- char fpath[1024];
- char *penv[] = {"TESTDIR", "TESTFILE0"};
- char buf[] = "test";
- mode_t res;
- mode_t mode = 0777 | extra;
-
- /*
- * Get the environment variable values.
- */
- for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
- if ((penv[i] = getenv(penv[i])) == NULL) {
- fprintf(stderr, "getenv(penv[%d])\n", i);
- exit(1);
- }
- }
-
- umask(0);
- if (stat(penv[0], &st) == -1 && mkdir(penv[0], mode) == -1) {
- perror("mkdir");
- exit(2);
- }
-
- snprintf(fpath, sizeof (fpath), "%s/%s", penv[0], penv[1]);
- unlink(fpath);
- if (stat(fpath, &st) == 0) {
- fprintf(stderr, "%s exists\n", fpath);
- exit(3);
- }
-
- fd = creat(fpath, mode);
- if (fd == -1) {
- perror("creat");
- exit(4);
- }
- close(fd);
-
- if (setuid(65534) == -1) {
- perror("setuid");
- exit(5);
- }
-
- fd = open(fpath, O_RDWR);
- if (fd == -1) {
- perror("open");
- exit(6);
- }
-
- if (write(fd, buf, sizeof (buf)) == -1) {
- perror("write");
- exit(7);
- }
- close(fd);
-
- if (stat(fpath, &st) == -1) {
- perror("stat");
- exit(8);
- }
- unlink(fpath);
-
- /* Verify SUID/SGID are dropped */
- res = st.st_mode & (0777 | S_ISUID | S_ISGID);
- if (res != (mode & 0777)) {
- fprintf(stderr, "stat(2) %o\n", res);
- exit(9);
- }
-}
+#include <stdbool.h>
int
main(int argc, char *argv[])
{
- const char *name;
+ const char *name, *phase;
mode_t extra;
+ struct stat st;
- if (argc < 2) {
+ if (argc < 3) {
fprintf(stderr, "Invalid argc\n");
exit(1);
}
exit(1);
}
- test_stat_mode(extra);
+ const char *testdir = getenv("TESTDIR");
+ if (!testdir) {
+ fprintf(stderr, "getenv(TESTDIR)\n");
+ exit(1);
+ }
+
+ umask(0);
+ if (stat(testdir, &st) == -1 && mkdir(testdir, 0777) == -1) {
+ perror("mkdir");
+ exit(2);
+ }
+
+ char fpath[1024];
+ snprintf(fpath, sizeof (fpath), "%s/%s", testdir, name);
+
+
+ phase = argv[2];
+ if (strcmp(phase, "PRECRASH") == 0) {
+
+ /* clean up last run */
+ unlink(fpath);
+ if (stat(fpath, &st) == 0) {
+ fprintf(stderr, "%s exists\n", fpath);
+ exit(3);
+ }
+
+ int fd;
+
+ fd = creat(fpath, 0777 | extra);
+ if (fd == -1) {
+ perror("creat");
+ exit(4);
+ }
+ close(fd);
+
+ if (setuid(65534) == -1) {
+ perror("setuid");
+ exit(5);
+ }
+
+ fd = open(fpath, O_RDWR);
+ if (fd == -1) {
+ perror("open");
+ exit(6);
+ }
+
+ const char buf[] = "test";
+ if (write(fd, buf, sizeof (buf)) == -1) {
+ perror("write");
+ exit(7);
+ }
+ close(fd);
+
+ } else if (strcmp(phase, "REPLAY") == 0) {
+ /* created in PRECRASH run */
+ } else {
+ fprintf(stderr, "Invalid phase %s\n", phase);
+ exit(1);
+ }
+
+ if (stat(fpath, &st) == -1) {
+ perror("stat");
+ exit(8);
+ }
+
+ /* Verify SUID/SGID are dropped */
+ mode_t res = st.st_mode & (0777 | S_ISUID | S_ISGID);
+ if (res != 0777) {
+ fprintf(stderr, "stat(2) %o\n", res);
+ exit(9);
+ }
return (0);
}
log_onexit cleanup
log_note "Verify write(2) to regular file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE" "PRECRASH"
log_pass "Verify write(2) to regular file by non-owner passed"
log_onexit cleanup
log_note "Verify write(2) to SGID file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID" "PRECRASH"
log_pass "Verify write(2) to SGID file by non-owner passed"
log_onexit cleanup
log_note "Verify write(2) to SUID file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID" "PRECRASH"
log_pass "Verify write(2) to SUID file by non-owner passed"
log_onexit cleanup
log_note "Verify write(2) to SUID/SGID file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID" "PRECRASH"
log_pass "Verify write(2) to SUID/SGID file by non-owner passed"
--- /dev/null
+#!/bin/ksh -p
+#
+# 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 http://www.opensolaris.org/os/licensing.
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+verify_runnable "global"
+
+function cleanup_fs
+{
+ cleanup
+}
+
+log_assert "Verify ZIL replay results in correct SUID/SGID bits for unprivileged write to SUID/SGID files"
+log_onexit cleanup_fs
+log_must setup
+
+#
+# 1. Create a file system (TESTFS)
+#
+log_must zpool destroy "$TESTPOOL"
+log_must zpool create $TESTPOOL $VDEV log mirror $LDEV
+log_must zfs set compression=on $TESTPOOL
+log_must zfs create -o mountpoint="$TESTDIR" $TESTPOOL/$TESTFS
+
+# Make all the writes from suid_write_to_file.c sync
+log_must zfs set sync=always "$TESTPOOL/$TESTFS"
+
+#
+# This dd command works around an issue where ZIL records aren't created
+# after freezing the pool unless a ZIL header already exists. Create a file
+# synchronously to force ZFS to write one out.
+#
+log_must dd if=/dev/zero of=$TESTDIR/sync \
+ conv=fdatasync,fsync bs=1 count=1
+
+#
+# 2. Freeze TESTFS
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 3. Unprivileged write to a setuid file
+#
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE" "PRECRASH"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID" "PRECRASH"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID" "PRECRASH"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID" "PRECRASH"
+
+#
+# 4. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is empty again and frozen, the intent log contains
+# a complete set of deltas to replay.
+#
+log_must zfs unmount $TESTPOOL/$TESTFS
+
+log_note "List transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 5. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must zpool import -f -d $VDIR $TESTPOOL
+
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE" "REPLAY"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID" "REPLAY"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID" "REPLAY"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID" "REPLAY"
+
+log_pass
userspace_001_pos.ksh \
userspace_002_pos.ksh \
userspace_003_pos.ksh \
- userspace_encrypted.ksh
+ userspace_encrypted.ksh \
+ userspace_send_encrypted.ksh
dist_pkgdata_DATA = \
userquota.cfg \
--- /dev/null
+#!/bin/ksh -p
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021, George Amanakis <gamanakis@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Sending raw encrypted datasets back to the source dataset succeeds.
+#
+#
+# STRATEGY:
+# 1. Create encrypted source dataset, set userquota and write a file
+# 2. Create base snapshot
+# 3. Write new file, snapshot, get userspace
+# 4. Raw send both snapshots
+# 5. Destroy latest snapshot at source and rollback
+# 6. Unmount, unload key from source
+# 7. Raw send latest snapshot back to source
+# 8. Mount both source and target datasets
+# 9. Verify encrypted datasets support 'zfs userspace' and 'zfs groupspace'
+# and the accounting is done correctly
+#
+
+function cleanup
+{
+ destroy_pool $POOLNAME
+ rm -f $FILEDEV
+}
+
+log_onexit cleanup
+
+FILEDEV="$TEST_BASE_DIR/userspace_encrypted"
+POOLNAME="testpool$$"
+ENC_SOURCE="$POOLNAME/source"
+ENC_TARGET="$POOLNAME/target"
+
+log_assert "Sending raw encrypted datasets back to the source dataset succeeds."
+
+# Setup pool and create source
+truncate -s 200m $FILEDEV
+log_must zpool create -o feature@encryption=enabled $POOLNAME \
+ $FILEDEV
+log_must eval "echo 'password' | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt " \
+ "$ENC_SOURCE"
+
+# Set user quota and write file
+log_must zfs set userquota@$QUSER1=50m $ENC_SOURCE
+mkmount_writable $ENC_SOURCE
+mntpnt=$(get_prop mountpoint $ENC_SOURCE)
+log_must user_run $QUSER1 mkfile 10m /$mntpnt/file1
+sync
+
+# Snapshot
+log_must zfs snap $ENC_SOURCE@base
+
+# Write new file, snapshot, get userspace
+log_must user_run $QUSER1 mkfile 20m /$mntpnt/file2
+log_must zfs snap $ENC_SOURCE@s1
+
+# Raw send both snapshots
+log_must eval "zfs send -w $ENC_SOURCE@base | zfs recv " \
+ "$ENC_TARGET"
+log_must eval "zfs send -w -i @base $ENC_SOURCE@s1 | zfs recv " \
+ "$ENC_TARGET"
+
+# Destroy latest snapshot at source and rollback
+log_must zfs destroy $ENC_SOURCE@s1
+log_must zfs rollback $ENC_SOURCE@base
+rollback_uspace=$(zfs userspace -Hp $ENC_SOURCE | \
+ awk "/$QUSER1/"' {printf "%d\n", $4 / 1024 / 1024}')
+
+# Unmount, unload key
+log_must zfs umount $ENC_SOURCE
+log_must zfs unload-key -a
+
+# Raw send latest snapshot back to source
+log_must eval "zfs send -w -i @base $ENC_TARGET@s1 | zfs recv " \
+ "$ENC_SOURCE"
+
+# Mount encrypted datasets and verify they support 'zfs userspace' and
+# 'zfs groupspace' and the accounting is done correctly
+log_must eval "echo 'password' | zfs load-key $ENC_SOURCE"
+log_must eval "echo 'password' | zfs load-key $ENC_TARGET"
+log_must zfs mount $ENC_SOURCE
+log_must zfs mount $ENC_TARGET
+sync
+
+sleep 5
+
+src_uspace=$(zfs userspace -Hp $ENC_SOURCE | \
+ awk "/$QUSER1/"' {printf "%d\n", $4 / 1024 / 1024}')
+tgt_uspace=$(zfs userspace -Hp $ENC_TARGET | \
+ awk "/$QUSER1/"' {printf "%d\n", $4 / 1024 / 1024}')
+log_must test "$src_uspace" -eq "$tgt_uspace"
+log_must test "$rollback_uspace" -ne "$src_uspace"
+
+src_uquota=$(zfs userspace -Hp $ENC_SOURCE | awk "/$QUSER1/"' {print $5}')
+tgt_uquota=$(zfs userspace -Hp $ENC_TARGET | awk "/$QUSER1/"' {print $5}')
+log_must test "$src_uquota" -eq "$tgt_uquota"
+
+# Cleanup
+cleanup
+
+log_pass "Sending raw encrypted datasets back to the source dataset succeeds."
#
function udev_wait
{
- sleep 1
- is_linux || return 0
udevadm trigger --action=change
udevadm settle
for i in {1..3}; do
#
function udev_cleanup
{
- is_linux || return 0
log_note "Pruning broken ZVOL symlinks ..."
udevadm settle
# because there are other commands (zfs snap, zfs inherit, zfs destroy)
# that can affect device nodes
for i in {1..3}; do
- udev_wait
+ is_linux && udev_wait
+ block_device_wait "$device"
is_disk_device "$device" && return 0
done
log_fail "$device does not exist as a block device"
# because there are other commands (zfs snap, zfs inherit, zfs destroy)
# that can affect device nodes
for i in {1..3}; do
- udev_wait
- [[ ! -e "$device" ]] && return 0
+ is_linux && udev_wait
+ block_device_wait
+ is_disk_device "$device" || return 0
done
log_fail "$device exists when not expected"
}
for ds in "$SENDFS" "$ZVOL" "$ZVOL-renamed"; do
destroy_dataset "$ds" '-rf'
done
- udev_wait
+ block_device_wait
}
log_assert "Verify 'zfs rename' works on a ZVOL already in use as block device"
log_must zfs create -V $VOLSIZE "$ZVOL"
# 2. Create a filesystem on the ZVOL device and mount it
-udev_wait
+block_device_wait "$ZDEV"
log_must eval "new_fs $ZDEV >/dev/null 2>&1"
log_must mkdir "$MNTPFS"
log_must mount "$ZDEV" "$MNTPFS"
datasetexists $ZVOL && destroy_dataset $ZVOL -r
log_must zfs inherit snapdev $TESTPOOL
block_device_wait
- udev_cleanup
+ is_linux && udev_cleanup
}
log_assert "Verify that ZFS volume property 'snapdev' works as expected."
# 7. Verify "volmode" behaves correctly at import time
# 8. Verify "volmode" behaves accordingly to zvol_inhibit_dev (Linux only)
#
-# NOTE: changing volmode may need to remove minors, which could be open, so call
-# udev_wait() before we "zfs set volmode=<value>".
verify_runnable "global"
function cleanup
{
- datasetexists $VOLFS && log_must_busy zfs destroy -r $VOLFS
- datasetexists $ZVOL && log_must_busy zfs destroy -r $ZVOL
- log_must zfs inherit volmode $TESTPOOL
- udev_wait
+ datasetexists $VOLFS && destroy_dataset $VOLFS -r
+ datasetexists $ZVOL && destroy_dataset $ZVOL -r
+ zfs inherit volmode $TESTPOOL
sysctl_inhibit_dev 0
sysctl_volmode 1
- udev_cleanup
+ is_linux && udev_cleanup
}
#
{
typeset dev=$1
- log_must dd if=/dev/zero of=$dev count=1
log_must dd if=$dev of=/dev/null count=1
+ log_must dd if=/dev/zero of=$dev count=1
+}
+
+#
+# Changing volmode may need to remove minors, which could be open, so call
+# udev_wait() before we "zfs set volmode=<value>". This ensures no udev
+# process has the zvol open (i.e. blkid) and the zvol_remove_minor_impl()
+# function won't skip removing the in use device.
+#
+function set_volmode # value ds
+{
+ typeset value="$1"
+ typeset ds="$2"
+
+ is_linux && udev_wait
+ log_must zfs set volmode="$value" "$ds"
}
log_assert "Verify that ZFS volume property 'volmode' works as intended"
VOLFS="$TESTPOOL/volfs"
ZVOL="$TESTPOOL/vol"
-ZDEV="${ZVOL_DEVDIR}/$ZVOL"
+ZDEV="$ZVOL_DEVDIR/$ZVOL"
SUBZVOL="$VOLFS/subvol"
-SUBZDEV="${ZVOL_DEVDIR}/$SUBZVOL"
+SUBZDEV="$ZVOL_DEVDIR/$SUBZVOL"
+# 0. Verify basic ZVOL functionality
log_must zfs create -o mountpoint=none $VOLFS
log_must zfs create -V $VOLSIZE -s $SUBZVOL
log_must zfs create -V $VOLSIZE -s $ZVOL
-udev_wait
blockdev_exists $ZDEV
blockdev_exists $SUBZDEV
test_io $ZDEV
done
# 2. Verify "volmode=none" hides ZVOL device nodes
-log_must zfs set volmode=none $ZVOL
+set_volmode none $ZVOL
blockdev_missing $ZDEV
log_must_busy zfs destroy $ZVOL
+blockdev_missing $ZDEV
# 3. Verify "volmode=full" exposes a fully functional device
log_must zfs create -V $VOLSIZE -s $ZVOL
-udev_wait
-log_must zfs set volmode=full $ZVOL
+blockdev_exists $ZDEV
+set_volmode full $ZVOL
blockdev_exists $ZDEV
test_io $ZDEV
log_must verify_partition $ZDEV
-udev_wait
# 3.1 Verify "volmode=geom" is an alias for "volmode=full"
-log_must zfs set volmode=geom $ZVOL
+set_volmode geom $ZVOL
blockdev_exists $ZDEV
if [[ "$(get_prop 'volmode' $ZVOL)" != "full" ]]; then
log_fail " Volmode value 'geom' is not an alias for 'full'"
fi
-udev_wait
log_must_busy zfs destroy $ZVOL
+blockdev_missing $ZDEV
# 4. Verify "volmode=dev" hides partition info on the device
log_must zfs create -V $VOLSIZE -s $ZVOL
-udev_wait
-log_must zfs set volmode=dev $ZVOL
+blockdev_exists $ZDEV
+set_volmode dev $ZVOL
blockdev_exists $ZDEV
test_io $ZDEV
log_mustnot verify_partition $ZDEV
-udev_wait
log_must_busy zfs destroy $ZVOL
+blockdev_missing $ZDEV
# 5. Verify "volmode=default" behaves accordingly to "volmode" module parameter
# 5.1 Verify sysctl "volmode=full"
sysctl_volmode 1
log_must zfs create -V $VOLSIZE -s $ZVOL
-udev_wait
-log_must zfs set volmode=default $ZVOL
+blockdev_exists $ZDEV
+set_volmode default $ZVOL
blockdev_exists $ZDEV
log_must verify_partition $ZDEV
-udev_wait
log_must_busy zfs destroy $ZVOL
+blockdev_missing $ZDEV
# 5.2 Verify sysctl "volmode=dev"
sysctl_volmode 2
log_must zfs create -V $VOLSIZE -s $ZVOL
-udev_wait
-log_must zfs set volmode=default $ZVOL
+blockdev_exists $ZDEV
+set_volmode default $ZVOL
blockdev_exists $ZDEV
log_mustnot verify_partition $ZDEV
-udev_wait
log_must_busy zfs destroy $ZVOL
+blockdev_missing $ZDEV
# 5.2 Verify sysctl "volmode=none"
sysctl_volmode 3
log_must zfs create -V $VOLSIZE -s $ZVOL
-udev_wait
-log_must zfs set volmode=default $ZVOL
+blockdev_missing $ZDEV
+set_volmode default $ZVOL
blockdev_missing $ZDEV
# 6. Verify "volmode" property is inherited correctly
log_must zfs inherit volmode $ZVOL
+blockdev_missing $ZDEV
# 6.1 Check volmode=full case
-log_must zfs set volmode=full $TESTPOOL
+set_volmode full $TESTPOOL
verify_inherited 'volmode' 'full' $ZVOL $TESTPOOL
blockdev_exists $ZDEV
# 6.2 Check volmode=none case
-log_must zfs set volmode=none $TESTPOOL
+set_volmode none $TESTPOOL
verify_inherited 'volmode' 'none' $ZVOL $TESTPOOL
blockdev_missing $ZDEV
# 6.3 Check volmode=dev case
-log_must zfs set volmode=dev $TESTPOOL
+set_volmode dev $TESTPOOL
verify_inherited 'volmode' 'dev' $ZVOL $TESTPOOL
blockdev_exists $ZDEV
# 6.4 Check volmode=default case
sysctl_volmode 1
-log_must zfs set volmode=default $TESTPOOL
+set_volmode default $TESTPOOL
verify_inherited 'volmode' 'default' $ZVOL $TESTPOOL
blockdev_exists $ZDEV
# 6.5 Check inheritance on multiple levels
log_must zfs inherit volmode $SUBZVOL
-udev_wait
-log_must zfs set volmode=none $VOLFS
-udev_wait
-log_must zfs set volmode=full $TESTPOOL
+set_volmode none $VOLFS
+set_volmode full $TESTPOOL
verify_inherited 'volmode' 'none' $SUBZVOL $VOLFS
blockdev_missing $SUBZDEV
blockdev_exists $ZDEV
blockdev_missing $SUBZDEV
log_must_busy zfs destroy $ZVOL
log_must_busy zfs destroy $SUBZVOL
+blockdev_missing $ZDEV
+blockdev_missing $SUBZDEV
# 8. Verify "volmode" behaves accordingly to zvol_inhibit_dev (Linux only)
if is_linux; then
sysctl_volmode 1
log_must zfs create -V $VOLSIZE -s $ZVOL
blockdev_missing $ZDEV
- log_must zfs set volmode=full $ZVOL
+ set_volmode full $ZVOL
blockdev_missing $ZDEV
log_must_busy zfs destroy $ZVOL
+ blockdev_missing $ZDEV
# 7.1 Verify device nodes not are not created with "volmode=dev"
sysctl_volmode 2
log_must zfs create -V $VOLSIZE -s $ZVOL
blockdev_missing $ZDEV
- log_must zfs set volmode=dev $ZVOL
+ set_volmode dev $ZVOL
blockdev_missing $ZDEV
log_must_busy zfs destroy $ZVOL
+ blockdev_missing $ZDEV
# 7.1 Verify device nodes not are not created with "volmode=none"
sysctl_volmode 3
log_must zfs create -V $VOLSIZE -s $ZVOL
blockdev_missing $ZDEV
- log_must zfs set volmode=none $ZVOL
+ set_volmode none $ZVOL
blockdev_missing $ZDEV
fi
function cleanup
{
- datasetexists $ZVOL && log_must_busy zfs destroy $ZVOL
- udev_wait
+ datasetexists $ZVOL && destroy_dataset $ZVOL
+ block_device_wait
}
log_assert "Verify ZIL functionality on ZVOLs"
CFLAGS.spl_vm.c= -Wno-cast-qual
CFLAGS.spl_zlib.c= -Wno-cast-qual
CFLAGS.abd.c= -Wno-cast-qual
+CFLAGS.arc.c= -Wno-unused-variable
CFLAGS.zfs_log.c= -Wno-cast-qual
CFLAGS.zfs_vnops_os.c= -Wno-pointer-arith
CFLAGS.u8_textprep.c= -Wno-cast-qual
/* posix_acl has refcount_t */
/* #undef HAVE_ACL_REFCOUNT */
+/* add_disk() returns int */
+/* #undef HAVE_ADD_DISK_RET */
+
/* Define if host toolchain supports AES */
#define HAVE_AES 1
/* DECLARE_EVENT_CLASS() is available */
/* #undef HAVE_DECLARE_EVENT_CLASS */
+/* dequeue_signal() takes 4 arguments */
+/* #undef HAVE_DEQUEUE_SIGNAL_4ARG */
+
/* lookup_bdev() wants dev_t arg */
/* #undef HAVE_DEVT_LOOKUP_BDEV */
/* sops->evict_inode() exists */
/* #undef HAVE_EVICT_INODE */
+/* FALLOC_FL_ZERO_RANGE is defined */
+/* #undef HAVE_FALLOC_FL_ZERO_RANGE */
+
+/* fault_in_iov_iter_readable() is available */
+/* #undef HAVE_FAULT_IN_IOV_ITER_READABLE */
+
/* fops->aio_fsync() exists */
/* #undef HAVE_FILE_AIO_FSYNC */
/* kernel has asm/fpu/xcr.h */
/* #undef HAVE_KERNEL_FPU_XCR_HEADER */
+/* kernel fpu and XSAVE internal */
+/* #undef HAVE_KERNEL_FPU_XSAVE_INTERNAL */
+
/* uncached_acl_sentinel() exists */
/* #undef HAVE_KERNEL_GET_ACL_HANDLE_CACHE */
/* xattr_handler->set() takes user_namespace */
/* #undef HAVE_XATTR_SET_USERNS */
+/* Define if host toolchain supports XSAVE */
+#define HAVE_XSAVE 1
+
+/* Define if host toolchain supports XSAVEOPT */
+#define HAVE_XSAVEOPT 1
+
+/* Define if host toolchain supports XSAVES */
+#define HAVE_XSAVES 1
+
/* Define if you have [z] */
#define HAVE_ZLIB 1
/* kernel exports FPU functions */
/* #undef KERNEL_EXPORTS_X86_FPU */
+/* TBD: fetch(3) support */
+#if 0
+/* whether the chosen libfetch is to be loaded at run-time */
+#define LIBFETCH_DYNAMIC 1
+
+/* libfetch is fetch(3) */
+#define LIBFETCH_IS_FETCH 1
+
+/* libfetch is libcurl */
+#define LIBFETCH_IS_LIBCURL 0
+
+/* soname of chosen libfetch */
+#define LIBFETCH_SONAME "libfetch.so.6"
+#endif
+
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* struct shrink_control has nid */
/* #undef SHRINK_CONTROL_HAS_NID */
+/* using complete_and_exit() instead */
+/* #undef SPL_KTHREAD_COMPLETE_AND_EXIT */
+
/* Defined for legacy compatibility. */
#define SPL_META_ALIAS ZFS_META_ALIAS
/* Defined for legacy compatibility. */
#define SPL_META_VERSION ZFS_META_VERSION
+/* pde_data() is PDE_DATA() */
+/* #undef SPL_PDE_DATA */
+
/* True if ZFS is to be compiled for a FreeBSD system */
#define SYSTEM_FREEBSD 1
/* #undef ZFS_IS_GPL_COMPATIBLE */
/* Define the project alias string. */
-#define ZFS_META_ALIAS "zfs-2.1.2-FreeBSD_gaf88d47f1"
+#define ZFS_META_ALIAS "zfs-2.1.3-FreeBSD_gef83e07db"
/* Define the project author. */
#define ZFS_META_AUTHOR "OpenZFS"
/* #undef ZFS_META_DATA */
/* Define the maximum compatible kernel version. */
-#define ZFS_META_KVER_MAX "5.15"
+#define ZFS_META_KVER_MAX "5.16"
/* Define the minimum compatible kernel version. */
#define ZFS_META_KVER_MIN "3.10"
#define ZFS_META_NAME "zfs"
/* Define the project release. */
-#define ZFS_META_RELEASE "FreeBSD_gaf88d47f1"
+#define ZFS_META_RELEASE "FreeBSD_gef83e07db"
/* Define the project version. */
-#define ZFS_META_VERSION "2.1.2"
+#define ZFS_META_VERSION "2.1.3"
/* count is located in percpu_ref.data */
/* #undef ZFS_PERCPU_REF_COUNT_IN_DATA */
* $FreeBSD$
*/
-#define ZFS_META_GITREV "zfs-2.1.2-0-gaf88d47f1"
+#define ZFS_META_GITREV "zfs-2.1.3-0-gef83e07db"