diff --git a/cddl/lib/libzfs/Makefile b/cddl/lib/libzfs/Makefile --- a/cddl/lib/libzfs/Makefile +++ b/cddl/lib/libzfs/Makefile @@ -67,7 +67,6 @@ zfs_fletcher_superscalar4.c \ zfs_namecheck.c \ zfs_prop.c \ - zfs_uio.c \ zpool_prop.c \ zprop_common.c diff --git a/cddl/lib/libzpool/Makefile b/cddl/lib/libzpool/Makefile --- a/cddl/lib/libzpool/Makefile +++ b/cddl/lib/libzpool/Makefile @@ -46,7 +46,6 @@ zfs_fletcher_superscalar4.c \ zfs_namecheck.c \ zfs_prop.c \ - zfs_uio.c \ zfs_zstd.c \ zpool_prop.c \ zprop_common.c \ diff --git a/sys/contrib/openzfs/.github/PULL_REQUEST_TEMPLATE.md b/sys/contrib/openzfs/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,42 @@ + + + + + + +### Motivation and Context + + + +### Description + + +### How Has This Been Tested? + + + + + + +### Types of changes + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Performance enhancement (non-breaking change which improves efficiency) +- [ ] Code cleanup (non-breaking change which makes code smaller or more readable) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) +- [ ] Library ABI change (libzfs, libzfs\_core, libnvpair, libuutil and libzfsbootenv) +- [ ] Documentation (a change to man pages or other documentation) + +### Checklist: + + +- [ ] My code follows the OpenZFS [code style requirements](https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md#coding-conventions). +- [ ] I have updated the documentation accordingly. +- [ ] I have read the [**contributing** document](https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md). +- [ ] I have added [tests](https://github.com/openzfs/zfs/tree/master/tests) to cover my changes. +- [ ] I have run the ZFS Test Suite with this change applied. +- [ ] All commit messages are properly formatted and contain [`Signed-off-by`](https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md#signed-off-by). diff --git a/sys/contrib/openzfs/.github/workflows/zfs-tests-functional.yml b/sys/contrib/openzfs/.github/workflows/zfs-tests-functional.yml new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/.github/workflows/zfs-tests-functional.yml @@ -0,0 +1,64 @@ +name: zfs-tests-functional + +on: + push: + pull_request: + +jobs: + tests-functional-ubuntu: + strategy: + fail-fast: false + matrix: + os: [18.04, 20.04] + runs-on: ubuntu-${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \ + git alien fakeroot wget curl bc fio acl \ + sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \ + nfs-kernel-server samba rng-tools xz-utils \ + zlib1g-dev uuid-dev libblkid-dev libselinux-dev \ + 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 + - name: Autogen.sh + run: | + sh autogen.sh + - name: Configure + run: | + ./configure --enable-debug --enable-debuginfo + - name: Make + run: | + make --no-print-directory -s pkg-utils pkg-kmod + - name: Install + run: | + sudo dpkg -i *.deb + # Update order of directories to search for modules, otherwise + # Ubuntu will load kernel-shipped ones. + sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf + sudo depmod + sudo modprobe zfs + - name: Tests + run: | + /usr/share/zfs/zfs-tests.sh -v -s 3G + - name: Prepare artifacts + if: failure() + run: | + RESULTS_PATH=$(readlink -f /var/tmp/test_results/current) + sudo dmesg > $RESULTS_PATH/dmesg + sudo cp /var/log/syslog $RESULTS_PATH/ + sudo chmod +r $RESULTS_PATH/* + # Replace ':' in dir names, actions/upload-artifact doesn't support it + for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done + - uses: actions/upload-artifact@v2 + if: failure() + with: + name: Test logs Ubuntu-${{ matrix.os }} + path: /var/tmp/test_results/20*/ + if-no-files-found: ignore diff --git a/sys/contrib/openzfs/.github/workflows/zfs-tests-sanity.yml b/sys/contrib/openzfs/.github/workflows/zfs-tests-sanity.yml new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/.github/workflows/zfs-tests-sanity.yml @@ -0,0 +1,60 @@ +name: zfs-tests-sanity + +on: + push: + pull_request: + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \ + git alien fakeroot wget curl bc fio acl \ + sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \ + nfs-kernel-server samba rng-tools xz-utils \ + zlib1g-dev uuid-dev libblkid-dev libselinux-dev \ + 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 + - name: Autogen.sh + run: | + sh autogen.sh + - name: Configure + run: | + ./configure --enable-debug --enable-debuginfo + - name: Make + run: | + make --no-print-directory -s pkg-utils pkg-kmod + - name: Install + run: | + sudo dpkg -i *.deb + # Update order of directories to search for modules, otherwise + # Ubuntu will load kernel-shipped ones. + sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf + sudo depmod + sudo modprobe zfs + - name: Tests + run: | + /usr/share/zfs/zfs-tests.sh -v -s 3G -r sanity + - name: Prepare artifacts + if: failure() + run: | + RESULTS_PATH=$(readlink -f /var/tmp/test_results/current) + sudo dmesg > $RESULTS_PATH/dmesg + sudo cp /var/log/syslog $RESULTS_PATH/ + sudo chmod +r $RESULTS_PATH/* + # Replace ':' in dir names, actions/upload-artifact doesn't support it + for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done + - uses: actions/upload-artifact@v2 + if: failure() + with: + name: Test logs + path: /var/tmp/test_results/20*/ + if-no-files-found: ignore diff --git a/sys/contrib/openzfs/META b/sys/contrib/openzfs/META --- a/sys/contrib/openzfs/META +++ b/sys/contrib/openzfs/META @@ -6,5 +6,5 @@ Release-Tags: relext License: CDDL Author: OpenZFS -Linux-Maximum: 5.10 +Linux-Maximum: 5.11 Linux-Minimum: 3.10 diff --git a/sys/contrib/openzfs/Makefile.am b/sys/contrib/openzfs/Makefile.am --- a/sys/contrib/openzfs/Makefile.am +++ b/sys/contrib/openzfs/Makefile.am @@ -25,7 +25,6 @@ AUTOMAKE_OPTIONS = foreign EXTRA_DIST = autogen.sh copy-builtin -EXTRA_DIST += cppcheck-suppressions.txt EXTRA_DIST += config/config.awk config/rpm.am config/deb.am config/tgz.am EXTRA_DIST += META AUTHORS COPYRIGHT LICENSE NEWS NOTICE README.md EXTRA_DIST += CODE_OF_CONDUCT.md @@ -204,13 +203,13 @@ PHONY += lint lint: cppcheck paxcheck +CPPCHECKDIRS = cmd lib module PHONY += cppcheck -cppcheck: - @if type cppcheck > /dev/null 2>&1; then \ - cppcheck --quiet --force --error-exitcode=2 --inline-suppr \ - --suppressions-list=${top_srcdir}/cppcheck-suppressions.txt \ - -UHAVE_SSE2 -UHAVE_AVX512F -UHAVE_UIO_ZEROCOPY \ - ${top_srcdir}; \ +cppcheck: $(CPPCHECKDIRS) + @if test -n "$(CPPCHECK)"; then \ + set -e ; for dir in $(CPPCHECKDIRS) ; do \ + $(MAKE) -C $$dir cppcheck ; \ + done \ else \ echo "skipping cppcheck because cppcheck is not installed"; \ fi diff --git a/sys/contrib/openzfs/cmd/Makefile.am b/sys/contrib/openzfs/cmd/Makefile.am --- a/sys/contrib/openzfs/cmd/Makefile.am +++ b/sys/contrib/openzfs/cmd/Makefile.am @@ -2,10 +2,20 @@ SUBDIRS += fsck_zfs vdev_id raidz_test zfs_ids_to_path SUBDIRS += zpool_influxdb +CPPCHECKDIRS = zfs zpool zdb zhack zinject zstream ztest +CPPCHECKDIRS += raidz_test zfs_ids_to_path zpool_influxdb + if USING_PYTHON SUBDIRS += arcstat arc_summary dbufstat endif if BUILD_LINUX SUBDIRS += mount_zfs zed zgenhostid zvol_id zvol_wait +CPPCHECKDIRS += mount_zfs zed zgenhostid zvol_id endif + +PHONY = cppcheck +cppcheck: $(CPPCHECKDIRS) + set -e ; for dir in $(CPPCHECKDIRS) ; do \ + $(MAKE) -C $$dir cppcheck ; \ + done diff --git a/sys/contrib/openzfs/cmd/mount_zfs/Makefile.am b/sys/contrib/openzfs/cmd/mount_zfs/Makefile.am --- a/sys/contrib/openzfs/cmd/mount_zfs/Makefile.am +++ b/sys/contrib/openzfs/cmd/mount_zfs/Makefile.am @@ -18,3 +18,5 @@ $(abs_top_builddir)/lib/libnvpair/libnvpair.la mount_zfs_LDADD += $(LTLIBINTL) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/mount_zfs/mount_zfs.c b/sys/contrib/openzfs/cmd/mount_zfs/mount_zfs.c --- a/sys/contrib/openzfs/cmd/mount_zfs/mount_zfs.c +++ b/sys/contrib/openzfs/cmd/mount_zfs/mount_zfs.c @@ -50,6 +50,21 @@ static void parse_dataset(const char *target, char **dataset) { + /* + * Prior to util-linux 2.36.2, if a file or directory in the + * current working directory was named 'dataset' then mount(8) + * would prepend the current working directory to the dataset. + * Check for it and strip the prepended path when it is added. + */ + char cwd[PATH_MAX]; + if (getcwd(cwd, PATH_MAX) == NULL) { + perror("getcwd"); + return; + } + int len = strlen(cwd); + if (strncmp(cwd, target, len) == 0) + target += len; + /* Assume pool/dataset is more likely */ strlcpy(*dataset, target, PATH_MAX); diff --git a/sys/contrib/openzfs/cmd/raidz_test/Makefile.am b/sys/contrib/openzfs/cmd/raidz_test/Makefile.am --- a/sys/contrib/openzfs/cmd/raidz_test/Makefile.am +++ b/sys/contrib/openzfs/cmd/raidz_test/Makefile.am @@ -18,3 +18,5 @@ $(abs_top_builddir)/lib/libzfs_core/libzfs_core.la raidz_test_LDADD += -lm + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/raidz_test/raidz_test.c b/sys/contrib/openzfs/cmd/raidz_test/raidz_test.c --- a/sys/contrib/openzfs/cmd/raidz_test/raidz_test.c +++ b/sys/contrib/openzfs/cmd/raidz_test/raidz_test.c @@ -492,8 +492,9 @@ (dc - r) * (rows - 1) + row; } rr->rr_col[c].rc_size = 1ULL << ashift; - rr->rr_col[c].rc_abd = - abd_get_offset(abd, off << ashift); + rr->rr_col[c].rc_abd = abd_get_offset_struct( + &rr->rr_col[c].rc_abdstruct, + abd, off << ashift, 1 << ashift); } asize += rr->rr_col[c].rc_size; diff --git a/sys/contrib/openzfs/cmd/vdev_id/vdev_id b/sys/contrib/openzfs/cmd/vdev_id/vdev_id --- a/sys/contrib/openzfs/cmd/vdev_id/vdev_id +++ b/sys/contrib/openzfs/cmd/vdev_id/vdev_id @@ -79,6 +79,34 @@ # channel 86:00.0 1 A # channel 86:00.0 0 B +# # +# # Example vdev_id.conf - multipath / multijbod-daisychaining +# # +# +# multipath yes +# multijbod yes +# +# # PCI_ID HBA PORT CHANNEL NAME +# channel 85:00.0 1 A +# channel 85:00.0 0 B +# channel 86:00.0 1 A +# channel 86:00.0 0 B + +# # +# # Example vdev_id.conf - multipath / mixed +# # +# +# multipath yes +# slot mix +# +# # PCI_ID HBA PORT CHANNEL NAME +# channel 85:00.0 3 A +# channel 85:00.0 2 B +# channel 86:00.0 3 A +# channel 86:00.0 2 B +# channel af:00.0 0 C +# channel af:00.0 1 C + # # # # Example vdev_id.conf - alias # # @@ -92,9 +120,10 @@ CONFIG=/etc/zfs/vdev_id.conf PHYS_PER_PORT= DEV= -MULTIPATH= TOPOLOGY= BAY= +ENCL_ID="" +UNIQ_ENCL_ID="" usage() { cat << EOF @@ -107,6 +136,7 @@ -e Create enclose device symlinks only (/dev/by-enclosure) -g Storage network topology [default="$TOPOLOGY"] -m Run in multipath mode + -j Run in multijbod mode -p number of phy's per switch port [default=$PHYS_PER_PORT] -h show this summary EOF @@ -117,12 +147,12 @@ LINUX_SLOT=$1 CHANNEL=$2 - MAPPED_SLOT=`awk "\\$1 == \"slot\" && \\$2 == ${LINUX_SLOT} && \ - \\$4 ~ /^${CHANNEL}$|^$/ { print \\$3; exit }" $CONFIG` + MAPPED_SLOT=$(awk '$1 == "slot" && $2 == "${LINUX_SLOT}" && \ + $4 ~ /^${CHANNEL}$|^$/ { print $3; exit}' $CONFIG) if [ -z "$MAPPED_SLOT" ] ; then MAPPED_SLOT=$LINUX_SLOT fi - printf "%d" ${MAPPED_SLOT} + printf "%d" "${MAPPED_SLOT}" } map_channel() { @@ -132,40 +162,120 @@ case $TOPOLOGY in "sas_switch") - MAPPED_CHAN=`awk "\\$1 == \"channel\" && \\$2 == ${PORT} \ - { print \\$3; exit }" $CONFIG` + MAPPED_CHAN=$(awk -v port="$PORT" \ + '$1 == "channel" && $2 == ${PORT} \ + { print $3; exit }' $CONFIG) ;; "sas_direct"|"scsi") - MAPPED_CHAN=`awk "\\$1 == \"channel\" && \ - \\$2 == \"${PCI_ID}\" && \\$3 == ${PORT} \ - { print \\$4; exit }" $CONFIG` + MAPPED_CHAN=$(awk -v pciID="$PCI_ID" -v port="$PORT" \ + '$1 == "channel" && $2 == pciID && $3 == port \ + {print $4}' $CONFIG) ;; esac - printf "%s" ${MAPPED_CHAN} + printf "%s" "${MAPPED_CHAN}" +} + +get_encl_id() { + set -- $(echo $1) + count=$# + + i=1 + while [ $i -le $count ] ; do + d=$(eval echo '$'{$i}) + id=$(cat "/sys/class/enclosure/${d}/id") + ENCL_ID="${ENCL_ID} $id" + i=$((i + 1)) + done +} + +get_uniq_encl_id() { + for uuid in ${ENCL_ID}; do + found=0 + + for count in ${UNIQ_ENCL_ID}; do + if [ $count = $uuid ]; then + found=1 + break + fi + done + + if [ $found -eq 0 ]; then + UNIQ_ENCL_ID="${UNIQ_ENCL_ID} $uuid" + fi + done +} + +# map_jbod explainer: The bsg driver knows the difference between a SAS +# expander and fanout expander. Use hostX instance along with top-level +# (whole enclosure) expander instances in /sys/class/enclosure and +# matching a field in an array of expanders, using the index of the +# matched array field as the enclosure instance, thereby making jbod IDs +# dynamic. Avoids reliance on high overhead userspace commands like +# multipath and lsscsi and instead uses existing sysfs data. $HOSTCHAN +# variable derived from devpath gymnastics in sas_handler() function. +map_jbod() { + DEVEXP=$(ls -l "/sys/block/$DEV/device/" | grep enclos | awk -F/ '{print $(NF-1) }') + DEV=$1 + + # Use "set --" to create index values (Arrays) + set -- $(ls -l /sys/class/enclosure | grep -v "^total" | awk '{print $9}') + # Get count of total elements + JBOD_COUNT=$# + JBOD_ITEM=$* + + # Build JBODs (enclosure) id from sys/class/enclosure//id + get_encl_id "$JBOD_ITEM" + # Different expander instances for each paths. + # Filter out and keep only unique id. + get_uniq_encl_id + + # Identify final 'mapped jbod' + j=0 + for count in ${UNIQ_ENCL_ID}; do + i=1 + j=$((j + 1)) + while [ $i -le $JBOD_COUNT ] ; do + d=$(eval echo '$'{$i}) + id=$(cat "/sys/class/enclosure/${d}/id") + if [ "$d" = "$DEVEXP" ] && [ $id = $count ] ; then + MAPPED_JBOD=$j + break + fi + i=$((i + 1)) + done + done + + printf "%d" "${MAPPED_JBOD}" } sas_handler() { if [ -z "$PHYS_PER_PORT" ] ; then - PHYS_PER_PORT=`awk "\\$1 == \"phys_per_port\" \ - {print \\$2; exit}" $CONFIG` + PHYS_PER_PORT=$(awk '$1 == "phys_per_port" \ + {print $2; exit}' $CONFIG) fi PHYS_PER_PORT=${PHYS_PER_PORT:-4} - if ! echo $PHYS_PER_PORT | grep -q -E '^[0-9]+$' ; then + + if ! echo "$PHYS_PER_PORT" | grep -q -E '^[0-9]+$' ; then echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric" exit 1 fi if [ -z "$MULTIPATH_MODE" ] ; then - MULTIPATH_MODE=`awk "\\$1 == \"multipath\" \ - {print \\$2; exit}" $CONFIG` + MULTIPATH_MODE=$(awk '$1 == "multipath" \ + {print $2; exit}' $CONFIG) + fi + + if [ -z "$MULTIJBOD_MODE" ] ; then + MULTIJBOD_MODE=$(awk '$1 == "multijbod" \ + {print $2; exit}' $CONFIG) fi # Use first running component device if we're handling a dm-mpath device if [ "$MULTIPATH_MODE" = "yes" ] ; then # If udev didn't tell us the UUID via DM_NAME, check /dev/mapper if [ -z "$DM_NAME" ] ; then - DM_NAME=`ls -l --full-time /dev/mapper | - awk "/\/$DEV$/{print \\$9}"` + DM_NAME=$(ls -l --full-time /dev/mapper | + grep "$DEV"$ | awk '{print $9}') fi # For raw disks udev exports DEVTYPE=partition when @@ -175,28 +285,41 @@ # we have to append the -part suffix directly in the # helper. if [ "$DEVTYPE" != "partition" ] ; then - PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'` + PART=$(echo "$DM_NAME" | awk -Fp '/p/{print "-part"$2}') fi # Strip off partition information. - DM_NAME=`echo $DM_NAME | sed 's/p[0-9][0-9]*$//'` + DM_NAME=$(echo "$DM_NAME" | sed 's/p[0-9][0-9]*$//') if [ -z "$DM_NAME" ] ; then return fi - # Get the raw scsi device name from multipath -ll. Strip off - # leading pipe symbols to make field numbering consistent. - DEV=`multipath -ll $DM_NAME | - awk '/running/{gsub("^[|]"," "); print $3 ; exit}'` + # Utilize DM device name to gather subordinate block devices + # using sysfs to avoid userspace utilities + DMDEV=$(ls -l --full-time /dev/mapper | grep $DM_NAME | + awk '{gsub("../", " "); print $NF}') + + # Use sysfs pointers in /sys/block/dm-X/slaves because using + # userspace tools creates lots of overhead and should be avoided + # whenever possible. Use awk to isolate lowest instance of + # sd device member in dm device group regardless of string + # length. + DEV=$(ls "/sys/block/$DMDEV/slaves" | awk ' + { len=sprintf ("%20s",length($0)); gsub(/ /,0,str); a[NR]=len "_" $0; } + END { + asort(a) + print substr(a[1],22) + }') + if [ -z "$DEV" ] ; then return fi fi - if echo $DEV | grep -q ^/devices/ ; then + if echo "$DEV" | grep -q ^/devices/ ; then sys_path=$DEV else - sys_path=`udevadm info -q path -p /sys/block/$DEV 2>/dev/null` + sys_path=$(udevadm info -q path -p "/sys/block/$DEV" 2>/dev/null) fi # Use positional parameters as an ad-hoc array @@ -206,84 +329,104 @@ # Get path up to /sys/.../hostX i=1 - while [ $i -le $num_dirs ] ; do - d=$(eval echo \${$i}) + + while [ $i -le "$num_dirs" ] ; do + d=$(eval echo '$'{$i}) scsi_host_dir="$scsi_host_dir/$d" - echo $d | grep -q -E '^host[0-9]+$' && break - i=$(($i + 1)) + echo "$d" | grep -q -E '^host[0-9]+$' && break + i=$((i + 1)) done - if [ $i = $num_dirs ] ; then + # Lets grab the SAS host channel number and save it for JBOD sorting later + HOSTCHAN=$(echo "$d" | awk -F/ '{ gsub("host","",$NF); print $NF}') + + if [ $i = "$num_dirs" ] ; then return fi - PCI_ID=$(eval echo \${$(($i -1))} | awk -F: '{print $2":"$3}') + PCI_ID=$(eval echo '$'{$((i -1))} | awk -F: '{print $2":"$3}') # In sas_switch mode, the directory four levels beneath # /sys/.../hostX contains symlinks to phy devices that reveal # the switch port number. In sas_direct mode, the phy links one # directory down reveal the HBA port. port_dir=$scsi_host_dir + case $TOPOLOGY in - "sas_switch") j=$(($i + 4)) ;; - "sas_direct") j=$(($i + 1)) ;; + "sas_switch") j=$((i + 4)) ;; + "sas_direct") j=$((i + 1)) ;; esac - i=$(($i + 1)) + i=$((i + 1)) + while [ $i -le $j ] ; do - port_dir="$port_dir/$(eval echo \${$i})" - i=$(($i + 1)) + port_dir="$port_dir/$(eval echo '$'{$i})" + i=$((i + 1)) done - PHY=`ls -d $port_dir/phy* 2>/dev/null | head -1 | awk -F: '{print $NF}'` + PHY=$(ls -d "$port_dir"/phy* 2>/dev/null | head -1 | awk -F: '{print $NF}') if [ -z "$PHY" ] ; then PHY=0 fi - PORT=$(( $PHY / $PHYS_PER_PORT )) + PORT=$((PHY / PHYS_PER_PORT)) # Look in /sys/.../sas_device/end_device-X for the bay_identifier # attribute. end_device_dir=$port_dir - while [ $i -lt $num_dirs ] ; do - d=$(eval echo \${$i}) + + while [ $i -lt "$num_dirs" ] ; do + d=$(eval echo '$'{$i}) end_device_dir="$end_device_dir/$d" - if echo $d | grep -q '^end_device' ; then + if echo "$d" | grep -q '^end_device' ; then end_device_dir="$end_device_dir/sas_device/$d" break fi - i=$(($i + 1)) + i=$((i + 1)) done + # Add 'mix' slot type for environments where dm-multipath devices + # include end-devices connected via SAS expanders or direct connection + # to SAS HBA. A mixed connectivity environment such as pool devices + # contained in a SAS JBOD and spare drives or log devices directly + # connected in a server backplane without expanders in the I/O path. SLOT= + case $BAY in "bay") - SLOT=`cat $end_device_dir/bay_identifier 2>/dev/null` + SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null) + ;; + "mix") + if [ $(cat "$end_device_dir/bay_identifier" 2>/dev/null) ] ; then + SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null) + else + SLOT=$(cat "$end_device_dir/phy_identifier" 2>/dev/null) + fi ;; "phy") - SLOT=`cat $end_device_dir/phy_identifier 2>/dev/null` + SLOT=$(cat "$end_device_dir/phy_identifier" 2>/dev/null) ;; "port") - d=$(eval echo \${$i}) - SLOT=`echo $d | sed -e 's/^.*://'` + d=$(eval echo '$'{$i}) + SLOT=$(echo "$d" | sed -e 's/^.*://') ;; "id") - i=$(($i + 1)) - d=$(eval echo \${$i}) - SLOT=`echo $d | sed -e 's/^.*://'` + i=$((i + 1)) + d=$(eval echo '$'{$i}) + SLOT=$(echo "$d" | sed -e 's/^.*://') ;; "lun") - i=$(($i + 2)) - d=$(eval echo \${$i}) - SLOT=`echo $d | sed -e 's/^.*://'` + i=$((i + 2)) + d=$(eval echo '$'{$i}) + SLOT=$(echo "$d" | sed -e 's/^.*://') ;; "ses") # look for this SAS path in all SCSI Enclosure Services # (SES) enclosures - sas_address=`cat $end_device_dir/sas_address 2>/dev/null` - enclosures=`lsscsi -g | \ - sed -n -e '/enclosu/s/^.* \([^ ][^ ]*\) *$/\1/p'` + sas_address=$(cat "$end_device_dir/sas_address" 2>/dev/null) + enclosures=$(lsscsi -g | \ + sed -n -e '/enclosu/s/^.* \([^ ][^ ]*\) *$/\1/p') for enclosure in $enclosures; do - set -- $(sg_ses -p aes $enclosure | \ + set -- $(sg_ses -p aes "$enclosure" | \ awk "/device slot number:/{slot=\$12} \ /SAS address: $sas_address/\ {print slot}") @@ -298,42 +441,55 @@ return fi - CHAN=`map_channel $PCI_ID $PORT` - SLOT=`map_slot $SLOT $CHAN` - if [ -z "$CHAN" ] ; then - return + if [ "$MULTIJBOD_MODE" = "yes" ] ; then + CHAN=$(map_channel "$PCI_ID" "$PORT") + SLOT=$(map_slot "$SLOT" "$CHAN") + JBOD=$(map_jbod "$DEV") + + if [ -z "$CHAN" ] ; then + return + fi + echo "${CHAN}"-"${JBOD}"-"${SLOT}${PART}" + else + CHAN=$(map_channel "$PCI_ID" "$PORT") + SLOT=$(map_slot "$SLOT" "$CHAN") + + if [ -z "$CHAN" ] ; then + return + fi + echo "${CHAN}${SLOT}${PART}" fi - echo ${CHAN}${SLOT}${PART} } scsi_handler() { if [ -z "$FIRST_BAY_NUMBER" ] ; then - FIRST_BAY_NUMBER=`awk "\\$1 == \"first_bay_number\" \ - {print \\$2; exit}" $CONFIG` + FIRST_BAY_NUMBER=$(awk '$1 == "first_bay_number" \ + {print $2; exit}' $CONFIG) fi FIRST_BAY_NUMBER=${FIRST_BAY_NUMBER:-0} if [ -z "$PHYS_PER_PORT" ] ; then - PHYS_PER_PORT=`awk "\\$1 == \"phys_per_port\" \ - {print \\$2; exit}" $CONFIG` + PHYS_PER_PORT=$(awk '$1 == "phys_per_port" \ + {print $2; exit}' $CONFIG) fi PHYS_PER_PORT=${PHYS_PER_PORT:-4} - if ! echo $PHYS_PER_PORT | grep -q -E '^[0-9]+$' ; then + + if ! echo "$PHYS_PER_PORT" | grep -q -E '^[0-9]+$' ; then echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric" exit 1 fi if [ -z "$MULTIPATH_MODE" ] ; then - MULTIPATH_MODE=`awk "\\$1 == \"multipath\" \ - {print \\$2; exit}" $CONFIG` + MULTIPATH_MODE=$(awk '$1 == "multipath" \ + {print $2; exit}' $CONFIG) fi # Use first running component device if we're handling a dm-mpath device if [ "$MULTIPATH_MODE" = "yes" ] ; then # If udev didn't tell us the UUID via DM_NAME, check /dev/mapper if [ -z "$DM_NAME" ] ; then - DM_NAME=`ls -l --full-time /dev/mapper | - awk "/\/$DEV$/{print \\$9}"` + DM_NAME=$(ls -l --full-time /dev/mapper | + grep "$DEV"$ | awk '{print $9}') fi # For raw disks udev exports DEVTYPE=partition when @@ -343,28 +499,28 @@ # we have to append the -part suffix directly in the # helper. if [ "$DEVTYPE" != "partition" ] ; then - PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'` + PART=$(echo "$DM_NAME" | awk -Fp '/p/{print "-part"$2}') fi # Strip off partition information. - DM_NAME=`echo $DM_NAME | sed 's/p[0-9][0-9]*$//'` + DM_NAME=$(echo "$DM_NAME" | sed 's/p[0-9][0-9]*$//') if [ -z "$DM_NAME" ] ; then return fi # Get the raw scsi device name from multipath -ll. Strip off # leading pipe symbols to make field numbering consistent. - DEV=`multipath -ll $DM_NAME | - awk '/running/{gsub("^[|]"," "); print $3 ; exit}'` + DEV=$(multipath -ll "$DM_NAME" | + awk '/running/{gsub("^[|]"," "); print $3 ; exit}') if [ -z "$DEV" ] ; then return fi fi - if echo $DEV | grep -q ^/devices/ ; then + if echo "$DEV" | grep -q ^/devices/ ; then sys_path=$DEV else - sys_path=`udevadm info -q path -p /sys/block/$DEV 2>/dev/null` + sys_path=$(udevadm info -q path -p "/sys/block/$DEV" 2>/dev/null) fi # expect sys_path like this, for example: @@ -377,44 +533,47 @@ # Get path up to /sys/.../hostX i=1 - while [ $i -le $num_dirs ] ; do - d=$(eval echo \${$i}) + + while [ $i -le "$num_dirs" ] ; do + d=$(eval echo '$'{$i}) scsi_host_dir="$scsi_host_dir/$d" - echo $d | grep -q -E '^host[0-9]+$' && break - i=$(($i + 1)) + + echo "$d" | grep -q -E '^host[0-9]+$' && break + i=$((i + 1)) done - if [ $i = $num_dirs ] ; then + if [ $i = "$num_dirs" ] ; then return fi - PCI_ID=$(eval echo \${$(($i -1))} | awk -F: '{print $2":"$3}') + PCI_ID=$(eval echo '$'{$((i -1))} | awk -F: '{print $2":"$3}') # In scsi mode, the directory two levels beneath # /sys/.../hostX reveals the port and slot. port_dir=$scsi_host_dir - j=$(($i + 2)) + j=$((i + 2)) - i=$(($i + 1)) + i=$((i + 1)) while [ $i -le $j ] ; do - port_dir="$port_dir/$(eval echo \${$i})" - i=$(($i + 1)) + port_dir="$port_dir/$(eval echo '$'{$i})" + i=$((i + 1)) done - set -- $(echo $port_dir | sed -e 's/^.*:\([^:]*\):\([^:]*\)$/\1 \2/') + set -- $(echo "$port_dir" | sed -e 's/^.*:\([^:]*\):\([^:]*\)$/\1 \2/') PORT=$1 - SLOT=$(($2 + $FIRST_BAY_NUMBER)) + SLOT=$(($2 + FIRST_BAY_NUMBER)) if [ -z "$SLOT" ] ; then return fi - CHAN=`map_channel $PCI_ID $PORT` - SLOT=`map_slot $SLOT $CHAN` + CHAN=$(map_channel "$PCI_ID" "$PORT") + SLOT=$(map_slot "$SLOT" "$CHAN") + if [ -z "$CHAN" ] ; then return fi - echo ${CHAN}${SLOT}${PART} + echo "${CHAN}${SLOT}${PART}" } # Figure out the name for the enclosure symlink @@ -425,7 +584,7 @@ # Get the enclosure ID ("0:0:0:0") ENC=$(basename $(readlink -m "/sys/$DEVPATH/../..")) - if [ ! -d /sys/class/enclosure/$ENC ] ; then + if [ ! -d "/sys/class/enclosure/$ENC" ] ; then # Not an enclosure, bail out return fi @@ -433,14 +592,14 @@ # Get the long sysfs device path to our enclosure. Looks like: # /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0/ ... /enclosure/0:0:0:0 - ENC_DEVICE=$(readlink /sys/class/enclosure/$ENC) + ENC_DEVICE=$(readlink "/sys/class/enclosure/$ENC") # Grab the full path to the hosts port dir: # /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0 - PORT_DIR=$(echo $ENC_DEVICE | grep -Eo '.+host[0-9]+/port-[0-9]+:[0-9]+') + PORT_DIR=$(echo "$ENC_DEVICE" | grep -Eo '.+host[0-9]+/port-[0-9]+:[0-9]+') # Get the port number - PORT_ID=$(echo $PORT_DIR | grep -Eo "[0-9]+$") + PORT_ID=$(echo "$PORT_DIR" | grep -Eo "[0-9]+$") # The PCI directory is two directories up from the port directory # /sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0 @@ -450,8 +609,8 @@ PCI_ID=$(echo "$PCI_ID_LONG" | sed -r 's/^[0-9]+://g') # Name our device according to vdev_id.conf (like "L0" or "U1"). - NAME=$(awk "/channel/{if (\$1 == \"channel\" && \$2 == \"$PCI_ID\" && \ - \$3 == \"$PORT_ID\") {print \$4int(count[\$4])}; count[\$4]++}" $CONFIG) + NAME=$(awk '/channel/{if ($1 == "channel" && $2 == "$PCI_ID" && \ + $3 == "$PORT_ID") {print ${4}int(count[$4])}; count[$4]++}' $CONFIG) echo "${NAME}" } @@ -487,9 +646,9 @@ # ambiguity seems unavoidable, so devices using this facility # must not use such names. DM_PART= - if echo $DM_NAME | grep -q -E 'p[0-9][0-9]*$' ; then + if echo "$DM_NAME" | grep -q -E 'p[0-9][0-9]*$' ; then if [ "$DEVTYPE" != "partition" ] ; then - DM_PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'` + DM_PART=$(echo "$DM_NAME" | awk -Fp '/p/{print "-part"$2}') fi fi @@ -497,21 +656,25 @@ for link in $DEVLINKS ; do # Remove partition information to match key of top-level device. if [ -n "$DM_PART" ] ; then - link=`echo $link | sed 's/p[0-9][0-9]*$//'` + 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 - alias=`awk "\\$1 == \"alias\" && \\$3 == \"${l}\" \ - { print \\$2; exit }" $CONFIG` - if [ -n "$alias" ] ; then - echo ${alias}${DM_PART} - return + for l in $link $(basename "$link") ; do + if [ ! -z "$l" ]; then + alias=$(awk -v var="$l" '($1 == "alias") && \ + ($3 == var) \ + { print $2; exit }' $CONFIG) + if [ -n "$alias" ] ; then + echo "${alias}${DM_PART}" + return + fi fi done done } -while getopts 'c:d:eg:mp:h' OPTION; do +# main +while getopts 'c:d:eg:jmp:h' OPTION; do case ${OPTION} in c) CONFIG=${OPTARG} @@ -524,7 +687,9 @@ # create the enclosure device symlinks only. We also need # "enclosure_symlinks yes" set in vdev_id.config to actually create the # symlink. - ENCLOSURE_MODE=$(awk '{if ($1 == "enclosure_symlinks") print $2}' $CONFIG) + ENCLOSURE_MODE=$(awk '{if ($1 == "enclosure_symlinks") \ + print $2}' "$CONFIG") + if [ "$ENCLOSURE_MODE" != "yes" ] ; then exit 0 fi @@ -535,6 +700,9 @@ p) PHYS_PER_PORT=${OPTARG} ;; + j) + MULTIJBOD_MODE=yes + ;; m) MULTIPATH_MODE=yes ;; @@ -544,7 +712,8 @@ esac done -if [ ! -r $CONFIG ] ; then +if [ ! -r "$CONFIG" ] ; then + echo "Error: Config file \"$CONFIG\" not found" exit 0 fi @@ -554,11 +723,11 @@ fi if [ -z "$TOPOLOGY" ] ; then - TOPOLOGY=`awk "\\$1 == \"topology\" {print \\$2; exit}" $CONFIG` + TOPOLOGY=$(awk '($1 == "topology") {print $2; exit}' "$CONFIG") fi if [ -z "$BAY" ] ; then - BAY=`awk "\\$1 == \"slot\" {print \\$2; exit}" $CONFIG` + BAY=$(awk '($1 == "slot") {print $2; exit}' "$CONFIG") fi TOPOLOGY=${TOPOLOGY:-sas_direct} @@ -571,7 +740,7 @@ fi # Just create the symlinks to the enclosure devices and then exit. - ENCLOSURE_PREFIX=$(awk '/enclosure_symlinks_prefix/{print $2}' $CONFIG) + ENCLOSURE_PREFIX=$(awk '/enclosure_symlinks_prefix/{print $2}' "$CONFIG") if [ -z "$ENCLOSURE_PREFIX" ] ; then ENCLOSURE_PREFIX="enc" fi @@ -581,16 +750,16 @@ fi # First check if an alias was defined for this device. -ID_VDEV=`alias_handler` +ID_VDEV=$(alias_handler) if [ -z "$ID_VDEV" ] ; then BAY=${BAY:-bay} case $TOPOLOGY in sas_direct|sas_switch) - ID_VDEV=`sas_handler` + ID_VDEV=$(sas_handler) ;; scsi) - ID_VDEV=`scsi_handler` + ID_VDEV=$(scsi_handler) ;; *) echo "Error: unknown topology $TOPOLOGY" diff --git a/sys/contrib/openzfs/cmd/zdb/Makefile.am b/sys/contrib/openzfs/cmd/zdb/Makefile.am --- a/sys/contrib/openzfs/cmd/zdb/Makefile.am +++ b/sys/contrib/openzfs/cmd/zdb/Makefile.am @@ -14,3 +14,5 @@ $(abs_top_builddir)/lib/libzpool/libzpool.la \ $(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \ $(abs_top_builddir)/lib/libnvpair/libnvpair.la + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zdb/zdb.c b/sys/contrib/openzfs/cmd/zdb/zdb.c --- a/sys/contrib/openzfs/cmd/zdb/zdb.c +++ b/sys/contrib/openzfs/cmd/zdb/zdb.c @@ -31,6 +31,7 @@ * * [1] Portions of this software were developed by Allan Jude * under sponsorship from the FreeBSD Foundation. + * Copyright (c) 2021 Allan Jude */ #include @@ -755,13 +756,14 @@ "\t%s -m [-AFLPX] [-e [-V] [-p ...]] [-t ] " "[-U ]\n\t\t [ [ ...]]\n" "\t%s -O \n" + "\t%s -r \n" "\t%s -R [-A] [-e [-V] [-p ...]] [-U ]\n" "\t\t ::[:]\n" "\t%s -E [-A] word0:word1:...:word15\n" "\t%s -S [-AP] [-e [-V] [-p ...]] [-U ] " "\n\n", cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, - cmdname, cmdname, cmdname); + cmdname, cmdname, cmdname, cmdname); (void) fprintf(stderr, " Dataset name must include at least one " "separator character '/' or '@'\n"); @@ -800,6 +802,7 @@ (void) fprintf(stderr, " -m metaslabs\n"); (void) fprintf(stderr, " -M metaslab groups\n"); (void) fprintf(stderr, " -O perform object lookups by path\n"); + (void) fprintf(stderr, " -r copy an object by path to file\n"); (void) fprintf(stderr, " -R read and display block from a " "device\n"); (void) fprintf(stderr, " -s report stats on zdb's I/O\n"); @@ -4490,7 +4493,7 @@ * for the last one. */ static int -dump_path_impl(objset_t *os, uint64_t obj, char *name) +dump_path_impl(objset_t *os, uint64_t obj, char *name, uint64_t *retobj) { int err; boolean_t header = B_TRUE; @@ -4540,10 +4543,15 @@ switch (doi.doi_type) { case DMU_OT_DIRECTORY_CONTENTS: if (s != NULL && *(s + 1) != '\0') - return (dump_path_impl(os, child_obj, s + 1)); + return (dump_path_impl(os, child_obj, s + 1, retobj)); /*FALLTHROUGH*/ case DMU_OT_PLAIN_FILE_CONTENTS: - dump_object(os, child_obj, dump_opt['v'], &header, NULL, 0); + if (retobj != NULL) { + *retobj = child_obj; + } else { + dump_object(os, child_obj, dump_opt['v'], &header, + NULL, 0); + } return (0); default: (void) fprintf(stderr, "object %llu has non-file/directory " @@ -4558,7 +4566,7 @@ * Dump the blocks for the object specified by path inside the dataset. */ static int -dump_path(char *ds, char *path) +dump_path(char *ds, char *path, uint64_t *retobj) { int err; objset_t *os; @@ -4578,12 +4586,89 @@ (void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds); - err = dump_path_impl(os, root_obj, path); + err = dump_path_impl(os, root_obj, path, retobj); close_objset(os, FTAG); return (err); } +static int +zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile) +{ + int err = 0; + uint64_t size, readsize, oursize, offset; + ssize_t writesize; + sa_handle_t *hdl; + + (void) printf("Copying object %" PRIu64 " to file %s\n", srcobj, + destfile); + + VERIFY3P(os, ==, sa_os); + if ((err = sa_handle_get(os, srcobj, NULL, SA_HDL_PRIVATE, &hdl))) { + (void) printf("Failed to get handle for SA znode\n"); + return (err); + } + if ((err = sa_lookup(hdl, sa_attr_table[ZPL_SIZE], &size, 8))) { + (void) sa_handle_destroy(hdl); + return (err); + } + (void) sa_handle_destroy(hdl); + + (void) printf("Object %" PRIu64 " is %" PRIu64 " bytes\n", srcobj, + size); + if (size == 0) { + return (EINVAL); + } + + int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); + /* + * We cap the size at 1 mebibyte here to prevent + * allocation failures and nigh-infinite printing if the + * object is extremely large. + */ + oursize = MIN(size, 1 << 20); + offset = 0; + char *buf = kmem_alloc(oursize, KM_NOSLEEP); + if (buf == NULL) { + return (ENOMEM); + } + + while (offset < size) { + readsize = MIN(size - offset, 1 << 20); + err = dmu_read(os, srcobj, offset, readsize, buf, 0); + if (err != 0) { + (void) printf("got error %u from dmu_read\n", err); + kmem_free(buf, oursize); + return (err); + } + if (dump_opt['v'] > 3) { + (void) printf("Read offset=%" PRIu64 " size=%" PRIu64 + " error=%d\n", offset, readsize, err); + } + + writesize = write(fd, buf, readsize); + if (writesize < 0) { + err = errno; + break; + } else if (writesize != readsize) { + /* Incomplete write */ + (void) fprintf(stderr, "Short write, only wrote %llu of" + " %" PRIu64 " bytes, exiting...\n", + (u_longlong_t)writesize, readsize); + break; + } + + offset += readsize; + } + + (void) close(fd); + + if (buf != NULL) + kmem_free(buf, oursize); + + return (err); +} + static int dump_label(const char *dev) { @@ -5844,6 +5929,7 @@ * metaslabs. We want to set them up for * zio_claim(). */ + vdev_metaslab_group_create(vd); VERIFY0(vdev_metaslab_init(vd, 0)); vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping; @@ -5882,6 +5968,7 @@ */ spa->spa_normal_class->mc_ops = &zdb_metaslab_ops; spa->spa_log_class->mc_ops = &zdb_metaslab_ops; + spa->spa_embedded_log_class->mc_ops = &zdb_metaslab_ops; zcb->zcb_vd_obsolete_counts = umem_zalloc(rvd->vdev_children * sizeof (uint32_t *), @@ -6015,7 +6102,6 @@ vdev_t *rvd = spa->spa_root_vdev; for (unsigned c = 0; c < rvd->vdev_children; c++) { vdev_t *vd = rvd->vdev_child[c]; - metaslab_group_t *mg __maybe_unused = vd->vdev_mg; if (zcb->zcb_vd_obsolete_counts[c] != NULL) { leaks |= zdb_check_for_obsolete_leaks(vd, zcb); @@ -6023,7 +6109,9 @@ for (uint64_t m = 0; m < vd->vdev_ms_count; m++) { metaslab_t *msp = vd->vdev_ms[m]; - ASSERT3P(mg, ==, msp->ms_group); + ASSERT3P(msp->ms_group, ==, (msp->ms_group->mg_class == + spa_embedded_log_class(spa)) ? + vd->vdev_log_mg : vd->vdev_mg); /* * ms_allocatable has been overloaded @@ -6230,6 +6318,8 @@ zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa)); zcb.zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa)); zcb.zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa)); + zcb.zcb_totalasize += + metaslab_class_get_alloc(spa_embedded_log_class(spa)); zcb.zcb_start = zcb.zcb_lastprint = gethrtime(); err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb); @@ -6277,6 +6367,7 @@ total_alloc = norm_alloc + metaslab_class_get_alloc(spa_log_class(spa)) + + metaslab_class_get_alloc(spa_embedded_log_class(spa)) + metaslab_class_get_alloc(spa_special_class(spa)) + metaslab_class_get_alloc(spa_dedup_class(spa)) + get_unflushed_alloc_space(spa); @@ -6344,6 +6435,17 @@ 100.0 * alloc / space); } + if (spa_embedded_log_class(spa)->mc_allocator[0].mca_rotor != NULL) { + uint64_t alloc = metaslab_class_get_alloc( + spa_embedded_log_class(spa)); + uint64_t space = metaslab_class_get_space( + spa_embedded_log_class(spa)); + + (void) printf("\t%-16s %14llu used: %5.2f%%\n", + "Embedded log class", (u_longlong_t)alloc, + 100.0 * alloc / space); + } + for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) { if (zcb.zcb_embedded_blocks[i] == 0) continue; @@ -8150,6 +8252,7 @@ nvlist_t *policy = NULL; uint64_t max_txg = UINT64_MAX; int64_t objset_id = -1; + uint64_t object; int flags = ZFS_IMPORT_MISSING_LOG; int rewind = ZPOOL_NEVER_REWIND; char *spa_config_path_env, *objset_str; @@ -8178,7 +8281,7 @@ zfs_btree_verify_intensity = 3; while ((c = getopt(argc, argv, - "AbcCdDeEFGhiI:klLmMo:Op:PqRsSt:uU:vVx:XYyZ")) != -1) { + "AbcCdDeEFGhiI:klLmMo:Op:PqrRsSt:uU:vVx:XYyZ")) != -1) { switch (c) { case 'b': case 'c': @@ -8193,6 +8296,7 @@ case 'm': case 'M': case 'O': + case 'r': case 'R': case 's': case 'S': @@ -8282,7 +8386,7 @@ (void) fprintf(stderr, "-p option requires use of -e\n"); usage(); } - if (dump_opt['d']) { + if (dump_opt['d'] || dump_opt['r']) { /* [/ is accepted */ if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL && objset_str++ != NULL) { @@ -8341,7 +8445,7 @@ verbose = MAX(verbose, 1); for (c = 0; c < 256; c++) { - if (dump_all && strchr("AeEFklLOPRSXy", c) == NULL) + if (dump_all && strchr("AeEFklLOPrRSXy", c) == NULL) dump_opt[c] = 1; if (dump_opt[c]) dump_opt[c] += verbose; @@ -8377,7 +8481,13 @@ if (argc != 2) usage(); dump_opt['v'] = verbose + 3; - return (dump_path(argv[0], argv[1])); + return (dump_path(argv[0], argv[1], NULL)); + } + if (dump_opt['r']) { + if (argc != 3) + usage(); + dump_opt['v'] = verbose; + error = dump_path(argv[0], argv[1], &object); } if (dump_opt['X'] || dump_opt['F']) @@ -8555,7 +8665,9 @@ argv++; argc--; - if (!dump_opt['R']) { + if (dump_opt['r']) { + error = zdb_copy_object(os, object, argv[1]); + } else if (!dump_opt['R']) { flagbits['d'] = ZOR_FLAG_DIRECTORY; flagbits['f'] = ZOR_FLAG_PLAIN_FILE; flagbits['m'] = ZOR_FLAG_SPACE_MAP; diff --git a/sys/contrib/openzfs/cmd/zed/Makefile.am b/sys/contrib/openzfs/cmd/zed/Makefile.am --- a/sys/contrib/openzfs/cmd/zed/Makefile.am +++ b/sys/contrib/openzfs/cmd/zed/Makefile.am @@ -47,3 +47,5 @@ zed_LDFLAGS = -pthread EXTRA_DIST = agents/README.md + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c b/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c --- a/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c +++ b/sys/contrib/openzfs/cmd/zed/agents/zfs_agents.c @@ -13,6 +13,7 @@ /* * Copyright (c) 2016, Intel Corporation. * Copyright (c) 2018, loli10K + * Copyright (c) 2021 Hewlett Packard Enterprise Development LP */ #include @@ -211,12 +212,18 @@ * For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or * ZFS_EV_POOL_GUID may be missing so find them. */ - (void) nvlist_lookup_string(nvl, DEV_IDENTIFIER, - &search.gs_devid); - (void) zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search); - pool_guid = search.gs_pool_guid; - vdev_guid = search.gs_vdev_guid; - devtype = search.gs_vdev_type; + if (pool_guid == 0 || vdev_guid == 0) { + if ((nvlist_lookup_string(nvl, DEV_IDENTIFIER, + &search.gs_devid) == 0) && + (zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search) + == 1)) { + if (pool_guid == 0) + pool_guid = search.gs_pool_guid; + if (vdev_guid == 0) + vdev_guid = search.gs_vdev_guid; + devtype = search.gs_vdev_type; + } + } /* * We want to avoid reporting "remove" events coming from diff --git a/sys/contrib/openzfs/cmd/zed/agents/zfs_retire.c b/sys/contrib/openzfs/cmd/zed/agents/zfs_retire.c --- a/sys/contrib/openzfs/cmd/zed/agents/zfs_retire.c +++ b/sys/contrib/openzfs/cmd/zed/agents/zfs_retire.c @@ -334,7 +334,7 @@ */ if (strcmp(class, "resource.fs.zfs.removed") == 0 || (strcmp(class, "resource.fs.zfs.statechange") == 0 && - state == VDEV_STATE_REMOVED)) { + (state == VDEV_STATE_REMOVED || state == VDEV_STATE_FAULTED))) { char *devtype; char *devname; diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh b/sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh old mode 100755 new mode 100644 diff --git a/sys/contrib/openzfs/cmd/zfs/Makefile.am b/sys/contrib/openzfs/cmd/zfs/Makefile.am --- a/sys/contrib/openzfs/cmd/zfs/Makefile.am +++ b/sys/contrib/openzfs/cmd/zfs/Makefile.am @@ -21,3 +21,5 @@ if BUILD_FREEBSD zfs_LDADD += -lgeom -ljail endif + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zfs_ids_to_path/Makefile.am b/sys/contrib/openzfs/cmd/zfs_ids_to_path/Makefile.am --- a/sys/contrib/openzfs/cmd/zfs_ids_to_path/Makefile.am +++ b/sys/contrib/openzfs/cmd/zfs_ids_to_path/Makefile.am @@ -7,3 +7,5 @@ zfs_ids_to_path_LDADD = \ $(abs_top_builddir)/lib/libzfs/libzfs.la + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zgenhostid/Makefile.am b/sys/contrib/openzfs/cmd/zgenhostid/Makefile.am --- a/sys/contrib/openzfs/cmd/zgenhostid/Makefile.am +++ b/sys/contrib/openzfs/cmd/zgenhostid/Makefile.am @@ -1,5 +1,7 @@ include $(top_srcdir)/config/Rules.am -bin_PROGRAMS = zgenhostid +sbin_PROGRAMS = zgenhostid zgenhostid_SOURCES = zgenhostid.c + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zhack/Makefile.am b/sys/contrib/openzfs/cmd/zhack/Makefile.am --- a/sys/contrib/openzfs/cmd/zhack/Makefile.am +++ b/sys/contrib/openzfs/cmd/zhack/Makefile.am @@ -12,3 +12,5 @@ $(abs_top_builddir)/lib/libzpool/libzpool.la \ $(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \ $(abs_top_builddir)/lib/libnvpair/libnvpair.la + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zinject/Makefile.am b/sys/contrib/openzfs/cmd/zinject/Makefile.am --- a/sys/contrib/openzfs/cmd/zinject/Makefile.am +++ b/sys/contrib/openzfs/cmd/zinject/Makefile.am @@ -11,3 +11,5 @@ $(abs_top_builddir)/lib/libzfs/libzfs.la \ $(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \ $(abs_top_builddir)/lib/libnvpair/libnvpair.la + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zpool/Makefile.am b/sys/contrib/openzfs/cmd/zpool/Makefile.am --- a/sys/contrib/openzfs/cmd/zpool/Makefile.am +++ b/sys/contrib/openzfs/cmd/zpool/Makefile.am @@ -34,6 +34,8 @@ endif zpool_LDADD += -lm $(LIBBLKID_LIBS) $(LIBUUID_LIBS) +include $(top_srcdir)/config/CppCheck.am + zpoolconfdir = $(sysconfdir)/zfs/zpool.d zpoolexecdir = $(zfsexecdir)/zpool.d diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_main.c b/sys/contrib/openzfs/cmd/zpool/zpool_main.c --- a/sys/contrib/openzfs/cmd/zpool/zpool_main.c +++ b/sys/contrib/openzfs/cmd/zpool/zpool_main.c @@ -1653,7 +1653,8 @@ if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0) (void) nvlist_remove_all(props, propname); - } else if (enable_all_pool_feat) { + } else if (enable_all_pool_feat && + feat->fi_zfs_mod_supported) { ret = add_prop_list(propname, ZFS_FEATURE_ENABLED, &props, B_TRUE); if (ret != 0) @@ -2009,7 +2010,7 @@ * Mark empty values with dashes to make output * awk-able. */ - if (is_blank_str(val)) + if (val == NULL || is_blank_str(val)) val = "-"; printf("%*s", vcdl->uniq_cols_width[j], val); @@ -9063,7 +9064,7 @@ &records, &numrecords) == 0); for (i = 0; i < numrecords; i++) { nvlist_t *rec = records[i]; - char tbuf[30] = ""; + char tbuf[64] = ""; if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { time_t tsec; @@ -9075,6 +9076,14 @@ (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); } + if (nvlist_exists(rec, ZPOOL_HIST_ELAPSED_NS)) { + uint64_t elapsed_ns = fnvlist_lookup_int64(records[i], + ZPOOL_HIST_ELAPSED_NS); + (void) snprintf(tbuf + strlen(tbuf), + sizeof (tbuf) - strlen(tbuf), + " (%lldms)", (long long)elapsed_ns / 1000 / 1000); + } + if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { (void) printf("%s %s", tbuf, fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); diff --git a/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am b/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am --- a/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am +++ b/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am @@ -9,3 +9,5 @@ $(top_builddir)/lib/libspl/libspl.la \ $(top_builddir)/lib/libnvpair/libnvpair.la \ $(top_builddir)/lib/libzfs/libzfs.la + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/zstream/Makefile.am b/sys/contrib/openzfs/cmd/zstream/Makefile.am --- a/sys/contrib/openzfs/cmd/zstream/Makefile.am +++ b/sys/contrib/openzfs/cmd/zstream/Makefile.am @@ -13,3 +13,5 @@ $(abs_top_builddir)/lib/libzfs/libzfs.la \ $(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \ $(abs_top_builddir)/lib/libnvpair/libnvpair.la + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/ztest/Makefile.am b/sys/contrib/openzfs/cmd/ztest/Makefile.am --- a/sys/contrib/openzfs/cmd/ztest/Makefile.am +++ b/sys/contrib/openzfs/cmd/ztest/Makefile.am @@ -21,3 +21,5 @@ ztest_LDADD += -lm ztest_LDFLAGS = -pthread + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/cmd/ztest/ztest.c b/sys/contrib/openzfs/cmd/ztest/ztest.c --- a/sys/contrib/openzfs/cmd/ztest/ztest.c +++ b/sys/contrib/openzfs/cmd/ztest/ztest.c @@ -998,13 +998,13 @@ cmd = umem_alloc(MAXPATHLEN, UMEM_NOFAIL); realaltdir = umem_alloc(MAXPATHLEN, UMEM_NOFAIL); - VERIFY(NULL != realpath(getexecname(), cmd)); + VERIFY3P(NULL, !=, realpath(getexecname(), cmd)); if (0 != access(altdir, F_OK)) { ztest_dump_core = B_FALSE; fatal(B_TRUE, "invalid alternate ztest path: %s", altdir); } - VERIFY(NULL != realpath(altdir, realaltdir)); + VERIFY3P(NULL, !=, realpath(altdir, realaltdir)); /* * 'cmd' should be of the form "/usr/bin//ztest". @@ -1122,11 +1122,11 @@ (void) close(fd); } - VERIFY0(nvlist_alloc(&file, NV_UNIQUE_NAME, 0)); - VERIFY0(nvlist_add_string(file, ZPOOL_CONFIG_TYPE, - draid_spare ? VDEV_TYPE_DRAID_SPARE : VDEV_TYPE_FILE)); - VERIFY0(nvlist_add_string(file, ZPOOL_CONFIG_PATH, path)); - VERIFY0(nvlist_add_uint64(file, ZPOOL_CONFIG_ASHIFT, ashift)); + file = fnvlist_alloc(); + fnvlist_add_string(file, ZPOOL_CONFIG_TYPE, + draid_spare ? VDEV_TYPE_DRAID_SPARE : VDEV_TYPE_FILE); + fnvlist_add_string(file, ZPOOL_CONFIG_PATH, path); + fnvlist_add_uint64(file, ZPOOL_CONFIG_ASHIFT, ashift); umem_free(pathbuf, MAXPATHLEN); return (file); @@ -1146,13 +1146,12 @@ for (c = 0; c < r; c++) child[c] = make_vdev_file(path, aux, pool, size, ashift); - VERIFY0(nvlist_alloc(&raid, NV_UNIQUE_NAME, 0)); - VERIFY0(nvlist_add_string(raid, ZPOOL_CONFIG_TYPE, - ztest_opts.zo_raid_type)); - VERIFY0(nvlist_add_uint64(raid, ZPOOL_CONFIG_NPARITY, - ztest_opts.zo_raid_parity)); - VERIFY0(nvlist_add_nvlist_array(raid, ZPOOL_CONFIG_CHILDREN, - child, r)); + raid = fnvlist_alloc(); + fnvlist_add_string(raid, ZPOOL_CONFIG_TYPE, + ztest_opts.zo_raid_type); + fnvlist_add_uint64(raid, ZPOOL_CONFIG_NPARITY, + ztest_opts.zo_raid_parity); + fnvlist_add_nvlist_array(raid, ZPOOL_CONFIG_CHILDREN, child, r); if (strcmp(ztest_opts.zo_raid_type, VDEV_TYPE_DRAID) == 0) { uint64_t ndata = ztest_opts.zo_draid_data; @@ -1176,7 +1175,7 @@ } for (c = 0; c < r; c++) - nvlist_free(child[c]); + fnvlist_free(child[c]); umem_free(child, r * sizeof (nvlist_t *)); @@ -1198,14 +1197,12 @@ for (c = 0; c < m; c++) child[c] = make_vdev_raid(path, aux, pool, size, ashift, r); - VERIFY(nvlist_alloc(&mirror, NV_UNIQUE_NAME, 0) == 0); - VERIFY(nvlist_add_string(mirror, ZPOOL_CONFIG_TYPE, - VDEV_TYPE_MIRROR) == 0); - VERIFY(nvlist_add_nvlist_array(mirror, ZPOOL_CONFIG_CHILDREN, - child, m) == 0); + mirror = fnvlist_alloc(); + fnvlist_add_string(mirror, ZPOOL_CONFIG_TYPE, VDEV_TYPE_MIRROR); + fnvlist_add_nvlist_array(mirror, ZPOOL_CONFIG_CHILDREN, child, m); for (c = 0; c < m; c++) - nvlist_free(child[c]); + fnvlist_free(child[c]); umem_free(child, m * sizeof (nvlist_t *)); @@ -1220,7 +1217,7 @@ int c; boolean_t log; - ASSERT(t > 0); + ASSERT3S(t, >, 0); log = (class != NULL && strcmp(class, "log") == 0); @@ -1229,23 +1226,22 @@ for (c = 0; c < t; c++) { child[c] = make_vdev_mirror(path, aux, pool, size, ashift, r, m); - VERIFY(nvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG, - log) == 0); + fnvlist_add_uint64(child[c], ZPOOL_CONFIG_IS_LOG, log); if (class != NULL && class[0] != '\0') { ASSERT(m > 1 || log); /* expecting a mirror */ - VERIFY(nvlist_add_string(child[c], - ZPOOL_CONFIG_ALLOCATION_BIAS, class) == 0); + fnvlist_add_string(child[c], + ZPOOL_CONFIG_ALLOCATION_BIAS, class); } } - VERIFY(nvlist_alloc(&root, NV_UNIQUE_NAME, 0) == 0); - VERIFY(nvlist_add_string(root, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) == 0); - VERIFY(nvlist_add_nvlist_array(root, aux ? aux : ZPOOL_CONFIG_CHILDREN, - child, t) == 0); + root = fnvlist_alloc(); + fnvlist_add_string(root, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT); + fnvlist_add_nvlist_array(root, aux ? aux : ZPOOL_CONFIG_CHILDREN, + child, t); for (c = 0; c < t; c++) - nvlist_free(child[c]); + fnvlist_free(child[c]); umem_free(child, t * sizeof (nvlist_t *)); @@ -1276,7 +1272,7 @@ static int ztest_random_blocksize(void) { - ASSERT(ztest_spa->spa_max_ashift != 0); + ASSERT3U(ztest_spa->spa_max_ashift, !=, 0); /* * Choose a block size >= the ashift. @@ -1334,7 +1330,7 @@ vdev_t *rvd = spa->spa_root_vdev; vdev_t *tvd; - ASSERT(spa_config_held(spa, SCL_ALL, RW_READER) != 0); + ASSERT3U(spa_config_held(spa, SCL_ALL, RW_READER), !=, 0); do { top = ztest_random(rvd->vdev_children); @@ -1402,12 +1398,12 @@ nvlist_t *props = NULL; int error; - VERIFY(nvlist_alloc(&props, NV_UNIQUE_NAME, 0) == 0); - VERIFY(nvlist_add_uint64(props, zpool_prop_to_name(prop), value) == 0); + props = fnvlist_alloc(); + fnvlist_add_uint64(props, zpool_prop_to_name(prop), value); error = spa_prop_set(spa, props); - nvlist_free(props); + fnvlist_free(props); if (error == ENOSPC) { ztest_record_enospc(FTAG); @@ -1485,8 +1481,8 @@ static void ztest_rll_destroy(rll_t *rll) { - ASSERT(rll->rll_writer == NULL); - ASSERT(rll->rll_readers == 0); + ASSERT3P(rll->rll_writer, ==, NULL); + ASSERT0(rll->rll_readers); mutex_destroy(&rll->rll_lock); cv_destroy(&rll->rll_cv); } @@ -1515,11 +1511,11 @@ mutex_enter(&rll->rll_lock); if (rll->rll_writer) { - ASSERT(rll->rll_readers == 0); + ASSERT0(rll->rll_readers); rll->rll_writer = NULL; } else { - ASSERT(rll->rll_readers != 0); - ASSERT(rll->rll_writer == NULL); + ASSERT3S(rll->rll_readers, >, 0); + ASSERT3P(rll->rll_writer, ==, NULL); rll->rll_readers--; } @@ -1625,7 +1621,7 @@ error = dmu_tx_assign(tx, txg_how); if (error) { if (error == ERESTART) { - ASSERT(txg_how == TXG_NOWAIT); + ASSERT3U(txg_how, ==, TXG_NOWAIT); dmu_tx_wait(tx); } else { ASSERT3U(error, ==, ENOSPC); @@ -1635,7 +1631,7 @@ return (0); } txg = dmu_tx_get_txg(tx); - ASSERT(txg != 0); + ASSERT3U(txg, !=, 0); return (txg); } @@ -1858,8 +1854,8 @@ if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); - ASSERT(lr->lr_doid == ZTEST_DIROBJ); - ASSERT(name[0] != '\0'); + ASSERT3U(lr->lr_doid, ==, ZTEST_DIROBJ); + ASSERT3S(name[0], !=, '\0'); tx = dmu_tx_create(os); @@ -1875,7 +1871,7 @@ if (txg == 0) return (ENOSPC); - ASSERT(dmu_objset_zil(os)->zl_replay == !!lr->lr_foid); + ASSERT3U(dmu_objset_zil(os)->zl_replay, ==, !!lr->lr_foid); bonuslen = DN_BONUS_SIZE(lr->lrz_dnodesize); if (lr->lrz_type == DMU_OT_ZAP_OTHER) { @@ -1907,13 +1903,13 @@ return (error); } - ASSERT(lr->lr_foid != 0); + ASSERT3U(lr->lr_foid, !=, 0); if (lr->lrz_type != DMU_OT_ZAP_OTHER) - VERIFY3U(0, ==, dmu_object_set_blocksize(os, lr->lr_foid, + VERIFY0(dmu_object_set_blocksize(os, lr->lr_foid, lr->lrz_blocksize, lr->lrz_ibshift, tx)); - VERIFY3U(0, ==, dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); + VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); bbt = ztest_bt_bonus(db); dmu_buf_will_dirty(db, tx); ztest_bt_generate(bbt, os, lr->lr_foid, lr->lrz_dnodesize, -1ULL, @@ -1921,7 +1917,7 @@ ztest_fill_unused_bonus(db, bbt, lr->lr_foid, os, lr->lr_gen); dmu_buf_rele(db, FTAG); - VERIFY3U(0, ==, zap_add(os, lr->lr_doid, name, sizeof (uint64_t), 1, + VERIFY0(zap_add(os, lr->lr_doid, name, sizeof (uint64_t), 1, &lr->lr_foid, tx)); (void) ztest_log_create(zd, tx, lr); @@ -1945,16 +1941,16 @@ if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); - ASSERT(lr->lr_doid == ZTEST_DIROBJ); - ASSERT(name[0] != '\0'); + ASSERT3U(lr->lr_doid, ==, ZTEST_DIROBJ); + ASSERT3S(name[0], !=, '\0'); - VERIFY3U(0, ==, + VERIFY0( zap_lookup(os, lr->lr_doid, name, sizeof (object), 1, &object)); - ASSERT(object != 0); + ASSERT3U(object, !=, 0); ztest_object_lock(zd, object, RL_WRITER); - VERIFY3U(0, ==, dmu_object_info(os, object, &doi)); + VERIFY0(dmu_object_info(os, object, &doi)); tx = dmu_tx_create(os); @@ -1968,12 +1964,12 @@ } if (doi.doi_type == DMU_OT_ZAP_OTHER) { - VERIFY3U(0, ==, zap_destroy(os, object, tx)); + VERIFY0(zap_destroy(os, object, tx)); } else { - VERIFY3U(0, ==, dmu_object_free(os, object, tx)); + VERIFY0(dmu_object_free(os, object, tx)); } - VERIFY3U(0, ==, zap_remove(os, lr->lr_doid, name, tx)); + VERIFY0(zap_remove(os, lr->lr_doid, name, tx)); (void) ztest_log_remove(zd, tx, lr, object); @@ -2025,7 +2021,7 @@ ztest_object_lock(zd, lr->lr_foid, RL_READER); rl = ztest_range_lock(zd, lr->lr_foid, offset, length, RL_WRITER); - VERIFY3U(0, ==, dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); + VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); dmu_object_info_from_db(db, &doi); @@ -2059,7 +2055,7 @@ * but not always, because we also want to verify correct * behavior when the data was not recently read into cache. */ - ASSERT(offset % doi.doi_data_block_size == 0); + ASSERT0(offset % doi.doi_data_block_size); if (ztest_random(4) != 0) { int prefetch = ztest_random(2) ? DMU_READ_PREFETCH : DMU_READ_NO_PREFETCH; @@ -2140,8 +2136,8 @@ return (ENOSPC); } - VERIFY(dmu_free_range(os, lr->lr_foid, lr->lr_offset, - lr->lr_length, tx) == 0); + VERIFY0(dmu_free_range(os, lr->lr_foid, lr->lr_offset, + lr->lr_length, tx)); (void) ztest_log_truncate(zd, tx, lr); @@ -2169,7 +2165,7 @@ ztest_object_lock(zd, lr->lr_foid, RL_WRITER); - VERIFY3U(0, ==, dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); + VERIFY0(dmu_bonus_hold(os, lr->lr_foid, FTAG, &db)); tx = dmu_tx_create(os); dmu_tx_hold_bonus(tx, lr->lr_foid); @@ -2188,9 +2184,9 @@ dnodesize = bbt->bt_dnodesize; if (zd->zd_zilog->zl_replay) { - ASSERT(lr->lr_size != 0); - ASSERT(lr->lr_mode != 0); - ASSERT(lrtxg != 0); + ASSERT3U(lr->lr_size, !=, 0); + ASSERT3U(lr->lr_mode, !=, 0); + ASSERT3U(lrtxg, !=, 0); } else { /* * Randomly change the size and increment the generation. @@ -2198,7 +2194,7 @@ lr->lr_size = (ztest_random(db->db_size / sizeof (*bbt)) + 1) * sizeof (*bbt); lr->lr_mode = bbt->bt_gen + 1; - ASSERT(lrtxg == 0); + ASSERT0(lrtxg); } /* @@ -2320,13 +2316,13 @@ error = dmu_read(os, object, offset, size, buf, DMU_READ_NO_PREFETCH); - ASSERT(error == 0); + ASSERT0(error); } else { size = doi.doi_data_block_size; if (ISP2(size)) { offset = P2ALIGN(offset, size); } else { - ASSERT(offset < size); + ASSERT3U(offset, <, size); offset = 0; } @@ -2342,8 +2338,8 @@ zgd->zgd_db = db; zgd->zgd_bp = bp; - ASSERT(db->db_offset == offset); - ASSERT(db->db_size == size); + ASSERT3U(db->db_offset, ==, offset); + ASSERT3U(db->db_size, ==, size); error = dmu_sync(zio, lr->lr_common.lrc_txg, ztest_get_done, zgd); @@ -2397,20 +2393,20 @@ error = zap_lookup(zd->zd_os, od->od_dir, od->od_name, sizeof (uint64_t), 1, &od->od_object); if (error) { - ASSERT(error == ENOENT); - ASSERT(od->od_object == 0); + ASSERT3S(error, ==, ENOENT); + ASSERT0(od->od_object); missing++; } else { dmu_buf_t *db; ztest_block_tag_t *bbt; dmu_object_info_t doi; - ASSERT(od->od_object != 0); - ASSERT(missing == 0); /* there should be no gaps */ + ASSERT3U(od->od_object, !=, 0); + ASSERT0(missing); /* there should be no gaps */ ztest_object_lock(zd, od->od_object, RL_READER); - VERIFY3U(0, ==, dmu_bonus_hold(zd->zd_os, - od->od_object, FTAG, &db)); + VERIFY0(dmu_bonus_hold(zd->zd_os, od->od_object, + FTAG, &db)); dmu_object_info_from_db(db, &doi); bbt = ztest_bt_bonus(db); ASSERT3U(bbt->bt_magic, ==, BT_MAGIC); @@ -2453,7 +2449,7 @@ lr->lr_crtime[0] = time(NULL); if (ztest_replay_create(zd, lr, B_FALSE) != 0) { - ASSERT(missing == 0); + ASSERT0(missing); od->od_object = 0; missing++; } else { @@ -2461,7 +2457,7 @@ od->od_type = od->od_crtype; od->od_blocksize = od->od_crblocksize; od->od_gen = od->od_crgen; - ASSERT(od->od_object != 0); + ASSERT3U(od->od_object, !=, 0); } ztest_lr_free(lr, sizeof (*lr), od->od_name); @@ -2612,7 +2608,7 @@ uint64_t blocksize; void *data; - VERIFY(dmu_object_info(zd->zd_os, object, &doi) == 0); + VERIFY0(dmu_object_info(zd->zd_os, object, &doi)); blocksize = doi.doi_data_block_size; data = umem_alloc(blocksize, UMEM_NOFAIL); @@ -2750,7 +2746,7 @@ * will verify that the log really does contain this record. */ mutex_enter(&zilog->zl_lock); - ASSERT(zd->zd_shared != NULL); + ASSERT3P(zd->zd_shared, !=, NULL); ASSERT3U(zd->zd_shared->zd_seq, <=, zilog->zl_commit_lr_seq); zd->zd_shared->zd_seq = zilog->zl_commit_lr_seq; mutex_exit(&zilog->zl_lock); @@ -2788,7 +2784,7 @@ zil_close(zd->zd_zilog); /* zfsvfs_setup() */ - VERIFY(zil_open(os, ztest_get_data) == zd->zd_zilog); + VERIFY3P(zil_open(os, ztest_get_data), ==, zd->zd_zilog); zil_replay(os, zd, ztest_replay_vector); (void) pthread_rwlock_unlock(&zd->zd_zilog_lock); @@ -2817,7 +2813,7 @@ nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1); VERIFY3U(ENOENT, ==, spa_create("ztest_bad_file", nvroot, NULL, NULL, NULL)); - nvlist_free(nvroot); + fnvlist_free(nvroot); /* * Attempt to create using a bad mirror. @@ -2825,7 +2821,7 @@ nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 2, 1); VERIFY3U(ENOENT, ==, spa_create("ztest_bad_mirror", nvroot, NULL, NULL, NULL)); - nvlist_free(nvroot); + fnvlist_free(nvroot); /* * Attempt to create an existing pool. It shouldn't matter @@ -2835,7 +2831,7 @@ nvroot = make_vdev_root("/dev/bogus", NULL, NULL, 0, 0, NULL, 0, 0, 1); VERIFY3U(EEXIST, ==, spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL)); - nvlist_free(nvroot); + fnvlist_free(nvroot); /* * We open a reference to the spa and then we try to export it @@ -2848,7 +2844,7 @@ * For the case that there is another ztest thread doing * an export concurrently. */ - VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG)); + VERIFY0(spa_open(zo->zo_pool, &spa, FTAG)); int error = spa_destroy(zo->zo_pool); if (error != EBUSY && error != ZFS_ERR_EXPORT_IN_PROGRESS) { fatal(0, "spa_destroy(%s) returned unexpected value %d", @@ -2965,11 +2961,11 @@ props = fnvlist_alloc(); fnvlist_add_uint64(props, zpool_prop_to_name(ZPOOL_PROP_VERSION), version); - VERIFY3S(spa_create(name, nvroot, props, NULL, NULL), ==, 0); + VERIFY0(spa_create(name, nvroot, props, NULL, NULL)); fnvlist_free(nvroot); fnvlist_free(props); - VERIFY3S(spa_open(name, &spa, FTAG), ==, 0); + VERIFY0(spa_open(name, &spa, FTAG)); VERIFY3U(spa_version(spa), ==, version); newversion = ztest_random_spa_version(version + 1); @@ -3146,7 +3142,7 @@ 1); error = spa_vdev_add(spa, nvroot); - nvlist_free(nvroot); + fnvlist_free(nvroot); switch (error) { case 0: @@ -3208,7 +3204,7 @@ class, ztest_opts.zo_raid_children, zs->zs_mirrors, 1); error = spa_vdev_add(spa, nvroot); - nvlist_free(nvroot); + fnvlist_free(nvroot); if (error == ENOSPC) ztest_record_enospc("spa_vdev_add"); @@ -3321,7 +3317,7 @@ default: fatal(0, "spa_vdev_add(%p) = %d", nvroot, error); } - nvlist_free(nvroot); + fnvlist_free(nvroot); } else { /* * Remove an existing device. Sometimes, dirty its @@ -3383,12 +3379,11 @@ /* generate a config from the existing config */ mutex_enter(&spa->spa_props_lock); - VERIFY(nvlist_lookup_nvlist(spa->spa_config, ZPOOL_CONFIG_VDEV_TREE, - &tree) == 0); + tree = fnvlist_lookup_nvlist(spa->spa_config, ZPOOL_CONFIG_VDEV_TREE); mutex_exit(&spa->spa_props_lock); - VERIFY(nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, &child, - &children) == 0); + VERIFY0(nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN, + &child, &children)); schild = malloc(rvd->vdev_children * sizeof (nvlist_t *)); for (c = 0; c < children; c++) { @@ -3397,37 +3392,35 @@ uint_t mchildren; if (tvd->vdev_islog || tvd->vdev_ops == &vdev_hole_ops) { - VERIFY(nvlist_alloc(&schild[schildren], NV_UNIQUE_NAME, - 0) == 0); - VERIFY(nvlist_add_string(schild[schildren], - ZPOOL_CONFIG_TYPE, VDEV_TYPE_HOLE) == 0); - VERIFY(nvlist_add_uint64(schild[schildren], - ZPOOL_CONFIG_IS_HOLE, 1) == 0); + schild[schildren] = fnvlist_alloc(); + fnvlist_add_string(schild[schildren], + ZPOOL_CONFIG_TYPE, VDEV_TYPE_HOLE); + fnvlist_add_uint64(schild[schildren], + ZPOOL_CONFIG_IS_HOLE, 1); if (lastlogid == 0) lastlogid = schildren; ++schildren; continue; } lastlogid = 0; - VERIFY(nvlist_lookup_nvlist_array(child[c], - ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren) == 0); - VERIFY(nvlist_dup(mchild[0], &schild[schildren++], 0) == 0); + VERIFY0(nvlist_lookup_nvlist_array(child[c], + ZPOOL_CONFIG_CHILDREN, &mchild, &mchildren)); + schild[schildren++] = fnvlist_dup(mchild[0]); } /* OK, create a config that can be used to split */ - VERIFY(nvlist_alloc(&split, NV_UNIQUE_NAME, 0) == 0); - VERIFY(nvlist_add_string(split, ZPOOL_CONFIG_TYPE, - VDEV_TYPE_ROOT) == 0); - VERIFY(nvlist_add_nvlist_array(split, ZPOOL_CONFIG_CHILDREN, schild, - lastlogid != 0 ? lastlogid : schildren) == 0); + split = fnvlist_alloc(); + fnvlist_add_string(split, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT); + fnvlist_add_nvlist_array(split, ZPOOL_CONFIG_CHILDREN, schild, + lastlogid != 0 ? lastlogid : schildren); - VERIFY(nvlist_alloc(&config, NV_UNIQUE_NAME, 0) == 0); - VERIFY(nvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, split) == 0); + config = fnvlist_alloc(); + fnvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, split); for (c = 0; c < schildren; c++) - nvlist_free(schild[c]); + fnvlist_free(schild[c]); free(schild); - nvlist_free(split); + fnvlist_free(split); spa_config_exit(spa, SCL_VDEV, FTAG); @@ -3435,7 +3428,7 @@ error = spa_vdev_split_mirror(spa, "splitp", config, NULL, B_FALSE); (void) pthread_rwlock_unlock(&ztest_name_lock); - nvlist_free(config); + fnvlist_free(config); if (error == 0) { (void) printf("successful split - results:\n"); @@ -3519,18 +3512,18 @@ /* pick a child from the mirror */ if (zs->zs_mirrors >= 1) { - ASSERT(oldvd->vdev_ops == &vdev_mirror_ops); - ASSERT(oldvd->vdev_children >= zs->zs_mirrors); + ASSERT3P(oldvd->vdev_ops, ==, &vdev_mirror_ops); + ASSERT3U(oldvd->vdev_children, >=, zs->zs_mirrors); oldvd = oldvd->vdev_child[leaf / ztest_opts.zo_raid_children]; } /* pick a child out of the raidz group */ if (ztest_opts.zo_raid_children > 1) { if (strcmp(oldvd->vdev_ops->vdev_op_type, "raidz") == 0) - ASSERT(oldvd->vdev_ops == &vdev_raidz_ops); + ASSERT3P(oldvd->vdev_ops, ==, &vdev_raidz_ops); else - ASSERT(oldvd->vdev_ops == &vdev_draid_ops); - ASSERT(oldvd->vdev_children == ztest_opts.zo_raid_children); + ASSERT3P(oldvd->vdev_ops, ==, &vdev_draid_ops); + ASSERT3U(oldvd->vdev_children, ==, ztest_opts.zo_raid_children); oldvd = oldvd->vdev_child[leaf % ztest_opts.zo_raid_children]; } @@ -3540,7 +3533,7 @@ */ while (oldvd->vdev_children != 0) { oldvd_has_siblings = B_TRUE; - ASSERT(oldvd->vdev_children >= 2); + ASSERT3U(oldvd->vdev_children, >=, 2); oldvd = oldvd->vdev_child[ztest_random(oldvd->vdev_children)]; } @@ -3658,7 +3651,7 @@ error = spa_vdev_attach(spa, oldguid, root, replacing, rebuilding); - nvlist_free(root); + fnvlist_free(root); /* * If our parent was the replacing vdev, but the replace completed, @@ -3767,14 +3760,14 @@ size_t fsize; int fd; - ASSERT(spa_config_held(spa, SCL_STATE, RW_READER) == SCL_STATE); + ASSERT3S(spa_config_held(spa, SCL_STATE, RW_READER), ==, SCL_STATE); ASSERT(vd->vdev_ops->vdev_op_leaf); if ((fd = open(vd->vdev_path, O_RDWR)) == -1) return (vd); fsize = lseek(fd, 0, SEEK_END); - VERIFY(ftruncate(fd, *newsize) == 0); + VERIFY0(ftruncate(fd, *newsize)); if (ztest_opts.zo_verbose >= 6) { (void) printf("%s grew from %lu to %lu bytes\n", @@ -3798,7 +3791,7 @@ vdev_state_t newstate = VDEV_STATE_UNKNOWN; int error; - ASSERT(spa_config_held(spa, SCL_STATE, RW_READER) == SCL_STATE); + ASSERT3S(spa_config_held(spa, SCL_STATE, RW_READER), ==, SCL_STATE); ASSERT(vd->vdev_ops->vdev_op_leaf); /* Calling vdev_online will initialize the new metaslabs */ @@ -3929,7 +3922,7 @@ mutex_exit(&ztest_checkpoint_lock); return; } - ASSERT(psize > 0); + ASSERT3U(psize, >, 0); newsize = psize + MAX(psize / 8, SPA_MAXBLOCKSIZE); ASSERT3U(newsize, >, psize); @@ -4031,8 +4024,8 @@ /* * Create the objects common to all ztest datasets. */ - VERIFY(zap_create_claim(os, ZTEST_DIROBJ, - DMU_OT_ZAP_OTHER, DMU_OT_NONE, 0, tx) == 0); + VERIFY0(zap_create_claim(os, ZTEST_DIROBJ, + DMU_OT_ZAP_OTHER, DMU_OT_NONE, 0, tx)); } static int @@ -4268,7 +4261,7 @@ /* * Verify that we can hold an objset that is also owned. */ - VERIFY3U(0, ==, dmu_objset_hold(name, FTAG, &os2)); + VERIFY0(dmu_objset_hold(name, FTAG, &os2)); dmu_objset_rele(os2, FTAG); /* @@ -4580,7 +4573,7 @@ bigobj = od[0].od_object; packobj = od[1].od_object; chunksize = od[0].od_gen; - ASSERT(chunksize == od[1].od_gen); + ASSERT3U(chunksize, ==, od[1].od_gen); /* * Prefetch a random chunk of the big object. @@ -4675,8 +4668,8 @@ /* LINTED */ bigT = (bufwad_t *)((char *)bigH + chunksize) - 1; - ASSERT((uintptr_t)bigH - (uintptr_t)bigbuf < bigsize); - ASSERT((uintptr_t)bigT - (uintptr_t)bigbuf < bigsize); + ASSERT3U((uintptr_t)bigH - (uintptr_t)bigbuf, <, bigsize); + ASSERT3U((uintptr_t)bigT - (uintptr_t)bigbuf, <, bigsize); if (pack->bw_txg > txg) fatal(0, "future leak: got %llx, open txg is %llx", @@ -4717,7 +4710,7 @@ (u_longlong_t)bigsize, (u_longlong_t)txg); } - VERIFY(0 == dmu_free_range(os, bigobj, bigoff, bigsize, tx)); + VERIFY0(dmu_free_range(os, bigobj, bigoff, bigsize, tx)); } else { if (ztest_opts.zo_verbose >= 7) { (void) printf("writing offset %llx size %llx" @@ -4738,13 +4731,13 @@ void *packcheck = umem_alloc(packsize, UMEM_NOFAIL); void *bigcheck = umem_alloc(bigsize, UMEM_NOFAIL); - VERIFY(0 == dmu_read(os, packobj, packoff, + VERIFY0(dmu_read(os, packobj, packoff, packsize, packcheck, DMU_READ_PREFETCH)); - VERIFY(0 == dmu_read(os, bigobj, bigoff, + VERIFY0(dmu_read(os, bigobj, bigoff, bigsize, bigcheck, DMU_READ_PREFETCH)); - ASSERT(bcmp(packbuf, packcheck, packsize) == 0); - ASSERT(bcmp(bigbuf, bigcheck, bigsize) == 0); + ASSERT0(bcmp(packbuf, packcheck, packsize)); + ASSERT0(bcmp(bigbuf, bigcheck, bigsize)); umem_free(packcheck, packsize); umem_free(bigcheck, bigsize); @@ -4778,8 +4771,8 @@ /* LINTED */ bigT = (bufwad_t *)((char *)bigH + chunksize) - 1; - ASSERT((uintptr_t)bigH - (uintptr_t)bigbuf < bigsize); - ASSERT((uintptr_t)bigT - (uintptr_t)bigbuf < bigsize); + ASSERT3U((uintptr_t)bigH - (uintptr_t)bigbuf, <, bigsize); + ASSERT3U((uintptr_t)bigT - (uintptr_t)bigbuf, <, bigsize); if (pack->bw_txg > txg) fatal(0, "future leak: got %llx, open txg is %llx", @@ -4864,12 +4857,12 @@ packobj = od[1].od_object; blocksize = od[0].od_blocksize; chunksize = blocksize; - ASSERT(chunksize == od[1].od_gen); + ASSERT3U(chunksize, ==, od[1].od_gen); - VERIFY(dmu_object_info(os, bigobj, &doi) == 0); + VERIFY0(dmu_object_info(os, bigobj, &doi)); VERIFY(ISP2(doi.doi_data_block_size)); - VERIFY(chunksize == doi.doi_data_block_size); - VERIFY(chunksize >= 2 * sizeof (bufwad_t)); + VERIFY3U(chunksize, ==, doi.doi_data_block_size); + VERIFY3U(chunksize, >=, 2 * sizeof (bufwad_t)); /* * Pick a random index and compute the offsets into packobj and bigobj. @@ -4886,7 +4879,7 @@ packbuf = umem_zalloc(packsize, UMEM_NOFAIL); bigbuf = umem_zalloc(bigsize, UMEM_NOFAIL); - VERIFY3U(0, ==, dmu_bonus_hold(os, bigobj, FTAG, &bonus_db)); + VERIFY0(dmu_bonus_hold(os, bigobj, FTAG, &bonus_db)); bigbuf_arcbufs = umem_zalloc(2 * s * sizeof (arc_buf_t *), UMEM_NOFAIL); @@ -5155,19 +5148,19 @@ goto out; for (i = 0; i < 2; i++) { value[i] = i; - VERIFY3U(0, ==, zap_add(os, object, hc[i], sizeof (uint64_t), + VERIFY0(zap_add(os, object, hc[i], sizeof (uint64_t), 1, &value[i], tx)); } for (i = 0; i < 2; i++) { VERIFY3U(EEXIST, ==, zap_add(os, object, hc[i], sizeof (uint64_t), 1, &value[i], tx)); - VERIFY3U(0, ==, + VERIFY0( zap_length(os, object, hc[i], &zl_intsize, &zl_ints)); ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); ASSERT3U(zl_ints, ==, 1); } for (i = 0; i < 2; i++) { - VERIFY3U(0, ==, zap_remove(os, object, hc[i], tx)); + VERIFY0(zap_remove(os, object, hc[i], tx)); } dmu_tx_commit(tx); @@ -5190,17 +5183,17 @@ ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); ASSERT3U(zl_ints, ==, 1); - VERIFY(zap_lookup(os, object, txgname, zl_intsize, - zl_ints, &last_txg) == 0); + VERIFY0(zap_lookup(os, object, txgname, zl_intsize, + zl_ints, &last_txg)); - VERIFY(zap_length(os, object, propname, &zl_intsize, - &zl_ints) == 0); + VERIFY0(zap_length(os, object, propname, &zl_intsize, + &zl_ints)); ASSERT3U(zl_intsize, ==, sizeof (uint64_t)); ASSERT3U(zl_ints, ==, ints); - VERIFY(zap_lookup(os, object, propname, zl_intsize, - zl_ints, value) == 0); + VERIFY0(zap_lookup(os, object, propname, zl_intsize, + zl_ints, value)); for (i = 0; i < ints; i++) { ASSERT3U(value[i], ==, last_txg + object + i); @@ -5228,9 +5221,9 @@ for (i = 0; i < ints; i++) value[i] = txg + object + i; - VERIFY3U(0, ==, zap_update(os, object, txgname, sizeof (uint64_t), + VERIFY0(zap_update(os, object, txgname, sizeof (uint64_t), 1, &txg, tx)); - VERIFY3U(0, ==, zap_update(os, object, propname, sizeof (uint64_t), + VERIFY0(zap_update(os, object, propname, sizeof (uint64_t), ints, value, tx)); dmu_tx_commit(tx); @@ -5254,8 +5247,8 @@ txg = ztest_tx_assign(tx, TXG_MIGHTWAIT, FTAG); if (txg == 0) goto out; - VERIFY3U(0, ==, zap_remove(os, object, txgname, tx)); - VERIFY3U(0, ==, zap_remove(os, object, propname, tx)); + VERIFY0(zap_remove(os, object, txgname, tx)); + VERIFY0(zap_remove(os, object, propname, tx)); dmu_tx_commit(tx); out: umem_free(od, sizeof (ztest_od_t)); @@ -5357,7 +5350,7 @@ count = -1ULL; VERIFY0(zap_count(os, object, &count)); - ASSERT(count != -1ULL); + ASSERT3S(count, !=, -1ULL); /* * Select an operation: length, lookup, add, update, remove. @@ -5409,7 +5402,7 @@ break; case 3: - VERIFY(zap_update(os, object, name, wsize, wc, data, tx) == 0); + VERIFY0(zap_update(os, object, name, wsize, wc, data, tx)); break; case 4: @@ -5443,7 +5436,7 @@ ztest_cb_data_t *data = arg; uint64_t synced_txg; - VERIFY(data != NULL); + VERIFY3P(data, !=, NULL); VERIFY3S(data->zcd_expected_err, ==, error); VERIFY(!data->zcd_called); @@ -5569,7 +5562,7 @@ /* * Read existing data to make sure there isn't a future leak. */ - VERIFY(0 == dmu_read(os, od->od_object, 0, sizeof (uint64_t), + VERIFY0(dmu_read(os, od->od_object, 0, sizeof (uint64_t), &old_txg, DMU_READ_PREFETCH)); if (old_txg > txg) @@ -5713,7 +5706,7 @@ if (ztest_opts.zo_verbose >= 6) dump_nvlist(props, 4); - nvlist_free(props); + fnvlist_free(props); (void) pthread_rwlock_unlock(&ztest_name_lock); } @@ -5905,7 +5898,7 @@ mirror_save = zs->zs_mirrors; mutex_exit(&ztest_vdev_lock); - ASSERT(leaves >= 1); + ASSERT3U(leaves, >=, 1); /* * While ztest is running the number of leaves will not change. This @@ -6034,7 +6027,7 @@ if (islog) (void) pthread_rwlock_wrlock(&ztest_name_lock); - VERIFY(vdev_offline(spa, guid0, flags) != EBUSY); + VERIFY3U(vdev_offline(spa, guid0, flags), !=, EBUSY); if (islog) (void) pthread_rwlock_unlock(&ztest_name_lock); @@ -6405,7 +6398,7 @@ return; } - VERIFY(realpath(getexecname(), bin) != NULL); + VERIFY3P(realpath(getexecname(), bin), !=, NULL); if (strstr(bin, "/ztest/")) { strstr(bin, "/ztest/")[0] = '\0'; /* In-tree */ strcat(bin, "/zdb/zdb"); @@ -6435,7 +6428,7 @@ eligible[eligible_idx++] = cvd; } } - VERIFY(eligible_idx > 0); + VERIFY3S(eligible_idx, >, 0); uint64_t child_no = ztest_random(eligible_idx); return (ztest_random_concrete_vdev_leaf(eligible[child_no])); @@ -6677,7 +6670,7 @@ /* * Get the pool's configuration and guid. */ - VERIFY3U(0, ==, spa_open(oldname, &spa, FTAG)); + VERIFY0(spa_open(oldname, &spa, FTAG)); /* * Kick off a scrub to tickle scrub/export races. @@ -6693,7 +6686,7 @@ /* * Export it. */ - VERIFY3U(0, ==, spa_export(oldname, &config, B_FALSE, B_FALSE)); + VERIFY0(spa_export(oldname, &config, B_FALSE, B_FALSE)); ztest_walk_pool_directory("pools after export"); @@ -6701,8 +6694,8 @@ * Try to import it. */ newconfig = spa_tryimport(config); - ASSERT(newconfig != NULL); - nvlist_free(newconfig); + ASSERT3P(newconfig, !=, NULL); + fnvlist_free(newconfig); /* * Import it under the new name. @@ -6734,11 +6727,11 @@ /* * Verify that we can open and close the pool using the new name. */ - VERIFY3U(0, ==, spa_open(newname, &spa, FTAG)); - ASSERT(pool_guid == spa_guid(spa)); + VERIFY0(spa_open(newname, &spa, FTAG)); + ASSERT3U(pool_guid, ==, spa_guid(spa)); spa_close(spa, FTAG); - nvlist_free(config); + fnvlist_free(config); } static void @@ -6942,7 +6935,7 @@ * That's because zap_count() returns the open-context value, * while dmu_objset_space() returns the rootbp fill count. */ - VERIFY3U(0, ==, zap_count(zd->zd_os, ZTEST_DIROBJ, &dirobjs)); + VERIFY0(zap_count(zd->zd_os, ZTEST_DIROBJ, &dirobjs)); dmu_objset_space(zd->zd_os, &scratch, &scratch, &usedobjs, &scratch); ASSERT3U(dirobjs + 1, ==, usedobjs); } @@ -7060,8 +7053,8 @@ (void) printf("testing spa_freeze()...\n"); kernel_init(SPA_MODE_READ | SPA_MODE_WRITE); - VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG)); - VERIFY3U(0, ==, ztest_dataset_open(0)); + VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG)); + VERIFY0(ztest_dataset_open(0)); ztest_spa = spa; /* @@ -7127,9 +7120,9 @@ * Open and close the pool and dataset to induce log replay. */ kernel_init(SPA_MODE_READ | SPA_MODE_WRITE); - VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG)); - ASSERT(spa_freeze_txg(spa) == UINT64_MAX); - VERIFY3U(0, ==, ztest_dataset_open(0)); + VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG)); + ASSERT3U(spa_freeze_txg(spa), ==, UINT64_MAX); + VERIFY0(ztest_dataset_open(0)); ztest_spa = spa; txg_wait_synced(spa_get_dsl(spa), 0); ztest_dataset_close(0); @@ -7452,13 +7445,13 @@ { nvlist_t *props; - VERIFY0(nvlist_alloc(&props, NV_UNIQUE_NAME, 0)); + props = fnvlist_alloc(); if (ztest_random(2) == 0) return (props); - VERIFY0(nvlist_add_uint64(props, - zpool_prop_to_name(ZPOOL_PROP_AUTOREPLACE), 1)); + fnvlist_add_uint64(props, + zpool_prop_to_name(ZPOOL_PROP_AUTOREPLACE), 1); return (props); } @@ -7496,9 +7489,9 @@ * in which case ztest_fault_inject() temporarily takes away * the only valid replica. */ - VERIFY0(nvlist_add_uint64(props, + fnvlist_add_uint64(props, zpool_prop_to_name(ZPOOL_PROP_FAILUREMODE), - MAXFAULTS(zs) ? ZIO_FAILURE_MODE_PANIC : ZIO_FAILURE_MODE_WAIT)); + MAXFAULTS(zs) ? ZIO_FAILURE_MODE_PANIC : ZIO_FAILURE_MODE_WAIT); for (i = 0; i < SPA_FEATURES; i++) { char *buf; @@ -7513,15 +7506,15 @@ VERIFY3S(-1, !=, asprintf(&buf, "feature@%s", spa_feature_table[i].fi_uname)); - VERIFY3U(0, ==, nvlist_add_uint64(props, buf, 0)); + fnvlist_add_uint64(props, buf, 0); free(buf); } VERIFY0(spa_create(ztest_opts.zo_pool, nvroot, props, NULL, NULL)); - nvlist_free(nvroot); - nvlist_free(props); + fnvlist_free(nvroot); + fnvlist_free(props); - VERIFY3U(0, ==, spa_open(ztest_opts.zo_pool, &spa, FTAG)); + VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG)); zs->zs_metaslab_sz = 1ULL << spa->spa_root_vdev->vdev_child[0]->vdev_ms_shift; spa_close(spa, FTAG); @@ -7571,9 +7564,9 @@ hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); - ASSERT(hdr != MAP_FAILED); + ASSERT3P(hdr, !=, MAP_FAILED); - VERIFY3U(0, ==, ftruncate(ztest_fd_data, sizeof (ztest_shared_hdr_t))); + VERIFY0(ftruncate(ztest_fd_data, sizeof (ztest_shared_hdr_t))); hdr->zh_hdr_size = sizeof (ztest_shared_hdr_t); hdr->zh_opts_size = sizeof (ztest_shared_opts_t); @@ -7584,7 +7577,7 @@ hdr->zh_ds_count = ztest_opts.zo_datasets; size = shared_data_size(hdr); - VERIFY3U(0, ==, ftruncate(ztest_fd_data, size)); + VERIFY0(ftruncate(ztest_fd_data, size)); (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); } @@ -7598,14 +7591,14 @@ hdr = (void *)mmap(0, P2ROUNDUP(sizeof (*hdr), getpagesize()), PROT_READ, MAP_SHARED, ztest_fd_data, 0); - ASSERT(hdr != MAP_FAILED); + ASSERT3P(hdr, !=, MAP_FAILED); size = shared_data_size(hdr); (void) munmap((caddr_t)hdr, P2ROUNDUP(sizeof (*hdr), getpagesize())); hdr = ztest_shared_hdr = (void *)mmap(0, P2ROUNDUP(size, getpagesize()), PROT_READ | PROT_WRITE, MAP_SHARED, ztest_fd_data, 0); - ASSERT(hdr != MAP_FAILED); + ASSERT3P(hdr, !=, MAP_FAILED); buf = (uint8_t *)hdr; offset = hdr->zh_hdr_size; @@ -7644,12 +7637,13 @@ (void) setrlimit(RLIMIT_NOFILE, &rl); (void) close(ztest_fd_rand); - VERIFY(11 >= snprintf(fd_data_str, 12, "%d", ztest_fd_data)); - VERIFY(0 == setenv("ZTEST_FD_DATA", fd_data_str, 1)); + VERIFY3S(11, >=, + snprintf(fd_data_str, 12, "%d", ztest_fd_data)); + VERIFY0(setenv("ZTEST_FD_DATA", fd_data_str, 1)); (void) enable_extended_FILE_stdio(-1, -1); if (libpath != NULL) - VERIFY(0 == setenv("LD_LIBRARY_PATH", libpath, 1)); + VERIFY0(setenv("LD_LIBRARY_PATH", libpath, 1)); (void) execv(cmd, emptyargv); ztest_dump_core = B_FALSE; fatal(B_TRUE, "exec failed: %s", cmd); @@ -7801,8 +7795,8 @@ ASSERT3U(ztest_opts.zo_datasets, ==, ztest_shared_hdr->zh_ds_count); /* Override location of zpool.cache */ - VERIFY(asprintf((char **)&spa_config_path, "%s/zpool.cache", - ztest_opts.zo_dir) != -1); + VERIFY3S(asprintf((char **)&spa_config_path, "%s/zpool.cache", + ztest_opts.zo_dir), !=, -1); ztest_ds = umem_alloc(ztest_opts.zo_datasets * sizeof (ztest_ds_t), UMEM_NOFAIL); diff --git a/sys/contrib/openzfs/cmd/zvol_id/Makefile.am b/sys/contrib/openzfs/cmd/zvol_id/Makefile.am --- a/sys/contrib/openzfs/cmd/zvol_id/Makefile.am +++ b/sys/contrib/openzfs/cmd/zvol_id/Makefile.am @@ -8,3 +8,5 @@ zvol_id_SOURCES = \ zvol_id_main.c + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/config/CppCheck.am b/sys/contrib/openzfs/config/CppCheck.am new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/config/CppCheck.am @@ -0,0 +1,11 @@ +# +# Default rules for running cppcheck against the the user space components. +# + +PHONY += cppcheck + +CPPCHECKFLAGS = --std=c99 --quiet --max-configs=1 --error-exitcode=2 +CPPCHECKFLAGS += --inline-suppr -U_KERNEL + +cppcheck: + $(CPPCHECK) -j$(CPU_COUNT) $(CPPCHECKFLAGS) $(DEFAULT_INCLUDES) $(SOURCES) diff --git a/sys/contrib/openzfs/config/Rules.am b/sys/contrib/openzfs/config/Rules.am --- a/sys/contrib/openzfs/config/Rules.am +++ b/sys/contrib/openzfs/config/Rules.am @@ -3,6 +3,7 @@ # should include these rules and override or extend them as needed. # +PHONY = DEFAULT_INCLUDES = \ -include $(top_builddir)/zfs_config.h \ -I$(top_builddir)/include \ diff --git a/sys/contrib/openzfs/config/always-cppcheck.m4 b/sys/contrib/openzfs/config/always-cppcheck.m4 new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/config/always-cppcheck.m4 @@ -0,0 +1,6 @@ +dnl # +dnl # Check if cppcheck is available. +dnl # +AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CPPCHECK], [ + AC_CHECK_PROG([CPPCHECK], [cppcheck], [cppcheck]) +]) diff --git a/sys/contrib/openzfs/config/ax_count_cpus.m4 b/sys/contrib/openzfs/config/ax_count_cpus.m4 new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/config/ax_count_cpus.m4 @@ -0,0 +1,101 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_count_cpus.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_COUNT_CPUS([ACTION-IF-DETECTED],[ACTION-IF-NOT-DETECTED]) +# +# DESCRIPTION +# +# Attempt to count the number of logical processor cores (including +# virtual and HT cores) currently available to use on the machine and +# place detected value in CPU_COUNT variable. +# +# On successful detection, ACTION-IF-DETECTED is executed if present. If +# the detection fails, then ACTION-IF-NOT-DETECTED is triggered. The +# default ACTION-IF-NOT-DETECTED is to set CPU_COUNT to 1. +# +# LICENSE +# +# Copyright (c) 2014,2016 Karlson2k (Evgeny Grin) +# Copyright (c) 2012 Brian Aker +# Copyright (c) 2008 Michael Paul Bailey +# Copyright (c) 2008 Christophe Tournayre +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 22 + + AC_DEFUN([AX_COUNT_CPUS],[dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([AC_PROG_EGREP])dnl + AC_MSG_CHECKING([the number of available CPUs]) + CPU_COUNT="0" + + # Try generic methods + + # 'getconf' is POSIX utility, but '_NPROCESSORS_ONLN' and + # 'NPROCESSORS_ONLN' are platform-specific + command -v getconf >/dev/null 2>&1 && \ + CPU_COUNT=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null` || CPU_COUNT="0" + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v nproc >/dev/null 2>&1]],[[: # empty]],[dnl + # 'nproc' is part of GNU Coreutils and is widely available + CPU_COUNT=`OMP_NUM_THREADS='' nproc 2>/dev/null` || CPU_COUNT=`nproc 2>/dev/null` || CPU_COUNT="0" + ])dnl + + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl + # Try platform-specific preferred methods + AS_CASE([[$host_os]],dnl + [[*linux*]],[[CPU_COUNT=`lscpu -p 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+,' -c` || CPU_COUNT="0"]],dnl + [[*darwin*]],[[CPU_COUNT=`sysctl -n hw.logicalcpu 2>/dev/null` || CPU_COUNT="0"]],dnl + [[freebsd*]],[[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n kern.smp.cpus 2>/dev/null` || CPU_COUNT="0"]],dnl + [[netbsd*]], [[command -v sysctl >/dev/null 2>&1 && CPU_COUNT=`sysctl -n hw.ncpuonline 2>/dev/null` || CPU_COUNT="0"]],dnl + [[solaris*]],[[command -v psrinfo >/dev/null 2>&1 && CPU_COUNT=`psrinfo 2>/dev/null | $EGREP -e '^@<:@0-9@:>@.*on-line' -c 2>/dev/null` || CPU_COUNT="0"]],dnl + [[mingw*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl + [[msys*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]],dnl + [[cygwin*]],[[CPU_COUNT=`ls -qpU1 /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor/ 2>/dev/null | $EGREP -e '^@<:@0-9@:>@+/' -c` || CPU_COUNT="0"]]dnl + )dnl + ])dnl + + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null || ! command -v sysctl >/dev/null 2>&1]],[[: # empty]],[dnl + # Try less preferred generic method + # 'hw.ncpu' exist on many platforms, but not on GNU/Linux + CPU_COUNT=`sysctl -n hw.ncpu 2>/dev/null` || CPU_COUNT="0" + ])dnl + + AS_IF([[test "$CPU_COUNT" -gt "0" 2>/dev/null]],[[: # empty]],[dnl + # Try platform-specific fallback methods + # They can be less accurate and slower then preferred methods + AS_CASE([[$host_os]],dnl + [[*linux*]],[[CPU_COUNT=`$EGREP -e '^processor' -c /proc/cpuinfo 2>/dev/null` || CPU_COUNT="0"]],dnl + [[*darwin*]],[[CPU_COUNT=`system_profiler SPHardwareDataType 2>/dev/null | $EGREP -i -e 'number of cores:'|cut -d : -f 2 -s|tr -d ' '` || CPU_COUNT="0"]],dnl + [[freebsd*]],[[CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+: '|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl + [[netbsd*]], [[CPU_COUNT=`command -v cpuctl >/dev/null 2>&1 && cpuctl list 2>/dev/null| $EGREP -e '^@<:@0-9@:>@+ .* online ' -c` || \ + CPU_COUNT=`dmesg 2>/dev/null| $EGREP -e '^cpu@<:@0-9@:>@+ at'|sort -u|$EGREP -e '^' -c` || CPU_COUNT="0"]],dnl + [[solaris*]],[[command -v kstat >/dev/null 2>&1 && CPU_COUNT=`kstat -m cpu_info -s state -p 2>/dev/null | $EGREP -c -e 'on-line'` || \ + CPU_COUNT=`kstat -m cpu_info 2>/dev/null | $EGREP -c -e 'module: cpu_info'` || CPU_COUNT="0"]],dnl + [[mingw*]],[AS_IF([[CPU_COUNT=`reg query 'HKLM\\Hardware\\Description\\System\\CentralProcessor' 2>/dev/null | $EGREP -e '\\\\@<:@0-9@:>@+$' -c`]],dnl + [[: # empty]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]])],dnl + [[msys*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]],dnl + [[cygwin*]],[[test "$NUMBER_OF_PROCESSORS" -gt "0" 2>/dev/null && CPU_COUNT="$NUMBER_OF_PROCESSORS"]]dnl + )dnl + ])dnl + + AS_IF([[test "x$CPU_COUNT" != "x0" && test "$CPU_COUNT" -gt 0 2>/dev/null]],[dnl + AC_MSG_RESULT([[$CPU_COUNT]]) + m4_ifvaln([$1],[$1],)dnl + ],[dnl + m4_ifval([$2],[dnl + AS_UNSET([[CPU_COUNT]]) + AC_MSG_RESULT([[unable to detect]]) + $2 + ], [dnl + CPU_COUNT="1" + AC_MSG_RESULT([[unable to detect (assuming 1)]]) + ])dnl + ])dnl + ])dnl diff --git a/sys/contrib/openzfs/config/kernel-get-disk-and-module.m4 b/sys/contrib/openzfs/config/kernel-get-disk-and-module.m4 deleted file mode 100644 diff --git a/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4 b/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4 --- a/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4 +++ b/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4 @@ -10,31 +10,6 @@ ITER_IOVEC | ITER_KVEC | ITER_BVEC | ITER_PIPE; ]) - ZFS_LINUX_TEST_SRC([iov_iter_init], [ - #include - #include - ],[ - struct iov_iter iter = { 0 }; - struct iovec iov; - unsigned long nr_segs = 1; - size_t count = 1024; - - iov_iter_init(&iter, WRITE, &iov, nr_segs, count); - ]) - - ZFS_LINUX_TEST_SRC([iov_iter_init_legacy], [ - #include - #include - ],[ - struct iov_iter iter = { 0 }; - struct iovec iov; - unsigned long nr_segs = 1; - size_t count = 1024; - size_t written = 0; - - iov_iter_init(&iter, &iov, nr_segs, count, written); - ]) - ZFS_LINUX_TEST_SRC([iov_iter_advance], [ #include #include @@ -114,25 +89,6 @@ enable_vfs_iov_iter="no" ]) - dnl # - dnl # 'iov_iter_init' available in Linux 3.16 and newer. - dnl # 'iov_iter_init_legacy' available in Linux 3.15 and older. - dnl # - AC_MSG_CHECKING([whether iov_iter_init() is available]) - ZFS_LINUX_TEST_RESULT([iov_iter_init], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_IOV_ITER_INIT, 1, - [iov_iter_init() is available]) - ],[ - ZFS_LINUX_TEST_RESULT([iov_iter_init_legacy], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_IOV_ITER_INIT_LEGACY, 1, - [iov_iter_init() is available]) - ],[ - ZFS_LINUX_TEST_ERROR([iov_iter_init()]) - ]) - ]) - AC_MSG_CHECKING([whether iov_iter_advance() is available]) ZFS_LINUX_TEST_RESULT([iov_iter_advance], [ AC_MSG_RESULT(yes) diff --git a/sys/contrib/openzfs/config/zfs-build.m4 b/sys/contrib/openzfs/config/zfs-build.m4 --- a/sys/contrib/openzfs/config/zfs-build.m4 +++ b/sys/contrib/openzfs/config/zfs-build.m4 @@ -153,6 +153,9 @@ ]) AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [ + AX_COUNT_CPUS([]) + AC_SUBST(CPU_COUNT) + ZFS_AC_CONFIG_ALWAYS_CC_NO_UNUSED_BUT_SET_VARIABLE ZFS_AC_CONFIG_ALWAYS_CC_NO_BOOL_COMPARE ZFS_AC_CONFIG_ALWAYS_CC_FRAME_LARGER_THAN @@ -167,6 +170,7 @@ ZFS_AC_CONFIG_ALWAYS_PYTHON ZFS_AC_CONFIG_ALWAYS_PYZFS ZFS_AC_CONFIG_ALWAYS_SED + ZFS_AC_CONFIG_ALWAYS_CPPCHECK ]) AC_DEFUN([ZFS_AC_CONFIG], [ @@ -191,12 +195,10 @@ ZFS_AC_CONFIG_ALWAYS - AM_COND_IF([BUILD_LINUX], [ - AC_ARG_VAR([TEST_JOBS], - [simultaneous jobs during configure (defaults to $(nproc))]) + AC_ARG_VAR([TEST_JOBS], [simultaneous jobs during configure]) if test "x$ac_cv_env_TEST_JOBS_set" != "xset"; then - TEST_JOBS=$(nproc) + TEST_JOBS=$CPU_COUNT fi AC_SUBST(TEST_JOBS) ]) diff --git a/sys/contrib/openzfs/contrib/dracut/90zfs/module-setup.sh.in b/sys/contrib/openzfs/contrib/dracut/90zfs/module-setup.sh.in --- a/sys/contrib/openzfs/contrib/dracut/90zfs/module-setup.sh.in +++ b/sys/contrib/openzfs/contrib/dracut/90zfs/module-setup.sh.in @@ -5,7 +5,7 @@ [ "${1}" = "-d" ] && return 0 # Verify the zfs tool chain - for tool in "@bindir@/zgenhostid" "@sbindir@/zpool" "@sbindir@/zfs" "@mounthelperdir@/mount.zfs" ; do + for tool in "@sbindir@/zgenhostid" "@sbindir@/zpool" "@sbindir@/zfs" "@mounthelperdir@/mount.zfs" ; do test -x "$tool" || return 1 done # Verify grep exists @@ -38,7 +38,7 @@ inst_rules @udevruledir@/60-zvol.rules dracut_install hostid dracut_install grep - dracut_install @bindir@/zgenhostid + dracut_install @sbindir@/zgenhostid dracut_install @sbindir@/zfs dracut_install @sbindir@/zpool # Workaround for https://github.com/openzfs/zfs/issues/4749 by diff --git a/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-env-bootfs.service.in b/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-env-bootfs.service.in --- a/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-env-bootfs.service.in +++ b/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-env-bootfs.service.in @@ -8,7 +8,7 @@ [Service] Type=oneshot -ExecStart=/bin/sh -c "/bin/systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')" +ExecStart=/bin/sh -c "systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')" [Install] WantedBy=zfs-import.target diff --git a/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-generator.sh.in b/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-generator.sh.in --- a/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-generator.sh.in +++ b/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-generator.sh.in @@ -59,4 +59,12 @@ [ -d "$GENERATOR_DIR"/initrd-root-fs.target.requires ] || mkdir -p "$GENERATOR_DIR"/initrd-root-fs.target.requires ln -s ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount + +[ -d "$GENERATOR_DIR"/dracut-pre-mount.service.d ] || mkdir "$GENERATOR_DIR"/dracut-pre-mount.service.d + +{ + echo "[Unit]" + echo "After=zfs-import.target" +} > "$GENERATOR_DIR"/dracut-pre-mount.service.d/zfs-enhancement.conf + echo "zfs-generator: finished" >> /dev/kmsg diff --git a/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-load-key.sh.in b/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-load-key.sh.in --- a/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-load-key.sh.in +++ b/sys/contrib/openzfs/contrib/dracut/90zfs/zfs-load-key.sh.in @@ -1,7 +1,7 @@ #!/bin/sh # only run this on systemd systems, we handle the decrypt in mount-zfs.sh in the mount hook otherwise -[ -e /bin/systemctl ] || return 0 +[ -e /bin/systemctl ] || [ -e /usr/bin/systemctl ] || return 0 # This script only gets executed on systemd systems, see mount-zfs.sh for non-systemd systems diff --git a/sys/contrib/openzfs/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py b/sys/contrib/openzfs/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py --- a/sys/contrib/openzfs/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py +++ b/sys/contrib/openzfs/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py @@ -154,8 +154,8 @@ @contextlib.contextmanager def dev_null(): - with os_open('/dev/null', os.O_WRONLY) as fd: - yield fd + with tempfile.TemporaryFile(suffix='.zstream') as fd: + yield fd.fileno() @contextlib.contextmanager diff --git a/sys/contrib/openzfs/cppcheck-suppressions.txt b/sys/contrib/openzfs/cppcheck-suppressions.txt deleted file mode 100644 --- a/sys/contrib/openzfs/cppcheck-suppressions.txt +++ /dev/null @@ -1,8 +0,0 @@ -preprocessorErrorDirective:./module/zfs/vdev_raidz_math_avx512f.c:243 -preprocessorErrorDirective:./module/zfs/vdev_raidz_math_sse2.c:266 -uninitvar:module/os/freebsd/zfs/vdev_geom.c -uninitvar:module/os/freebsd/zfs/zfs_vfsops.c -uninitvar:module/os/freebsd/spl/spl_zone.c -uninitvar:lib/libzutil/os/freebsd/zutil_import_os.c -*:module/zstd/lib/zstd.c -*:module/zstd/lib/zstd.h diff --git a/sys/contrib/openzfs/etc/systemd/system/zfs-import-cache.service.in b/sys/contrib/openzfs/etc/systemd/system/zfs-import-cache.service.in --- a/sys/contrib/openzfs/etc/systemd/system/zfs-import-cache.service.in +++ b/sys/contrib/openzfs/etc/systemd/system/zfs-import-cache.service.in @@ -8,7 +8,7 @@ After=multipathd.target After=systemd-remount-fs.service Before=zfs-import.target -ConditionPathExists=@sysconfdir@/zfs/zpool.cache +ConditionFileNotEmpty=@sysconfdir@/zfs/zpool.cache ConditionPathIsDirectory=/sys/module/zfs [Service] diff --git a/sys/contrib/openzfs/etc/systemd/system/zfs-import-scan.service.in b/sys/contrib/openzfs/etc/systemd/system/zfs-import-scan.service.in --- a/sys/contrib/openzfs/etc/systemd/system/zfs-import-scan.service.in +++ b/sys/contrib/openzfs/etc/systemd/system/zfs-import-scan.service.in @@ -7,7 +7,7 @@ After=cryptsetup.target After=multipathd.target Before=zfs-import.target -ConditionPathExists=!@sysconfdir@/zfs/zpool.cache +ConditionFileNotEmpty=!@sysconfdir@/zfs/zpool.cache ConditionPathIsDirectory=/sys/module/zfs [Service] diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am b/sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am --- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am +++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/Makefile.am @@ -15,6 +15,7 @@ disp.h \ dkio.h \ extdirent.h \ + fcntl.h \ file.h \ freebsd_rwlock.h \ inttypes.h \ diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h b/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h --- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h +++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h @@ -166,9 +166,6 @@ #define ECHRNG ENXIO #define ETIME ETIMEDOUT -#define O_LARGEFILE 0 -#define O_RSYNC 0 - #ifndef LOCORE #ifndef HAVE_RPC_TYPES typedef int bool_t; diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/fcntl.h b/sys/contrib/openzfs/include/os/freebsd/spl/sys/fcntl.h new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/fcntl.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 iXsystems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _SPL_SYS_FCNTL_H_ +#define _SPL_SYS_FCNTL_H_ + +#include_next + +#define O_LARGEFILE 0 +#define O_RSYNC 0 + +#ifndef O_DSYNC +#define O_DSYNC 0 +#endif + +#endif /* _SPL_SYS_FCNTL_H_ */ diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/uio.h b/sys/contrib/openzfs/include/os/freebsd/spl/sys/uio.h --- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/uio.h +++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/uio.h @@ -35,55 +35,72 @@ #include #include - - -#define uio_loffset uio_offset - -typedef struct uio uio_t; typedef struct iovec iovec_t; -typedef enum uio_seg uio_seg_t; - -static __inline int -zfs_uiomove(void *cp, size_t n, enum uio_rw dir, uio_t *uio) +typedef enum uio_seg zfs_uio_seg_t; +typedef enum uio_rw zfs_uio_rw_t; + +typedef struct zfs_uio { + struct uio *uio; +} zfs_uio_t; + +#define GET_UIO_STRUCT(u) (u)->uio +#define zfs_uio_segflg(u) GET_UIO_STRUCT(u)->uio_segflg +#define zfs_uio_offset(u) GET_UIO_STRUCT(u)->uio_offset +#define zfs_uio_resid(u) GET_UIO_STRUCT(u)->uio_resid +#define zfs_uio_iovcnt(u) GET_UIO_STRUCT(u)->uio_iovcnt +#define zfs_uio_iovlen(u, idx) GET_UIO_STRUCT(u)->uio_iov[(idx)].iov_len +#define zfs_uio_iovbase(u, idx) GET_UIO_STRUCT(u)->uio_iov[(idx)].iov_base +#define zfs_uio_td(u) GET_UIO_STRUCT(u)->uio_td +#define zfs_uio_rw(u) GET_UIO_STRUCT(u)->uio_rw +#define zfs_uio_fault_disable(u, set) +#define zfs_uio_prefaultpages(size, u) (0) + + +static __inline void +zfs_uio_init(zfs_uio_t *uio, struct uio *uio_s) { + GET_UIO_STRUCT(uio) = uio_s; +} - ASSERT(uio->uio_rw == dir); - return (uiomove(cp, (int)n, uio)); +static __inline void +zfs_uio_setoffset(zfs_uio_t *uio, offset_t off) +{ + zfs_uio_offset(uio) = off; } -#define uiomove(cp, n, dir, uio) zfs_uiomove((cp), (n), (dir), (uio)) -int uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes); -void uioskip(uio_t *uiop, size_t n); +static __inline int +zfs_uiomove(void *cp, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio) +{ + ASSERT(zfs_uio_rw(uio) == dir); + return (uiomove(cp, (int)n, GET_UIO_STRUCT(uio))); +} -#define uio_segflg(uio) (uio)->uio_segflg -#define uio_offset(uio) (uio)->uio_loffset -#define uio_resid(uio) (uio)->uio_resid -#define uio_iovcnt(uio) (uio)->uio_iovcnt -#define uio_iovlen(uio, idx) (uio)->uio_iov[(idx)].iov_len -#define uio_iovbase(uio, idx) (uio)->uio_iov[(idx)].iov_base -#define uio_fault_disable(uio, set) -#define uio_prefaultpages(size, uio) (0) +int zfs_uiocopy(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio, + size_t *cbytes); +void zfs_uioskip(zfs_uio_t *uiop, size_t n); +int zfs_uio_fault_move(void *p, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio); static inline void -uio_iov_at_index(uio_t *uio, uint_t idx, void **base, uint64_t *len) +zfs_uio_iov_at_index(zfs_uio_t *uio, uint_t idx, void **base, uint64_t *len) { - *base = uio_iovbase(uio, idx); - *len = uio_iovlen(uio, idx); + *base = zfs_uio_iovbase(uio, idx); + *len = zfs_uio_iovlen(uio, idx); } static inline void -uio_advance(uio_t *uio, size_t size) +zfs_uio_advance(zfs_uio_t *uio, size_t size) { - uio->uio_resid -= size; - uio->uio_loffset += size; + zfs_uio_resid(uio) -= size; + zfs_uio_offset(uio) += size; } static inline offset_t -uio_index_at_offset(uio_t *uio, offset_t off, uint_t *vec_idx) +zfs_uio_index_at_offset(zfs_uio_t *uio, offset_t off, uint_t *vec_idx) { *vec_idx = 0; - while (*vec_idx < uio_iovcnt(uio) && off >= uio_iovlen(uio, *vec_idx)) { - off -= uio_iovlen(uio, *vec_idx); + while (*vec_idx < zfs_uio_iovcnt(uio) && + off >= zfs_uio_iovlen(uio, *vec_idx)) { + off -= zfs_uio_iovlen(uio, *vec_idx); (*vec_idx)++; } diff --git a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/freebsd_crypto.h b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/freebsd_crypto.h --- a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/freebsd_crypto.h +++ b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/freebsd_crypto.h @@ -92,7 +92,7 @@ void freebsd_crypt_freesession(freebsd_crypt_session_t *sessp); int freebsd_crypt_uio(boolean_t, freebsd_crypt_session_t *, - struct zio_crypt_info *, uio_t *, crypto_key_t *, uint8_t *, + struct zio_crypt_info *, zfs_uio_t *, crypto_key_t *, uint8_t *, size_t, size_t); #endif /* _ZFS_FREEBSD_CRYPTO_H */ diff --git a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h --- a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h +++ b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_znode_impl.h @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -118,7 +119,8 @@ #define Z_ISDIR(type) ((type) == VDIR) #define zn_has_cached_data(zp) vn_has_cached_data(ZTOV(zp)) -#define zn_rlimit_fsize(zp, uio, td) vn_rlimit_fsize(ZTOV(zp), (uio), (td)) +#define zn_rlimit_fsize(zp, uio) \ + vn_rlimit_fsize(ZTOV(zp), GET_UIO_STRUCT(uio), zfs_uio_td(uio)) /* Called on entry to each ZFS vnode and vfs operation */ #define ZFS_ENTER(zfsvfs) \ @@ -179,7 +181,6 @@ extern int zfs_znode_parent_and_name(struct znode *zp, struct znode **dzpp, char *buf); -extern void zfs_inode_update(struct znode *); #ifdef __cplusplus } #endif diff --git a/sys/contrib/openzfs/include/os/linux/spl/sys/uio.h b/sys/contrib/openzfs/include/os/linux/spl/sys/uio.h --- a/sys/contrib/openzfs/include/os/linux/spl/sys/uio.h +++ b/sys/contrib/openzfs/include/os/linux/spl/sys/uio.h @@ -36,21 +36,21 @@ typedef struct iovec iovec_t; -typedef enum uio_rw { +typedef enum zfs_uio_rw { UIO_READ = 0, UIO_WRITE = 1, -} uio_rw_t; +} zfs_uio_rw_t; -typedef enum uio_seg { +typedef enum zfs_uio_seg { UIO_USERSPACE = 0, UIO_SYSSPACE = 1, UIO_BVEC = 2, #if defined(HAVE_VFS_IOV_ITER) UIO_ITER = 3, #endif -} uio_seg_t; +} zfs_uio_seg_t; -typedef struct uio { +typedef struct zfs_uio { union { const struct iovec *uio_iov; const struct bio_vec *uio_bvec; @@ -60,42 +60,51 @@ }; int uio_iovcnt; offset_t uio_loffset; - uio_seg_t uio_segflg; + zfs_uio_seg_t uio_segflg; boolean_t uio_fault_disable; uint16_t uio_fmode; uint16_t uio_extflg; ssize_t uio_resid; size_t uio_skip; -} uio_t; +} zfs_uio_t; + +#define zfs_uio_segflg(u) (u)->uio_segflg +#define zfs_uio_offset(u) (u)->uio_loffset +#define zfs_uio_resid(u) (u)->uio_resid +#define zfs_uio_iovcnt(u) (u)->uio_iovcnt +#define zfs_uio_iovlen(u, idx) (u)->uio_iov[(idx)].iov_len +#define zfs_uio_iovbase(u, idx) (u)->uio_iov[(idx)].iov_base +#define zfs_uio_fault_disable(u, set) (u)->uio_fault_disable = set +#define zfs_uio_rlimit_fsize(z, u) (0) +#define zfs_uio_fault_move(p, n, rw, u) zfs_uiomove((p), (n), (rw), (u)) -#define uio_segflg(uio) (uio)->uio_segflg -#define uio_offset(uio) (uio)->uio_loffset -#define uio_resid(uio) (uio)->uio_resid -#define uio_iovcnt(uio) (uio)->uio_iovcnt -#define uio_iovlen(uio, idx) (uio)->uio_iov[(idx)].iov_len -#define uio_iovbase(uio, idx) (uio)->uio_iov[(idx)].iov_base -#define uio_fault_disable(uio, set) (uio)->uio_fault_disable = set +static inline void +zfs_uio_setoffset(zfs_uio_t *uio, offset_t off) +{ + uio->uio_loffset = off; +} static inline void -uio_iov_at_index(uio_t *uio, uint_t idx, void **base, uint64_t *len) +zfs_uio_iov_at_index(zfs_uio_t *uio, uint_t idx, void **base, uint64_t *len) { - *base = uio_iovbase(uio, idx); - *len = uio_iovlen(uio, idx); + *base = zfs_uio_iovbase(uio, idx); + *len = zfs_uio_iovlen(uio, idx); } static inline void -uio_advance(uio_t *uio, size_t size) +zfs_uio_advance(zfs_uio_t *uio, size_t size) { uio->uio_resid -= size; uio->uio_loffset += size; } static inline offset_t -uio_index_at_offset(uio_t *uio, offset_t off, uint_t *vec_idx) +zfs_uio_index_at_offset(zfs_uio_t *uio, offset_t off, uint_t *vec_idx) { *vec_idx = 0; - while (*vec_idx < uio_iovcnt(uio) && off >= uio_iovlen(uio, *vec_idx)) { - off -= uio_iovlen(uio, *vec_idx); + while (*vec_idx < zfs_uio_iovcnt(uio) && + off >= zfs_uio_iovlen(uio, *vec_idx)) { + off -= zfs_uio_iovlen(uio, *vec_idx); (*vec_idx)++; } @@ -103,21 +112,9 @@ } static inline void -iov_iter_init_compat(struct iov_iter *iter, unsigned int dir, - const struct iovec *iov, unsigned long nr_segs, size_t count) -{ -#if defined(HAVE_IOV_ITER_INIT) - iov_iter_init(iter, dir, iov, nr_segs, count); -#elif defined(HAVE_IOV_ITER_INIT_LEGACY) - iov_iter_init(iter, iov, nr_segs, count, 0); -#else -#error "Unsupported kernel" -#endif -} - -static inline void -uio_iovec_init(uio_t *uio, const struct iovec *iov, unsigned long nr_segs, - offset_t offset, uio_seg_t seg, ssize_t resid, size_t skip) +zfs_uio_iovec_init(zfs_uio_t *uio, const struct iovec *iov, + unsigned long nr_segs, offset_t offset, zfs_uio_seg_t seg, ssize_t resid, + size_t skip) { ASSERT(seg == UIO_USERSPACE || seg == UIO_SYSSPACE); @@ -133,7 +130,7 @@ } static inline void -uio_bvec_init(uio_t *uio, struct bio *bio) +zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio) { uio->uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)]; uio->uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio); @@ -148,7 +145,7 @@ #if defined(HAVE_VFS_IOV_ITER) static inline void -uio_iov_iter_init(uio_t *uio, struct iov_iter *iter, offset_t offset, +zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset, ssize_t resid, size_t skip) { uio->uio_iter = iter; diff --git a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vnops_os.h b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vnops_os.h --- a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vnops_os.h +++ b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vnops_os.h @@ -60,7 +60,7 @@ char *tnm, cred_t *cr, int flags); extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, znode_t **zpp, cred_t *cr, int flags); -extern int zfs_readlink(struct inode *ip, uio_t *uio, cred_t *cr); +extern int zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr); extern int zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr, int flags); extern void zfs_inactive(struct inode *ip); diff --git a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h --- a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h +++ b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_znode_impl.h @@ -70,8 +70,8 @@ #define Z_ISDEV(type) (S_ISCHR(type) || S_ISBLK(type) || S_ISFIFO(type)) #define Z_ISDIR(type) S_ISDIR(type) -#define zn_has_cached_data(zp) ((zp)->z_is_mapped) -#define zn_rlimit_fsize(zp, uio, td) (0) +#define zn_has_cached_data(zp) ((zp)->z_is_mapped) +#define zn_rlimit_fsize(zp, uio) (0) #define zhold(zp) igrab(ZTOI((zp))) #define zrele(zp) iput(ZTOI((zp))) @@ -158,7 +158,6 @@ extern int zfs_sync(struct super_block *, int, cred_t *); extern int zfs_inode_alloc(struct super_block *, struct inode **ip); extern void zfs_inode_destroy(struct inode *); -extern void zfs_inode_update(struct znode *); extern void zfs_mark_inode_dirty(struct inode *); extern boolean_t zfs_relatime_need_update(const struct inode *); diff --git a/sys/contrib/openzfs/include/sys/abd.h b/sys/contrib/openzfs/include/sys/abd.h --- a/sys/contrib/openzfs/include/sys/abd.h +++ b/sys/contrib/openzfs/include/sys/abd.h @@ -35,8 +35,48 @@ extern "C" { #endif -struct abd; /* forward declaration */ -typedef struct abd abd_t; +typedef enum abd_flags { + ABD_FLAG_LINEAR = 1 << 0, /* is buffer linear (or scattered)? */ + ABD_FLAG_OWNER = 1 << 1, /* does it own its data buffers? */ + ABD_FLAG_META = 1 << 2, /* does this represent FS metadata? */ + ABD_FLAG_MULTI_ZONE = 1 << 3, /* pages split over memory zones */ + ABD_FLAG_MULTI_CHUNK = 1 << 4, /* pages split over multiple chunks */ + ABD_FLAG_LINEAR_PAGE = 1 << 5, /* linear but allocd from page */ + ABD_FLAG_GANG = 1 << 6, /* mult ABDs chained together */ + ABD_FLAG_GANG_FREE = 1 << 7, /* gang ABD is responsible for mem */ + ABD_FLAG_ZEROS = 1 << 8, /* ABD for zero-filled buffer */ + ABD_FLAG_ALLOCD = 1 << 9, /* we allocated the abd_t */ +} abd_flags_t; + +typedef struct abd { + abd_flags_t abd_flags; + uint_t abd_size; /* excludes scattered abd_offset */ + list_node_t abd_gang_link; +#ifdef ZFS_DEBUG + struct abd *abd_parent; + zfs_refcount_t abd_children; +#endif + kmutex_t abd_mtx; + union { + struct abd_scatter { + uint_t abd_offset; +#if defined(__FreeBSD__) && defined(_KERNEL) + uint_t abd_chunk_size; + void *abd_chunks[1]; /* actually variable-length */ +#else + uint_t abd_nents; + struct scatterlist *abd_sgl; +#endif + } abd_scatter; + struct abd_linear { + void *abd_buf; + struct scatterlist *abd_sgl; /* for LINEAR_PAGE */ + } abd_linear; + struct abd_gang { + list_t abd_gang_chain; + } abd_gang; + } abd_u; +} abd_t; typedef int abd_iter_func_t(void *buf, size_t len, void *priv); typedef int abd_iter_func2_t(void *bufa, void *bufb, size_t len, void *priv); @@ -49,14 +89,14 @@ abd_t *abd_alloc(size_t, boolean_t); abd_t *abd_alloc_linear(size_t, boolean_t); -abd_t *abd_alloc_gang_abd(void); +abd_t *abd_alloc_gang(void); abd_t *abd_alloc_for_io(size_t, boolean_t); abd_t *abd_alloc_sametype(abd_t *, size_t); void abd_gang_add(abd_t *, abd_t *, boolean_t); void abd_free(abd_t *); -void abd_put(abd_t *); abd_t *abd_get_offset(abd_t *, size_t); abd_t *abd_get_offset_size(abd_t *, size_t, size_t); +abd_t *abd_get_offset_struct(abd_t *, abd_t *, size_t, size_t); abd_t *abd_get_zeros(size_t); abd_t *abd_get_from_buf(void *, size_t); void abd_cache_reap_now(void); @@ -87,7 +127,6 @@ int abd_cmp_buf_off(abd_t *, const void *, size_t, size_t); void abd_zero_off(abd_t *, size_t, size_t); void abd_verify(abd_t *); -uint_t abd_get_size(abd_t *); void abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd, ssize_t csize, ssize_t dsize, const unsigned parity, @@ -135,9 +174,29 @@ /* * ABD type check functions */ -boolean_t abd_is_linear(abd_t *); -boolean_t abd_is_gang(abd_t *); -boolean_t abd_is_linear_page(abd_t *); +static inline boolean_t +abd_is_linear(abd_t *abd) +{ + return ((abd->abd_flags & ABD_FLAG_LINEAR) ? B_TRUE : B_FALSE); +} + +static inline boolean_t +abd_is_linear_page(abd_t *abd) +{ + return ((abd->abd_flags & ABD_FLAG_LINEAR_PAGE) ? B_TRUE : B_FALSE); +} + +static inline boolean_t +abd_is_gang(abd_t *abd) +{ + return ((abd->abd_flags & ABD_FLAG_GANG) ? B_TRUE : B_FALSE); +} + +static inline uint_t +abd_get_size(abd_t *abd) +{ + return (abd->abd_size); +} /* * Module lifecycle diff --git a/sys/contrib/openzfs/include/sys/abd_impl.h b/sys/contrib/openzfs/include/sys/abd_impl.h --- a/sys/contrib/openzfs/include/sys/abd_impl.h +++ b/sys/contrib/openzfs/include/sys/abd_impl.h @@ -32,51 +32,11 @@ extern "C" { #endif -typedef enum abd_flags { - ABD_FLAG_LINEAR = 1 << 0, /* is buffer linear (or scattered)? */ - ABD_FLAG_OWNER = 1 << 1, /* does it own its data buffers? */ - ABD_FLAG_META = 1 << 2, /* does this represent FS metadata? */ - ABD_FLAG_MULTI_ZONE = 1 << 3, /* pages split over memory zones */ - ABD_FLAG_MULTI_CHUNK = 1 << 4, /* pages split over multiple chunks */ - ABD_FLAG_LINEAR_PAGE = 1 << 5, /* linear but allocd from page */ - ABD_FLAG_GANG = 1 << 6, /* mult ABDs chained together */ - ABD_FLAG_GANG_FREE = 1 << 7, /* gang ABD is responsible for mem */ - ABD_FLAG_ZEROS = 1 << 8, /* ABD for zero-filled buffer */ -} abd_flags_t; - typedef enum abd_stats_op { ABDSTAT_INCR, /* Increase abdstat values */ ABDSTAT_DECR /* Decrease abdstat values */ } abd_stats_op_t; -struct abd { - abd_flags_t abd_flags; - uint_t abd_size; /* excludes scattered abd_offset */ - list_node_t abd_gang_link; - struct abd *abd_parent; - zfs_refcount_t abd_children; - kmutex_t abd_mtx; - union { - struct abd_scatter { - uint_t abd_offset; -#if defined(__FreeBSD__) && defined(_KERNEL) - uint_t abd_chunk_size; - void *abd_chunks[]; -#else - uint_t abd_nents; - struct scatterlist *abd_sgl; -#endif - } abd_scatter; - struct abd_linear { - void *abd_buf; - struct scatterlist *abd_sgl; /* for LINEAR_PAGE */ - } abd_linear; - struct abd_gang { - list_t abd_gang_chain; - } abd_gang; - } abd_u; -}; - struct scatterlist; /* forward declaration */ struct abd_iter { @@ -95,14 +55,16 @@ extern abd_t *abd_zero_scatter; abd_t *abd_gang_get_offset(abd_t *, size_t *); +abd_t *abd_alloc_struct(size_t); +void abd_free_struct(abd_t *); /* * OS specific functions */ -abd_t *abd_alloc_struct(size_t); -abd_t *abd_get_offset_scatter(abd_t *, size_t); -void abd_free_struct(abd_t *); +abd_t *abd_alloc_struct_impl(size_t); +abd_t *abd_get_offset_scatter(abd_t *, abd_t *, size_t); +void abd_free_struct_impl(abd_t *); void abd_alloc_chunks(abd_t *, size_t); void abd_free_chunks(abd_t *); boolean_t abd_size_alloc_linear(size_t); diff --git a/sys/contrib/openzfs/include/sys/crypto/common.h b/sys/contrib/openzfs/include/sys/crypto/common.h --- a/sys/contrib/openzfs/include/sys/crypto/common.h +++ b/sys/contrib/openzfs/include/sys/crypto/common.h @@ -244,7 +244,7 @@ iovec_t cdu_raw; /* Pointer and length */ /* uio scatter-gather format */ - uio_t *cdu_uio; + zfs_uio_t *cdu_uio; } cdu; /* Crypto Data Union */ } crypto_data_t; diff --git a/sys/contrib/openzfs/include/sys/dmu.h b/sys/contrib/openzfs/include/sys/dmu.h --- a/sys/contrib/openzfs/include/sys/dmu.h +++ b/sys/contrib/openzfs/include/sys/dmu.h @@ -142,9 +142,6 @@ #define DMU_OT_IS_DDT(ot) \ ((ot) == DMU_OT_DDT_ZAP) -#define DMU_OT_IS_ZIL(ot) \ - ((ot) == DMU_OT_INTENT_LOG) - /* Note: ztest uses DMU_OT_UINT64_OTHER as a proxy for file blocks */ #define DMU_OT_IS_FILE(ot) \ ((ot) == DMU_OT_PLAIN_FILE_CONTENTS || (ot) == DMU_OT_UINT64_OTHER) @@ -847,14 +844,14 @@ void dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size, dmu_tx_t *tx); #ifdef _KERNEL -int dmu_read_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size); -int dmu_read_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size); -int dmu_read_uio_dnode(dnode_t *dn, struct uio *uio, uint64_t size); -int dmu_write_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size, +int dmu_read_uio(objset_t *os, uint64_t object, zfs_uio_t *uio, uint64_t size); +int dmu_read_uio_dbuf(dmu_buf_t *zdb, zfs_uio_t *uio, uint64_t size); +int dmu_read_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size); +int dmu_write_uio(objset_t *os, uint64_t object, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx); -int dmu_write_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size, +int dmu_write_uio_dbuf(dmu_buf_t *zdb, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx); -int dmu_write_uio_dnode(dnode_t *dn, struct uio *uio, uint64_t size, +int dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx); #endif struct arc_buf *dmu_request_arcbuf(dmu_buf_t *handle, int size); diff --git a/sys/contrib/openzfs/include/sys/fs/zfs.h b/sys/contrib/openzfs/include/sys/fs/zfs.h --- a/sys/contrib/openzfs/include/sys/fs/zfs.h +++ b/sys/contrib/openzfs/include/sys/fs/zfs.h @@ -1456,6 +1456,7 @@ #define ZPOOL_HIST_DSNAME "dsname" #define ZPOOL_HIST_DSID "dsid" #define ZPOOL_HIST_ERRNO "errno" +#define ZPOOL_HIST_ELAPSED_NS "elapsed_ns" /* * Special nvlist name that will not have its args recorded in the pool's diff --git a/sys/contrib/openzfs/include/sys/sa.h b/sys/contrib/openzfs/include/sys/sa.h --- a/sys/contrib/openzfs/include/sys/sa.h +++ b/sys/contrib/openzfs/include/sys/sa.h @@ -158,7 +158,7 @@ void sa_handle_unlock(sa_handle_t *); #ifdef _KERNEL -int sa_lookup_uio(sa_handle_t *, sa_attr_type_t, uio_t *); +int sa_lookup_uio(sa_handle_t *, sa_attr_type_t, zfs_uio_t *); int sa_add_projid(sa_handle_t *, dmu_tx_t *, uint64_t); #endif diff --git a/sys/contrib/openzfs/include/sys/spa.h b/sys/contrib/openzfs/include/sys/spa.h --- a/sys/contrib/openzfs/include/sys/spa.h +++ b/sys/contrib/openzfs/include/sys/spa.h @@ -1047,6 +1047,7 @@ extern boolean_t spa_deflate(spa_t *spa); extern metaslab_class_t *spa_normal_class(spa_t *spa); extern metaslab_class_t *spa_log_class(spa_t *spa); +extern metaslab_class_t *spa_embedded_log_class(spa_t *spa); extern metaslab_class_t *spa_special_class(spa_t *spa); extern metaslab_class_t *spa_dedup_class(spa_t *spa); extern metaslab_class_t *spa_preferred_class(spa_t *spa, uint64_t size, diff --git a/sys/contrib/openzfs/include/sys/spa_impl.h b/sys/contrib/openzfs/include/sys/spa_impl.h --- a/sys/contrib/openzfs/include/sys/spa_impl.h +++ b/sys/contrib/openzfs/include/sys/spa_impl.h @@ -226,6 +226,7 @@ boolean_t spa_is_exporting; /* true while exporting pool */ metaslab_class_t *spa_normal_class; /* normal data class */ metaslab_class_t *spa_log_class; /* intent log data class */ + metaslab_class_t *spa_embedded_log_class; /* log on normal vdevs */ metaslab_class_t *spa_special_class; /* special allocation class */ metaslab_class_t *spa_dedup_class; /* dedup allocation class */ uint64_t spa_first_txg; /* first txg after spa_open() */ diff --git a/sys/contrib/openzfs/include/sys/uio_impl.h b/sys/contrib/openzfs/include/sys/uio_impl.h --- a/sys/contrib/openzfs/include/sys/uio_impl.h +++ b/sys/contrib/openzfs/include/sys/uio_impl.h @@ -41,9 +41,9 @@ #include -extern int uiomove(void *, size_t, enum uio_rw, uio_t *); -extern int uio_prefaultpages(ssize_t, uio_t *); -extern int uiocopy(void *, size_t, enum uio_rw, uio_t *, size_t *); -extern void uioskip(uio_t *, size_t); +extern int zfs_uiomove(void *, size_t, zfs_uio_rw_t, zfs_uio_t *); +extern int zfs_uio_prefaultpages(ssize_t, zfs_uio_t *); +extern int zfs_uiocopy(void *, size_t, zfs_uio_rw_t, zfs_uio_t *, size_t *); +extern void zfs_uioskip(zfs_uio_t *, size_t); #endif /* _SYS_UIO_IMPL_H */ diff --git a/sys/contrib/openzfs/include/sys/vdev.h b/sys/contrib/openzfs/include/sys/vdev.h --- a/sys/contrib/openzfs/include/sys/vdev.h +++ b/sys/contrib/openzfs/include/sys/vdev.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -113,6 +114,9 @@ vdev_xlate_func_t *func, void *arg); extern void vdev_get_stats_ex(vdev_t *vd, vdev_stat_t *vs, vdev_stat_ex_t *vsx); + +extern metaslab_group_t *vdev_get_mg(vdev_t *vd, metaslab_class_t *mc); + extern void vdev_get_stats(vdev_t *vd, vdev_stat_t *vs); extern void vdev_clear_stats(vdev_t *vd); extern void vdev_stat_update(zio_t *zio, uint64_t psize); diff --git a/sys/contrib/openzfs/include/sys/vdev_impl.h b/sys/contrib/openzfs/include/sys/vdev_impl.h --- a/sys/contrib/openzfs/include/sys/vdev_impl.h +++ b/sys/contrib/openzfs/include/sys/vdev_impl.h @@ -269,8 +269,11 @@ boolean_t vdev_expanding; /* expand the vdev? */ boolean_t vdev_reopening; /* reopen in progress? */ boolean_t vdev_nonrot; /* true if solid state */ + int vdev_load_error; /* error on last load */ int vdev_open_error; /* error on last open */ + int vdev_validate_error; /* error on last validate */ kthread_t *vdev_open_thread; /* thread opening children */ + kthread_t *vdev_validate_thread; /* thread validating children */ uint64_t vdev_crtxg; /* txg when top-level was added */ /* @@ -280,6 +283,7 @@ uint64_t vdev_ms_shift; /* metaslab size shift */ uint64_t vdev_ms_count; /* number of metaslabs */ metaslab_group_t *vdev_mg; /* metaslab group */ + metaslab_group_t *vdev_log_mg; /* embedded slog metaslab group */ metaslab_t **vdev_ms; /* metaslab array */ uint64_t vdev_pending_fastwrite; /* allocated fastwrites */ txg_list_t vdev_ms_list; /* per-txg dirty metaslab lists */ @@ -636,6 +640,7 @@ * Other miscellaneous functions */ int vdev_checkpoint_sm_object(vdev_t *vd, uint64_t *sm_obj); +void vdev_metaslab_group_create(vdev_t *vd); /* * Vdev ashift optimization tunables diff --git a/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h b/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h --- a/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h +++ b/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h @@ -106,6 +106,7 @@ uint64_t rc_devidx; /* child device index for I/O */ uint64_t rc_offset; /* device offset */ uint64_t rc_size; /* I/O size */ + abd_t rc_abdstruct; /* rc_abd probably points here */ abd_t *rc_abd; /* I/O data */ void *rc_orig_data; /* pre-reconstruction */ abd_t *rc_gdata; /* used to store the "good" version */ diff --git a/sys/contrib/openzfs/include/sys/zfs_debug.h b/sys/contrib/openzfs/include/sys/zfs_debug.h --- a/sys/contrib/openzfs/include/sys/zfs_debug.h +++ b/sys/contrib/openzfs/include/sys/zfs_debug.h @@ -56,6 +56,7 @@ #define ZFS_DEBUG_INDIRECT_REMAP (1 << 10) #define ZFS_DEBUG_TRIM (1 << 11) #define ZFS_DEBUG_LOG_SPACEMAP (1 << 12) +#define ZFS_DEBUG_METASLAB_ALLOC (1 << 13) extern void __set_error(const char *file, const char *func, int line, int err); extern void __zfs_dbgmsg(char *buf); diff --git a/sys/contrib/openzfs/include/sys/zfs_sa.h b/sys/contrib/openzfs/include/sys/zfs_sa.h --- a/sys/contrib/openzfs/include/sys/zfs_sa.h +++ b/sys/contrib/openzfs/include/sys/zfs_sa.h @@ -134,7 +134,7 @@ #define DXATTR_MAX_ENTRY_SIZE (32768) #define DXATTR_MAX_SA_SIZE (SPA_OLD_MAXBLOCKSIZE >> 1) -int zfs_sa_readlink(struct znode *, uio_t *); +int zfs_sa_readlink(struct znode *, zfs_uio_t *); void zfs_sa_symlink(struct znode *, char *link, int len, dmu_tx_t *); void zfs_sa_get_scanstamp(struct znode *, xvattr_t *); void zfs_sa_set_scanstamp(struct znode *, xvattr_t *, dmu_tx_t *); diff --git a/sys/contrib/openzfs/include/sys/zfs_vnops.h b/sys/contrib/openzfs/include/sys/zfs_vnops.h --- a/sys/contrib/openzfs/include/sys/zfs_vnops.h +++ b/sys/contrib/openzfs/include/sys/zfs_vnops.h @@ -27,16 +27,16 @@ #include extern int zfs_fsync(znode_t *, int, cred_t *); -extern int zfs_read(znode_t *, uio_t *, int, cred_t *); -extern int zfs_write(znode_t *, uio_t *, int, cred_t *); +extern int zfs_read(znode_t *, zfs_uio_t *, int, cred_t *); +extern int zfs_write(znode_t *, zfs_uio_t *, int, cred_t *); extern int zfs_holey(znode_t *, ulong_t, loff_t *); extern int zfs_access(znode_t *, int, int, cred_t *); extern int zfs_getsecattr(znode_t *, vsecattr_t *, int, cred_t *); extern int zfs_setsecattr(znode_t *, vsecattr_t *, int, cred_t *); -extern int mappedread(znode_t *, int, uio_t *); -extern int mappedread_sf(znode_t *, int, uio_t *); +extern int mappedread(znode_t *, int, zfs_uio_t *); +extern int mappedread_sf(znode_t *, int, zfs_uio_t *); extern void update_pages(znode_t *, int64_t, int, objset_t *); /* diff --git a/sys/contrib/openzfs/include/sys/zfs_znode.h b/sys/contrib/openzfs/include/sys/zfs_znode.h --- a/sys/contrib/openzfs/include/sys/zfs_znode.h +++ b/sys/contrib/openzfs/include/sys/zfs_znode.h @@ -287,6 +287,8 @@ extern void zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx); extern void zfs_upgrade(zfsvfs_t *zfsvfs, dmu_tx_t *tx); +extern void zfs_znode_update_vfs(struct znode *); + #endif #ifdef __cplusplus } diff --git a/sys/contrib/openzfs/lib/Makefile.am b/sys/contrib/openzfs/lib/Makefile.am --- a/sys/contrib/openzfs/lib/Makefile.am +++ b/sys/contrib/openzfs/lib/Makefile.am @@ -1,9 +1,12 @@ # NB: GNU Automake Manual, Chapter 8.3.5: Libtool Convenience Libraries # These nine libraries are intermediary build components. SUBDIRS = libavl libicp libshare libspl libtpool libzstd +CPPCHECKDIRS = libavl libicp libnvpair libshare libspl libtpool libunicode +CPPCHECKDIRS += libuutil libzfs libzfs_core libzfsbootenv libzpool libzutil if BUILD_LINUX SUBDIRS += libefi +CPPCHECKDIRS += libefi endif # libnvpair is installed as part of the final build product @@ -23,7 +26,7 @@ # is only linked against by ztest and zdb and no stable ABI is provided. ABILIBS = libnvpair libuutil libzfs_core libzfs libzfsbootenv -PHONY = checkabi storeabi +PHONY = checkabi storeabi cppcheck checkabi: $(ABILIBS) set -e ; for dir in $(ABILIBS) ; do \ $(MAKE) -C $$dir checkabi ; \ @@ -33,3 +36,8 @@ set -e ; for dir in $(ABILIBS) ; do \ $(MAKE) -C $$dir storeabi ; \ done + +cppcheck: $(CPPCHECKDIRS) + set -e ; for dir in $(CPPCHECKDIRS) ; do \ + $(MAKE) -C $$dir cppcheck ; \ + done diff --git a/sys/contrib/openzfs/lib/libavl/Makefile.am b/sys/contrib/openzfs/lib/libavl/Makefile.am --- a/sys/contrib/openzfs/lib/libavl/Makefile.am +++ b/sys/contrib/openzfs/lib/libavl/Makefile.am @@ -12,3 +12,5 @@ nodist_libavl_la_SOURCES = \ $(KERNEL_C) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libefi/Makefile.am b/sys/contrib/openzfs/lib/libefi/Makefile.am --- a/sys/contrib/openzfs/lib/libefi/Makefile.am +++ b/sys/contrib/openzfs/lib/libefi/Makefile.am @@ -10,3 +10,5 @@ libefi_la_SOURCES = $(USER_C) libefi_la_LIBADD = $(LIBUUID_LIBS) $(ZLIB_LIBS) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libefi/rdwr_efi.c b/sys/contrib/openzfs/lib/libefi/rdwr_efi.c --- a/sys/contrib/openzfs/lib/libefi/rdwr_efi.c +++ b/sys/contrib/openzfs/lib/libefi/rdwr_efi.c @@ -468,6 +468,7 @@ (int) sizeof (struct dk_part) * (vptr->efi_nparts - 1); nparts = vptr->efi_nparts; if ((tmp = realloc(vptr, length)) == NULL) { + /* cppcheck-suppress doubleFree */ free(vptr); *vtoc = NULL; return (VT_ERROR); diff --git a/sys/contrib/openzfs/lib/libicp/Makefile.am b/sys/contrib/openzfs/lib/libicp/Makefile.am --- a/sys/contrib/openzfs/lib/libicp/Makefile.am +++ b/sys/contrib/openzfs/lib/libicp/Makefile.am @@ -71,3 +71,5 @@ nodist_libicp_la_SOURCES = \ $(KERNEL_C) \ $(KERNEL_ASM) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libnvpair/Makefile.am b/sys/contrib/openzfs/lib/libnvpair/Makefile.am --- a/sys/contrib/openzfs/lib/libnvpair/Makefile.am +++ b/sys/contrib/openzfs/lib/libnvpair/Makefile.am @@ -1,5 +1,4 @@ include $(top_srcdir)/config/Rules.am -PHONY = VPATH = \ $(top_srcdir)/module/nvpair \ @@ -42,5 +41,7 @@ libnvpair_la_LDFLAGS += -version-info 3:0:0 +include $(top_srcdir)/config/CppCheck.am + # Library ABI EXTRA_DIST = libnvpair.abi libnvpair.suppr diff --git a/sys/contrib/openzfs/lib/libshare/Makefile.am b/sys/contrib/openzfs/lib/libshare/Makefile.am --- a/sys/contrib/openzfs/lib/libshare/Makefile.am +++ b/sys/contrib/openzfs/lib/libshare/Makefile.am @@ -23,3 +23,5 @@ endif libshare_la_SOURCES = $(USER_C) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libspl/Makefile.am b/sys/contrib/openzfs/lib/libspl/Makefile.am --- a/sys/contrib/openzfs/lib/libspl/Makefile.am +++ b/sys/contrib/openzfs/lib/libspl/Makefile.am @@ -55,3 +55,12 @@ libspl_assert.la libspl_la_LIBADD += $(LIBCLOCK_GETTIME) + +include $(top_srcdir)/config/CppCheck.am + +# Override the default SOURCES which includes TARGET_CPU_ATOMIC_SOURCE +# in order to always evaluate the generic asm-generic/atomic.c source. +CPPCHECKSRC = $(USER_C) asm-generic/atomic.c +cppcheck: + $(CPPCHECK) -j$(CPU_COUNT) $(CPPCHECKFLAGS) --force \ + $(DEFAULT_INCLUDES) $(CPPCHECKSRC) diff --git a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/Makefile.am b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/Makefile.am --- a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/Makefile.am +++ b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/Makefile.am @@ -1 +1,5 @@ SUBDIRS = sys + +libspldir = $(includedir)/libspl +libspl_HEADERS = \ + fcntl.h diff --git a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/fcntl.h b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/fcntl.h new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/fcntl.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 iXsystems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LIBSPL_FCNTL_H_ +#define _LIBSPL_FCNTL_H_ + +#include_next + +#include + +#endif /* _LIBSPL_FCNTL_H_ */ diff --git a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/Makefile.am b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/Makefile.am --- a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/Makefile.am +++ b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/Makefile.am @@ -1,6 +1,7 @@ libspldir = $(includedir)/libspl/sys libspl_HEADERS = \ byteorder.h \ + fcntl.h \ file.h \ mnttab.h \ mount.h \ diff --git a/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/fcntl.h b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/fcntl.h new file mode 100644 --- /dev/null +++ b/sys/contrib/openzfs/lib/libspl/include/os/freebsd/sys/fcntl.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 iXsystems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LIBSPL_SYS_FCNTL_H_ +#define _LIBSPL_SYS_FCNTL_H_ + +#include_next + +#define O_LARGEFILE 0 +#define O_RSYNC 0 + +#ifndef O_DSYNC +#define O_DSYNC 0 +#endif + +#endif /* _LIBSPL_SYS_FCNTL_H_ */ diff --git a/sys/contrib/openzfs/lib/libspl/include/sys/uio.h b/sys/contrib/openzfs/lib/libspl/include/sys/uio.h --- a/sys/contrib/openzfs/lib/libspl/include/sys/uio.h +++ b/sys/contrib/openzfs/lib/libspl/include/sys/uio.h @@ -51,58 +51,58 @@ typedef struct iovec iovec_t; #if defined(__linux__) || defined(__APPLE__) -typedef enum uio_rw { +typedef enum zfs_uio_rw { UIO_READ = 0, UIO_WRITE = 1, -} uio_rw_t; +} zfs_uio_rw_t; -typedef enum uio_seg { +typedef enum zfs_uio_seg { UIO_USERSPACE = 0, UIO_SYSSPACE = 1, -} uio_seg_t; +} zfs_uio_seg_t; #elif defined(__FreeBSD__) -typedef enum uio_seg uio_seg_t; +typedef enum uio_seg zfs_uio_seg_t; #endif -typedef struct uio { +typedef struct zfs_uio { struct iovec *uio_iov; /* pointer to array of iovecs */ int uio_iovcnt; /* number of iovecs */ offset_t uio_loffset; /* file offset */ - uio_seg_t uio_segflg; /* address space (kernel or user) */ + zfs_uio_seg_t uio_segflg; /* address space (kernel or user) */ uint16_t uio_fmode; /* file mode flags */ uint16_t uio_extflg; /* extended flags */ ssize_t uio_resid; /* residual count */ -} uio_t; +} zfs_uio_t; -#define uio_segflg(uio) (uio)->uio_segflg -#define uio_offset(uio) (uio)->uio_loffset -#define uio_resid(uio) (uio)->uio_resid -#define uio_iovcnt(uio) (uio)->uio_iovcnt -#define uio_iovlen(uio, idx) (uio)->uio_iov[(idx)].iov_len -#define uio_iovbase(uio, idx) (uio)->uio_iov[(idx)].iov_base +#define zfs_uio_segflg(uio) (uio)->uio_segflg +#define zfs_uio_offset(uio) (uio)->uio_loffset +#define zfs_uio_resid(uio) (uio)->uio_resid +#define zfs_uio_iovcnt(uio) (uio)->uio_iovcnt +#define zfs_uio_iovlen(uio, idx) (uio)->uio_iov[(idx)].iov_len +#define zfs_uio_iovbase(uio, idx) (uio)->uio_iov[(idx)].iov_base static inline void -uio_iov_at_index(uio_t *uio, uint_t idx, void **base, uint64_t *len) +zfs_uio_iov_at_index(zfs_uio_t *uio, uint_t idx, void **base, uint64_t *len) { - *base = uio_iovbase(uio, idx); - *len = uio_iovlen(uio, idx); + *base = zfs_uio_iovbase(uio, idx); + *len = zfs_uio_iovlen(uio, idx); } static inline void -uio_advance(uio_t *uio, size_t size) +zfs_uio_advance(zfs_uio_t *uio, size_t size) { uio->uio_resid -= size; uio->uio_loffset += size; } static inline offset_t -uio_index_at_offset(uio_t *uio, offset_t off, uint_t *vec_idx) +zfs_uio_index_at_offset(zfs_uio_t *uio, offset_t off, uint_t *vec_idx) { *vec_idx = 0; - while (*vec_idx < (uint_t)uio_iovcnt(uio) && - off >= (offset_t)uio_iovlen(uio, *vec_idx)) { - off -= uio_iovlen(uio, *vec_idx); + while (*vec_idx < (uint_t)zfs_uio_iovcnt(uio) && + off >= (offset_t)zfs_uio_iovlen(uio, *vec_idx)) { + off -= zfs_uio_iovlen(uio, *vec_idx); (*vec_idx)++; } diff --git a/sys/contrib/openzfs/lib/libtpool/Makefile.am b/sys/contrib/openzfs/lib/libtpool/Makefile.am --- a/sys/contrib/openzfs/lib/libtpool/Makefile.am +++ b/sys/contrib/openzfs/lib/libtpool/Makefile.am @@ -7,3 +7,5 @@ thread_pool_impl.h libtpool_la_SOURCES = $(USER_C) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libunicode/Makefile.am b/sys/contrib/openzfs/lib/libunicode/Makefile.am --- a/sys/contrib/openzfs/lib/libunicode/Makefile.am +++ b/sys/contrib/openzfs/lib/libunicode/Makefile.am @@ -13,3 +13,5 @@ nodist_libunicode_la_SOURCES = \ $(KERNEL_C) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libuutil/Makefile.am b/sys/contrib/openzfs/lib/libuutil/Makefile.am --- a/sys/contrib/openzfs/lib/libuutil/Makefile.am +++ b/sys/contrib/openzfs/lib/libuutil/Makefile.am @@ -1,5 +1,4 @@ include $(top_srcdir)/config/Rules.am -PHONY = lib_LTLIBRARIES = libuutil.la @@ -32,5 +31,7 @@ libuutil_la_LDFLAGS += -version-info 3:0:0 +include $(top_srcdir)/config/CppCheck.am + # Library ABI EXTRA_DIST = libuutil.abi libuutil.suppr diff --git a/sys/contrib/openzfs/lib/libuutil/uu_avl.c b/sys/contrib/openzfs/lib/libuutil/uu_avl.c --- a/sys/contrib/openzfs/lib/libuutil/uu_avl.c +++ b/sys/contrib/openzfs/lib/libuutil/uu_avl.c @@ -128,6 +128,7 @@ pp->uap_next->uap_prev = pp->uap_prev; pp->uap_prev->uap_next = pp->uap_next; (void) pthread_mutex_unlock(&uu_apool_list_lock); + (void) pthread_mutex_destroy(&pp->uap_lock); pp->uap_prev = NULL; pp->uap_next = NULL; uu_free(pp); diff --git a/sys/contrib/openzfs/lib/libzfs/Makefile.am b/sys/contrib/openzfs/lib/libzfs/Makefile.am --- a/sys/contrib/openzfs/lib/libzfs/Makefile.am +++ b/sys/contrib/openzfs/lib/libzfs/Makefile.am @@ -1,5 +1,4 @@ include $(top_srcdir)/config/Rules.am -PHONY = VPATH = \ $(top_srcdir)/module/icp \ @@ -90,6 +89,8 @@ libzfs_la_LDFLAGS += -version-info 4:0:0 +include $(top_srcdir)/config/CppCheck.am + # Library ABI EXTRA_DIST = libzfs.abi libzfs.suppr diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_import.c b/sys/contrib/openzfs/lib/libzfs/libzfs_import.c --- a/sys/contrib/openzfs/lib/libzfs/libzfs_import.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_import.c @@ -77,7 +77,7 @@ if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0) return (NULL); - dstbuf_size = MAX(CONFIG_BUF_MINSIZE, zc.zc_nvlist_conf_size * 4); + dstbuf_size = MAX(CONFIG_BUF_MINSIZE, zc.zc_nvlist_conf_size * 32); if (zcmd_alloc_dst_nvlist(hdl, &zc, dstbuf_size) != 0) { zcmd_free_nvlists(&zc); diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c --- a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c @@ -1188,6 +1188,30 @@ return (B_FALSE); } +/* + * Check if vdev list contains a dRAID vdev + */ +static boolean_t +zpool_has_draid_vdev(nvlist_t *nvroot) +{ + nvlist_t **child; + uint_t children; + + if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, + &child, &children) == 0) { + for (uint_t c = 0; c < children; c++) { + char *type; + + if (nvlist_lookup_string(child[c], + ZPOOL_CONFIG_TYPE, &type) == 0 && + strcmp(type, VDEV_TYPE_DRAID) == 0) { + return (B_TRUE); + } + } + } + return (B_FALSE); +} + /* * Output a dRAID top-level vdev name in to the provided buffer. */ @@ -1373,6 +1397,17 @@ "one or more devices is out of space")); return (zfs_error(hdl, EZFS_BADDEV, msg)); + case EINVAL: + if (zpool_has_draid_vdev(nvroot) && + zfeature_lookup_name("draid", NULL) != 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "dRAID vdevs are unsupported by the " + "kernel")); + return (zfs_error(hdl, EZFS_BADDEV, msg)); + } else { + return (zpool_standard_error(hdl, errno, msg)); + } + default: return (zpool_standard_error(hdl, errno, msg)); } @@ -1528,9 +1563,19 @@ break; case EINVAL: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "invalid config; a pool with removing/removed " - "vdevs does not support adding raidz vdevs")); + + if (zpool_has_draid_vdev(nvroot) && + zfeature_lookup_name("draid", NULL) != 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "dRAID vdevs are unsupported by the " + "kernel")); + } else { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "invalid config; a pool with removing/" + "removed vdevs does not support adding " + "raidz or dRAID vdevs")); + } + (void) zfs_error(hdl, EZFS_BADDEV, msg); break; diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c --- a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c @@ -186,15 +186,15 @@ nvlist_t *nvfs, *snaps; nvpair_t *snapelem = NULL; - VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs)); - VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps)); + nvfs = fnvpair_value_nvlist(fselem); + snaps = fnvlist_lookup_nvlist(nvfs, "snaps"); while ((snapelem = nvlist_next_nvpair(snaps, snapelem)) != NULL) { fsavl_node_t *fn; uint64_t guid; - VERIFY(0 == nvpair_value_uint64(snapelem, &guid)); + guid = fnvpair_value_uint64(snapelem); if ((fn = malloc(sizeof (fsavl_node_t))) == NULL) { fsavl_destroy(fsavl); return (NULL); @@ -311,7 +311,7 @@ return (0); } - VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid)); + fnvlist_add_uint64(sd->parent_snaps, snapname, guid); /* * NB: if there is no fromsnap here (it's a newly created fs in * an incremental replication), we will substitute the tosnap. @@ -336,16 +336,15 @@ sd->seento = B_TRUE; } - VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0)); + nv = fnvlist_alloc(); send_iterate_prop(zhp, sd->backup, nv); - VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, nv)); - nvlist_free(nv); + 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) { - VERIFY(0 == nvlist_add_nvlist(sd->snapholds, - snapname, holds)); + fnvlist_add_nvlist(sd->snapholds, snapname, holds); } fnvlist_free(holds); } @@ -420,14 +419,12 @@ if (zfs_prop_user(propname) || zfs_prop_get_type(prop) == PROP_TYPE_STRING) { char *value; - verify(nvlist_lookup_string(propnv, - ZPROP_VALUE, &value) == 0); - VERIFY(0 == nvlist_add_string(nv, propname, value)); + value = fnvlist_lookup_string(propnv, ZPROP_VALUE); + fnvlist_add_string(nv, propname, value); } else { uint64_t value; - verify(nvlist_lookup_uint64(propnv, - ZPROP_VALUE, &value) == 0); - VERIFY(0 == nvlist_add_uint64(nv, propname, value)); + value = fnvlist_lookup_uint64(propnv, ZPROP_VALUE); + fnvlist_add_uint64(nv, propname, value); } } } @@ -572,8 +569,7 @@ sd->parent_snaps = fnvlist_alloc(); sd->snapprops = fnvlist_alloc(); if (sd->holds) - VERIFY(0 == nvlist_alloc(&sd->snapholds, NV_UNIQUE_NAME, 0)); - + sd->snapholds = fnvlist_alloc(); /* * If this is a "doall" send, a replicate send or we're just trying @@ -656,7 +652,7 @@ if (zhp == NULL) return (EZFS_BADTYPE); - VERIFY(0 == nvlist_alloc(&sd.fss, NV_UNIQUE_NAME, 0)); + sd.fss = fnvlist_alloc(); sd.fsname = fsname; sd.fromsnap = fromsnap; sd.tosnap = tosnap; @@ -670,7 +666,7 @@ sd.props = props; if ((error = send_iterate_fs(zhp, &sd)) != 0) { - nvlist_free(sd.fss); + fnvlist_free(sd.fss); if (avlp != NULL) *avlp = NULL; *nvlp = NULL; @@ -678,7 +674,7 @@ } if (avlp != NULL && (*avlp = fsavl_create(sd.fss)) == NULL) { - nvlist_free(sd.fss); + fnvlist_free(sd.fss); *nvlp = NULL; return (EZFS_NOMEM); } @@ -789,10 +785,9 @@ zc.zc_fromobj = fromsnap_obj; zc.zc_flags = flags; - VERIFY(0 == nvlist_alloc(&thisdbg, NV_UNIQUE_NAME, 0)); + thisdbg = fnvlist_alloc(); if (fromsnap && fromsnap[0] != '\0') { - VERIFY(0 == nvlist_add_string(thisdbg, - "fromsnap", fromsnap)); + fnvlist_add_string(thisdbg, "fromsnap", fromsnap); } if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) { @@ -800,12 +795,11 @@ (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "warning: cannot send '%s'"), zhp->zfs_name); - VERIFY(0 == nvlist_add_uint64(thisdbg, "error", errno)); + fnvlist_add_uint64(thisdbg, "error", errno); if (debugnv) { - VERIFY(0 == nvlist_add_nvlist(debugnv, - zhp->zfs_name, thisdbg)); + fnvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg); } - nvlist_free(thisdbg); + fnvlist_free(thisdbg); switch (errno) { case EXDEV: @@ -847,8 +841,8 @@ } if (debugnv) - VERIFY(0 == nvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg)); - nvlist_free(thisdbg); + fnvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg); + fnvlist_free(thisdbg); return (0); } @@ -1047,10 +1041,8 @@ nvlist_t *nvfs = fsavl_find(sdd->fsavl, zhp->zfs_dmustats.dds_guid, &snapname); - VERIFY(0 == nvlist_lookup_nvlist(nvfs, - "snapprops", &snapprops)); - VERIFY(0 == nvlist_lookup_nvlist(snapprops, - thissnap, &snapprops)); + snapprops = fnvlist_lookup_nvlist(nvfs, "snapprops"); + snapprops = fnvlist_lookup_nvlist(snapprops, thissnap); exclude = !nvlist_exists(snapprops, "is_clone_origin"); } else { exclude = B_TRUE; @@ -1269,7 +1261,7 @@ nvlist_t *nvfs; uint64_t origin_guid = 0; - VERIFY(0 == nvpair_value_nvlist(fspair, &nvfs)); + nvfs = fnvpair_value_nvlist(fspair); (void) nvlist_lookup_uint64(nvfs, "origin", &origin_guid); if (origin_guid != 0) { char *snapname; @@ -1277,12 +1269,12 @@ origin_guid, &snapname); if (origin_nv != NULL) { nvlist_t *snapprops; - VERIFY(0 == nvlist_lookup_nvlist(origin_nv, - "snapprops", &snapprops)); - VERIFY(0 == nvlist_lookup_nvlist(snapprops, - snapname, &snapprops)); - VERIFY(0 == nvlist_add_boolean( - snapprops, "is_clone_origin")); + snapprops = fnvlist_lookup_nvlist(origin_nv, + "snapprops"); + snapprops = fnvlist_lookup_nvlist(snapprops, + snapname); + fnvlist_add_boolean(snapprops, + "is_clone_origin"); } } } @@ -1297,11 +1289,11 @@ uint64_t origin_guid = 0; uint64_t parent_guid = 0; - VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0); + fslist = fnvpair_value_nvlist(fspair); if (nvlist_lookup_boolean(fslist, "sent") == 0) continue; - VERIFY(nvlist_lookup_string(fslist, "name", &fsname) == 0); + fsname = fnvlist_lookup_string(fslist, "name"); (void) nvlist_lookup_uint64(fslist, "origin", &origin_guid); (void) nvlist_lookup_uint64(fslist, "parentfromsnap", &parent_guid); @@ -1333,7 +1325,7 @@ if (zhp == NULL) return (-1); err = dump_filesystem(zhp, sdd); - VERIFY(nvlist_add_boolean(fslist, "sent") == 0); + fnvlist_add_boolean(fslist, "sent"); progress = B_TRUE; zfs_close(zhp); if (err) @@ -1349,7 +1341,7 @@ fspair = nvlist_next_nvpair(sdd->fss, fspair)) { nvlist_t *fslist; - VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0); + fslist = fnvpair_value_nvlist(fspair); (void) nvlist_remove_all(fslist, "sent"); } @@ -1560,7 +1552,7 @@ fnvlist_add_boolean(props, "redact_complete"); fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS)); error = lzc_get_bookmarks(path, props, &bmarks); - nvlist_free(props); + fnvlist_free(props); if (error != 0) { if (error == ESRCH) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -1850,7 +1842,7 @@ } ret = zfs_send_resume_impl(hdl, flags, outfd, resume_nvl); - nvlist_free(resume_nvl); + fnvlist_free(resume_nvl); return (ret); } @@ -1940,8 +1932,8 @@ ret = zfs_send_resume_impl(hdl, flags, outfd, saved_nvl); out: - nvlist_free(saved_nvl); - nvlist_free(resume_nvl); + fnvlist_free(saved_nvl); + fnvlist_free(resume_nvl); return (ret); } @@ -2018,7 +2010,7 @@ fnvlist_add_boolean(hdrnv, "not_recursive"); if (raw) { - VERIFY0(nvlist_add_boolean(hdrnv, "raw")); + fnvlist_add_boolean(hdrnv, "raw"); } if ((err = gather_nvlist(zhp->zfs_hdl, tofs, @@ -2048,9 +2040,9 @@ if (fssp != NULL) { *fssp = fss; } else { - nvlist_free(fss); + fnvlist_free(fss); } - nvlist_free(hdrnv); + fnvlist_free(hdrnv); } if (!dryrun) { @@ -2267,7 +2259,7 @@ err = dump_filesystems(zhp, &sdd); fsavl_destroy(fsavl); - nvlist_free(fss); + fnvlist_free(fss); /* Ensure no snaps found is treated as an error. */ if (err == 0 && !sdd.seento) @@ -2296,7 +2288,7 @@ err = zfs_standard_error(zhp->zfs_hdl, err, errbuf); err_out: fsavl_destroy(fsavl); - nvlist_free(fss); + fnvlist_free(fss); fnvlist_free(sdd.snapholds); if (sdd.cleanup_fd != -1) @@ -3041,14 +3033,14 @@ return (1); nvfs = fsavl_find(avl, guid1, &snapname); - VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); + fsname = fnvlist_lookup_string(nvfs, "name"); (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); guid1hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); if (guid1hdl == NULL) return (-1); nvfs = fsavl_find(avl, guid2, &snapname); - VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); + fsname = fnvlist_lookup_string(nvfs, "name"); (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); guid2hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); if (guid2hdl == NULL) { @@ -3086,7 +3078,7 @@ nvpair_t *fselem = NULL; nvlist_t *stream_fss; - VERIFY(0 == nvlist_lookup_nvlist(stream_nv, "fss", &stream_fss)); + stream_fss = fnvlist_lookup_nvlist(stream_nv, "fss"); while ((fselem = nvlist_next_nvpair(stream_fss, fselem)) != NULL) { zfs_handle_t *zhp = NULL; @@ -3100,9 +3092,9 @@ char fsname[ZFS_MAX_DATASET_NAME_LEN]; keylocation[0] = '\0'; - VERIFY(0 == nvpair_value_nvlist(fselem, &stream_nvfs)); - VERIFY(0 == nvlist_lookup_nvlist(stream_nvfs, "snaps", &snaps)); - VERIFY(0 == nvlist_lookup_nvlist(stream_nvfs, "props", &props)); + stream_nvfs = fnvpair_value_nvlist(fselem); + snaps = fnvlist_lookup_nvlist(stream_nvfs, "snaps"); + props = fnvlist_lookup_nvlist(stream_nvfs, "props"); stream_encroot = nvlist_exists(stream_nvfs, "is_encroot"); /* find a snapshot from the stream that exists locally */ @@ -3110,7 +3102,7 @@ while ((snapel = nvlist_next_nvpair(snaps, snapel)) != NULL) { uint64_t guid; - VERIFY(0 == nvpair_value_uint64(snapel, &guid)); + guid = fnvpair_value_uint64(snapel); err = guid_to_name(hdl, top_zfs, guid, B_FALSE, fsname); if (err == 0) @@ -3155,9 +3147,8 @@ } } - VERIFY(0 == nvlist_lookup_string(props, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), - &stream_keylocation)); + stream_keylocation = fnvlist_lookup_string(props, + zfs_prop_to_name(ZFS_PROP_KEYLOCATION)); /* * Refresh the properties in case the call to @@ -3223,7 +3214,7 @@ boolean_t needagain, progress, recursive; char *s1, *s2; - VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap)); + fromsnap = fnvlist_lookup_string(stream_nv, "fromsnap"); recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") == ENOENT); @@ -3234,7 +3225,7 @@ again: needagain = progress = B_FALSE; - VERIFY(0 == nvlist_alloc(&deleted, NV_UNIQUE_NAME, 0)); + deleted = fnvlist_alloc(); if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL, recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, @@ -3257,11 +3248,11 @@ nextfselem = nvlist_next_nvpair(local_nv, fselem); - VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs)); - VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps)); - VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); - VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap", - &parent_fromsnap_guid)); + nvfs = fnvpair_value_nvlist(fselem); + snaps = fnvlist_lookup_nvlist(nvfs, "snaps"); + fsname = fnvlist_lookup_string(nvfs, "name"); + parent_fromsnap_guid = fnvlist_lookup_uint64(nvfs, + "parentfromsnap"); (void) nvlist_lookup_uint64(nvfs, "origin", &originguid); /* @@ -3272,7 +3263,7 @@ snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) { uint64_t thisguid; - VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid)); + thisguid = fnvpair_value_uint64(snapelem); stream_nvfs = fsavl_find(stream_avl, thisguid, NULL); if (stream_nvfs != NULL) @@ -3292,8 +3283,8 @@ origin_nvfs = fsavl_find(local_avl, originguid, NULL); - VERIFY(0 == nvlist_lookup_string(origin_nvfs, - "name", &origin_fsname)); + origin_fsname = fnvlist_lookup_string( + origin_nvfs, "name"); error = recv_promote(hdl, fsname, origin_fsname, flags); if (error == 0) @@ -3304,7 +3295,7 @@ break; case -1: fsavl_destroy(local_avl); - nvlist_free(local_nv); + fnvlist_free(local_nv); return (-1); } /* @@ -3324,7 +3315,7 @@ nextsnapelem = nvlist_next_nvpair(snaps, snapelem); - VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid)); + thisguid = fnvpair_value_uint64(snapelem); found = fsavl_find(stream_avl, thisguid, &stream_snapname); @@ -3418,10 +3409,9 @@ continue; } - VERIFY(0 == nvlist_lookup_string(stream_nvfs, - "name", &stream_fsname)); - VERIFY(0 == nvlist_lookup_uint64(stream_nvfs, - "parentfromsnap", &stream_parent_fromsnap_guid)); + stream_fsname = fnvlist_lookup_string(stream_nvfs, "name"); + stream_parent_fromsnap_guid = fnvlist_lookup_uint64( + stream_nvfs, "parentfromsnap"); s1 = strrchr(fsname, '/'); s2 = strrchr(stream_fsname, '/'); @@ -3470,8 +3460,7 @@ if (parent != NULL) { char *pname; - VERIFY(0 == nvlist_lookup_string(parent, "name", - &pname)); + pname = fnvlist_lookup_string(parent, "name"); (void) snprintf(tryname, sizeof (tryname), "%s%s", pname, strrchr(stream_fsname, '/')); } else { @@ -3488,8 +3477,7 @@ strlen(tofs)+1, newname, flags); if (renamed != NULL && newname[0] != '\0') { - VERIFY(0 == nvlist_add_boolean(renamed, - newname)); + fnvlist_add_boolean(renamed, newname); } if (error) @@ -3501,8 +3489,8 @@ doagain: fsavl_destroy(local_avl); - nvlist_free(local_nv); - nvlist_free(deleted); + fnvlist_free(local_nv); + fnvlist_free(deleted); if (needagain && progress) { /* do another pass to fix up temporary names */ @@ -3597,8 +3585,7 @@ if (drr->drr_payloadlen != 0) { nvlist_t *stream_fss; - VERIFY(0 == nvlist_lookup_nvlist(stream_nv, "fss", - &stream_fss)); + stream_fss = fnvlist_lookup_nvlist(stream_nv, "fss"); if ((stream_avl = fsavl_create(stream_fss)) == NULL) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "couldn't allocate avl tree")); @@ -3634,8 +3621,7 @@ } if (!flags->dryrun && !flags->nomount) { - VERIFY(0 == nvlist_alloc(&renamed, - NV_UNIQUE_NAME, 0)); + renamed = fnvlist_alloc(); } softerr = recv_incremental_replication(hdl, tofs, flags, @@ -3662,7 +3648,7 @@ } } - nvlist_free(renamed); + fnvlist_free(renamed); } } @@ -3718,7 +3704,7 @@ out: fsavl_destroy(stream_avl); - nvlist_free(stream_nv); + fnvlist_free(stream_nv); if (softerr) error = -2; if (anyerr) @@ -4141,7 +4127,7 @@ &parent_snapguid); err = nvlist_lookup_nvlist(fs, "props", &rcvprops); if (err) { - VERIFY(0 == nvlist_alloc(&rcvprops, NV_UNIQUE_NAME, 0)); + rcvprops = fnvlist_alloc(); newprops = B_TRUE; } @@ -4162,22 +4148,22 @@ } if (flags->canmountoff) { - VERIFY(0 == nvlist_add_uint64(rcvprops, - zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0)); + fnvlist_add_uint64(rcvprops, + zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0); } else if (newprops) { /* nothing in rcvprops, eliminate it */ - nvlist_free(rcvprops); + fnvlist_free(rcvprops); rcvprops = NULL; newprops = B_FALSE; } if (0 == nvlist_lookup_nvlist(fs, "snapprops", &lookup)) { - VERIFY(0 == nvlist_lookup_nvlist(lookup, - snapname, &snapprops_nvlist)); + snapprops_nvlist = fnvlist_lookup_nvlist(lookup, + snapname); } if (holds) { if (0 == nvlist_lookup_nvlist(fs, "snapholds", &lookup)) { - VERIFY(0 == nvlist_lookup_nvlist(lookup, - snapname, &snapholds_nvlist)); + snapholds_nvlist = fnvlist_lookup_nvlist( + lookup, snapname); } } } @@ -4711,12 +4697,11 @@ for (pair = nvlist_next_nvpair(snapholds_nvlist, NULL); pair != NULL; pair = nvlist_next_nvpair(snapholds_nvlist, pair)) { - VERIFY(0 == nvlist_add_string(holds, destsnap, - nvpair_name(pair))); + fnvlist_add_string(holds, destsnap, nvpair_name(pair)); } (void) lzc_hold(holds, cleanup_fd, &errors); - nvlist_free(snapholds_nvlist); - nvlist_free(holds); + fnvlist_free(snapholds_nvlist); + fnvlist_free(holds); } if (err && (ioctl_errno == ENOENT || ioctl_errno == EEXIST)) { @@ -4741,7 +4726,7 @@ *cp = '@'; fs = fsavl_find(local_avl, drrb->drr_toguid, NULL); fsavl_destroy(local_avl); - nvlist_free(local_nv); + fnvlist_free(local_nv); if (fs != NULL) { if (flags->verbose) { @@ -4917,18 +4902,18 @@ err = 0; out: if (prop_errors != NULL) - nvlist_free(prop_errors); + fnvlist_free(prop_errors); if (tmp_keylocation[0] != '\0') { - VERIFY(0 == nvlist_add_string(rcvprops, - zfs_prop_to_name(ZFS_PROP_KEYLOCATION), tmp_keylocation)); + fnvlist_add_string(rcvprops, + zfs_prop_to_name(ZFS_PROP_KEYLOCATION), tmp_keylocation); } if (newprops) - nvlist_free(rcvprops); + fnvlist_free(rcvprops); - nvlist_free(oxprops); - nvlist_free(origprops); + fnvlist_free(oxprops); + fnvlist_free(origprops); return (err); } diff --git a/sys/contrib/openzfs/lib/libzfs_core/Makefile.am b/sys/contrib/openzfs/lib/libzfs_core/Makefile.am --- a/sys/contrib/openzfs/lib/libzfs_core/Makefile.am +++ b/sys/contrib/openzfs/lib/libzfs_core/Makefile.am @@ -1,5 +1,4 @@ include $(top_srcdir)/config/Rules.am -PHONY = pkgconfig_DATA = libzfs_core.pc @@ -30,5 +29,7 @@ libzfs_core_la_LDFLAGS += -version-info 3:0:0 +include $(top_srcdir)/config/CppCheck.am + # Library ABI EXTRA_DIST = libzfs_core.abi libzfs_core.suppr diff --git a/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am b/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am --- a/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am +++ b/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am @@ -1,5 +1,4 @@ include $(top_srcdir)/config/Rules.am -PHONY = pkgconfig_DATA = libzfsbootenv.pc @@ -34,5 +33,7 @@ libzfsbootenv_la_LDFLAGS += -version-info 1:0:0 +include $(top_srcdir)/config/CppCheck.am + # Library ABI EXTRA_DIST = libzfsbootenv.abi libzfsbootenv.suppr diff --git a/sys/contrib/openzfs/lib/libzpool/Makefile.am b/sys/contrib/openzfs/lib/libzpool/Makefile.am --- a/sys/contrib/openzfs/lib/libzpool/Makefile.am +++ b/sys/contrib/openzfs/lib/libzpool/Makefile.am @@ -235,3 +235,5 @@ vdev_raidz_math_powerpc_altivec.$(OBJEXT): CFLAGS += -maltivec vdev_raidz_math_powerpc_altivec.l$(OBJEXT): CFLAGS += -maltivec endif + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libzstd/Makefile.am b/sys/contrib/openzfs/lib/libzstd/Makefile.am --- a/sys/contrib/openzfs/lib/libzstd/Makefile.am +++ b/sys/contrib/openzfs/lib/libzstd/Makefile.am @@ -19,3 +19,5 @@ zfs_zstd.$(OBJEXT): CFLAGS += -include $(top_srcdir)/module/zstd/include/zstd_compat_wrapper.h zfs_zstd.l$(OBJEXT): CFLAGS += -include $(top_srcdir)/module/zstd/include/zstd_compat_wrapper.h + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libzutil/Makefile.am b/sys/contrib/openzfs/lib/libzutil/Makefile.am --- a/sys/contrib/openzfs/lib/libzutil/Makefile.am +++ b/sys/contrib/openzfs/lib/libzutil/Makefile.am @@ -45,7 +45,10 @@ if BUILD_LINUX libzutil_la_LIBADD += \ - $(abs_top_builddir)/lib/libefi/libefi.la + $(abs_top_builddir)/lib/libefi/libefi.la \ + -lrt endif libzutil_la_LIBADD += -lm $(LIBBLKID_LIBS) $(LIBUDEV_LIBS) + +include $(top_srcdir)/config/CppCheck.am diff --git a/sys/contrib/openzfs/lib/libzutil/os/freebsd/zutil_import_os.c b/sys/contrib/openzfs/lib/libzutil/os/freebsd/zutil_import_os.c --- a/sys/contrib/openzfs/lib/libzutil/os/freebsd/zutil_import_os.c +++ b/sys/contrib/openzfs/lib/libzutil/os/freebsd/zutil_import_os.c @@ -42,6 +42,12 @@ * using our derived config, and record the results. */ +#include +#include +#include +#include +#include + #include #include #include @@ -51,9 +57,6 @@ #include #include #include -#include -#include -#include #include #include @@ -181,6 +184,7 @@ zpool_find_import_blkid(libpc_handle_t *hdl, pthread_mutex_t *lock, avl_tree_t **slice_cache) { + const char *oid = "vfs.zfs.vol.recursive"; char *end, path[MAXPATHLEN]; rdsk_node_t *slice; struct gmesh mesh; @@ -188,8 +192,9 @@ struct ggeom *gp; struct gprovider *pp; avl_index_t where; - size_t pathleft; - int error; + int error, value; + size_t pathleft, size = sizeof (value); + boolean_t skip_zvols = B_FALSE; end = stpcpy(path, "/dev/"); pathleft = &path[sizeof (path)] - end; @@ -198,11 +203,16 @@ if (error != 0) return (error); + if (sysctlbyname(oid, &value, &size, NULL, 0) == 0 && value == 0) + skip_zvols = B_TRUE; + *slice_cache = zutil_alloc(hdl, sizeof (avl_tree_t)); avl_create(*slice_cache, slice_cache_compare, sizeof (rdsk_node_t), offsetof(rdsk_node_t, rn_node)); LIST_FOREACH(mp, &mesh.lg_class, lg_class) { + if (skip_zvols && strcmp(mp->lg_name, "ZFS::ZVOL") == 0) + continue; LIST_FOREACH(gp, &mp->lg_geom, lg_geom) { LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { strlcpy(end, pp->lg_name, pathleft); diff --git a/sys/contrib/openzfs/lib/libzutil/zutil_import.c b/sys/contrib/openzfs/lib/libzutil/zutil_import.c --- a/sys/contrib/openzfs/lib/libzutil/zutil_import.c +++ b/sys/contrib/openzfs/lib/libzutil/zutil_import.c @@ -46,6 +46,7 @@ * using our derived config, and record the results. */ +#include #include #include #include @@ -887,11 +888,12 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels) { struct stat64 statbuf; - int l, count = 0; - vdev_label_t *label; + struct aiocb aiocbs[VDEV_LABELS]; + struct aiocb *aiocbps[VDEV_LABELS]; + vdev_phys_t *labels; nvlist_t *expected_config = NULL; uint64_t expected_guid = 0, size; - int error; + int error, l, count = 0; *config = NULL; @@ -899,19 +901,51 @@ return (0); size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t); - error = posix_memalign((void **)&label, PAGESIZE, sizeof (*label)); + error = posix_memalign((void **)&labels, PAGESIZE, + VDEV_LABELS * sizeof (*labels)); if (error) return (-1); + memset(aiocbs, 0, sizeof (aiocbs)); + for (l = 0; l < VDEV_LABELS; l++) { + off_t offset = label_offset(size, l) + VDEV_SKIP_SIZE; + + aiocbs[l].aio_fildes = fd; + aiocbs[l].aio_offset = offset; + aiocbs[l].aio_buf = &labels[l]; + aiocbs[l].aio_nbytes = sizeof (vdev_phys_t); + aiocbs[l].aio_lio_opcode = LIO_READ; + aiocbps[l] = &aiocbs[l]; + } + + if (lio_listio(LIO_WAIT, aiocbps, VDEV_LABELS, NULL) != 0) { + int saved_errno = errno; + + if (errno == EAGAIN || errno == EINTR || errno == EIO) { + /* + * A portion of the requests may have been submitted. + * Clean them up. + */ + for (l = 0; l < VDEV_LABELS; l++) { + errno = 0; + int r = aio_error(&aiocbs[l]); + if (r != EINVAL) + (void) aio_return(&aiocbs[l]); + } + } + free(labels); + errno = saved_errno; + return (-1); + } + for (l = 0; l < VDEV_LABELS; l++) { uint64_t state, guid, txg; - if (pread64(fd, label, sizeof (vdev_label_t), - label_offset(size, l)) != sizeof (vdev_label_t)) + if (aio_return(&aiocbs[l]) != sizeof (vdev_phys_t)) continue; - if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist, - sizeof (label->vl_vdev_phys.vp_nvlist), config, 0) != 0) + if (nvlist_unpack(labels[l].vp_nvlist, + sizeof (labels[l].vp_nvlist), config, 0) != 0) continue; if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_GUID, @@ -948,7 +982,7 @@ if (num_labels != NULL) *num_labels = count; - free(label); + free(labels); *config = expected_config; return (0); diff --git a/sys/contrib/openzfs/man/man5/zfs-module-parameters.5 b/sys/contrib/openzfs/man/man5/zfs-module-parameters.5 --- a/sys/contrib/openzfs/man/man5/zfs-module-parameters.5 +++ b/sys/contrib/openzfs/man/man5/zfs-module-parameters.5 @@ -3936,6 +3936,22 @@ Default value: \fB786,432\fR. .RE +.sp +.ne 2 +.na +\fBzfs_embedded_slog_min_ms\fR (int) +.ad +.RS 12n +Usually, one metaslab from each (normal-class) vdev is dedicated for use by +the ZIL (to log synchronous writes). +However, if there are fewer than zfs_embedded_slog_min_ms metaslabs in the +vdev, this functionality is disabled. +This ensures that we don't set aside an unreasonable amount of space for the +ZIL. +.sp +Default value: \fB64\fR. +.RE + .sp .ne 2 .na diff --git a/sys/contrib/openzfs/man/man8/zdb.8 b/sys/contrib/openzfs/man/man8/zdb.8 --- a/sys/contrib/openzfs/man/man8/zdb.8 +++ b/sys/contrib/openzfs/man/man8/zdb.8 @@ -15,7 +15,7 @@ .\" Copyright (c) 2017 Lawrence Livermore National Security, LLC. .\" Copyright (c) 2017 Intel Corporation. .\" -.Dd April 14, 2019 +.Dd October 7, 2020 .Dt ZDB 8 SMM .Os .Sh NAME @@ -60,6 +60,9 @@ .Fl O .Ar dataset path .Nm +.Fl r +.Ar dataset path destination +.Nm .Fl R .Op Fl A .Op Fl e Oo Fl V Oc Op Fl p Ar path ... @@ -274,6 +277,19 @@ This option can be combined with .Fl v for increasing verbosity. +.It Fl r Ar dataset path destination +Copy the specified +.Ar path +inside of the +.Ar dataset +to the specified destination. +Specified +.Ar path +must be relative to the root of +.Ar dataset . +This option can be combined with +.Fl v +for increasing verbosity. .It Xo .Fl R Ar poolname vdev Ns \&: Ns Ar offset Ns \&: Ns Ar [/] Ns Op : Ns Ar flags .Xc diff --git a/sys/contrib/openzfs/man/man8/zfs-list.8 b/sys/contrib/openzfs/man/man8/zfs-list.8 --- a/sys/contrib/openzfs/man/man8/zfs-list.8 +++ b/sys/contrib/openzfs/man/man8/zfs-list.8 @@ -63,12 +63,17 @@ relative pathname. By default, all file systems and volumes are displayed. Snapshots are displayed if the -.Sy listsnaps -property is +.Sy listsnapshots +pool property is .Sy on .Po the default is .Sy off -.Pc . +.Pc , +or if the +.Fl t Sy snapshot +or +.Fl t Sy all +options are specified. The following fields are displayed: .Sy name Ns \&, Sy used Ns \&, Sy available Ns \&, Sy referenced Ns \&, Sy mountpoint Ns . .Bl -tag -width "-H" diff --git a/sys/contrib/openzfs/man/man8/zfs-program.8 b/sys/contrib/openzfs/man/man8/zfs-program.8 --- a/sys/contrib/openzfs/man/man8/zfs-program.8 +++ b/sys/contrib/openzfs/man/man8/zfs-program.8 @@ -12,7 +12,7 @@ .\" Copyright (c) 2019, 2020 by Christian Schwarz. All Rights Reserved. .\" Copyright 2020 Joyent, Inc. .\" -.Dd February 3, 2020 +.Dd January 26, 2021 .Dt ZFS-PROGRAM 8 .Os .Sh NAME @@ -290,7 +290,7 @@ .Ss API Functions For detailed descriptions of the exact behavior of any zfs administrative operations, see the main -.Xr zfs 1 +.Xr zfs 8 manual page. .Bl -tag -width "xx" .It Em zfs.debug(msg) diff --git a/sys/contrib/openzfs/man/man8/zfsprops.8 b/sys/contrib/openzfs/man/man8/zfsprops.8 --- a/sys/contrib/openzfs/man/man8/zfsprops.8 +++ b/sys/contrib/openzfs/man/man8/zfsprops.8 @@ -1766,7 +1766,7 @@ and .Sy none are encoded as 1, 2 and 3 respectively. -The default values is +The default value is .Sy full . .It Sy vscan Ns = Ns Sy on Ns | Ns Sy off Controls whether regular files should be scanned for viruses when a file is diff --git a/sys/contrib/openzfs/module/Makefile.in b/sys/contrib/openzfs/module/Makefile.in --- a/sys/contrib/openzfs/module/Makefile.in +++ b/sys/contrib/openzfs/module/Makefile.in @@ -14,7 +14,8 @@ modules modules-Linux modules-FreeBSD modules-unknown \ clean clean-Linux clean-FreeBSD \ modules_install modules_install-Linux modules_install-FreeBSD \ - modules_uninstall modules_uninstall-Linux modules_uninstall-FreeBSD + modules_uninstall modules_uninstall-Linux modules_uninstall-FreeBSD \ + cppcheck cppcheck-Linux cppcheck-FreeBSD # Filter out options that FreeBSD make doesn't understand getflags = ( \ @@ -106,6 +107,25 @@ modules_uninstall: modules_uninstall-@ac_system@ +cppcheck-Linux: + @CPPCHECK@ -j@CPU_COUNT@ --std=c99 --quiet --force --error-exitcode=2 \ + --inline-suppr --suppress=noValidConfiguration \ + --enable=warning,information -D_KERNEL \ + --include=@LINUX_OBJ@/include/generated/autoconf.h \ + --include=@top_srcdir@/zfs_config.h \ + --config-exclude=@LINUX_OBJ@/include \ + -I @LINUX_OBJ@/include \ + -I @top_srcdir@/include/os/linux/kernel \ + -I @top_srcdir@/include/os/linux/spl \ + -I @top_srcdir@/include/os/linux/zfs \ + -I @top_srcdir@/include \ + avl icp lua nvpair spl unicode zcommon zfs zstd os/linux + +cppcheck-FreeBSD: + @true + +cppcheck: cppcheck-@ac_system@ + distdir: (cd @srcdir@ && find $(ZFS_MODULES) os -name '*.[chS]') | \ while read path; do \ diff --git a/sys/contrib/openzfs/module/avl/avl.c b/sys/contrib/openzfs/module/avl/avl.c --- a/sys/contrib/openzfs/module/avl/avl.c +++ b/sys/contrib/openzfs/module/avl/avl.c @@ -492,7 +492,6 @@ int which_child = AVL_INDEX2CHILD(where); size_t off = tree->avl_offset; - ASSERT(tree); #ifdef _LP64 ASSERT(((uintptr_t)new_data & 0x7) == 0); #endif @@ -680,8 +679,6 @@ int which_child; size_t off = tree->avl_offset; - ASSERT(tree); - delete = AVL_DATA2NODE(data, off); /* diff --git a/sys/contrib/openzfs/module/icp/algs/modes/modes.c b/sys/contrib/openzfs/module/icp/algs/modes/modes.c --- a/sys/contrib/openzfs/module/icp/algs/modes/modes.c +++ b/sys/contrib/openzfs/module/icp/algs/modes/modes.c @@ -43,11 +43,11 @@ break; case CRYPTO_DATA_UIO: { - uio_t *uiop = out->cd_uio; + zfs_uio_t *uiop = out->cd_uio; uint_t vec_idx; offset = out->cd_offset; - offset = uio_index_at_offset(uiop, offset, &vec_idx); + offset = zfs_uio_index_at_offset(uiop, offset, &vec_idx); *current_offset = offset; *iov_or_mp = (void *)(uintptr_t)vec_idx; @@ -85,7 +85,7 @@ } case CRYPTO_DATA_UIO: { - uio_t *uio = out->cd_uio; + zfs_uio_t *uio = out->cd_uio; offset_t offset; uint_t vec_idx; uint8_t *p; @@ -94,7 +94,7 @@ offset = *current_offset; vec_idx = (uintptr_t)(*iov_or_mp); - uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len); + zfs_uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len); p = (uint8_t *)iov_base + offset; *out_data_1 = p; @@ -106,10 +106,10 @@ } else { /* one block spans two iovecs */ *out_data_1_len = iov_len - offset; - if (vec_idx == uio_iovcnt(uio)) + if (vec_idx == zfs_uio_iovcnt(uio)) return; vec_idx++; - uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len); + zfs_uio_iov_at_index(uio, vec_idx, &iov_base, &iov_len); *out_data_2 = (uint8_t *)iov_base; *current_offset = amt - *out_data_1_len; } diff --git a/sys/contrib/openzfs/module/icp/core/kcf_prov_lib.c b/sys/contrib/openzfs/module/icp/core/kcf_prov_lib.c --- a/sys/contrib/openzfs/module/icp/core/kcf_prov_lib.c +++ b/sys/contrib/openzfs/module/icp/core/kcf_prov_lib.c @@ -40,7 +40,7 @@ crypto_uio_data(crypto_data_t *data, uchar_t *buf, int len, cmd_type_t cmd, void *digest_ctx, void (*update)(void)) { - uio_t *uiop = data->cd_uio; + zfs_uio_t *uiop = data->cd_uio; off_t offset = data->cd_offset; size_t length = len; uint_t vec_idx; @@ -48,7 +48,7 @@ uchar_t *datap; ASSERT(data->cd_format == CRYPTO_DATA_UIO); - if (uio_segflg(uiop) != UIO_SYSSPACE) { + if (zfs_uio_segflg(uiop) != UIO_SYSSPACE) { return (CRYPTO_ARGUMENTS_BAD); } @@ -56,9 +56,9 @@ * Jump to the first iovec containing data to be * processed. */ - offset = uio_index_at_offset(uiop, offset, &vec_idx); + offset = zfs_uio_index_at_offset(uiop, offset, &vec_idx); - if (vec_idx == uio_iovcnt(uiop) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(uiop) && length > 0) { /* * The caller specified an offset that is larger than * the total size of the buffers it provided. @@ -66,11 +66,11 @@ return (CRYPTO_DATA_LEN_RANGE); } - while (vec_idx < uio_iovcnt(uiop) && length > 0) { - cur_len = MIN(uio_iovlen(uiop, vec_idx) - + while (vec_idx < zfs_uio_iovcnt(uiop) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(uiop, vec_idx) - offset, length); - datap = (uchar_t *)(uio_iovbase(uiop, vec_idx) + offset); + datap = (uchar_t *)(zfs_uio_iovbase(uiop, vec_idx) + offset); switch (cmd) { case COPY_FROM_DATA: bcopy(datap, buf, cur_len); @@ -97,7 +97,7 @@ offset = 0; } - if (vec_idx == uio_iovcnt(uiop) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(uiop) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed. @@ -166,7 +166,7 @@ void (*copy_block)(uint8_t *, uint64_t *)) { common_ctx_t *common_ctx = ctx; - uio_t *uiop = input->cd_uio; + zfs_uio_t *uiop = input->cd_uio; off_t offset = input->cd_offset; size_t length = input->cd_length; uint_t vec_idx; @@ -178,7 +178,7 @@ &common_ctx->cc_iv[0]); } - if (uio_segflg(input->cd_uio) != UIO_SYSSPACE) { + if (zfs_uio_segflg(input->cd_uio) != UIO_SYSSPACE) { return (CRYPTO_ARGUMENTS_BAD); } @@ -186,8 +186,8 @@ * Jump to the first iovec containing data to be * processed. */ - offset = uio_index_at_offset(uiop, offset, &vec_idx); - if (vec_idx == uio_iovcnt(uiop) && length > 0) { + offset = zfs_uio_index_at_offset(uiop, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(uiop) && length > 0) { /* * The caller specified an offset that is larger than the * total size of the buffers it provided. @@ -198,11 +198,11 @@ /* * Now process the iovecs. */ - while (vec_idx < uio_iovcnt(uiop) && length > 0) { - cur_len = MIN(uio_iovlen(uiop, vec_idx) - + while (vec_idx < zfs_uio_iovcnt(uiop) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(uiop, vec_idx) - offset, length); - int rv = (cipher)(ctx, uio_iovbase(uiop, vec_idx) + offset, + int rv = (cipher)(ctx, zfs_uio_iovbase(uiop, vec_idx) + offset, cur_len, output); if (rv != CRYPTO_SUCCESS) { @@ -213,7 +213,7 @@ offset = 0; } - if (vec_idx == uio_iovcnt(uiop) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(uiop) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed, i.e. diff --git a/sys/contrib/openzfs/module/icp/io/sha1_mod.c b/sys/contrib/openzfs/module/icp/io/sha1_mod.c --- a/sys/contrib/openzfs/module/icp/io/sha1_mod.c +++ b/sys/contrib/openzfs/module/icp/io/sha1_mod.c @@ -271,15 +271,15 @@ size_t cur_len; /* we support only kernel buffer */ - if (uio_segflg(data->cd_uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(data->cd_uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* * Jump to the first iovec containing data to be * digested. */ - offset = uio_index_at_offset(data->cd_uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(data->cd_uio)) { + offset = zfs_uio_index_at_offset(data->cd_uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(data->cd_uio)) { /* * The caller specified an offset that is larger than the * total size of the buffers it provided. @@ -290,12 +290,12 @@ /* * Now do the digesting on the iovecs. */ - while (vec_idx < uio_iovcnt(data->cd_uio) && length > 0) { - cur_len = MIN(uio_iovlen(data->cd_uio, vec_idx) - + while (vec_idx < zfs_uio_iovcnt(data->cd_uio) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(data->cd_uio, vec_idx) - offset, length); SHA1Update(sha1_ctx, - (uint8_t *)uio_iovbase(data->cd_uio, vec_idx) + offset, + (uint8_t *)zfs_uio_iovbase(data->cd_uio, vec_idx) + offset, cur_len); length -= cur_len; @@ -303,7 +303,7 @@ offset = 0; } - if (vec_idx == uio_iovcnt(data->cd_uio) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(data->cd_uio) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed, i.e. @@ -330,15 +330,15 @@ uint_t vec_idx = 0; /* we support only kernel buffer */ - if (uio_segflg(digest->cd_uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(digest->cd_uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* * Jump to the first iovec containing ptr to the digest to * be returned. */ - offset = uio_index_at_offset(digest->cd_uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(digest->cd_uio)) { + offset = zfs_uio_index_at_offset(digest->cd_uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(digest->cd_uio)) { /* * The caller specified an offset that is * larger than the total size of the buffers @@ -348,7 +348,7 @@ } if (offset + digest_len <= - uio_iovlen(digest->cd_uio, vec_idx)) { + zfs_uio_iovlen(digest->cd_uio, vec_idx)) { /* * The computed SHA1 digest will fit in the current * iovec. @@ -360,11 +360,11 @@ * the user only what was requested. */ SHA1Final(digest_scratch, sha1_ctx); - bcopy(digest_scratch, (uchar_t *)uio_iovbase(digest-> - cd_uio, vec_idx) + offset, + bcopy(digest_scratch, (uchar_t *) + zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, digest_len); } else { - SHA1Final((uchar_t *)uio_iovbase(digest-> + SHA1Final((uchar_t *)zfs_uio_iovbase(digest-> cd_uio, vec_idx) + offset, sha1_ctx); } @@ -382,11 +382,11 @@ SHA1Final(digest_tmp, sha1_ctx); - while (vec_idx < uio_iovcnt(digest->cd_uio) && length > 0) { - cur_len = MIN(uio_iovlen(digest->cd_uio, vec_idx) - + while (vec_idx < zfs_uio_iovcnt(digest->cd_uio) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(digest->cd_uio, vec_idx) - offset, length); bcopy(digest_tmp + scratch_offset, - uio_iovbase(digest->cd_uio, vec_idx) + offset, + zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, cur_len); length -= cur_len; @@ -395,7 +395,7 @@ offset = 0; } - if (vec_idx == uio_iovcnt(digest->cd_uio) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(digest->cd_uio) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed, i.e. @@ -1096,12 +1096,12 @@ size_t cur_len; /* we support only kernel buffer */ - if (uio_segflg(mac->cd_uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(mac->cd_uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* jump to the first iovec containing the expected digest */ - offset = uio_index_at_offset(mac->cd_uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(mac->cd_uio)) { + offset = zfs_uio_index_at_offset(mac->cd_uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(mac->cd_uio)) { /* * The caller specified an offset that is * larger than the total size of the buffers @@ -1112,12 +1112,12 @@ } /* do the comparison of computed digest vs specified one */ - while (vec_idx < uio_iovcnt(mac->cd_uio) && length > 0) { - cur_len = MIN(uio_iovlen(mac->cd_uio, vec_idx) - + while (vec_idx < zfs_uio_iovcnt(mac->cd_uio) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(mac->cd_uio, vec_idx) - offset, length); if (bcmp(digest + scratch_offset, - uio_iovbase(mac->cd_uio, vec_idx) + offset, + zfs_uio_iovbase(mac->cd_uio, vec_idx) + offset, cur_len) != 0) { ret = CRYPTO_INVALID_MAC; break; diff --git a/sys/contrib/openzfs/module/icp/io/sha2_mod.c b/sys/contrib/openzfs/module/icp/io/sha2_mod.c --- a/sys/contrib/openzfs/module/icp/io/sha2_mod.c +++ b/sys/contrib/openzfs/module/icp/io/sha2_mod.c @@ -296,15 +296,15 @@ size_t cur_len; /* we support only kernel buffer */ - if (uio_segflg(data->cd_uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(data->cd_uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* * Jump to the first iovec containing data to be * digested. */ - offset = uio_index_at_offset(data->cd_uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(data->cd_uio)) { + offset = zfs_uio_index_at_offset(data->cd_uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(data->cd_uio)) { /* * The caller specified an offset that is larger than the * total size of the buffers it provided. @@ -315,18 +315,18 @@ /* * Now do the digesting on the iovecs. */ - while (vec_idx < uio_iovcnt(data->cd_uio) && length > 0) { - cur_len = MIN(uio_iovlen(data->cd_uio, vec_idx) - + while (vec_idx < zfs_uio_iovcnt(data->cd_uio) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(data->cd_uio, vec_idx) - offset, length); - SHA2Update(sha2_ctx, (uint8_t *)uio_iovbase(data->cd_uio, + SHA2Update(sha2_ctx, (uint8_t *)zfs_uio_iovbase(data->cd_uio, vec_idx) + offset, cur_len); length -= cur_len; vec_idx++; offset = 0; } - if (vec_idx == uio_iovcnt(data->cd_uio) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(data->cd_uio) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed, i.e. @@ -353,15 +353,15 @@ uint_t vec_idx = 0; /* we support only kernel buffer */ - if (uio_segflg(digest->cd_uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(digest->cd_uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* * Jump to the first iovec containing ptr to the digest to * be returned. */ - offset = uio_index_at_offset(digest->cd_uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(digest->cd_uio)) { + offset = zfs_uio_index_at_offset(digest->cd_uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(digest->cd_uio)) { /* * The caller specified an offset that is * larger than the total size of the buffers @@ -371,7 +371,7 @@ } if (offset + digest_len <= - uio_iovlen(digest->cd_uio, vec_idx)) { + zfs_uio_iovlen(digest->cd_uio, vec_idx)) { /* * The computed SHA2 digest will fit in the current * iovec. @@ -387,11 +387,11 @@ */ SHA2Final(digest_scratch, sha2_ctx); - bcopy(digest_scratch, (uchar_t *)uio_iovbase(digest-> - cd_uio, vec_idx) + offset, + bcopy(digest_scratch, (uchar_t *) + zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, digest_len); } else { - SHA2Final((uchar_t *)uio_iovbase(digest-> + SHA2Final((uchar_t *)zfs_uio_iovbase(digest-> cd_uio, vec_idx) + offset, sha2_ctx); @@ -410,12 +410,12 @@ SHA2Final(digest_tmp, sha2_ctx); - while (vec_idx < uio_iovcnt(digest->cd_uio) && length > 0) { + while (vec_idx < zfs_uio_iovcnt(digest->cd_uio) && length > 0) { cur_len = - MIN(uio_iovlen(digest->cd_uio, vec_idx) - + MIN(zfs_uio_iovlen(digest->cd_uio, vec_idx) - offset, length); bcopy(digest_tmp + scratch_offset, - uio_iovbase(digest->cd_uio, vec_idx) + offset, + zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, cur_len); length -= cur_len; @@ -424,7 +424,7 @@ offset = 0; } - if (vec_idx == uio_iovcnt(digest->cd_uio) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(digest->cd_uio) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed, i.e. @@ -1251,12 +1251,12 @@ size_t cur_len; /* we support only kernel buffer */ - if (uio_segflg(mac->cd_uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(mac->cd_uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* jump to the first iovec containing the expected digest */ - offset = uio_index_at_offset(mac->cd_uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(mac->cd_uio)) { + offset = zfs_uio_index_at_offset(mac->cd_uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(mac->cd_uio)) { /* * The caller specified an offset that is * larger than the total size of the buffers @@ -1267,12 +1267,12 @@ } /* do the comparison of computed digest vs specified one */ - while (vec_idx < uio_iovcnt(mac->cd_uio) && length > 0) { - cur_len = MIN(uio_iovlen(mac->cd_uio, vec_idx) - + while (vec_idx < zfs_uio_iovcnt(mac->cd_uio) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(mac->cd_uio, vec_idx) - offset, length); if (bcmp(digest + scratch_offset, - uio_iovbase(mac->cd_uio, vec_idx) + offset, + zfs_uio_iovbase(mac->cd_uio, vec_idx) + offset, cur_len) != 0) { ret = CRYPTO_INVALID_MAC; break; diff --git a/sys/contrib/openzfs/module/icp/io/skein_mod.c b/sys/contrib/openzfs/module/icp/io/skein_mod.c --- a/sys/contrib/openzfs/module/icp/io/skein_mod.c +++ b/sys/contrib/openzfs/module/icp/io/skein_mod.c @@ -272,18 +272,18 @@ size_t length = data->cd_length; uint_t vec_idx = 0; size_t cur_len; - uio_t *uio = data->cd_uio; + zfs_uio_t *uio = data->cd_uio; /* we support only kernel buffer */ - if (uio_segflg(uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* * Jump to the first iovec containing data to be * digested. */ - offset = uio_index_at_offset(uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(uio)) { + offset = zfs_uio_index_at_offset(uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(uio)) { /* * The caller specified an offset that is larger than the * total size of the buffers it provided. @@ -294,16 +294,16 @@ /* * Now do the digesting on the iovecs. */ - while (vec_idx < uio_iovcnt(uio) && length > 0) { - cur_len = MIN(uio_iovlen(uio, vec_idx) - offset, length); - SKEIN_OP(ctx, Update, (uint8_t *)uio_iovbase(uio, vec_idx) + while (vec_idx < zfs_uio_iovcnt(uio) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(uio, vec_idx) - offset, length); + SKEIN_OP(ctx, Update, (uint8_t *)zfs_uio_iovbase(uio, vec_idx) + offset, cur_len); length -= cur_len; vec_idx++; offset = 0; } - if (vec_idx == uio_iovcnt(uio) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(uio) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed, i.e. @@ -322,19 +322,19 @@ skein_digest_final_uio(skein_ctx_t *ctx, crypto_data_t *digest, crypto_req_handle_t req) { - off_t offset = digest->cd_offset; - uint_t vec_idx = 0; - uio_t *uio = digest->cd_uio; + off_t offset = digest->cd_offset; + uint_t vec_idx = 0; + zfs_uio_t *uio = digest->cd_uio; /* we support only kernel buffer */ - if (uio_segflg(uio) != UIO_SYSSPACE) + if (zfs_uio_segflg(uio) != UIO_SYSSPACE) return (CRYPTO_ARGUMENTS_BAD); /* * Jump to the first iovec containing ptr to the digest to be returned. */ - offset = uio_index_at_offset(uio, offset, &vec_idx); - if (vec_idx == uio_iovcnt(uio)) { + offset = zfs_uio_index_at_offset(uio, offset, &vec_idx); + if (vec_idx == zfs_uio_iovcnt(uio)) { /* * The caller specified an offset that is larger than the * total size of the buffers it provided. @@ -342,10 +342,10 @@ return (CRYPTO_DATA_LEN_RANGE); } if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <= - uio_iovlen(uio, vec_idx)) { + zfs_uio_iovlen(uio, vec_idx)) { /* The computed digest will fit in the current iovec. */ SKEIN_OP(ctx, Final, - (uchar_t *)uio_iovbase(uio, vec_idx) + offset); + (uchar_t *)zfs_uio_iovbase(uio, vec_idx) + offset); } else { uint8_t *digest_tmp; off_t scratch_offset = 0; @@ -357,11 +357,11 @@ if (digest_tmp == NULL) return (CRYPTO_HOST_MEMORY); SKEIN_OP(ctx, Final, digest_tmp); - while (vec_idx < uio_iovcnt(uio) && length > 0) { - cur_len = MIN(uio_iovlen(uio, vec_idx) - offset, + while (vec_idx < zfs_uio_iovcnt(uio) && length > 0) { + cur_len = MIN(zfs_uio_iovlen(uio, vec_idx) - offset, length); bcopy(digest_tmp + scratch_offset, - uio_iovbase(uio, vec_idx) + offset, cur_len); + zfs_uio_iovbase(uio, vec_idx) + offset, cur_len); length -= cur_len; vec_idx++; @@ -370,7 +370,7 @@ } kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen)); - if (vec_idx == uio_iovcnt(uio) && length > 0) { + if (vec_idx == zfs_uio_iovcnt(uio) && length > 0) { /* * The end of the specified iovec's was reached but * the length requested could not be processed, i.e. diff --git a/sys/contrib/openzfs/module/lua/ldebug.c b/sys/contrib/openzfs/module/lua/ldebug.c --- a/sys/contrib/openzfs/module/lua/ldebug.c +++ b/sys/contrib/openzfs/module/lua/ldebug.c @@ -324,7 +324,6 @@ if (ISK(c)) { /* is 'c' a constant? */ TValue *kvalue = &p->k[INDEXK(c)]; if (ttisstring(kvalue)) { /* literal constant? */ - // cppcheck-suppress autoVariables *name = svalue(kvalue); /* it is its own name */ return; } diff --git a/sys/contrib/openzfs/module/lua/ldo.c b/sys/contrib/openzfs/module/lua/ldo.c --- a/sys/contrib/openzfs/module/lua/ldo.c +++ b/sys/contrib/openzfs/module/lua/ldo.c @@ -196,7 +196,6 @@ struct lua_longjmp lj; lj.status = LUA_OK; lj.previous = L->errorJmp; /* chain new error handler */ - // cppcheck-suppress autoVariables L->errorJmp = &lj; LUAI_TRY(L, &lj, (*f)(L, ud); diff --git a/sys/contrib/openzfs/module/os/freebsd/spl/spl_uio.c b/sys/contrib/openzfs/module/os/freebsd/spl/spl_uio.c --- a/sys/contrib/openzfs/module/os/freebsd/spl/spl_uio.c +++ b/sys/contrib/openzfs/module/os/freebsd/spl/spl_uio.c @@ -43,31 +43,32 @@ #include #include #include +#include /* - * same as uiomove() but doesn't modify uio structure. + * same as zfs_uiomove() but doesn't modify uio structure. * return in cbytes how many bytes were copied. */ int -uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes) +zfs_uiocopy(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio, size_t *cbytes) { struct iovec small_iovec[1]; struct uio small_uio_clone; struct uio *uio_clone; int error; - ASSERT3U(uio->uio_rw, ==, rw); - if (uio->uio_iovcnt == 1) { - small_uio_clone = *uio; - small_iovec[0] = *uio->uio_iov; + ASSERT3U(zfs_uio_rw(uio), ==, rw); + if (zfs_uio_iovcnt(uio) == 1) { + small_uio_clone = *(GET_UIO_STRUCT(uio)); + small_iovec[0] = *(GET_UIO_STRUCT(uio)->uio_iov); small_uio_clone.uio_iov = small_iovec; uio_clone = &small_uio_clone; } else { - uio_clone = cloneuio(uio); + uio_clone = cloneuio(GET_UIO_STRUCT(uio)); } error = vn_io_fault_uiomove(p, n, uio_clone); - *cbytes = uio->uio_resid - uio_clone->uio_resid; + *cbytes = zfs_uio_resid(uio) - uio_clone->uio_resid; if (uio_clone != &small_uio_clone) free(uio_clone, M_IOV); return (error); @@ -77,16 +78,23 @@ * Drop the next n chars out of *uiop. */ void -uioskip(uio_t *uio, size_t n) +zfs_uioskip(zfs_uio_t *uio, size_t n) { - enum uio_seg segflg; + zfs_uio_seg_t segflg; /* For the full compatibility with illumos. */ - if (n > uio->uio_resid) + if (n > zfs_uio_resid(uio)) return; - segflg = uio->uio_segflg; - uio->uio_segflg = UIO_NOCOPY; - uiomove(NULL, n, uio->uio_rw, uio); - uio->uio_segflg = segflg; + segflg = zfs_uio_segflg(uio); + zfs_uio_segflg(uio) = UIO_NOCOPY; + zfs_uiomove(NULL, n, zfs_uio_rw(uio), uio); + zfs_uio_segflg(uio) = segflg; +} + +int +zfs_uio_fault_move(void *p, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio) +{ + ASSERT(zfs_uio_rw(uio) == dir); + return (vn_io_fault_uiomove(p, n, GET_UIO_STRUCT(uio))); } diff --git a/sys/contrib/openzfs/module/os/freebsd/spl/spl_vfs.c b/sys/contrib/openzfs/module/os/freebsd/spl/spl_vfs.c --- a/sys/contrib/openzfs/module/os/freebsd/spl/spl_vfs.c +++ b/sys/contrib/openzfs/module/os/freebsd/spl/spl_vfs.c @@ -240,7 +240,9 @@ #endif VI_LOCK(vp); vp->v_iflag &= ~VI_MOUNT; +#ifdef VIRF_MOUNTPOINT vn_irflag_set_locked(vp, VIRF_MOUNTPOINT); +#endif vp->v_mountedhere = mp; VI_UNLOCK(vp); /* Put the new filesystem on the mount list. */ diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/abd_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/abd_os.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/abd_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/abd_os.c @@ -202,7 +202,7 @@ } abd_t * -abd_alloc_struct(size_t size) +abd_alloc_struct_impl(size_t size) { uint_t chunkcnt = abd_chunkcnt_for_bytes(size); /* @@ -216,22 +216,18 @@ offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt])); abd_t *abd = kmem_alloc(abd_size, KM_PUSHPAGE); ASSERT3P(abd, !=, NULL); - list_link_init(&abd->abd_gang_link); - mutex_init(&abd->abd_mtx, NULL, MUTEX_DEFAULT, NULL); ABDSTAT_INCR(abdstat_struct_size, abd_size); return (abd); } void -abd_free_struct(abd_t *abd) +abd_free_struct_impl(abd_t *abd) { uint_t chunkcnt = abd_is_linear(abd) || abd_is_gang(abd) ? 0 : abd_scatter_chunkcnt(abd); ssize_t size = MAX(sizeof (abd_t), offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt])); - mutex_destroy(&abd->abd_mtx); - ASSERT(!list_link_active(&abd->abd_gang_link)); kmem_free(abd, size); ABDSTAT_INCR(abdstat_struct_size, -size); } @@ -249,10 +245,8 @@ abd_zero_buf = kmem_zalloc(zfs_abd_chunk_size, KM_SLEEP); abd_zero_scatter = abd_alloc_struct(SPA_MAXBLOCKSIZE); - abd_zero_scatter->abd_flags = ABD_FLAG_OWNER | ABD_FLAG_ZEROS; + abd_zero_scatter->abd_flags |= ABD_FLAG_OWNER | ABD_FLAG_ZEROS; abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE; - abd_zero_scatter->abd_parent = NULL; - zfs_refcount_create(&abd_zero_scatter->abd_children); ABD_SCATTER(abd_zero_scatter).abd_offset = 0; ABD_SCATTER(abd_zero_scatter).abd_chunk_size = @@ -270,7 +264,6 @@ static void abd_free_zero_scatter(void) { - zfs_refcount_destroy(&abd_zero_scatter->abd_children); ABDSTAT_BUMPDOWN(abdstat_scatter_cnt); ABDSTAT_INCR(abdstat_scatter_data_size, -(int)zfs_abd_chunk_size); @@ -355,10 +348,8 @@ } abd_t * -abd_get_offset_scatter(abd_t *sabd, size_t off) +abd_get_offset_scatter(abd_t *abd, abd_t *sabd, size_t off) { - abd_t *abd = NULL; - abd_verify(sabd); ASSERT3U(off, <=, sabd->abd_size); @@ -366,14 +357,24 @@ uint_t chunkcnt = abd_scatter_chunkcnt(sabd) - (new_offset / zfs_abd_chunk_size); - abd = abd_alloc_scatter_offset_chunkcnt(chunkcnt); + /* + * If an abd struct is provided, it is only the minimum size. If we + * need additional chunks, we need to allocate a new struct. + */ + if (abd != NULL && + offsetof(abd_t, abd_u.abd_scatter.abd_chunks[chunkcnt]) > + sizeof (abd_t)) { + abd = NULL; + } + + if (abd == NULL) + abd = abd_alloc_struct(chunkcnt * zfs_abd_chunk_size); /* * Even if this buf is filesystem metadata, we only track that * if we own the underlying data buffer, which is not true in * this case. Therefore, we don't ever use ABD_FLAG_META here. */ - abd->abd_flags = 0; ABD_SCATTER(abd).abd_offset = new_offset % zfs_abd_chunk_size; ABD_SCATTER(abd).abd_chunk_size = zfs_abd_chunk_size; diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/crypto_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/crypto_os.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/crypto_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/crypto_os.c @@ -197,7 +197,7 @@ freebsd_crypt_uio_debug_log(boolean_t encrypt, freebsd_crypt_session_t *input_sessionp, struct zio_crypt_info *c_info, - uio_t *data_uio, + zfs_uio_t *data_uio, crypto_key_t *key, uint8_t *ivbuf, size_t datalen, @@ -222,13 +222,13 @@ printf("%02x ", b[i]); } printf("}\n"); - for (int i = 0; i < data_uio->uio_iovcnt; i++) { + for (int i = 0; i < zfs_uio_iovcnt(data_uio); i++) { printf("\tiovec #%d: <%p, %u>\n", i, - data_uio->uio_iov[i].iov_base, - (unsigned int)data_uio->uio_iov[i].iov_len); - total += data_uio->uio_iov[i].iov_len; + zfs_uio_iovbase(data_uio, i), + (unsigned int)zfs_uio_iovlen(data_uio, i)); + total += zfs_uio_iovlen(data_uio, i); } - data_uio->uio_resid = total; + zfs_uio_resid(data_uio) = total; #endif } /* @@ -310,7 +310,7 @@ freebsd_crypt_uio(boolean_t encrypt, freebsd_crypt_session_t *input_sessionp, struct zio_crypt_info *c_info, - uio_t *data_uio, + zfs_uio_t *data_uio, crypto_key_t *key, uint8_t *ivbuf, size_t datalen, @@ -323,9 +323,9 @@ freebsd_crypt_uio_debug_log(encrypt, input_sessionp, c_info, data_uio, key, ivbuf, datalen, auth_len); - for (int i = 0; i < data_uio->uio_iovcnt; i++) - total += data_uio->uio_iov[i].iov_len; - data_uio->uio_resid = total; + for (int i = 0; i < zfs_uio_iovcnt(data_uio); i++) + total += zfs_uio_iovlen(data_uio, i); + zfs_uio_resid(data_uio) = total; if (input_sessionp == NULL) { session = kmem_zalloc(sizeof (*session), KM_SLEEP); error = freebsd_crypt_newsession(session, c_info, key); @@ -343,7 +343,7 @@ CRYPTO_OP_VERIFY_DIGEST; } crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_IV_SEPARATE; - crypto_use_uio(crp, data_uio); + crypto_use_uio(crp, GET_UIO_STRUCT(data_uio)); crp->crp_aad_start = 0; crp->crp_aad_length = auth_len; @@ -480,7 +480,7 @@ freebsd_crypt_uio(boolean_t encrypt, freebsd_crypt_session_t *input_sessionp, struct zio_crypt_info *c_info, - uio_t *data_uio, + zfs_uio_t *data_uio, crypto_key_t *key, uint8_t *ivbuf, size_t datalen, @@ -564,7 +564,7 @@ crp->crp_session = session->fs_sid; crp->crp_ilen = auth_len + datalen; - crp->crp_buf = (void*)data_uio; + crp->crp_buf = (void*)GET_UIO_STRUCT(data_uio); crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIFSYNC; auth_desc->crd_skip = 0; diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c @@ -251,7 +251,7 @@ static int sfs_readdir_common(uint64_t parent_id, uint64_t id, struct vop_readdir_args *ap, - uio_t *uio, off_t *offp) + zfs_uio_t *uio, off_t *offp) { struct dirent entry; int error; @@ -260,26 +260,26 @@ if (ap->a_ncookies != NULL) *ap->a_ncookies = 0; - if (uio->uio_resid < sizeof (entry)) + if (zfs_uio_resid(uio) < sizeof (entry)) return (SET_ERROR(EINVAL)); - if (uio->uio_offset < 0) + if (zfs_uio_offset(uio) < 0) return (SET_ERROR(EINVAL)); - if (uio->uio_offset == 0) { + if (zfs_uio_offset(uio) == 0) { entry.d_fileno = id; entry.d_type = DT_DIR; entry.d_name[0] = '.'; entry.d_name[1] = '\0'; entry.d_namlen = 1; entry.d_reclen = sizeof (entry); - error = vfs_read_dirent(ap, &entry, uio->uio_offset); + error = vfs_read_dirent(ap, &entry, zfs_uio_offset(uio)); if (error != 0) return (SET_ERROR(error)); } - if (uio->uio_offset < sizeof (entry)) + if (zfs_uio_offset(uio) < sizeof (entry)) return (SET_ERROR(EINVAL)); - if (uio->uio_offset == sizeof (entry)) { + if (zfs_uio_offset(uio) == sizeof (entry)) { entry.d_fileno = parent_id; entry.d_type = DT_DIR; entry.d_name[0] = '.'; @@ -287,7 +287,7 @@ entry.d_name[2] = '\0'; entry.d_namlen = 2; entry.d_reclen = sizeof (entry); - error = vfs_read_dirent(ap, &entry, uio->uio_offset); + error = vfs_read_dirent(ap, &entry, zfs_uio_offset(uio)); if (error != 0) return (SET_ERROR(error)); } @@ -666,21 +666,23 @@ vnode_t *vp = ap->a_vp; zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; zfsctl_root_t *node = vp->v_data; - uio_t *uio = ap->a_uio; + zfs_uio_t uio; int *eofp = ap->a_eofflag; off_t dots_offset; int error; + zfs_uio_init(&uio, ap->a_uio); + ASSERT(vp->v_type == VDIR); - error = sfs_readdir_common(zfsvfs->z_root, ZFSCTL_INO_ROOT, ap, uio, + error = sfs_readdir_common(zfsvfs->z_root, ZFSCTL_INO_ROOT, ap, &uio, &dots_offset); if (error != 0) { if (error == ENAMETOOLONG) /* ran out of destination space */ error = 0; return (error); } - if (uio->uio_offset != dots_offset) + if (zfs_uio_offset(&uio) != dots_offset) return (SET_ERROR(EINVAL)); CTASSERT(sizeof (node->snapdir->sn_name) <= sizeof (entry.d_name)); @@ -689,7 +691,7 @@ strcpy(entry.d_name, node->snapdir->sn_name); entry.d_namlen = strlen(entry.d_name); entry.d_reclen = sizeof (entry); - error = vfs_read_dirent(ap, &entry, uio->uio_offset); + error = vfs_read_dirent(ap, &entry, zfs_uio_offset(&uio)); if (error != 0) { if (error == ENAMETOOLONG) error = 0; @@ -1030,15 +1032,17 @@ struct dirent entry; vnode_t *vp = ap->a_vp; zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; - uio_t *uio = ap->a_uio; + zfs_uio_t uio; int *eofp = ap->a_eofflag; off_t dots_offset; int error; + zfs_uio_init(&uio, ap->a_uio); + ASSERT(vp->v_type == VDIR); - error = sfs_readdir_common(ZFSCTL_INO_ROOT, ZFSCTL_INO_SNAPDIR, ap, uio, - &dots_offset); + error = sfs_readdir_common(ZFSCTL_INO_ROOT, ZFSCTL_INO_SNAPDIR, ap, + &uio, &dots_offset); if (error != 0) { if (error == ENAMETOOLONG) /* ran out of destination space */ error = 0; @@ -1050,7 +1054,7 @@ uint64_t cookie; uint64_t id; - cookie = uio->uio_offset - dots_offset; + cookie = zfs_uio_offset(&uio) - dots_offset; dsl_pool_config_enter(dmu_objset_pool(zfsvfs->z_os), FTAG); error = dmu_snapshot_list_next(zfsvfs->z_os, sizeof (snapname), @@ -1071,14 +1075,14 @@ strcpy(entry.d_name, snapname); entry.d_namlen = strlen(entry.d_name); entry.d_reclen = sizeof (entry); - error = vfs_read_dirent(ap, &entry, uio->uio_offset); + error = vfs_read_dirent(ap, &entry, zfs_uio_offset(&uio)); if (error != 0) { if (error == ENAMETOOLONG) error = 0; ZFS_EXIT(zfsvfs); return (SET_ERROR(error)); } - uio->uio_offset = cookie + dots_offset; + zfs_uio_setoffset(&uio, cookie + dots_offset); } /* NOTREACHED */ } diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c @@ -290,7 +290,7 @@ int zfs_file_unlink(const char *fnamep) { - enum uio_seg seg = UIO_SYSSPACE; + zfs_uio_seg_t seg = UIO_SYSSPACE; int rc; #if __FreeBSD_version >= 1300018 diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c @@ -518,7 +518,7 @@ * in one single dmu_read() call. */ int -mappedread_sf(znode_t *zp, int nbytes, uio_t *uio) +mappedread_sf(znode_t *zp, int nbytes, zfs_uio_t *uio) { vnode_t *vp = ZTOV(zp); objset_t *os = zp->z_zfsvfs->z_os; @@ -530,14 +530,14 @@ int len = nbytes; int error = 0; - ASSERT(uio->uio_segflg == UIO_NOCOPY); + ASSERT(zfs_uio_segflg(uio) == UIO_NOCOPY); ASSERT(vp->v_mount != NULL); obj = vp->v_object; ASSERT(obj != NULL); - ASSERT((uio->uio_loffset & PAGEOFFSET) == 0); + ASSERT((zfs_uio_offset(uio) & PAGEOFFSET) == 0); zfs_vmobject_wlock_12(obj); - for (start = uio->uio_loffset; len > 0; start += PAGESIZE) { + for (start = zfs_uio_offset(uio); len > 0; start += PAGESIZE) { int bytes = MIN(PAGESIZE, len); pp = vm_page_grab_unlocked(obj, OFF_TO_IDX(start), @@ -584,8 +584,7 @@ } if (error) break; - uio->uio_resid -= bytes; - uio->uio_offset += bytes; + zfs_uio_advance(uio, bytes); len -= bytes; } zfs_vmobject_wunlock_12(obj); @@ -603,7 +602,7 @@ * the file is memory mapped. */ int -mappedread(znode_t *zp, int nbytes, uio_t *uio) +mappedread(znode_t *zp, int nbytes, zfs_uio_t *uio) { vnode_t *vp = ZTOV(zp); vm_object_t obj; @@ -616,7 +615,7 @@ obj = vp->v_object; ASSERT(obj != NULL); - start = uio->uio_loffset; + start = zfs_uio_offset(uio); off = start & PAGEOFFSET; zfs_vmobject_wlock_12(obj); for (start &= PAGEMASK; len > 0; start += PAGESIZE) { @@ -629,7 +628,8 @@ zfs_vmobject_wunlock_12(obj); va = zfs_map_page(pp, &sf); - error = vn_io_fault_uiomove(va + off, bytes, uio); + error = vn_io_fault_uiomove(va + off, bytes, + GET_UIO_STRUCT(uio)); zfs_unmap_page(sf); zfs_vmobject_wlock_12(obj); page_unhold(pp); @@ -1649,7 +1649,7 @@ */ /* ARGSUSED */ static int -zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, +zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp, int *ncookies, ulong_t **cookies) { znode_t *zp = VTOZ(vp); @@ -1694,7 +1694,7 @@ /* * Check for valid iov_len. */ - if (uio->uio_iov->iov_len <= 0) { + if (GET_UIO_STRUCT(uio)->uio_iov->iov_len <= 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } @@ -1709,7 +1709,7 @@ error = 0; os = zfsvfs->z_os; - offset = uio->uio_loffset; + offset = zfs_uio_offset(uio); prefetch = zp->z_zn_prefetch; /* @@ -1730,9 +1730,9 @@ /* * Get space to change directory entries into fs independent format. */ - iovp = uio->uio_iov; + iovp = GET_UIO_STRUCT(uio)->uio_iov; bytes_wanted = iovp->iov_len; - if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) { + if (zfs_uio_segflg(uio) != UIO_SYSSPACE || zfs_uio_iovcnt(uio) != 1) { bufsize = bytes_wanted; outbuf = kmem_alloc(bufsize, KM_SLEEP); odp = (struct dirent64 *)outbuf; @@ -1747,7 +1747,7 @@ /* * Minimum entry size is dirent size and 1 byte for a file name. */ - ncooks = uio->uio_resid / (sizeof (struct dirent) - + 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); *cookies = cooks; @@ -1927,20 +1927,21 @@ if (ncookies != NULL) *ncookies -= ncooks; - if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) { + if (zfs_uio_segflg(uio) == UIO_SYSSPACE && zfs_uio_iovcnt(uio) == 1) { iovp->iov_base += outcount; iovp->iov_len -= outcount; - uio->uio_resid -= outcount; - } else if ((error = uiomove(outbuf, (long)outcount, UIO_READ, uio))) { + zfs_uio_resid(uio) -= outcount; + } else if ((error = + zfs_uiomove(outbuf, (long)outcount, UIO_READ, uio))) { /* * Reset the pointer. */ - offset = uio->uio_loffset; + offset = zfs_uio_offset(uio); } update: zap_cursor_fini(&zc); - if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) + if (zfs_uio_segflg(uio) != UIO_SYSSPACE || zfs_uio_iovcnt(uio) != 1) kmem_free(outbuf, bufsize); if (error == ENOENT) @@ -1948,7 +1949,7 @@ ZFS_ACCESSTIME_STAMP(zfsvfs, zp); - uio->uio_loffset = offset; + zfs_uio_setoffset(uio, offset); ZFS_EXIT(zfsvfs); if (error != 0 && cookies != NULL) { free(*cookies, M_TEMP); @@ -3631,7 +3632,7 @@ */ /* ARGSUSED */ static int -zfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr, caller_context_t *ct) +zfs_readlink(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, caller_context_t *ct) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; @@ -4414,8 +4415,9 @@ static int zfs_freebsd_read(struct vop_read_args *ap) { - - return (zfs_read(VTOZ(ap->a_vp), ap->a_uio, ioflags(ap->a_ioflag), + zfs_uio_t uio; + zfs_uio_init(&uio, ap->a_uio); + return (zfs_read(VTOZ(ap->a_vp), &uio, ioflags(ap->a_ioflag), ap->a_cred)); } @@ -4431,8 +4433,9 @@ static int zfs_freebsd_write(struct vop_write_args *ap) { - - return (zfs_write(VTOZ(ap->a_vp), ap->a_uio, ioflags(ap->a_ioflag), + zfs_uio_t uio; + zfs_uio_init(&uio, ap->a_uio); + return (zfs_write(VTOZ(ap->a_vp), &uio, ioflags(ap->a_ioflag), ap->a_cred)); } @@ -4704,8 +4707,9 @@ static int zfs_freebsd_readdir(struct vop_readdir_args *ap) { - - return (zfs_readdir(ap->a_vp, ap->a_uio, ap->a_cred, ap->a_eofflag, + zfs_uio_t uio; + zfs_uio_init(&uio, ap->a_uio); + return (zfs_readdir(ap->a_vp, &uio, ap->a_cred, ap->a_eofflag, ap->a_ncookies, ap->a_cookies)); } @@ -5008,26 +5012,27 @@ static int zfs_freebsd_readlink(struct vop_readlink_args *ap) { + zfs_uio_t uio; znode_t *zp = VTOZ(ap->a_vp); - struct uio *auio; char *symlink, *base; size_t symlink_len; int error; bool trycache; - auio = ap->a_uio; + zfs_uio_init(&uio, ap->a_uio); trycache = false; - if (auio->uio_segflg == UIO_SYSSPACE && auio->uio_iovcnt == 1) { - base = auio->uio_iov->iov_base; - symlink_len = auio->uio_iov->iov_len; + if (zfs_uio_segflg(&uio) == UIO_SYSSPACE && + zfs_uio_iovcnt(&uio) == 1) { + base = zfs_uio_iovbase(&uio, 0); + symlink_len = zfs_uio_iovlen(&uio, 0); trycache = true; } - error = zfs_readlink(ap->a_vp, auio, ap->a_cred, NULL); + error = zfs_readlink(ap->a_vp, &uio, ap->a_cred, NULL); if (atomic_load_ptr(&zp->z_cached_symlink) != NULL || error != 0 || !trycache) { return (error); } - symlink_len -= auio->uio_resid; + symlink_len -= zfs_uio_resid(&uio); symlink = cache_symlink_alloc(symlink_len + 1, M_WAITOK); if (symlink != NULL) { memcpy(symlink, base, symlink_len); @@ -5504,11 +5509,14 @@ uint8_t dirbuf[sizeof (struct dirent)]; struct dirent *dp; struct iovec aiov; - struct uio auio, *uio = ap->a_uio; + struct uio auio; size_t *sizep = ap->a_size; size_t plen; vnode_t *xvp = NULL, *vp; int done, error, eof, pos; + zfs_uio_t uio; + + zfs_uio_init(&uio, ap->a_uio); /* * If the xattr property is off, refuse the request. @@ -5590,15 +5598,16 @@ nlen = dp->d_namlen - plen; if (sizep != NULL) *sizep += 1 + nlen; - else if (uio != NULL) { + else if (GET_UIO_STRUCT(&uio) != NULL) { /* * Format of extattr name entry is one byte for * length and the rest for name. */ - error = uiomove(&nlen, 1, uio->uio_rw, uio); + error = zfs_uiomove(&nlen, 1, zfs_uio_rw(&uio), + &uio); if (error == 0) { - error = uiomove(dp->d_name + plen, nlen, - uio->uio_rw, uio); + error = zfs_uiomove(dp->d_name + plen, + nlen, zfs_uio_rw(&uio), &uio); } if (error != 0) break; diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c @@ -1912,8 +1912,10 @@ size_t complen; int is_xattrdir; - if (prevdb) + if (prevdb) { + ASSERT(prevhdl != NULL); zfs_release_sa_handle(prevhdl, prevdb, FTAG); + } if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj, &is_xattrdir)) != 0) @@ -2020,7 +2022,7 @@ void -zfs_inode_update(znode_t *zp) +zfs_znode_update_vfs(znode_t *zp) { vm_object_t object; diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c @@ -404,7 +404,7 @@ static int zio_do_crypt_uio_opencrypto(boolean_t encrypt, freebsd_crypt_session_t *sess, uint64_t crypt, crypto_key_t *key, uint8_t *ivbuf, uint_t datalen, - uio_t *uio, uint_t auth_len) + zfs_uio_t *uio, uint_t auth_len) { zio_crypt_info_t *ci; int ret; @@ -439,7 +439,8 @@ * input and output. Also, the AAD (for AES-GMC at least) * needs to logically go in front. */ - uio_t cuio; + zfs_uio_t cuio; + struct uio cuio_s; iovec_t iovecs[4]; uint64_t crypt = key->zk_crypt; uint_t enc_len, keydata_len, aad_len; @@ -447,6 +448,8 @@ ASSERT3U(crypt, <, ZIO_CRYPT_FUNCTIONS); ASSERT3U(cwkey->ck_format, ==, CRYPTO_KEY_RAW); + zfs_uio_init(&cuio, &cuio_s); + keydata_len = zio_crypt_table[crypt].ci_keylen; /* generate iv for wrapping the master and hmac key */ @@ -489,9 +492,9 @@ iovecs[0].iov_len = aad_len; enc_len = zio_crypt_table[crypt].ci_keylen + SHA512_HMAC_KEYLEN; - cuio.uio_iov = iovecs; - cuio.uio_iovcnt = 4; - cuio.uio_segflg = UIO_SYSSPACE; + GET_UIO_STRUCT(&cuio)->uio_iov = iovecs; + zfs_uio_iovcnt(&cuio) = 4; + zfs_uio_segflg(&cuio) = UIO_SYSSPACE; /* encrypt the keys and store the resulting ciphertext and mac */ ret = zio_do_crypt_uio_opencrypto(B_TRUE, NULL, crypt, cwkey, @@ -517,7 +520,8 @@ * input and output. Also, the AAD (for AES-GMC at least) * needs to logically go in front. */ - uio_t cuio; + zfs_uio_t cuio; + struct uio cuio_s; iovec_t iovecs[4]; void *src, *dst; uint_t enc_len, keydata_len, aad_len; @@ -528,6 +532,8 @@ keydata_len = zio_crypt_table[crypt].ci_keylen; rw_init(&key->zk_salt_lock, NULL, RW_DEFAULT, NULL); + zfs_uio_init(&cuio, &cuio_s); + /* * Since we only support one buffer, we need to copy * the encrypted buffer (source) to the plain buffer @@ -565,9 +571,9 @@ iovecs[0].iov_base = aad; iovecs[0].iov_len = aad_len; - cuio.uio_iov = iovecs; - cuio.uio_iovcnt = 4; - cuio.uio_segflg = UIO_SYSSPACE; + GET_UIO_STRUCT(&cuio)->uio_iov = iovecs; + zfs_uio_iovcnt(&cuio) = 4; + zfs_uio_segflg(&cuio) = UIO_SYSSPACE; /* decrypt the keys and store the result in the output buffers */ ret = zio_do_crypt_uio_opencrypto(B_FALSE, NULL, crypt, cwkey, @@ -1150,10 +1156,11 @@ } static void -zio_crypt_destroy_uio(uio_t *uio) +zio_crypt_destroy_uio(zfs_uio_t *uio) { - if (uio->uio_iov) - kmem_free(uio->uio_iov, uio->uio_iovcnt * sizeof (iovec_t)); + if (GET_UIO_STRUCT(uio)->uio_iov) + kmem_free(GET_UIO_STRUCT(uio)->uio_iov, + zfs_uio_iovcnt(uio) * sizeof (iovec_t)); } /* @@ -1247,14 +1254,14 @@ * accommodate some of the drivers, the authbuf needs to be logically before * the data. This means that we need to copy the source to the destination, * and set up an extra iovec_t at the beginning to handle the authbuf. - * It also means we'll only return one uio_t. + * 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, uio_t *puio, - uio_t *out_uio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len, + 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) { uint8_t *aadbuf = zio_buf_alloc(datalen); @@ -1398,8 +1405,8 @@ *enc_len = total_len; *authbuf = aadbuf; *auth_len = aad_len; - out_uio->uio_iov = dst_iovecs; - out_uio->uio_iovcnt = nr_iovecs; + GET_UIO_STRUCT(out_uio)->uio_iov = dst_iovecs; + zfs_uio_iovcnt(out_uio) = nr_iovecs; return (0); } @@ -1410,7 +1417,7 @@ static int zio_crypt_init_uios_dnode(boolean_t encrypt, uint64_t version, uint8_t *plainbuf, uint8_t *cipherbuf, uint_t datalen, boolean_t byteswap, - uio_t *puio, uio_t *out_uio, uint_t *enc_len, uint8_t **authbuf, + zfs_uio_t *puio, zfs_uio_t *out_uio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len, boolean_t *no_crypt) { uint8_t *aadbuf = zio_buf_alloc(datalen); @@ -1547,8 +1554,8 @@ *enc_len = total_len; *authbuf = aadbuf; *auth_len = aad_len; - out_uio->uio_iov = dst_iovecs; - out_uio->uio_iovcnt = nr_iovecs; + GET_UIO_STRUCT(out_uio)->uio_iov = dst_iovecs; + zfs_uio_iovcnt(out_uio) = nr_iovecs; return (0); } @@ -1556,7 +1563,7 @@ /* ARGSUSED */ static int zio_crypt_init_uios_normal(boolean_t encrypt, uint8_t *plainbuf, - uint8_t *cipherbuf, uint_t datalen, uio_t *puio, uio_t *out_uio, + uint8_t *cipherbuf, uint_t datalen, zfs_uio_t *puio, zfs_uio_t *out_uio, uint_t *enc_len) { int ret; @@ -1584,8 +1591,8 @@ cipher_iovecs[0].iov_len = datalen; *enc_len = datalen; - out_uio->uio_iov = cipher_iovecs; - out_uio->uio_iovcnt = nr_cipher; + GET_UIO_STRUCT(out_uio)->uio_iov = cipher_iovecs; + zfs_uio_iovcnt(out_uio) = nr_cipher; return (0); @@ -1596,8 +1603,8 @@ kmem_free(cipher_iovecs, nr_cipher * sizeof (iovec_t)); *enc_len = 0; - out_uio->uio_iov = NULL; - out_uio->uio_iovcnt = 0; + GET_UIO_STRUCT(out_uio)->uio_iov = NULL; + zfs_uio_iovcnt(out_uio) = 0; return (ret); } @@ -1613,8 +1620,8 @@ static int zio_crypt_init_uios(boolean_t encrypt, uint64_t version, dmu_object_type_t ot, uint8_t *plainbuf, uint8_t *cipherbuf, uint_t datalen, boolean_t byteswap, - uint8_t *mac, uio_t *puio, uio_t *cuio, uint_t *enc_len, uint8_t **authbuf, - uint_t *auth_len, boolean_t *no_crypt) + uint8_t *mac, zfs_uio_t *puio, zfs_uio_t *cuio, uint_t *enc_len, + uint8_t **authbuf, uint_t *auth_len, boolean_t *no_crypt) { int ret; iovec_t *mac_iov; @@ -1646,9 +1653,11 @@ goto error; /* populate the uios */ - cuio->uio_segflg = UIO_SYSSPACE; + zfs_uio_segflg(cuio) = UIO_SYSSPACE; - mac_iov = ((iovec_t *)&cuio->uio_iov[cuio->uio_iovcnt - 1]); + mac_iov = + ((iovec_t *)&(GET_UIO_STRUCT(cuio)-> + uio_iov[zfs_uio_iovcnt(cuio) - 1])); mac_iov->iov_base = (void *)mac; mac_iov->iov_len = ZIO_DATA_MAC_LEN; @@ -1675,14 +1684,18 @@ uint64_t crypt = key->zk_crypt; uint_t keydata_len = zio_crypt_table[crypt].ci_keylen; uint_t enc_len, auth_len; - uio_t puio, cuio; + zfs_uio_t puio, cuio; + struct uio puio_s, cuio_s; uint8_t enc_keydata[MASTER_KEY_MAX_LEN]; crypto_key_t tmp_ckey, *ckey = NULL; freebsd_crypt_session_t *tmpl = NULL; uint8_t *authbuf = NULL; - bzero(&puio, sizeof (uio_t)); - bzero(&cuio, sizeof (uio_t)); + + zfs_uio_init(&puio, &puio_s); + zfs_uio_init(&cuio, &cuio_s); + bzero(GET_UIO_STRUCT(&puio), sizeof (struct uio)); + bzero(GET_UIO_STRUCT(&cuio), sizeof (struct uio)); #ifdef FCRYPTO_DEBUG printf("%s(%s, %p, %p, %d, %p, %p, %u, %s, %p, %p, %p)\n", diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c @@ -746,12 +746,15 @@ */ static int -zvol_cdev_read(struct cdev *dev, struct uio *uio, int ioflag) +zvol_cdev_read(struct cdev *dev, struct uio *uio_s, int ioflag) { zvol_state_t *zv; uint64_t volsize; zfs_locked_range_t *lr; int error = 0; + zfs_uio_t uio; + + zfs_uio_init(&uio, uio_s); zv = dev->si_drv2; @@ -760,20 +763,20 @@ * uio_loffset == volsize isn't an error as * its required for EOF processing. */ - if (uio->uio_resid > 0 && - (uio->uio_loffset < 0 || uio->uio_loffset > volsize)) + if (zfs_uio_resid(&uio) > 0 && + (zfs_uio_offset(&uio) < 0 || zfs_uio_offset(&uio) > volsize)) return (SET_ERROR(EIO)); - lr = zfs_rangelock_enter(&zv->zv_rangelock, uio->uio_loffset, - uio->uio_resid, RL_READER); - while (uio->uio_resid > 0 && uio->uio_loffset < volsize) { - uint64_t bytes = MIN(uio->uio_resid, DMU_MAX_ACCESS >> 1); + lr = zfs_rangelock_enter(&zv->zv_rangelock, zfs_uio_offset(&uio), + zfs_uio_resid(&uio), RL_READER); + while (zfs_uio_resid(&uio) > 0 && zfs_uio_offset(&uio) < volsize) { + uint64_t bytes = MIN(zfs_uio_resid(&uio), DMU_MAX_ACCESS >> 1); /* don't read past the end */ - if (bytes > volsize - uio->uio_loffset) - bytes = volsize - uio->uio_loffset; + if (bytes > volsize - zfs_uio_offset(&uio)) + bytes = volsize - zfs_uio_offset(&uio); - error = dmu_read_uio_dnode(zv->zv_dn, uio, bytes); + error = dmu_read_uio_dnode(zv->zv_dn, &uio, bytes); if (error) { /* convert checksum errors into IO errors */ if (error == ECKSUM) @@ -787,20 +790,23 @@ } static int -zvol_cdev_write(struct cdev *dev, struct uio *uio, int ioflag) +zvol_cdev_write(struct cdev *dev, struct uio *uio_s, int ioflag) { zvol_state_t *zv; uint64_t volsize; zfs_locked_range_t *lr; int error = 0; boolean_t sync; + zfs_uio_t uio; zv = dev->si_drv2; volsize = zv->zv_volsize; - if (uio->uio_resid > 0 && - (uio->uio_loffset < 0 || uio->uio_loffset > volsize)) + zfs_uio_init(&uio, uio_s); + + if (zfs_uio_resid(&uio) > 0 && + (zfs_uio_offset(&uio) < 0 || zfs_uio_offset(&uio) > volsize)) return (SET_ERROR(EIO)); sync = (ioflag & IO_SYNC) || @@ -809,11 +815,11 @@ rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER); zvol_ensure_zilog(zv); - lr = zfs_rangelock_enter(&zv->zv_rangelock, uio->uio_loffset, - uio->uio_resid, RL_WRITER); - while (uio->uio_resid > 0 && uio->uio_loffset < volsize) { - uint64_t bytes = MIN(uio->uio_resid, DMU_MAX_ACCESS >> 1); - uint64_t off = uio->uio_loffset; + lr = zfs_rangelock_enter(&zv->zv_rangelock, zfs_uio_offset(&uio), + zfs_uio_resid(&uio), RL_WRITER); + while (zfs_uio_resid(&uio) > 0 && zfs_uio_offset(&uio) < volsize) { + uint64_t bytes = MIN(zfs_uio_resid(&uio), DMU_MAX_ACCESS >> 1); + uint64_t off = zfs_uio_offset(&uio); dmu_tx_t *tx = dmu_tx_create(zv->zv_objset); if (bytes > volsize - off) /* don't write past the end */ @@ -825,7 +831,7 @@ dmu_tx_abort(tx); break; } - error = dmu_write_uio_dnode(zv->zv_dn, uio, bytes, tx); + error = dmu_write_uio_dnode(zv->zv_dn, &uio, bytes, tx); if (error == 0) zvol_log_write(zv, tx, off, bytes, sync); dmu_tx_commit(tx); diff --git a/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c b/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c --- a/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c +++ b/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c @@ -284,9 +284,7 @@ __divdi3(int64_t u, int64_t v) { int64_t q, t; - // cppcheck-suppress shiftTooManyBitsSigned q = __udivdi3(abs64(u), abs64(v)); - // cppcheck-suppress shiftTooManyBitsSigned t = (u ^ v) >> 63; // If u, v have different return ((q ^ t) - t); // signs, negate q. } diff --git a/sys/contrib/openzfs/module/os/linux/spl/spl-kstat.c b/sys/contrib/openzfs/module/os/linux/spl/spl-kstat.c --- a/sys/contrib/openzfs/module/os/linux/spl/spl-kstat.c +++ b/sys/contrib/openzfs/module/os/linux/spl/spl-kstat.c @@ -486,7 +486,7 @@ f = filp->private_data; f->private = PDE_DATA(inode); - return (rc); + return (0); } static ssize_t diff --git a/sys/contrib/openzfs/module/os/linux/spl/spl-taskq.c b/sys/contrib/openzfs/module/os/linux/spl/spl-taskq.c --- a/sys/contrib/openzfs/module/os/linux/spl/spl-taskq.c +++ b/sys/contrib/openzfs/module/os/linux/spl/spl-taskq.c @@ -274,8 +274,6 @@ taskq_ent_t *t; taskq_thread_t *tqt; - ASSERT(tq); - if (!list_empty(&tq->tq_pend_list)) { t = list_entry(tq->tq_pend_list.next, taskq_ent_t, tqent_list); lowest_id = MIN(lowest_id, t->tqent_id); @@ -995,6 +993,7 @@ spin_unlock_irqrestore(&tq->tq_lock, flags); tsd_set(taskq_tsd, NULL); + thread_exit(); return (0); } diff --git a/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c b/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c --- a/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/abd_os.c @@ -185,7 +185,7 @@ } abd_t * -abd_alloc_struct(size_t size) +abd_alloc_struct_impl(size_t size) { /* * In Linux we do not use the size passed in during ABD @@ -193,18 +193,14 @@ */ abd_t *abd = kmem_cache_alloc(abd_cache, KM_PUSHPAGE); ASSERT3P(abd, !=, NULL); - list_link_init(&abd->abd_gang_link); - mutex_init(&abd->abd_mtx, NULL, MUTEX_DEFAULT, NULL); ABDSTAT_INCR(abdstat_struct_size, sizeof (abd_t)); return (abd); } void -abd_free_struct(abd_t *abd) +abd_free_struct_impl(abd_t *abd) { - mutex_destroy(&abd->abd_mtx); - ASSERT(!list_link_active(&abd->abd_gang_link)); kmem_cache_free(abd_cache, abd); ABDSTAT_INCR(abdstat_struct_size, -(int)sizeof (abd_t)); } @@ -472,14 +468,12 @@ ASSERT3U(table.nents, ==, nr_pages); abd_zero_scatter = abd_alloc_struct(SPA_MAXBLOCKSIZE); - abd_zero_scatter->abd_flags = ABD_FLAG_OWNER; + abd_zero_scatter->abd_flags |= ABD_FLAG_OWNER; ABD_SCATTER(abd_zero_scatter).abd_offset = 0; ABD_SCATTER(abd_zero_scatter).abd_sgl = table.sgl; ABD_SCATTER(abd_zero_scatter).abd_nents = nr_pages; abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE; - abd_zero_scatter->abd_parent = NULL; abd_zero_scatter->abd_flags |= ABD_FLAG_MULTI_CHUNK | ABD_FLAG_ZEROS; - zfs_refcount_create(&abd_zero_scatter->abd_children); abd_for_each_sg(abd_zero_scatter, sg, nr_pages, i) { sg_set_page(sg, abd_zero_page, PAGESIZE, 0); @@ -599,12 +593,11 @@ abd_zero_page = umem_alloc_aligned(PAGESIZE, 64, KM_SLEEP); memset(abd_zero_page, 0, PAGESIZE); abd_zero_scatter = abd_alloc_struct(SPA_MAXBLOCKSIZE); - abd_zero_scatter->abd_flags = ABD_FLAG_OWNER; + abd_zero_scatter->abd_flags |= ABD_FLAG_OWNER; abd_zero_scatter->abd_flags |= ABD_FLAG_MULTI_CHUNK | ABD_FLAG_ZEROS; ABD_SCATTER(abd_zero_scatter).abd_offset = 0; ABD_SCATTER(abd_zero_scatter).abd_nents = nr_pages; abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE; - abd_zero_scatter->abd_parent = NULL; zfs_refcount_create(&abd_zero_scatter->abd_children); ABD_SCATTER(abd_zero_scatter).abd_sgl = vmem_alloc(nr_pages * sizeof (struct scatterlist), KM_SLEEP); @@ -678,7 +671,6 @@ static void abd_free_zero_scatter(void) { - zfs_refcount_destroy(&abd_zero_scatter->abd_children); ABDSTAT_BUMPDOWN(abdstat_scatter_cnt); ABDSTAT_INCR(abdstat_scatter_data_size, -(int)PAGESIZE); ABDSTAT_BUMPDOWN(abdstat_scatter_page_multi_chunk); @@ -747,9 +739,7 @@ ABD_SCATTER(abd).abd_sgl = sg; abd_free_chunks(abd); - zfs_refcount_destroy(&abd->abd_children); abd_update_scatter_stats(abd, ABDSTAT_DECR); - abd_free_struct(abd); } /* @@ -770,9 +760,8 @@ } abd_t * -abd_get_offset_scatter(abd_t *sabd, size_t off) +abd_get_offset_scatter(abd_t *abd, abd_t *sabd, size_t off) { - abd_t *abd = NULL; int i = 0; struct scatterlist *sg = NULL; @@ -781,14 +770,14 @@ size_t new_offset = ABD_SCATTER(sabd).abd_offset + off; - abd = abd_alloc_struct(0); + if (abd == NULL) + abd = abd_alloc_struct(0); /* * Even if this buf is filesystem metadata, we only track that * if we own the underlying data buffer, which is not true in * this case. Therefore, we don't ever use ABD_FLAG_META here. */ - abd->abd_flags = 0; abd_for_each_sg(sabd, sg, ABD_SCATTER(sabd).abd_nents, i) { if (new_offset < sg->length) @@ -936,17 +925,28 @@ { unsigned long pos; - while (abd_is_gang(abd)) - abd = abd_gang_get_offset(abd, &off); + if (abd_is_gang(abd)) { + unsigned long count = 0; + + for (abd_t *cabd = abd_gang_get_offset(abd, &off); + cabd != NULL && size != 0; + cabd = list_next(&ABD_GANG(abd).abd_gang_chain, cabd)) { + ASSERT3U(off, <, cabd->abd_size); + int mysize = MIN(size, cabd->abd_size - off); + count += abd_nr_pages_off(cabd, mysize, off); + size -= mysize; + off = 0; + } + return (count); + } - ASSERT(!abd_is_gang(abd)); if (abd_is_linear(abd)) pos = (unsigned long)abd_to_buf(abd) + off; else pos = ABD_SCATTER(abd).abd_offset + off; - return ((pos + size + PAGESIZE - 1) >> PAGE_SHIFT) - - (pos >> PAGE_SHIFT); + return (((pos + size + PAGESIZE - 1) >> PAGE_SHIFT) - + (pos >> PAGE_SHIFT)); } static unsigned int @@ -1021,7 +1021,6 @@ abd_bio_map_off(struct bio *bio, abd_t *abd, unsigned int io_size, size_t off) { - int i; struct abd_iter aiter; ASSERT3U(io_size, <=, abd->abd_size - off); @@ -1035,7 +1034,7 @@ abd_iter_init(&aiter, abd); abd_iter_advance(&aiter, off); - for (i = 0; i < bio->bi_max_vecs; i++) { + for (int i = 0; i < bio->bi_max_vecs; i++) { struct page *pg; size_t len, sgoff, pgoff; struct scatterlist *sg; diff --git a/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c b/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c --- a/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c @@ -350,19 +350,14 @@ static dio_request_t * vdev_disk_dio_alloc(int bio_count) { - dio_request_t *dr; - int i; - - dr = kmem_zalloc(sizeof (dio_request_t) + + dio_request_t *dr = kmem_zalloc(sizeof (dio_request_t) + sizeof (struct bio *) * bio_count, KM_SLEEP); - if (dr) { - atomic_set(&dr->dr_ref, 0); - dr->dr_bio_count = bio_count; - dr->dr_error = 0; + atomic_set(&dr->dr_ref, 0); + dr->dr_bio_count = bio_count; + dr->dr_error = 0; - for (i = 0; i < dr->dr_bio_count; i++) - dr->dr_bio[i] = NULL; - } + for (int i = 0; i < dr->dr_bio_count; i++) + dr->dr_bio[i] = NULL; return (dr); } @@ -536,8 +531,9 @@ dio_request_t *dr; uint64_t abd_offset; uint64_t bio_offset; - int bio_size, bio_count = 16; - int i = 0, error = 0; + int bio_size; + int bio_count = 16; + int error = 0; struct blk_plug plug; /* @@ -552,8 +548,6 @@ retry: dr = vdev_disk_dio_alloc(bio_count); - if (dr == NULL) - return (SET_ERROR(ENOMEM)); if (zio && !(zio->io_flags & (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD))) bio_set_flags_failfast(bdev, &flags); @@ -561,26 +555,28 @@ dr->dr_zio = zio; /* - * When the IO size exceeds the maximum bio size for the request - * queue we are forced to break the IO in multiple bio's and wait - * for them all to complete. Ideally, all pool users will set - * their volume block size to match the maximum request size and - * the common case will be one bio per vdev IO request. + * Since bio's can have up to BIO_MAX_PAGES=256 iovec's, each of which + * is at least 512 bytes and at most PAGESIZE (typically 4K), one bio + * can cover at least 128KB and at most 1MB. When the required number + * of iovec's exceeds this, we are forced to break the IO in multiple + * bio's and wait for them all to complete. This is likely if the + * recordsize property is increased beyond 1MB. The default + * bio_count=16 should typically accommodate the maximum-size zio of + * 16MB. */ abd_offset = 0; bio_offset = io_offset; - bio_size = io_size; - for (i = 0; i <= dr->dr_bio_count; i++) { + bio_size = io_size; + for (int i = 0; i <= dr->dr_bio_count; i++) { /* Finished constructing bio's for given buffer */ if (bio_size <= 0) break; /* - * By default only 'bio_count' bio's per dio are allowed. - * However, if we find ourselves in a situation where more - * are needed we allocate a larger dio and warn the user. + * If additional bio's are required, we have to retry, but + * this should be rare - see the comment above. */ if (dr->dr_bio_count == i) { vdev_disk_dio_free(dr); @@ -622,9 +618,10 @@ blk_start_plug(&plug); /* Submit all bio's associated with this dio */ - for (i = 0; i < dr->dr_bio_count; i++) + for (int i = 0; i < dr->dr_bio_count; i++) { if (dr->dr_bio[i]) vdev_submit_bio(dr->dr_bio[i]); + } if (dr->dr_bio_count > 1) blk_finish_plug(&plug); diff --git a/sys/contrib/openzfs/module/zcommon/zfs_uio.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c rename from sys/contrib/openzfs/module/zcommon/zfs_uio.c rename to sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c --- a/sys/contrib/openzfs/module/zcommon/zfs_uio.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c @@ -55,7 +55,7 @@ * a non-zero errno on failure. */ static int -uiomove_iov(void *p, size_t n, enum uio_rw rw, struct uio *uio) +zfs_uiomove_iov(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio) { const struct iovec *iov = uio->uio_iov; size_t skip = uio->uio_skip; @@ -126,7 +126,7 @@ } static int -uiomove_bvec(void *p, size_t n, enum uio_rw rw, struct uio *uio) +zfs_uiomove_bvec(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio) { const struct bio_vec *bv = uio->uio_bvec; size_t skip = uio->uio_skip; @@ -160,7 +160,7 @@ #if defined(HAVE_VFS_IOV_ITER) static int -uiomove_iter(void *p, size_t n, enum uio_rw rw, struct uio *uio, +zfs_uiomove_iter(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio, boolean_t revert) { size_t cnt = MIN(n, uio->uio_resid); @@ -182,7 +182,7 @@ return (EFAULT); /* - * Revert advancing the uio_iter. This is set by uiocopy() + * Revert advancing the uio_iter. This is set by zfs_uiocopy() * to avoid consuming the uio and its iov_iter structure. */ if (revert) @@ -196,33 +196,69 @@ #endif int -uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio) +zfs_uiomove(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio) { if (uio->uio_segflg == UIO_BVEC) - return (uiomove_bvec(p, n, rw, uio)); + return (zfs_uiomove_bvec(p, n, rw, uio)); #if defined(HAVE_VFS_IOV_ITER) else if (uio->uio_segflg == UIO_ITER) - return (uiomove_iter(p, n, rw, uio, B_FALSE)); + return (zfs_uiomove_iter(p, n, rw, uio, B_FALSE)); #endif else - return (uiomove_iov(p, n, rw, uio)); + return (zfs_uiomove_iov(p, n, rw, uio)); } -EXPORT_SYMBOL(uiomove); +EXPORT_SYMBOL(zfs_uiomove); +/* + * Fault in the pages of the first n bytes specified by the uio structure. + * 1 byte in each page is touched and the uio struct is unmodified. Any + * error will terminate the process as this is only a best attempt to get + * the pages resident. + */ int -uio_prefaultpages(ssize_t n, struct uio *uio) +zfs_uio_prefaultpages(ssize_t n, zfs_uio_t *uio) { - struct iov_iter iter, *iterp = NULL; - -#if defined(HAVE_IOV_ITER_FAULT_IN_READABLE) - if (uio->uio_segflg == UIO_USERSPACE) { - iterp = &iter; - iov_iter_init_compat(iterp, READ, uio->uio_iov, - uio->uio_iovcnt, uio->uio_resid); + if (uio->uio_segflg == UIO_SYSSPACE || uio->uio_segflg == UIO_BVEC) { + /* There's never a need to fault in kernel pages */ + return (0); #if defined(HAVE_VFS_IOV_ITER) } else if (uio->uio_segflg == UIO_ITER) { - iterp = uio->uio_iter; + /* + * At least a Linux 4.9 kernel, iov_iter_fault_in_readable() + * can be relied on to fault in user pages when referenced. + */ + if (iov_iter_fault_in_readable(uio->uio_iter, n)) + return (EFAULT); #endif + } else { + /* Fault in all user pages */ + ASSERT3S(uio->uio_segflg, ==, UIO_USERSPACE); + const struct iovec *iov = uio->uio_iov; + int iovcnt = uio->uio_iovcnt; + size_t skip = uio->uio_skip; + uint8_t tmp; + caddr_t p; + + for (; n > 0 && iovcnt > 0; iov++, iovcnt--, skip = 0) { + ulong_t cnt = MIN(iov->iov_len - skip, n); + /* empty iov */ + if (cnt == 0) + continue; + n -= cnt; + /* touch each page in this segment. */ + p = iov->iov_base + skip; + while (cnt) { + if (get_user(tmp, (uint8_t *)p)) + return (EFAULT); + ulong_t incr = MIN(cnt, PAGESIZE); + p += incr; + cnt -= incr; + } + /* touch the last byte in case it straddles a page. */ + p--; + if (get_user(tmp, (uint8_t *)p)) + return (EFAULT); + } } if (iterp && iov_iter_fault_in_readable(iterp, n)) @@ -230,40 +266,40 @@ #endif return (0); } -EXPORT_SYMBOL(uio_prefaultpages); +EXPORT_SYMBOL(zfs_uio_prefaultpages); /* - * The same as uiomove() but doesn't modify uio structure. + * The same as zfs_uiomove() but doesn't modify uio structure. * return in cbytes how many bytes were copied. */ int -uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes) +zfs_uiocopy(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio, size_t *cbytes) { - struct uio uio_copy; + zfs_uio_t uio_copy; int ret; - bcopy(uio, &uio_copy, sizeof (struct uio)); + bcopy(uio, &uio_copy, sizeof (zfs_uio_t)); if (uio->uio_segflg == UIO_BVEC) - ret = uiomove_bvec(p, n, rw, &uio_copy); + ret = zfs_uiomove_bvec(p, n, rw, &uio_copy); #if defined(HAVE_VFS_IOV_ITER) else if (uio->uio_segflg == UIO_ITER) - ret = uiomove_iter(p, n, rw, &uio_copy, B_TRUE); + ret = zfs_uiomove_iter(p, n, rw, &uio_copy, B_TRUE); #endif else - ret = uiomove_iov(p, n, rw, &uio_copy); + ret = zfs_uiomove_iov(p, n, rw, &uio_copy); *cbytes = uio->uio_resid - uio_copy.uio_resid; return (ret); } -EXPORT_SYMBOL(uiocopy); +EXPORT_SYMBOL(zfs_uiocopy); /* * Drop the next n chars out of *uio. */ void -uioskip(uio_t *uio, size_t n) +zfs_uioskip(zfs_uio_t *uio, size_t n) { if (n > uio->uio_resid) return; @@ -292,5 +328,6 @@ uio->uio_loffset += n; uio->uio_resid -= n; } -EXPORT_SYMBOL(uioskip); +EXPORT_SYMBOL(zfs_uioskip); + #endif /* _KERNEL */ diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c @@ -1772,7 +1772,7 @@ *ipp = ZTOI(zp); if (*ipp) - zfs_inode_update(ITOZ(*ipp)); + zfs_znode_update_vfs(ITOZ(*ipp)); ZFS_EXIT(zfsvfs); return (0); diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c @@ -87,15 +87,18 @@ * must be checked with ZFS_VERIFY_ZP(zp). Both of these macros * can return EIO from the calling function. * - * (2) zrele() should always be the last thing except for zil_commit() - * (if necessary) and ZFS_EXIT(). This is for 3 reasons: - * First, if it's the last reference, the vnode/znode - * can be freed, so the zp may point to freed memory. Second, the last - * reference will call zfs_zinactive(), which may induce a lot of work -- - * pushing cached pages (which acquires range locks) and syncing out - * cached atime changes. Third, zfs_zinactive() may require a new tx, - * which could deadlock the system if you were already holding one. - * If you must call zrele() within a tx then use zfs_zrele_async(). + * (2) zrele() should always be the last thing except for zil_commit() (if + * necessary) and ZFS_EXIT(). This is for 3 reasons: First, if it's the + * last reference, the vnode/znode can be freed, so the zp may point to + * freed memory. Second, the last reference will call zfs_zinactive(), + * which may induce a lot of work -- pushing cached pages (which acquires + * range locks) and syncing out cached atime changes. Third, + * zfs_zinactive() may require a new tx, which could deadlock the system + * if you were already holding one. This deadlock occurs because the tx + * currently being operated on prevents a txg from syncing, which + * prevents the new tx from progressing, resulting in a deadlock. If you + * must call zrele() within a tx, use zfs_zrele_async(). Note that iput() + * is a synonym for zrele(). * * (3) All range locks must be grabbed before calling dmu_tx_assign(), * as they can span dmu_tx_assign() calls. @@ -298,7 +301,7 @@ * the file is memory mapped. */ int -mappedread(znode_t *zp, int nbytes, uio_t *uio) +mappedread(znode_t *zp, int nbytes, zfs_uio_t *uio) { struct inode *ip = ZTOI(zp); struct address_space *mp = ip->i_mapping; @@ -320,7 +323,7 @@ unlock_page(pp); pb = kmap(pp); - error = uiomove(pb + off, bytes, UIO_READ, uio); + error = zfs_uiomove(pb + off, bytes, UIO_READ, uio); kunmap(pp); if (mapping_writably_mapped(mp)) @@ -372,8 +375,8 @@ iov.iov_base = (void *)data; iov.iov_len = len; - uio_t uio; - uio_iovec_init(&uio, &iov, 1, pos, UIO_SYSSPACE, len, 0); + zfs_uio_t uio; + zfs_uio_iovec_init(&uio, &iov, 1, pos, UIO_SYSSPACE, len, 0); cookie = spl_fstrans_mark(); error = zfs_write(zp, &uio, 0, kcred); @@ -381,8 +384,8 @@ if (error == 0) { if (residp != NULL) - *residp = uio_resid(&uio); - else if (uio_resid(&uio) != 0) + *residp = zfs_uio_resid(&uio); + else if (zfs_uio_resid(&uio) != 0) error = SET_ERROR(EIO); } @@ -398,11 +401,18 @@ ASSERT(atomic_read(&ip->i_count) > 0); ASSERT(os != NULL); - if (atomic_read(&ip->i_count) == 1) + /* + * If decrementing the count would put us at 0, we can't do it inline + * here, because that would be synchronous. Instead, dispatch an iput + * to run later. + * + * For more information on the dangers of a synchronous iput, see the + * header comment of this file. + */ + if (!atomic_add_unless(&ip->i_count, -1, 1)) { VERIFY(taskq_dispatch(dsl_pool_zrele_taskq(dmu_objset_pool(os)), (task_func_t *)iput, ip, TQ_SLEEP) != TASKQID_INVALID); - else - zrele(zp); + } } @@ -516,7 +526,7 @@ error = zfs_dirlook(zdp, nm, zpp, flags, direntflags, realpnp); if ((error == 0) && (*zpp)) - zfs_inode_update(*zpp); + zfs_znode_update_vfs(*zpp); ZFS_EXIT(zfsvfs); return (error); @@ -779,8 +789,8 @@ if (zp) zrele(zp); } else { - zfs_inode_update(dzp); - zfs_inode_update(zp); + zfs_znode_update_vfs(dzp); + zfs_znode_update_vfs(zp); *zpp = zp; } @@ -902,8 +912,8 @@ if (zp) zrele(zp); } else { - zfs_inode_update(dzp); - zfs_inode_update(zp); + zfs_znode_update_vfs(dzp); + zfs_znode_update_vfs(zp); *ipp = ZTOI(zp); } @@ -1129,8 +1139,8 @@ pn_free(realnmp); zfs_dirent_unlock(dl); - zfs_inode_update(dzp); - zfs_inode_update(zp); + zfs_znode_update_vfs(dzp); + zfs_znode_update_vfs(zp); if (delete_now) zrele(zp); @@ -1138,7 +1148,7 @@ zfs_zrele_async(zp); if (xzp) { - zfs_inode_update(xzp); + zfs_znode_update_vfs(xzp); zfs_zrele_async(xzp); } @@ -1335,8 +1345,8 @@ if (error != 0) { zrele(zp); } else { - zfs_inode_update(dzp); - zfs_inode_update(zp); + zfs_znode_update_vfs(dzp); + zfs_znode_update_vfs(zp); } ZFS_EXIT(zfsvfs); return (error); @@ -1461,8 +1471,8 @@ out: zfs_dirent_unlock(dl); - zfs_inode_update(dzp); - zfs_inode_update(zp); + zfs_znode_update_vfs(dzp); + zfs_znode_update_vfs(zp); zrele(zp); if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) @@ -2532,7 +2542,7 @@ err2 = zfs_setattr_dir(attrzp); zrele(attrzp); } - zfs_inode_update(zp); + zfs_znode_update_vfs(zp); } out2: @@ -2990,17 +3000,17 @@ zfs_dirent_unlock(sdl); zfs_dirent_unlock(tdl); - zfs_inode_update(sdzp); + zfs_znode_update_vfs(sdzp); if (sdzp == tdzp) rw_exit(&sdzp->z_name_lock); if (sdzp != tdzp) - zfs_inode_update(tdzp); + zfs_znode_update_vfs(tdzp); - zfs_inode_update(szp); + zfs_znode_update_vfs(szp); zrele(szp); if (tzp) { - zfs_inode_update(tzp); + zfs_znode_update_vfs(tzp); zrele(tzp); } @@ -3159,8 +3169,8 @@ txtype |= TX_CI; zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link); - zfs_inode_update(dzp); - zfs_inode_update(zp); + zfs_znode_update_vfs(dzp); + zfs_znode_update_vfs(zp); } zfs_acl_ids_free(&acl_ids); @@ -3198,7 +3208,7 @@ */ /* ARGSUSED */ int -zfs_readlink(struct inode *ip, uio_t *uio, cred_t *cr) +zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr) { znode_t *zp = ITOZ(ip); zfsvfs_t *zfsvfs = ITOZSB(ip); @@ -3409,8 +3419,8 @@ if (is_tmpfile && zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED) txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), txg); - zfs_inode_update(tdzp); - zfs_inode_update(szp); + zfs_znode_update_vfs(tdzp); + zfs_znode_update_vfs(szp); ZFS_EXIT(zfsvfs); return (error); } diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c @@ -479,14 +479,10 @@ } /* - * Update the embedded inode given the znode. We should work toward - * eliminating this function as soon as possible by removing values - * which are duplicated between the znode and inode. If the generic - * inode has the correct field it should be used, and the ZFS code - * updated to access the inode. This can be done incrementally. + * Update the embedded inode given the znode. */ void -zfs_inode_update(znode_t *zp) +zfs_znode_update_vfs(znode_t *zp) { zfsvfs_t *zfsvfs; struct inode *ip; @@ -602,7 +598,7 @@ ZFS_TIME_DECODE(&ip->i_ctime, ctime); ip->i_ino = zp->z_id; - zfs_inode_update(zp); + zfs_znode_update_vfs(zp); zfs_inode_set_ops(zfsvfs, ip); /* @@ -1278,7 +1274,7 @@ zp->z_blksz = doi.doi_data_block_size; zp->z_atime_dirty = B_FALSE; - zfs_inode_update(zp); + zfs_znode_update_vfs(zp); /* * If the file has zero links, then it has been unlinked on the send @@ -1796,7 +1792,7 @@ dmu_tx_commit(tx); - zfs_inode_update(zp); + zfs_znode_update_vfs(zp); error = 0; out: @@ -2127,8 +2123,10 @@ size_t complen; int is_xattrdir = 0; - if (prevdb) + if (prevdb) { + ASSERT(prevhdl != NULL); zfs_release_sa_handle(prevhdl, prevdb, FTAG); + } if ((error = zfs_obj_to_pobj(osp, sa_hdl, sa_table, &pobj, &is_xattrdir)) != 0) diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c b/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c @@ -376,7 +376,7 @@ static int zio_do_crypt_uio(boolean_t encrypt, uint64_t crypt, crypto_key_t *key, crypto_ctx_template_t tmpl, uint8_t *ivbuf, uint_t datalen, - uio_t *puio, uio_t *cuio, uint8_t *authbuf, uint_t auth_len) + zfs_uio_t *puio, zfs_uio_t *cuio, uint8_t *authbuf, uint_t auth_len) { int ret; crypto_data_t plaindata, cipherdata; @@ -479,7 +479,7 @@ uint8_t *mac, uint8_t *keydata_out, uint8_t *hmac_keydata_out) { int ret; - uio_t puio, cuio; + zfs_uio_t puio, cuio; uint64_t aad[3]; iovec_t plain_iovecs[2], cipher_iovecs[3]; uint64_t crypt = key->zk_crypt; @@ -495,7 +495,7 @@ if (ret != 0) goto error; - /* initialize uio_ts */ + /* initialize zfs_uio_ts */ plain_iovecs[0].iov_base = key->zk_master_keydata; plain_iovecs[0].iov_len = keydata_len; plain_iovecs[1].iov_base = key->zk_hmac_keydata; @@ -550,7 +550,7 @@ uint8_t *mac, zio_crypt_key_t *key) { crypto_mechanism_t mech; - uio_t puio, cuio; + zfs_uio_t puio, cuio; uint64_t aad[3]; iovec_t plain_iovecs[2], cipher_iovecs[3]; uint_t enc_len, keydata_len, aad_len; @@ -563,7 +563,7 @@ keydata_len = zio_crypt_table[crypt].ci_keylen; - /* initialize uio_ts */ + /* initialize zfs_uio_ts */ plain_iovecs[0].iov_base = key->zk_master_keydata; plain_iovecs[0].iov_len = keydata_len; plain_iovecs[1].iov_base = key->zk_hmac_keydata; @@ -1296,7 +1296,7 @@ } static void -zio_crypt_destroy_uio(uio_t *uio) +zio_crypt_destroy_uio(zfs_uio_t *uio) { if (uio->uio_iov) kmem_free(uio->uio_iov, uio->uio_iovcnt * sizeof (iovec_t)); @@ -1386,8 +1386,8 @@ */ static int zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, - uint8_t *cipherbuf, uint_t datalen, boolean_t byteswap, uio_t *puio, - uio_t *cuio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len, + uint8_t *cipherbuf, uint_t datalen, boolean_t byteswap, zfs_uio_t *puio, + zfs_uio_t *cuio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len, boolean_t *no_crypt) { int ret; @@ -1581,7 +1581,7 @@ static int zio_crypt_init_uios_dnode(boolean_t encrypt, uint64_t version, uint8_t *plainbuf, uint8_t *cipherbuf, uint_t datalen, boolean_t byteswap, - uio_t *puio, uio_t *cuio, uint_t *enc_len, uint8_t **authbuf, + zfs_uio_t *puio, zfs_uio_t *cuio, uint_t *enc_len, uint8_t **authbuf, uint_t *auth_len, boolean_t *no_crypt) { int ret; @@ -1764,7 +1764,7 @@ static int zio_crypt_init_uios_normal(boolean_t encrypt, uint8_t *plainbuf, - uint8_t *cipherbuf, uint_t datalen, uio_t *puio, uio_t *cuio, + uint8_t *cipherbuf, uint_t datalen, zfs_uio_t *puio, zfs_uio_t *cuio, uint_t *enc_len) { int ret; @@ -1824,8 +1824,8 @@ static int zio_crypt_init_uios(boolean_t encrypt, uint64_t version, dmu_object_type_t ot, uint8_t *plainbuf, uint8_t *cipherbuf, uint_t datalen, boolean_t byteswap, - uint8_t *mac, uio_t *puio, uio_t *cuio, uint_t *enc_len, uint8_t **authbuf, - uint_t *auth_len, boolean_t *no_crypt) + uint8_t *mac, zfs_uio_t *puio, zfs_uio_t *cuio, uint_t *enc_len, + uint8_t **authbuf, uint_t *auth_len, boolean_t *no_crypt) { int ret; iovec_t *mac_iov; @@ -1884,7 +1884,7 @@ uint64_t crypt = key->zk_crypt; uint_t keydata_len = zio_crypt_table[crypt].ci_keylen; uint_t enc_len, auth_len; - uio_t puio, cuio; + zfs_uio_t puio, cuio; uint8_t enc_keydata[MASTER_KEY_MAX_LEN]; crypto_key_t tmp_ckey, *ckey = NULL; crypto_ctx_template_t tmpl; @@ -1950,8 +1950,8 @@ /* If the hardware implementation fails fall back to software */ } - bzero(&puio, sizeof (uio_t)); - bzero(&cuio, sizeof (uio_t)); + bzero(&puio, sizeof (zfs_uio_t)); + bzero(&cuio, sizeof (zfs_uio_t)); /* create uios for encryption */ ret = zio_crypt_init_uios(encrypt, key->zk_version, ot, plainbuf, diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c @@ -242,13 +242,13 @@ * Otherwise, for older kernels extract the iovec and pass it instead. */ static void -zpl_uio_init(uio_t *uio, struct kiocb *kiocb, struct iov_iter *to, +zpl_uio_init(zfs_uio_t *uio, struct kiocb *kiocb, struct iov_iter *to, loff_t pos, ssize_t count, size_t skip) { #if defined(HAVE_VFS_IOV_ITER) - uio_iov_iter_init(uio, to, pos, count, skip); + zfs_uio_iov_iter_init(uio, to, pos, count, skip); #else - uio_iovec_init(uio, to->iov, to->nr_segs, pos, + zfs_uio_iovec_init(uio, to->iov, to->nr_segs, pos, to->type & ITER_KVEC ? UIO_SYSSPACE : UIO_USERSPACE, count, skip); #endif @@ -261,7 +261,7 @@ fstrans_cookie_t cookie; struct file *filp = kiocb->ki_filp; ssize_t count = iov_iter_count(to); - uio_t uio; + zfs_uio_t uio; zpl_uio_init(&uio, kiocb, to, kiocb->ki_pos, count, 0); @@ -317,7 +317,7 @@ fstrans_cookie_t cookie; struct file *filp = kiocb->ki_filp; struct inode *ip = filp->f_mapping->host; - uio_t uio; + zfs_uio_t uio; size_t count = 0; ssize_t ret; @@ -364,8 +364,8 @@ if (ret) return (ret); - uio_t uio; - uio_iovec_init(&uio, iov, nr_segs, kiocb->ki_pos, UIO_USERSPACE, + zfs_uio_t uio; + zfs_uio_iovec_init(&uio, iov, nr_segs, kiocb->ki_pos, UIO_USERSPACE, count, 0); crhold(cr); @@ -407,8 +407,8 @@ if (ret) return (ret); - uio_t uio; - uio_iovec_init(&uio, iov, nr_segs, kiocb->ki_pos, UIO_USERSPACE, + zfs_uio_t uio; + zfs_uio_iovec_init(&uio, iov, nr_segs, kiocb->ki_pos, UIO_USERSPACE, count, 0); crhold(cr); diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c @@ -499,8 +499,8 @@ iov.iov_len = MAXPATHLEN; iov.iov_base = kmem_zalloc(MAXPATHLEN, KM_SLEEP); - uio_t uio; - uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, MAXPATHLEN - 1, 0); + zfs_uio_t uio; + zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, MAXPATHLEN - 1, 0); cookie = spl_fstrans_mark(); error = -zfs_readlink(ip, &uio, cr); diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_xattr.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_xattr.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_xattr.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_xattr.c @@ -306,15 +306,15 @@ iov.iov_base = (void *)value; iov.iov_len = size; - uio_t uio; - uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, size, 0); + zfs_uio_t uio; + zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, size, 0); cookie = spl_fstrans_mark(); error = -zfs_read(ITOZ(xip), &uio, 0, cr); spl_fstrans_unmark(cookie); if (error == 0) - error = size - uio_resid(&uio); + error = size - zfs_uio_resid(&uio); out: if (xzp) zrele(xzp); diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c --- a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c +++ b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c @@ -85,9 +85,9 @@ zv_request_t *zvr = arg; struct bio *bio = zvr->bio; int error = 0; - uio_t uio; + zfs_uio_t uio; - uio_bvec_init(&uio, bio); + zfs_uio_bvec_init(&uio, bio); zvol_state_t *zv = zvr->zv; ASSERT3P(zv, !=, NULL); @@ -247,9 +247,9 @@ zv_request_t *zvr = arg; struct bio *bio = zvr->bio; int error = 0; - uio_t uio; + zfs_uio_t uio; - uio_bvec_init(&uio, bio); + zfs_uio_bvec_init(&uio, bio); zvol_state_t *zv = zvr->zv; ASSERT3P(zv, !=, NULL); diff --git a/sys/contrib/openzfs/module/zfs/abd.c b/sys/contrib/openzfs/module/zfs/abd.c --- a/sys/contrib/openzfs/module/zfs/abd.c +++ b/sys/contrib/openzfs/module/zfs/abd.c @@ -105,26 +105,6 @@ /* see block comment above for description */ int zfs_abd_scatter_enabled = B_TRUE; -boolean_t -abd_is_linear(abd_t *abd) -{ - return ((abd->abd_flags & ABD_FLAG_LINEAR) != 0 ? B_TRUE : B_FALSE); -} - -boolean_t -abd_is_linear_page(abd_t *abd) -{ - return ((abd->abd_flags & ABD_FLAG_LINEAR_PAGE) != 0 ? - B_TRUE : B_FALSE); -} - -boolean_t -abd_is_gang(abd_t *abd) -{ - return ((abd->abd_flags & ABD_FLAG_GANG) != 0 ? B_TRUE : - B_FALSE); -} - void abd_verify(abd_t *abd) { @@ -133,8 +113,10 @@ ASSERT3U(abd->abd_flags, ==, abd->abd_flags & (ABD_FLAG_LINEAR | ABD_FLAG_OWNER | ABD_FLAG_META | ABD_FLAG_MULTI_ZONE | ABD_FLAG_MULTI_CHUNK | ABD_FLAG_LINEAR_PAGE | ABD_FLAG_GANG | - ABD_FLAG_GANG_FREE | ABD_FLAG_ZEROS)); + ABD_FLAG_GANG_FREE | ABD_FLAG_ZEROS | ABD_FLAG_ALLOCD)); +#ifdef ZFS_DEBUG IMPLY(abd->abd_parent != NULL, !(abd->abd_flags & ABD_FLAG_OWNER)); +#endif IMPLY(abd->abd_flags & ABD_FLAG_META, abd->abd_flags & ABD_FLAG_OWNER); if (abd_is_linear(abd)) { ASSERT3P(ABD_LINEAR_BUF(abd), !=, NULL); @@ -153,11 +135,43 @@ } } -uint_t -abd_get_size(abd_t *abd) +static void +abd_init_struct(abd_t *abd) { - abd_verify(abd); - return (abd->abd_size); + list_link_init(&abd->abd_gang_link); + mutex_init(&abd->abd_mtx, NULL, MUTEX_DEFAULT, NULL); + abd->abd_flags = 0; +#ifdef ZFS_DEBUG + zfs_refcount_create(&abd->abd_children); + abd->abd_parent = NULL; +#endif + abd->abd_size = 0; +} + +static void +abd_fini_struct(abd_t *abd) +{ + mutex_destroy(&abd->abd_mtx); + ASSERT(!list_link_active(&abd->abd_gang_link)); +#ifdef ZFS_DEBUG + zfs_refcount_destroy(&abd->abd_children); +#endif +} + +abd_t * +abd_alloc_struct(size_t size) +{ + abd_t *abd = abd_alloc_struct_impl(size); + abd_init_struct(abd); + abd->abd_flags |= ABD_FLAG_ALLOCD; + return (abd); +} + +void +abd_free_struct(abd_t *abd) +{ + abd_fini_struct(abd); + abd_free_struct_impl(abd); } /* @@ -173,7 +187,7 @@ VERIFY3U(size, <=, SPA_MAXBLOCKSIZE); abd_t *abd = abd_alloc_struct(size); - abd->abd_flags = ABD_FLAG_OWNER; + abd->abd_flags |= ABD_FLAG_OWNER; abd->abd_u.abd_scatter.abd_offset = 0; abd_alloc_chunks(abd, size); @@ -181,65 +195,12 @@ abd->abd_flags |= ABD_FLAG_META; } abd->abd_size = size; - abd->abd_parent = NULL; - zfs_refcount_create(&abd->abd_children); abd_update_scatter_stats(abd, ABDSTAT_INCR); return (abd); } -static void -abd_free_scatter(abd_t *abd) -{ - abd_free_chunks(abd); - - zfs_refcount_destroy(&abd->abd_children); - abd_update_scatter_stats(abd, ABDSTAT_DECR); - abd_free_struct(abd); -} - -static void -abd_put_gang_abd(abd_t *abd) -{ - ASSERT(abd_is_gang(abd)); - abd_t *cabd; - - while ((cabd = list_remove_head(&ABD_GANG(abd).abd_gang_chain)) - != NULL) { - ASSERT0(cabd->abd_flags & ABD_FLAG_GANG_FREE); - abd->abd_size -= cabd->abd_size; - abd_put(cabd); - } - ASSERT0(abd->abd_size); - list_destroy(&ABD_GANG(abd).abd_gang_chain); -} - -/* - * Free an ABD allocated from abd_get_offset() or abd_get_from_buf(). Will not - * free the underlying scatterlist or buffer. - */ -void -abd_put(abd_t *abd) -{ - if (abd == NULL) - return; - - abd_verify(abd); - ASSERT(!(abd->abd_flags & ABD_FLAG_OWNER)); - - if (abd->abd_parent != NULL) { - (void) zfs_refcount_remove_many(&abd->abd_parent->abd_children, - abd->abd_size, abd); - } - - if (abd_is_gang(abd)) - abd_put_gang_abd(abd); - - zfs_refcount_destroy(&abd->abd_children); - abd_free_struct(abd); -} - /* * Allocate an ABD that must be linear, along with its own underlying data * buffer. Only use this when it would be very annoying to write your ABD @@ -252,13 +213,11 @@ VERIFY3U(size, <=, SPA_MAXBLOCKSIZE); - abd->abd_flags = ABD_FLAG_LINEAR | ABD_FLAG_OWNER; + abd->abd_flags |= ABD_FLAG_LINEAR | ABD_FLAG_OWNER; if (is_metadata) { abd->abd_flags |= ABD_FLAG_META; } abd->abd_size = size; - abd->abd_parent = NULL; - zfs_refcount_create(&abd->abd_children); if (is_metadata) { ABD_LINEAR_BUF(abd) = zio_buf_alloc(size); @@ -284,19 +243,16 @@ zio_data_buf_free(ABD_LINEAR_BUF(abd), abd->abd_size); } - zfs_refcount_destroy(&abd->abd_children); abd_update_linear_stats(abd, ABDSTAT_DECR); - - abd_free_struct(abd); } static void -abd_free_gang_abd(abd_t *abd) +abd_free_gang(abd_t *abd) { ASSERT(abd_is_gang(abd)); - abd_t *cabd = list_head(&ABD_GANG(abd).abd_gang_chain); + abd_t *cabd; - while (cabd != NULL) { + while ((cabd = list_head(&ABD_GANG(abd).abd_gang_chain)) != NULL) { /* * We must acquire the child ABDs mutex to ensure that if it * is being added to another gang ABD we will set the link @@ -307,24 +263,29 @@ ASSERT(list_link_active(&cabd->abd_gang_link)); list_remove(&ABD_GANG(abd).abd_gang_chain, cabd); mutex_exit(&cabd->abd_mtx); - abd->abd_size -= cabd->abd_size; - if (cabd->abd_flags & ABD_FLAG_GANG_FREE) { - if (cabd->abd_flags & ABD_FLAG_OWNER) - abd_free(cabd); - else - abd_put(cabd); - } - cabd = list_head(&ABD_GANG(abd).abd_gang_chain); + if (cabd->abd_flags & ABD_FLAG_GANG_FREE) + abd_free(cabd); } - ASSERT0(abd->abd_size); list_destroy(&ABD_GANG(abd).abd_gang_chain); - zfs_refcount_destroy(&abd->abd_children); - abd_free_struct(abd); +} + +static void +abd_free_scatter(abd_t *abd) +{ + abd_free_chunks(abd); + abd_update_scatter_stats(abd, ABDSTAT_DECR); } /* - * Free an ABD. Only use this on ABDs allocated with abd_alloc(), - * abd_alloc_linear(), or abd_alloc_gang_abd(). + * Free an ABD. Use with any kind of abd: those created with abd_alloc_*() + * and abd_get_*(), including abd_get_offset_struct(). + * + * If the ABD was created with abd_alloc_*(), the underlying data + * (scatterlist or linear buffer) will also be freed. (Subject to ownership + * changes via abd_*_ownership_of_buf().) + * + * Unless the ABD was created with abd_get_offset_struct(), the abd_t will + * also be freed. */ void abd_free(abd_t *abd) @@ -333,14 +294,30 @@ return; abd_verify(abd); - ASSERT3P(abd->abd_parent, ==, NULL); - ASSERT(abd->abd_flags & ABD_FLAG_OWNER); - if (abd_is_linear(abd)) - abd_free_linear(abd); - else if (abd_is_gang(abd)) - abd_free_gang_abd(abd); - else - abd_free_scatter(abd); +#ifdef ZFS_DEBUG + IMPLY(abd->abd_flags & ABD_FLAG_OWNER, abd->abd_parent == NULL); +#endif + + if (abd_is_gang(abd)) { + abd_free_gang(abd); + } else if (abd_is_linear(abd)) { + if (abd->abd_flags & ABD_FLAG_OWNER) + abd_free_linear(abd); + } else { + if (abd->abd_flags & ABD_FLAG_OWNER) + abd_free_scatter(abd); + } + +#ifdef ZFS_DEBUG + if (abd->abd_parent != NULL) { + (void) zfs_refcount_remove_many(&abd->abd_parent->abd_children, + abd->abd_size, abd); + } +#endif + + abd_fini_struct(abd); + if (abd->abd_flags & ABD_FLAG_ALLOCD) + abd_free_struct_impl(abd); } /* @@ -359,24 +336,18 @@ } } - /* * Create gang ABD that will be the head of a list of ABD's. This is used * to "chain" scatter/gather lists together when constructing aggregated * IO's. To free this abd, abd_free() must be called. */ abd_t * -abd_alloc_gang_abd(void) +abd_alloc_gang(void) { - abd_t *abd; - - abd = abd_alloc_struct(0); - abd->abd_flags = ABD_FLAG_GANG | ABD_FLAG_OWNER; - abd->abd_size = 0; - abd->abd_parent = NULL; + abd_t *abd = abd_alloc_struct(0); + abd->abd_flags |= ABD_FLAG_GANG | ABD_FLAG_OWNER; list_create(&ABD_GANG(abd).abd_gang_chain, sizeof (abd_t), offsetof(abd_t, abd_gang_link)); - zfs_refcount_create(&abd->abd_children); return (abd); } @@ -392,8 +363,8 @@ if (free_on_free) { /* * If the parent is responsible for freeing the child gang - * ABD we will just splice the childs children ABD list to - * the parents list and immediately free the child gang ABD + * ABD we will just splice the child's children ABD list to + * the parent's list and immediately free the child gang ABD * struct. The parent gang ABDs children from the child gang * will retain all the free_on_free settings after being * added to the parents list. @@ -403,7 +374,7 @@ &ABD_GANG(cabd).abd_gang_chain); ASSERT(list_is_empty(&ABD_GANG(cabd).abd_gang_chain)); abd_verify(pabd); - abd_free_struct(cabd); + abd_free(cabd); } else { for (abd_t *child = list_head(&ABD_GANG(cabd).abd_gang_chain); child != NULL; @@ -431,7 +402,7 @@ /* * If the child being added is a gang ABD, we will add the - * childs ABDs to the parent gang ABD. This alllows us to account + * child's ABDs to the parent gang ABD. This allows us to account * for the offset correctly in the parent gang ABD. */ if (abd_is_gang(cabd)) { @@ -458,7 +429,7 @@ * allocated ABD with ABD_FLAG_GANG_FREE, before * adding it to the gang ABD's list, to make the * gang ABD aware that it is responsible to call - * abd_put(). We use abd_get_offset() in order + * abd_free(). We use abd_get_offset() in order * to just allocate a new ABD but avoid copying the * data over into the newly allocated ABD. * @@ -515,73 +486,96 @@ } /* - * Allocate a new ABD to point to offset off of sabd. It shares the underlying - * buffer data with sabd. Use abd_put() to free. sabd must not be freed while - * any derived ABDs exist. + * Allocate a new ABD, using the provided struct (if non-NULL, and if + * circumstances allow - otherwise allocate the struct). The returned ABD will + * point to offset off of sabd. It shares the underlying buffer data with sabd. + * Use abd_free() to free. sabd must not be freed while any derived ABDs exist. */ static abd_t * -abd_get_offset_impl(abd_t *sabd, size_t off, size_t size) +abd_get_offset_impl(abd_t *abd, abd_t *sabd, size_t off, size_t size) { - abd_t *abd = NULL; - abd_verify(sabd); - ASSERT3U(off, <=, sabd->abd_size); + ASSERT3U(off + size, <=, sabd->abd_size); if (abd_is_linear(sabd)) { - abd = abd_alloc_struct(0); - + if (abd == NULL) + abd = abd_alloc_struct(0); /* * Even if this buf is filesystem metadata, we only track that * if we own the underlying data buffer, which is not true in * this case. Therefore, we don't ever use ABD_FLAG_META here. */ - abd->abd_flags = ABD_FLAG_LINEAR; + abd->abd_flags |= ABD_FLAG_LINEAR; ABD_LINEAR_BUF(abd) = (char *)ABD_LINEAR_BUF(sabd) + off; } else if (abd_is_gang(sabd)) { size_t left = size; - abd = abd_alloc_gang_abd(); + if (abd == NULL) { + abd = abd_alloc_gang(); + } else { + abd->abd_flags |= ABD_FLAG_GANG; + list_create(&ABD_GANG(abd).abd_gang_chain, + sizeof (abd_t), offsetof(abd_t, abd_gang_link)); + } + abd->abd_flags &= ~ABD_FLAG_OWNER; for (abd_t *cabd = abd_gang_get_offset(sabd, &off); cabd != NULL && left > 0; cabd = list_next(&ABD_GANG(sabd).abd_gang_chain, cabd)) { int csize = MIN(left, cabd->abd_size - off); - abd_t *nabd = abd_get_offset_impl(cabd, off, csize); - abd_gang_add(abd, nabd, B_FALSE); + abd_t *nabd = abd_get_offset_size(cabd, off, csize); + abd_gang_add(abd, nabd, B_TRUE); left -= csize; off = 0; } ASSERT3U(left, ==, 0); } else { - abd = abd_get_offset_scatter(sabd, off); + abd = abd_get_offset_scatter(abd, sabd, off); } + ASSERT3P(abd, !=, NULL); abd->abd_size = size; +#ifdef ZFS_DEBUG abd->abd_parent = sabd; - zfs_refcount_create(&abd->abd_children); (void) zfs_refcount_add_many(&sabd->abd_children, abd->abd_size, abd); +#endif return (abd); } +/* + * Like abd_get_offset_size(), but memory for the abd_t is provided by the + * caller. Using this routine can improve performance by avoiding the cost + * of allocating memory for the abd_t struct, and updating the abd stats. + * Usually, the provided abd is returned, but in some circumstances (FreeBSD, + * if sabd is scatter and size is more than 2 pages) a new abd_t may need to + * be allocated. Therefore callers should be careful to use the returned + * abd_t*. + */ +abd_t * +abd_get_offset_struct(abd_t *abd, abd_t *sabd, size_t off, size_t size) +{ + abd_init_struct(abd); + return (abd_get_offset_impl(abd, sabd, off, size)); +} + abd_t * abd_get_offset(abd_t *sabd, size_t off) { size_t size = sabd->abd_size > off ? sabd->abd_size - off : 0; VERIFY3U(size, >, 0); - return (abd_get_offset_impl(sabd, off, size)); + return (abd_get_offset_impl(NULL, sabd, off, size)); } abd_t * abd_get_offset_size(abd_t *sabd, size_t off, size_t size) { ASSERT3U(off + size, <=, sabd->abd_size); - return (abd_get_offset_impl(sabd, off, size)); + return (abd_get_offset_impl(NULL, sabd, off, size)); } /* - * Return a size scatter ABD. In order to free the returned - * ABD abd_put() must be called. + * Return a size scatter ABD containing only zeros. */ abd_t * abd_get_zeros(size_t size) @@ -592,8 +586,7 @@ } /* - * Allocate a linear ABD structure for buf. You must free this with abd_put() - * since the resulting ABD doesn't own its own buffer. + * Allocate a linear ABD structure for buf. */ abd_t * abd_get_from_buf(void *buf, size_t size) @@ -607,10 +600,8 @@ * own the underlying data buffer, which is not true in this case. * Therefore, we don't ever use ABD_FLAG_META here. */ - abd->abd_flags = ABD_FLAG_LINEAR; + abd->abd_flags |= ABD_FLAG_LINEAR; abd->abd_size = size; - abd->abd_parent = NULL; - zfs_refcount_create(&abd->abd_children); ABD_LINEAR_BUF(abd) = buf; @@ -645,7 +636,9 @@ } else { buf = zio_buf_alloc(n); } +#ifdef ZFS_DEBUG (void) zfs_refcount_add_many(&abd->abd_children, n, buf); +#endif return (buf); } @@ -676,7 +669,9 @@ ASSERT0(abd_cmp_buf(abd, buf, n)); zio_buf_free(buf, n); } +#ifdef ZFS_DEBUG (void) zfs_refcount_remove_many(&abd->abd_children, n, buf); +#endif } void @@ -790,12 +785,12 @@ abd_verify(abd); ASSERT3U(off + size, <=, abd->abd_size); - boolean_t abd_multi = abd_is_gang(abd); + boolean_t gang = abd_is_gang(abd); abd_t *c_abd = abd_init_abd_iter(abd, &aiter, off); while (size > 0) { /* If we are at the end of the gang ABD we are done */ - if (abd_multi && !c_abd) + if (gang && !c_abd) break; abd_iter_map(&aiter); diff --git a/sys/contrib/openzfs/module/zfs/arc.c b/sys/contrib/openzfs/module/zfs/arc.c --- a/sys/contrib/openzfs/module/zfs/arc.c +++ b/sys/contrib/openzfs/module/zfs/arc.c @@ -3065,7 +3065,7 @@ arc_hdr_size(hdr), hdr, buf); arc_hdr_clear_flags(hdr, ARC_FLAG_SHARED_DATA); abd_release_ownership_of_buf(hdr->b_l1hdr.b_pabd); - abd_put(hdr->b_l1hdr.b_pabd); + abd_free(hdr->b_l1hdr.b_pabd); hdr->b_l1hdr.b_pabd = NULL; buf->b_flags &= ~ARC_BUF_FLAG_SHARED; @@ -4163,7 +4163,7 @@ mutex_enter(&arc_evict_lock); arc_evict_count += bytes_evicted; - if ((int64_t)(arc_free_memory() - arc_sys_free / 2) > 0) { + if (arc_free_memory() > arc_sys_free / 2) { arc_evict_waiter_t *aw; while ((aw = list_head(&arc_evict_waiters)) != NULL && aw->aew_count <= arc_evict_count) { @@ -5242,14 +5242,20 @@ list_link_init(&aw.aew_node); cv_init(&aw.aew_cv, NULL, CV_DEFAULT, NULL); - arc_evict_waiter_t *last = - list_tail(&arc_evict_waiters); - if (last != NULL) { - ASSERT3U(last->aew_count, >, arc_evict_count); - aw.aew_count = last->aew_count + amount; - } else { - aw.aew_count = arc_evict_count + amount; + uint64_t last_count = 0; + if (!list_is_empty(&arc_evict_waiters)) { + arc_evict_waiter_t *last = + list_tail(&arc_evict_waiters); + last_count = last->aew_count; } + /* + * Note, the last waiter's count may be less than + * arc_evict_count if we are low on memory in which + * case arc_evict_state_impl() may have deferred + * wakeups (but still incremented arc_evict_count). + */ + aw.aew_count = + MAX(last_count, arc_evict_count) + amount; list_insert_tail(&arc_evict_waiters, &aw); @@ -7041,7 +7047,7 @@ ASSERT(!zfs_refcount_is_zero(&hdr->b_l1hdr.b_refcnt)); callback->awcb_done(zio, buf, callback->awcb_private); - abd_put(zio->io_abd); + abd_free(zio->io_abd); kmem_free(callback, sizeof (arc_write_callback_t)); } @@ -9037,7 +9043,7 @@ cb = zio->io_private; if (cb->l2rcb_abd != NULL) - abd_put(cb->l2rcb_abd); + abd_free(cb->l2rcb_abd); kmem_free(cb, sizeof (l2arc_read_callback_t)); } @@ -9075,17 +9081,17 @@ /* * Copy buffers for L2ARC writing. */ - for (int try = 0; try < L2ARC_FEED_TYPES; try++) { + for (int pass = 0; pass < L2ARC_FEED_TYPES; pass++) { /* - * If try == 1 or 3, we cache MRU metadata and data + * If pass == 1 or 3, we cache MRU metadata and data * respectively. */ if (l2arc_mfuonly) { - if (try == 1 || try == 3) + if (pass == 1 || pass == 3) continue; } - multilist_sublist_t *mls = l2arc_sublist_lock(try); + multilist_sublist_t *mls = l2arc_sublist_lock(pass); uint64_t passed_sz = 0; VERIFY3P(mls, !=, NULL); @@ -10011,7 +10017,7 @@ ZIO_FLAG_DONT_PROPAGATE | ZIO_FLAG_DONT_RETRY | ZIO_FLAG_SPECULATIVE, B_FALSE)); - abd_put(abd); + abd_free(abd); if (err != 0) { ARCSTAT_BUMP(arcstat_l2_rebuild_abort_dh_errors); @@ -10379,7 +10385,7 @@ VDEV_LABEL_START_SIZE, l2dhdr_asize, abd, ZIO_CHECKSUM_LABEL, NULL, NULL, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_CANFAIL, B_FALSE)); - abd_put(abd); + abd_free(abd); if (err != 0) { zfs_dbgmsg("L2ARC IO error (%d) while writing device header, " @@ -10468,7 +10474,7 @@ fletcher_4_native(tmpbuf, asize, NULL, &l2dhdr->dh_start_lbps[0].lbp_cksum); - abd_put(abd_buf->abd); + abd_free(abd_buf->abd); /* perform the write itself */ abd_buf->abd = abd_get_from_buf(tmpbuf, sizeof (*lb)); diff --git a/sys/contrib/openzfs/module/zfs/dbuf.c b/sys/contrib/openzfs/module/zfs/dbuf.c --- a/sys/contrib/openzfs/module/zfs/dbuf.c +++ b/sys/contrib/openzfs/module/zfs/dbuf.c @@ -4656,7 +4656,7 @@ dbuf_write_done(zio, NULL, db); if (zio->io_abd != NULL) - abd_put(zio->io_abd); + abd_free(zio->io_abd); } typedef struct dbuf_remap_impl_callback_arg { diff --git a/sys/contrib/openzfs/module/zfs/dmu.c b/sys/contrib/openzfs/module/zfs/dmu.c --- a/sys/contrib/openzfs/module/zfs/dmu.c +++ b/sys/contrib/openzfs/module/zfs/dmu.c @@ -1170,7 +1170,7 @@ #ifdef _KERNEL int -dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size) +dmu_read_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size) { dmu_buf_t **dbp; int numbufs, i, err; @@ -1179,7 +1179,7 @@ * NB: we could do this block-at-a-time, but it's nice * to be reading in parallel. */ - err = dmu_buf_hold_array_by_dnode(dn, uio_offset(uio), size, + err = dmu_buf_hold_array_by_dnode(dn, zfs_uio_offset(uio), size, TRUE, FTAG, &numbufs, &dbp, 0); if (err) return (err); @@ -1191,16 +1191,12 @@ ASSERT(size > 0); - bufoff = uio_offset(uio) - db->db_offset; + bufoff = zfs_uio_offset(uio) - db->db_offset; tocpy = MIN(db->db_size - bufoff, size); -#ifdef __FreeBSD__ - err = vn_io_fault_uiomove((char *)db->db_data + bufoff, - tocpy, uio); -#else - err = uiomove((char *)db->db_data + bufoff, tocpy, - UIO_READ, uio); -#endif + err = zfs_uio_fault_move((char *)db->db_data + bufoff, tocpy, + UIO_READ, uio); + if (err) break; @@ -1214,14 +1210,14 @@ /* * Read 'size' bytes into the uio buffer. * From object zdb->db_object. - * Starting at offset uio->uio_loffset. + * Starting at zfs_uio_offset(uio). * * If the caller already has a dbuf in the target object * (e.g. its bonus buffer), this routine is faster than dmu_read_uio(), * because we don't have to find the dnode_t for the object. */ int -dmu_read_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size) +dmu_read_uio_dbuf(dmu_buf_t *zdb, zfs_uio_t *uio, uint64_t size) { dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb; dnode_t *dn; @@ -1241,10 +1237,10 @@ /* * Read 'size' bytes into the uio buffer. * From the specified object - * Starting at offset uio->uio_loffset. + * Starting at offset zfs_uio_offset(uio). */ int -dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size) +dmu_read_uio(objset_t *os, uint64_t object, zfs_uio_t *uio, uint64_t size) { dnode_t *dn; int err; @@ -1264,14 +1260,14 @@ } int -dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx) +dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx) { dmu_buf_t **dbp; int numbufs; int err = 0; int i; - err = dmu_buf_hold_array_by_dnode(dn, uio_offset(uio), size, + err = dmu_buf_hold_array_by_dnode(dn, zfs_uio_offset(uio), size, FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH); if (err) return (err); @@ -1283,7 +1279,7 @@ ASSERT(size > 0); - bufoff = uio_offset(uio) - db->db_offset; + bufoff = zfs_uio_offset(uio) - db->db_offset; tocpy = MIN(db->db_size - bufoff, size); ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size); @@ -1294,18 +1290,14 @@ dmu_buf_will_dirty(db, tx); /* - * XXX uiomove could block forever (eg.nfs-backed + * XXX zfs_uiomove could block forever (eg.nfs-backed * pages). There needs to be a uiolockdown() function - * to lock the pages in memory, so that uiomove won't + * to lock the pages in memory, so that zfs_uiomove won't * block. */ -#ifdef __FreeBSD__ - err = vn_io_fault_uiomove((char *)db->db_data + bufoff, - tocpy, uio); -#else - err = uiomove((char *)db->db_data + bufoff, tocpy, - UIO_WRITE, uio); -#endif + err = zfs_uio_fault_move((char *)db->db_data + bufoff, + tocpy, UIO_WRITE, uio); + if (tocpy == db->db_size) dmu_buf_fill_done(db, tx); @@ -1322,14 +1314,14 @@ /* * Write 'size' bytes from the uio buffer. * To object zdb->db_object. - * Starting at offset uio->uio_loffset. + * Starting at offset zfs_uio_offset(uio). * * If the caller already has a dbuf in the target object * (e.g. its bonus buffer), this routine is faster than dmu_write_uio(), * because we don't have to find the dnode_t for the object. */ int -dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size, +dmu_write_uio_dbuf(dmu_buf_t *zdb, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx) { dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb; @@ -1350,10 +1342,10 @@ /* * Write 'size' bytes from the uio buffer. * To the specified object. - * Starting at offset uio->uio_loffset. + * Starting at offset zfs_uio_offset(uio). */ int -dmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size, +dmu_write_uio(objset_t *os, uint64_t object, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx) { dnode_t *dn; @@ -1600,7 +1592,7 @@ dsa->dsa_done(dsa->dsa_zgd, zio->io_error); - abd_put(zio->io_abd); + abd_free(zio->io_abd); kmem_free(dsa, sizeof (*dsa)); } diff --git a/sys/contrib/openzfs/module/zfs/dmu_objset.c b/sys/contrib/openzfs/module/zfs/dmu_objset.c --- a/sys/contrib/openzfs/module/zfs/dmu_objset.c +++ b/sys/contrib/openzfs/module/zfs/dmu_objset.c @@ -326,7 +326,7 @@ /* * Inheritance and range checking should have been done by now. */ - ASSERT(newval <= SPA_OLD_MAXBLOCKSIZE); + ASSERT(newval <= SPA_MAXBLOCKSIZE); ASSERT(ISP2(newval)); os->os_zpl_special_smallblock = newval; diff --git a/sys/contrib/openzfs/module/zfs/dmu_tx.c b/sys/contrib/openzfs/module/zfs/dmu_tx.c --- a/sys/contrib/openzfs/module/zfs/dmu_tx.c +++ b/sys/contrib/openzfs/module/zfs/dmu_tx.c @@ -1012,6 +1012,22 @@ * details on the throttle). This is used by the VFS operations, after * they have already called dmu_tx_wait() (though most likely on a * different tx). + * + * It is guaranteed that subsequent successful calls to dmu_tx_assign() + * will assign the tx to monotonically increasing txgs. Of course this is + * not strong monotonicity, because the same txg can be returned multiple + * times in a row. This guarantee holds both for subsequent calls from + * one thread and for multiple threads. For example, it is impossible to + * observe the following sequence of events: + * + * Thread 1 Thread 2 + * + * dmu_tx_assign(T1, ...) + * 1 <- dmu_tx_get_txg(T1) + * dmu_tx_assign(T2, ...) + * 2 <- dmu_tx_get_txg(T2) + * dmu_tx_assign(T3, ...) + * 1 <- dmu_tx_get_txg(T3) */ int dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how) diff --git a/sys/contrib/openzfs/module/zfs/dsl_dataset.c b/sys/contrib/openzfs/module/zfs/dsl_dataset.c --- a/sys/contrib/openzfs/module/zfs/dsl_dataset.c +++ b/sys/contrib/openzfs/module/zfs/dsl_dataset.c @@ -2322,18 +2322,7 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv) { nvlist_t *propval = fnvlist_alloc(); - nvlist_t *val; - - /* - * We use nvlist_alloc() instead of fnvlist_alloc() because the - * latter would allocate the list with NV_UNIQUE_NAME flag. - * As a result, every time a clone name is appended to the list - * it would be (linearly) searched for a duplicate name. - * We already know that all clone names must be unique and we - * want avoid the quadratic complexity of double-checking that - * because we can have a large number of clones. - */ - VERIFY0(nvlist_alloc(&val, 0, KM_SLEEP)); + nvlist_t *val = fnvlist_alloc(); if (get_clones_stat_impl(ds, val) == 0) { fnvlist_add_nvlist(propval, ZPROP_VALUE, val); diff --git a/sys/contrib/openzfs/module/zfs/dsl_destroy.c b/sys/contrib/openzfs/module/zfs/dsl_destroy.c --- a/sys/contrib/openzfs/module/zfs/dsl_destroy.c +++ b/sys/contrib/openzfs/module/zfs/dsl_destroy.c @@ -600,26 +600,21 @@ /* * lzc_destroy_snaps() is documented to take an nvlist whose * values "don't matter". We need to convert that nvlist to - * one that we know can be converted to LUA. We also don't - * care about any duplicate entries because the nvlist will - * be converted to a LUA table which should take care of this. + * one that we know can be converted to LUA. */ - nvlist_t *snaps_normalized; - VERIFY0(nvlist_alloc(&snaps_normalized, 0, KM_SLEEP)); + nvlist_t *snaps_normalized = fnvlist_alloc(); for (nvpair_t *pair = nvlist_next_nvpair(snaps, NULL); pair != NULL; pair = nvlist_next_nvpair(snaps, pair)) { fnvlist_add_boolean_value(snaps_normalized, nvpair_name(pair), B_TRUE); } - nvlist_t *arg; - VERIFY0(nvlist_alloc(&arg, 0, KM_SLEEP)); + nvlist_t *arg = fnvlist_alloc(); fnvlist_add_nvlist(arg, "snaps", snaps_normalized); fnvlist_free(snaps_normalized); fnvlist_add_boolean_value(arg, "defer", defer); - nvlist_t *wrapper; - VERIFY0(nvlist_alloc(&wrapper, 0, KM_SLEEP)); + nvlist_t *wrapper = fnvlist_alloc(); fnvlist_add_nvlist(wrapper, ZCP_ARG_ARGLIST, arg); fnvlist_free(arg); @@ -654,7 +649,7 @@ B_TRUE, 0, zfs_lua_max_memlimit, - nvlist_next_nvpair(wrapper, NULL), result); + fnvlist_lookup_nvpair(wrapper, ZCP_ARG_ARGLIST), result); if (error != 0) { char *errorstr = NULL; (void) nvlist_lookup_string(result, ZCP_RET_ERROR, &errorstr); diff --git a/sys/contrib/openzfs/module/zfs/metaslab.c b/sys/contrib/openzfs/module/zfs/metaslab.c --- a/sys/contrib/openzfs/module/zfs/metaslab.c +++ b/sys/contrib/openzfs/module/zfs/metaslab.c @@ -522,9 +522,10 @@ mc_hist = kmem_zalloc(sizeof (uint64_t) * RANGE_TREE_HISTOGRAM_SIZE, KM_SLEEP); + mutex_enter(&mc->mc_lock); for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; - metaslab_group_t *mg = tvd->vdev_mg; + metaslab_group_t *mg = vdev_get_mg(tvd, mc); /* * Skip any holes, uninitialized top-levels, or @@ -535,13 +536,18 @@ continue; } + IMPLY(mg == mg->mg_vd->vdev_log_mg, + mc == spa_embedded_log_class(mg->mg_vd->vdev_spa)); + for (i = 0; i < RANGE_TREE_HISTOGRAM_SIZE; i++) mc_hist[i] += mg->mg_histogram[i]; } - for (i = 0; i < RANGE_TREE_HISTOGRAM_SIZE; i++) + for (i = 0; i < RANGE_TREE_HISTOGRAM_SIZE; i++) { VERIFY3U(mc_hist[i], ==, mc->mc_histogram[i]); + } + mutex_exit(&mc->mc_lock); kmem_free(mc_hist, sizeof (uint64_t) * RANGE_TREE_HISTOGRAM_SIZE); } @@ -1004,16 +1010,22 @@ uint64_t metaslab_group_get_space(metaslab_group_t *mg) { - return ((1ULL << mg->mg_vd->vdev_ms_shift) * mg->mg_vd->vdev_ms_count); + /* + * Note that the number of nodes in mg_metaslab_tree may be one less + * than vdev_ms_count, due to the embedded log metaslab. + */ + mutex_enter(&mg->mg_lock); + uint64_t ms_count = avl_numnodes(&mg->mg_metaslab_tree); + mutex_exit(&mg->mg_lock); + return ((1ULL << mg->mg_vd->vdev_ms_shift) * ms_count); } void metaslab_group_histogram_verify(metaslab_group_t *mg) { uint64_t *mg_hist; - vdev_t *vd = mg->mg_vd; - uint64_t ashift = vd->vdev_ashift; - int i; + avl_tree_t *t = &mg->mg_metaslab_tree; + uint64_t ashift = mg->mg_vd->vdev_ashift; if ((zfs_flags & ZFS_DEBUG_HISTOGRAM_VERIFY) == 0) return; @@ -1024,21 +1036,25 @@ ASSERT3U(RANGE_TREE_HISTOGRAM_SIZE, >=, SPACE_MAP_HISTOGRAM_SIZE + ashift); - for (int m = 0; m < vd->vdev_ms_count; m++) { - metaslab_t *msp = vd->vdev_ms[m]; - - /* skip if not active or not a member */ - if (msp->ms_sm == NULL || msp->ms_group != mg) + mutex_enter(&mg->mg_lock); + for (metaslab_t *msp = avl_first(t); + msp != NULL; msp = AVL_NEXT(t, msp)) { + VERIFY3P(msp->ms_group, ==, mg); + /* skip if not active */ + if (msp->ms_sm == NULL) continue; - for (i = 0; i < SPACE_MAP_HISTOGRAM_SIZE; i++) + for (int i = 0; i < SPACE_MAP_HISTOGRAM_SIZE; i++) { mg_hist[i + ashift] += msp->ms_sm->sm_phys->smp_histogram[i]; + } } - for (i = 0; i < RANGE_TREE_HISTOGRAM_SIZE; i ++) + for (int i = 0; i < RANGE_TREE_HISTOGRAM_SIZE; i ++) VERIFY3U(mg_hist[i], ==, mg->mg_histogram[i]); + mutex_exit(&mg->mg_lock); + kmem_free(mg_hist, sizeof (uint64_t) * RANGE_TREE_HISTOGRAM_SIZE); } @@ -1053,12 +1069,16 @@ return; mutex_enter(&mg->mg_lock); + mutex_enter(&mc->mc_lock); for (int i = 0; i < SPACE_MAP_HISTOGRAM_SIZE; i++) { + IMPLY(mg == mg->mg_vd->vdev_log_mg, + mc == spa_embedded_log_class(mg->mg_vd->vdev_spa)); mg->mg_histogram[i + ashift] += msp->ms_sm->sm_phys->smp_histogram[i]; mc->mc_histogram[i + ashift] += msp->ms_sm->sm_phys->smp_histogram[i]; } + mutex_exit(&mc->mc_lock); mutex_exit(&mg->mg_lock); } @@ -1073,17 +1093,21 @@ return; mutex_enter(&mg->mg_lock); + mutex_enter(&mc->mc_lock); for (int i = 0; i < SPACE_MAP_HISTOGRAM_SIZE; i++) { ASSERT3U(mg->mg_histogram[i + ashift], >=, msp->ms_sm->sm_phys->smp_histogram[i]); ASSERT3U(mc->mc_histogram[i + ashift], >=, msp->ms_sm->sm_phys->smp_histogram[i]); + IMPLY(mg == mg->mg_vd->vdev_log_mg, + mc == spa_embedded_log_class(mg->mg_vd->vdev_spa)); mg->mg_histogram[i + ashift] -= msp->ms_sm->sm_phys->smp_histogram[i]; mc->mc_histogram[i + ashift] -= msp->ms_sm->sm_phys->smp_histogram[i]; } + mutex_exit(&mc->mc_lock); mutex_exit(&mg->mg_lock); } @@ -2741,37 +2765,47 @@ mutex_enter(&msp->ms_lock); VERIFY(msp->ms_group == NULL); - metaslab_space_update(vd, mg->mg_class, - -metaslab_allocated_space(msp), 0, -msp->ms_size); + /* + * If the range trees haven't been allocated, this metaslab hasn't + * been through metaslab_sync_done() for the first time yet, so its + * space hasn't been accounted for in its vdev and doesn't need to be + * subtracted. + */ + if (msp->ms_freed != NULL) { + metaslab_space_update(vd, mg->mg_class, + -metaslab_allocated_space(msp), 0, -msp->ms_size); + } space_map_close(msp->ms_sm); msp->ms_sm = NULL; metaslab_unload(msp); + range_tree_destroy(msp->ms_allocatable); - range_tree_destroy(msp->ms_freeing); - range_tree_destroy(msp->ms_freed); - ASSERT3U(spa->spa_unflushed_stats.sus_memused, >=, - metaslab_unflushed_changes_memused(msp)); - spa->spa_unflushed_stats.sus_memused -= - metaslab_unflushed_changes_memused(msp); - range_tree_vacate(msp->ms_unflushed_allocs, NULL, NULL); - range_tree_destroy(msp->ms_unflushed_allocs); - range_tree_vacate(msp->ms_unflushed_frees, NULL, NULL); - range_tree_destroy(msp->ms_unflushed_frees); + if (msp->ms_freed != NULL) { + range_tree_destroy(msp->ms_freeing); + range_tree_destroy(msp->ms_freed); - for (int t = 0; t < TXG_SIZE; t++) { - range_tree_destroy(msp->ms_allocating[t]); - } + ASSERT3U(spa->spa_unflushed_stats.sus_memused, >=, + metaslab_unflushed_changes_memused(msp)); + spa->spa_unflushed_stats.sus_memused -= + metaslab_unflushed_changes_memused(msp); + range_tree_vacate(msp->ms_unflushed_allocs, NULL, NULL); + range_tree_destroy(msp->ms_unflushed_allocs); + range_tree_destroy(msp->ms_checkpointing); + range_tree_vacate(msp->ms_unflushed_frees, NULL, NULL); + range_tree_destroy(msp->ms_unflushed_frees); - for (int t = 0; t < TXG_DEFER_SIZE; t++) { - range_tree_destroy(msp->ms_defer[t]); + for (int t = 0; t < TXG_SIZE; t++) { + range_tree_destroy(msp->ms_allocating[t]); + } + for (int t = 0; t < TXG_DEFER_SIZE; t++) { + range_tree_destroy(msp->ms_defer[t]); + } } ASSERT0(msp->ms_deferspace); - range_tree_destroy(msp->ms_checkpointing); - for (int t = 0; t < TXG_SIZE; t++) ASSERT(!txg_list_member(&vd->vdev_ms_list, msp, t)); @@ -5113,7 +5147,7 @@ * all else fails. */ if (vd != NULL && vd->vdev_mg != NULL) { - mg = vd->vdev_mg; + mg = vdev_get_mg(vd, mc); if (flags & METASLAB_HINTBP_AVOID && mg->mg_next != NULL) diff --git a/sys/contrib/openzfs/module/zfs/sa.c b/sys/contrib/openzfs/module/zfs/sa.c --- a/sys/contrib/openzfs/module/zfs/sa.c +++ b/sys/contrib/openzfs/module/zfs/sa.c @@ -1502,7 +1502,7 @@ #ifdef _KERNEL int -sa_lookup_uio(sa_handle_t *hdl, sa_attr_type_t attr, uio_t *uio) +sa_lookup_uio(sa_handle_t *hdl, sa_attr_type_t attr, zfs_uio_t *uio) { int error; sa_bulk_attr_t bulk; @@ -1515,8 +1515,8 @@ mutex_enter(&hdl->sa_lock); if ((error = sa_attr_op(hdl, &bulk, 1, SA_LOOKUP, NULL)) == 0) { - error = uiomove((void *)bulk.sa_addr, MIN(bulk.sa_size, - uio_resid(uio)), UIO_READ, uio); + error = zfs_uiomove((void *)bulk.sa_addr, MIN(bulk.sa_size, + zfs_uio_resid(uio)), UIO_READ, uio); } mutex_exit(&hdl->sa_lock); return (error); diff --git a/sys/contrib/openzfs/module/zfs/spa.c b/sys/contrib/openzfs/module/zfs/spa.c --- a/sys/contrib/openzfs/module/zfs/spa.c +++ b/sys/contrib/openzfs/module/zfs/spa.c @@ -303,10 +303,12 @@ alloc = metaslab_class_get_alloc(mc); alloc += metaslab_class_get_alloc(spa_special_class(spa)); alloc += metaslab_class_get_alloc(spa_dedup_class(spa)); + alloc += metaslab_class_get_alloc(spa_embedded_log_class(spa)); size = metaslab_class_get_space(mc); size += metaslab_class_get_space(spa_special_class(spa)); size += metaslab_class_get_space(spa_dedup_class(spa)); + size += metaslab_class_get_space(spa_embedded_log_class(spa)); spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src); spa_prop_add_list(*nvp, ZPOOL_PROP_SIZE, NULL, size, src); @@ -1196,6 +1198,8 @@ spa->spa_normal_class = metaslab_class_create(spa, zfs_metaslab_ops); spa->spa_log_class = metaslab_class_create(spa, zfs_metaslab_ops); + spa->spa_embedded_log_class = + metaslab_class_create(spa, zfs_metaslab_ops); spa->spa_special_class = metaslab_class_create(spa, zfs_metaslab_ops); spa->spa_dedup_class = metaslab_class_create(spa, zfs_metaslab_ops); @@ -1347,6 +1351,9 @@ metaslab_class_destroy(spa->spa_log_class); spa->spa_log_class = NULL; + metaslab_class_destroy(spa->spa_embedded_log_class); + spa->spa_embedded_log_class = NULL; + metaslab_class_destroy(spa->spa_special_class); spa->spa_special_class = NULL; @@ -2103,6 +2110,9 @@ return (rv); } +/* + * Passivate any log vdevs (note, does not apply to embedded log metaslabs). + */ static boolean_t spa_passivate_log(spa_t *spa) { @@ -2113,10 +2123,10 @@ for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; - metaslab_group_t *mg = tvd->vdev_mg; if (tvd->vdev_islog) { - metaslab_group_passivate(mg); + ASSERT3P(tvd->vdev_log_mg, ==, NULL); + metaslab_group_passivate(tvd->vdev_mg); slog_found = B_TRUE; } } @@ -2124,6 +2134,9 @@ return (slog_found); } +/* + * Activate any log vdevs (note, does not apply to embedded log metaslabs). + */ static void spa_activate_log(spa_t *spa) { @@ -2133,10 +2146,11 @@ for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; - metaslab_group_t *mg = tvd->vdev_mg; - if (tvd->vdev_islog) - metaslab_group_activate(mg); + if (tvd->vdev_islog) { + ASSERT3P(tvd->vdev_log_mg, ==, NULL); + metaslab_group_activate(tvd->vdev_mg); + } } } @@ -6236,6 +6250,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig, boolean_t force, boolean_t hardforce) { + int error; spa_t *spa; if (oldconfig) @@ -6288,13 +6303,9 @@ * references. If we are resetting a pool, allow references by * fault injection handlers. */ - if (!spa_refcount_zero(spa) || - (spa->spa_inject_ref != 0 && - new_state != POOL_STATE_UNINITIALIZED)) { - spa_async_resume(spa); - spa->spa_is_exporting = B_FALSE; - mutex_exit(&spa_namespace_lock); - return (SET_ERROR(EBUSY)); + if (!spa_refcount_zero(spa) || (spa->spa_inject_ref != 0)) { + error = SET_ERROR(EBUSY); + goto fail; } if (spa->spa_sync_on) { @@ -6306,10 +6317,8 @@ */ if (!force && new_state == POOL_STATE_EXPORTED && spa_has_active_shared_spare(spa)) { - spa_async_resume(spa); - spa->spa_is_exporting = B_FALSE; - mutex_exit(&spa_namespace_lock); - return (SET_ERROR(EXDEV)); + error = SET_ERROR(EXDEV); + goto fail; } /* @@ -6371,6 +6380,12 @@ mutex_exit(&spa_namespace_lock); return (0); + +fail: + spa->spa_is_exporting = B_FALSE; + spa_async_resume(spa); + mutex_exit(&spa_namespace_lock); + return (error); } /* @@ -8033,12 +8048,16 @@ old_space = metaslab_class_get_space(spa_normal_class(spa)); old_space += metaslab_class_get_space(spa_special_class(spa)); old_space += metaslab_class_get_space(spa_dedup_class(spa)); + old_space += metaslab_class_get_space( + spa_embedded_log_class(spa)); spa_config_update(spa, SPA_CONFIG_UPDATE_POOL); new_space = metaslab_class_get_space(spa_normal_class(spa)); new_space += metaslab_class_get_space(spa_special_class(spa)); new_space += metaslab_class_get_space(spa_dedup_class(spa)); + new_space += metaslab_class_get_space( + spa_embedded_log_class(spa)); mutex_exit(&spa_namespace_lock); /* diff --git a/sys/contrib/openzfs/module/zfs/spa_history.c b/sys/contrib/openzfs/module/zfs/spa_history.c --- a/sys/contrib/openzfs/module/zfs/spa_history.c +++ b/sys/contrib/openzfs/module/zfs/spa_history.c @@ -288,7 +288,6 @@ } #endif - fnvlist_add_uint64(nvl, ZPOOL_HIST_TIME, gethrestime_sec()); fnvlist_add_string(nvl, ZPOOL_HIST_HOST, utsname()->nodename); if (nvlist_exists(nvl, ZPOOL_HIST_CMD)) { @@ -396,6 +395,12 @@ } fnvlist_add_uint64(nvarg, ZPOOL_HIST_WHO, crgetruid(CRED())); + /* + * Since the history is recorded asynchronously, the effective time is + * now, which may be considerably before the change is made on disk. + */ + fnvlist_add_uint64(nvarg, ZPOOL_HIST_TIME, gethrestime_sec()); + /* Kick this off asynchronously; errors are ignored. */ dsl_sync_task_nowait(spa_get_dsl(spa), spa_history_log_sync, nvarg, tx); dmu_tx_commit(tx); @@ -526,6 +531,7 @@ fnvlist_add_string(nvl, ZPOOL_HIST_INT_NAME, operation); fnvlist_add_uint64(nvl, ZPOOL_HIST_TXG, tx->tx_txg); + fnvlist_add_uint64(nvl, ZPOOL_HIST_TIME, gethrestime_sec()); if (dmu_tx_is_syncing(tx)) { spa_history_log_sync(nvl, tx); diff --git a/sys/contrib/openzfs/module/zfs/spa_misc.c b/sys/contrib/openzfs/module/zfs/spa_misc.c --- a/sys/contrib/openzfs/module/zfs/spa_misc.c +++ b/sys/contrib/openzfs/module/zfs/spa_misc.c @@ -349,9 +349,11 @@ * Normally, we don't allow the last 3.2% (1/(2^spa_slop_shift)) of space in * the pool to be consumed. This ensures that we don't run the pool * completely out of space, due to unaccounted changes (e.g. to the MOS). - * It also limits the worst-case time to allocate space. If we have - * less than this amount of free space, most ZPL operations (e.g. write, - * create) will return ENOSPC. + * It also limits the worst-case time to allocate space. If we have less than + * this amount of free space, most ZPL operations (e.g. write, create) will + * return ENOSPC. The ZIL metaslabs (spa_embedded_log_class) are also part of + * this 3.2% of space which can't be consumed by normal writes; the slop space + * "proper" (spa_get_slop_space()) is decreased by the embedded log space. * * Certain operations (e.g. file removal, most administrative actions) can * use half the slop space. They will only return ENOSPC if less than half @@ -1026,10 +1028,10 @@ /* * Spares are tracked globally due to the following constraints: * - * - A spare may be part of multiple pools. - * - A spare may be added to a pool even if it's actively in use within + * - A spare may be part of multiple pools. + * - A spare may be added to a pool even if it's actively in use within * another pool. - * - A spare in use in any pool can only be the source of a replacement if + * - A spare in use in any pool can only be the source of a replacement if * the target is a spare in the same pool. * * We keep track of all spares on the system through the use of a reference @@ -1236,6 +1238,7 @@ */ ASSERT(metaslab_class_validate(spa_normal_class(spa)) == 0); ASSERT(metaslab_class_validate(spa_log_class(spa)) == 0); + ASSERT(metaslab_class_validate(spa_embedded_log_class(spa)) == 0); ASSERT(metaslab_class_validate(spa_special_class(spa)) == 0); ASSERT(metaslab_class_validate(spa_dedup_class(spa)) == 0); @@ -1776,17 +1779,37 @@ } /* - * Return the amount of slop space in bytes. It is 1/32 of the pool (3.2%), - * or at least 128MB, unless that would cause it to be more than half the - * pool size. - * - * See the comment above spa_slop_shift for details. + * Return the amount of slop space in bytes. It is typically 1/32 of the pool + * (3.2%), minus the embedded log space. On very small pools, it may be + * slightly larger than this. The embedded log space is not included in + * spa_dspace. By subtracting it, the usable space (per "zfs list") is a + * constant 97% of the total space, regardless of metaslab size (assuming the + * default spa_slop_shift=5 and a non-tiny pool). + * + * See the comment above spa_slop_shift for more details. */ uint64_t spa_get_slop_space(spa_t *spa) { uint64_t space = spa_get_dspace(spa); - return (MAX(space >> spa_slop_shift, MIN(space >> 1, spa_min_slop))); + uint64_t slop = space >> spa_slop_shift; + + /* + * Subtract the embedded log space, but no more than half the (3.2%) + * unusable space. Note, the "no more than half" is only relevant if + * zfs_embedded_slog_min_ms >> spa_slop_shift < 2, which is not true by + * default. + */ + uint64_t embedded_log = + metaslab_class_get_dspace(spa_embedded_log_class(spa)); + slop -= MIN(embedded_log, slop >> 1); + + /* + * Slop space should be at least spa_min_slop, but no more than half + * the entire pool. + */ + slop = MAX(slop, MIN(space >> 1, spa_min_slop)); + return (slop); } uint64_t @@ -1872,6 +1895,12 @@ return (spa->spa_log_class); } +metaslab_class_t * +spa_embedded_log_class(spa_t *spa) +{ + return (spa->spa_embedded_log_class); +} + metaslab_class_t * spa_special_class(spa_t *spa) { @@ -1891,12 +1920,10 @@ spa_preferred_class(spa_t *spa, uint64_t size, dmu_object_type_t objtype, uint_t level, uint_t special_smallblk) { - if (DMU_OT_IS_ZIL(objtype)) { - if (spa->spa_log_class->mc_groups != 0) - return (spa_log_class(spa)); - else - return (spa_normal_class(spa)); - } + /* + * ZIL allocations determine their class in zio_alloc_zil(). + */ + ASSERT(objtype != DMU_OT_INTENT_LOG); boolean_t has_special_class = spa->spa_special_class->mc_groups != 0; @@ -2432,9 +2459,9 @@ } /* - * Return whether this pool has slogs. No locking needed. + * Return whether this pool has a dedicated slog device. No locking needed. * It's not a problem if the wrong answer is returned as it's only for - * performance and not correctness + * performance and not correctness. */ boolean_t spa_has_slogs(spa_t *spa) diff --git a/sys/contrib/openzfs/module/zfs/txg.c b/sys/contrib/openzfs/module/zfs/txg.c --- a/sys/contrib/openzfs/module/zfs/txg.c +++ b/sys/contrib/openzfs/module/zfs/txg.c @@ -292,6 +292,27 @@ mutex_exit(&tx->tx_sync_lock); } +/* + * Get a handle on the currently open txg and keep it open. + * + * The txg is guaranteed to stay open until txg_rele_to_quiesce() is called for + * the handle. Once txg_rele_to_quiesce() has been called, the txg stays + * in quiescing state until txg_rele_to_sync() is called for the handle. + * + * It is guaranteed that subsequent calls return monotonically increasing + * txgs for the same dsl_pool_t. Of course this is not strong monotonicity, + * because the same txg can be returned multiple times in a row. This + * guarantee holds both for subsequent calls from one thread and for multiple + * threads. For example, it is impossible to observe the following sequence + * of events: + * + * Thread 1 Thread 2 + * + * 1 <- txg_hold_open(P, ...) + * 2 <- txg_hold_open(P, ...) + * 1 <- txg_hold_open(P, ...) + * + */ uint64_t txg_hold_open(dsl_pool_t *dp, txg_handle_t *th) { @@ -393,7 +414,8 @@ spa_txg_history_add(dp->dp_spa, txg + 1, tx_open_time); /* - * Quiesce the transaction group by waiting for everyone to txg_exit(). + * Quiesce the transaction group by waiting for everyone to + * call txg_rele_to_sync() for their open transaction handles. */ for (c = 0; c < max_ncpus; c++) { tx_cpu_t *tc = &tx->tx_cpu[c]; diff --git a/sys/contrib/openzfs/module/zfs/vdev.c b/sys/contrib/openzfs/module/zfs/vdev.c --- a/sys/contrib/openzfs/module/zfs/vdev.c +++ b/sys/contrib/openzfs/module/zfs/vdev.c @@ -59,6 +59,27 @@ #include #include +/* + * One metaslab from each (normal-class) vdev is used by the ZIL. These are + * called "embedded slog metaslabs", are referenced by vdev_log_mg, and are + * part of the spa_embedded_log_class. The metaslab with the most free space + * in each vdev is selected for this purpose when the pool is opened (or a + * vdev is added). See vdev_metaslab_init(). + * + * Log blocks can be allocated from the following locations. Each one is tried + * in order until the allocation succeeds: + * 1. dedicated log vdevs, aka "slog" (spa_log_class) + * 2. embedded slog metaslabs (spa_embedded_log_class) + * 3. other metaslabs in normal vdevs (spa_normal_class) + * + * zfs_embedded_slog_min_ms disables the embedded slog if there are fewer + * than this number of metaslabs in the vdev. This ensures that we don't set + * aside an unreasonable amount of space for the ZIL. If set to less than + * 1 << (spa_slop_shift + 1), on small pools the usable space may be reduced + * (by more than 1<vdev_spa) && + vd->vdev_log_mg != NULL) + return (vd->vdev_log_mg); + else + return (vd->vdev_mg); +} + /* ARGSUSED */ void vdev_default_xlate(vdev_t *vd, const range_seg64_t *logical_rs, @@ -978,6 +1015,11 @@ metaslab_group_destroy(vd->vdev_mg); vd->vdev_mg = NULL; } + if (vd->vdev_log_mg != NULL) { + ASSERT0(vd->vdev_ms_count); + metaslab_group_destroy(vd->vdev_log_mg); + vd->vdev_log_mg = NULL; + } ASSERT0(vd->vdev_stat.vs_space); ASSERT0(vd->vdev_stat.vs_dspace); @@ -1098,14 +1140,20 @@ if (tvd->vdev_mg) ASSERT3P(tvd->vdev_mg, ==, svd->vdev_mg); + if (tvd->vdev_log_mg) + ASSERT3P(tvd->vdev_log_mg, ==, svd->vdev_log_mg); tvd->vdev_mg = svd->vdev_mg; + tvd->vdev_log_mg = svd->vdev_log_mg; tvd->vdev_ms = svd->vdev_ms; svd->vdev_mg = NULL; + svd->vdev_log_mg = NULL; svd->vdev_ms = NULL; if (tvd->vdev_mg != NULL) tvd->vdev_mg->mg_vd = tvd; + if (tvd->vdev_log_mg != NULL) + tvd->vdev_log_mg->mg_vd = tvd; tvd->vdev_checkpoint_sm = svd->vdev_checkpoint_sm; svd->vdev_checkpoint_sm = NULL; @@ -1283,7 +1331,7 @@ vdev_free(mvd); } -static void +void vdev_metaslab_group_create(vdev_t *vd) { spa_t *spa = vd->vdev_spa; @@ -1317,6 +1365,11 @@ vd->vdev_mg = metaslab_group_create(mc, vd, spa->spa_alloc_count); + if (!vd->vdev_islog) { + vd->vdev_log_mg = metaslab_group_create( + spa_embedded_log_class(spa), vd, 1); + } + /* * The spa ashift min/max only apply for the normal metaslab * class. Class destination is late binding so ashift boundry @@ -1340,8 +1393,6 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg) { spa_t *spa = vd->vdev_spa; - objset_t *mos = spa->spa_meta_objset; - uint64_t m; uint64_t oldc = vd->vdev_ms_count; uint64_t newc = vd->vdev_asize >> vd->vdev_ms_shift; metaslab_t **mspp; @@ -1369,16 +1420,17 @@ vd->vdev_ms = mspp; vd->vdev_ms_count = newc; - for (m = oldc; m < newc; m++) { - uint64_t object = 0; + for (uint64_t m = oldc; m < newc; m++) { + uint64_t object = 0; /* * vdev_ms_array may be 0 if we are creating the "fake" * metaslabs for an indirect vdev for zdb's leak detection. * See zdb_leak_init(). */ if (txg == 0 && vd->vdev_ms_array != 0) { - error = dmu_read(mos, vd->vdev_ms_array, + error = dmu_read(spa->spa_meta_objset, + vd->vdev_ms_array, m * sizeof (uint64_t), sizeof (uint64_t), &object, DMU_READ_PREFETCH); if (error != 0) { @@ -1388,17 +1440,6 @@ } } -#ifndef _KERNEL - /* - * To accommodate zdb_leak_init() fake indirect - * metaslabs, we allocate a metaslab group for - * indirect vdevs which normally don't have one. - */ - if (vd->vdev_mg == NULL) { - ASSERT0(vdev_is_concrete(vd)); - vdev_metaslab_group_create(vd); - } -#endif error = metaslab_init(vd->vdev_mg, m, object, txg, &(vd->vdev_ms[m])); if (error != 0) { @@ -1408,6 +1449,47 @@ } } + /* + * Find the emptiest metaslab on the vdev and mark it for use for + * embedded slog by moving it from the regular to the log metaslab + * group. + */ + if (vd->vdev_mg->mg_class == spa_normal_class(spa) && + vd->vdev_ms_count > zfs_embedded_slog_min_ms && + avl_is_empty(&vd->vdev_log_mg->mg_metaslab_tree)) { + uint64_t slog_msid = 0; + uint64_t smallest = UINT64_MAX; + + /* + * Note, we only search the new metaslabs, because the old + * (pre-existing) ones may be active (e.g. have non-empty + * range_tree's), and we don't move them to the new + * metaslab_t. + */ + for (uint64_t m = oldc; m < newc; m++) { + uint64_t alloc = + space_map_allocated(vd->vdev_ms[m]->ms_sm); + if (alloc < smallest) { + slog_msid = m; + smallest = alloc; + } + } + metaslab_t *slog_ms = vd->vdev_ms[slog_msid]; + /* + * The metaslab was marked as dirty at the end of + * metaslab_init(). Remove it from the dirty list so that we + * can uninitialize and reinitialize it to the new class. + */ + if (txg != 0) { + (void) txg_list_remove_this(&vd->vdev_ms_list, + slog_ms, txg); + } + uint64_t sm_obj = space_map_object(slog_ms->ms_sm); + metaslab_fini(slog_ms); + VERIFY0(metaslab_init(vd->vdev_log_mg, slog_msid, sm_obj, txg, + &vd->vdev_ms[slog_msid])); + } + if (txg == 0) spa_config_enter(spa, SCL_ALLOC, FTAG, RW_WRITER); @@ -1418,6 +1500,8 @@ */ if (!expanding && !vd->vdev_removing) { metaslab_group_activate(vd->vdev_mg); + if (vd->vdev_log_mg != NULL) + metaslab_group_activate(vd->vdev_log_mg); } if (txg == 0) @@ -1453,7 +1537,12 @@ if (vd->vdev_ms != NULL) { metaslab_group_t *mg = vd->vdev_mg; + metaslab_group_passivate(mg); + if (vd->vdev_log_mg != NULL) { + ASSERT(!vd->vdev_islog); + metaslab_group_passivate(vd->vdev_log_mg); + } uint64_t count = vd->vdev_ms_count; for (uint64_t m = 0; m < count; m++) { @@ -1463,11 +1552,13 @@ } vmem_free(vd->vdev_ms, count * sizeof (metaslab_t *)); vd->vdev_ms = NULL; - vd->vdev_ms_count = 0; - for (int i = 0; i < RANGE_TREE_HISTOGRAM_SIZE; i++) + for (int i = 0; i < RANGE_TREE_HISTOGRAM_SIZE; i++) { ASSERT0(mg->mg_histogram[i]); + if (vd->vdev_log_mg != NULL) + ASSERT0(vd->vdev_log_mg->mg_histogram[i]); + } } ASSERT0(vd->vdev_ms_count); ASSERT3U(vd->vdev_pending_fastwrite, ==, 0); @@ -1633,6 +1724,14 @@ return (NULL); } +static void +vdev_load_child(void *arg) +{ + vdev_t *vd = arg; + + vd->vdev_load_error = vdev_load(vd); +} + static void vdev_open_child(void *arg) { @@ -2037,6 +2136,16 @@ return (0); } +static void +vdev_validate_child(void *arg) +{ + vdev_t *vd = arg; + + vd->vdev_validate_thread = curthread; + vd->vdev_validate_error = vdev_validate(vd); + vd->vdev_validate_thread = NULL; +} + /* * Called once the vdevs are all opened, this routine validates the label * contents. This needs to be done before vdev_load() so that we don't @@ -2051,18 +2160,43 @@ vdev_validate(vdev_t *vd) { spa_t *spa = vd->vdev_spa; + taskq_t *tq = NULL; nvlist_t *label; uint64_t guid = 0, aux_guid = 0, top_guid; uint64_t state; nvlist_t *nvl; uint64_t txg; + int children = vd->vdev_children; if (vdev_validate_skip) return (0); - for (uint64_t c = 0; c < vd->vdev_children; c++) - if (vdev_validate(vd->vdev_child[c]) != 0) + if (children > 0) { + tq = taskq_create("vdev_validate", children, minclsyspri, + children, children, TASKQ_PREPOPULATE); + } + + for (uint64_t c = 0; c < children; c++) { + vdev_t *cvd = vd->vdev_child[c]; + + if (tq == NULL || vdev_uses_zvols(cvd)) { + vdev_validate_child(cvd); + } else { + VERIFY(taskq_dispatch(tq, vdev_validate_child, cvd, + TQ_SLEEP) != TASKQID_INVALID); + } + } + if (tq != NULL) { + taskq_wait(tq); + taskq_destroy(tq); + } + for (int c = 0; c < children; c++) { + int error = vd->vdev_child[c]->vdev_validate_error; + + if (error != 0) return (SET_ERROR(EBADF)); + } + /* * If the device has already failed, or was marked offline, don't do @@ -3259,18 +3393,46 @@ int vdev_load(vdev_t *vd) { + int children = vd->vdev_children; int error = 0; + taskq_t *tq = NULL; + + /* + * It's only worthwhile to use the taskq for the root vdev, because the + * slow part is metaslab_init, and that only happens for top-level + * vdevs. + */ + if (vd->vdev_ops == &vdev_root_ops && vd->vdev_children > 0) { + tq = taskq_create("vdev_load", children, minclsyspri, + children, children, TASKQ_PREPOPULATE); + } /* * Recursively load all children. */ for (int c = 0; c < vd->vdev_children; c++) { - error = vdev_load(vd->vdev_child[c]); - if (error != 0) { - return (error); + vdev_t *cvd = vd->vdev_child[c]; + + if (tq == NULL || vdev_uses_zvols(cvd)) { + cvd->vdev_load_error = vdev_load(cvd); + } else { + VERIFY(taskq_dispatch(tq, vdev_load_child, + cvd, TQ_SLEEP) != TASKQID_INVALID); } } + if (tq != NULL) { + taskq_wait(tq); + taskq_destroy(tq); + } + + for (int c = 0; c < vd->vdev_children; c++) { + int error = vd->vdev_child[c]->vdev_load_error; + + if (error != 0) + return (error); + } + vdev_set_deflate_ratio(vd); /* @@ -3531,8 +3693,11 @@ != NULL) metaslab_sync_done(msp, txg); - if (reassess) + if (reassess) { metaslab_sync_reassess(vd->vdev_mg); + if (vd->vdev_log_mg != NULL) + metaslab_sync_reassess(vd->vdev_log_mg); + } } void @@ -3856,6 +4021,7 @@ /* * Prevent any future allocations. */ + ASSERT3P(tvd->vdev_log_mg, ==, NULL); metaslab_group_passivate(mg); (void) spa_vdev_state_exit(spa, vd, 0); @@ -4256,6 +4422,12 @@ */ if (vd->vdev_aux == NULL && vd == vd->vdev_top && vdev_is_concrete(vd)) { + /* + * The vdev fragmentation rating doesn't take into + * account the embedded slog metaslab (vdev_log_mg). + * Since it's only one metaslab, it would have a tiny + * impact on the overall fragmentation. + */ vs->vs_fragmentation = (vd->vdev_mg != NULL) ? vd->vdev_mg->mg_fragmentation : 0; } @@ -5234,6 +5406,9 @@ ZFS_MODULE_PARAM(zfs, zfs_, nocacheflush, INT, ZMOD_RW, "Disable cache flushes"); +ZFS_MODULE_PARAM(zfs, zfs_, embedded_slog_min_ms, INT, ZMOD_RW, + "Minimum number of metaslabs required to dedicate one for log blocks"); + ZFS_MODULE_PARAM_CALL(zfs_vdev, zfs_vdev_, min_auto_ashift, param_set_min_auto_ashift, param_get_ulong, ZMOD_RW, "Minimum ashift used when creating new top-level vdevs"); diff --git a/sys/contrib/openzfs/module/zfs/vdev_draid.c b/sys/contrib/openzfs/module/zfs/vdev_draid.c --- a/sys/contrib/openzfs/module/zfs/vdev_draid.c +++ b/sys/contrib/openzfs/module/zfs/vdev_draid.c @@ -716,7 +716,7 @@ offset = 0; for (; x < rr->rr_cols; x++) { - abd_put(rr->rr_col[x].rc_abd); + abd_free(rr->rr_col[x].rc_abd); if (offset == good_size) { /* empty data column (small write) */ @@ -754,11 +754,7 @@ offset = 0; for (x = rr->rr_firstdatacol; x < rr->rr_cols; x++) { - if (offset == good_size || x < rr->rr_bigcols) - abd_put(rr->rr_col[x].rc_abd); - else - abd_free(rr->rr_col[x].rc_abd); - + abd_free(rr->rr_col[x].rc_abd); rr->rr_col[x].rc_abd = abd_get_offset_size( rr->rr_abd_copy, offset, rr->rr_col[x].rc_size); @@ -797,7 +793,7 @@ /* we drop the ereport if it ends up that the data was good */ zfs_ereport_finish_checksum(zcr, good, bad, B_TRUE); - abd_put((abd_t *)good); + abd_free((abd_t *)good); } /* @@ -852,11 +848,7 @@ offset, col->rc_size); abd_copy(tmp, col->rc_abd, col->rc_size); - - if (abd_is_gang(col->rc_abd)) - abd_free(col->rc_abd); - else - abd_put(col->rc_abd); + abd_free(col->rc_abd); col->rc_abd = tmp; offset += col->rc_size; @@ -902,12 +894,12 @@ rc->rc_abd = abd_get_zeros(skip_size); } else if (rc->rc_size == parity_size) { /* this is a "big column" */ - rc->rc_abd = abd_get_offset_size(zio->io_abd, - abd_off, rc->rc_size); + rc->rc_abd = abd_get_offset_struct(&rc->rc_abdstruct, + zio->io_abd, abd_off, rc->rc_size); } else { /* short data column, add a skip sector */ ASSERT3U(rc->rc_size + skip_size, ==, parity_size); - rc->rc_abd = abd_alloc_gang_abd(); + rc->rc_abd = abd_alloc_gang(); abd_gang_add(rc->rc_abd, abd_get_offset_size( zio->io_abd, abd_off, rc->rc_size), B_TRUE); abd_gang_add(rc->rc_abd, abd_get_zeros(skip_size), @@ -958,13 +950,13 @@ skip_off += skip_size; } else if (rc->rc_size == parity_size) { /* this is a "big column" */ - rc->rc_abd = abd_get_offset_size(zio->io_abd, - abd_off, rc->rc_size); + rc->rc_abd = abd_get_offset_struct(&rc->rc_abdstruct, + zio->io_abd, abd_off, rc->rc_size); } else { /* short data column, add a skip sector */ ASSERT3U(rc->rc_size + skip_size, ==, parity_size); ASSERT3U(rr->rr_nempty, !=, 0); - rc->rc_abd = abd_alloc_gang_abd(); + rc->rc_abd = abd_alloc_gang(); abd_gang_add(rc->rc_abd, abd_get_offset_size( zio->io_abd, abd_off, rc->rc_size), B_TRUE); abd_gang_add(rc->rc_abd, abd_get_offset_size( @@ -1006,8 +998,8 @@ raidz_col_t *rc = &rr->rr_col[c]; if (rc->rc_size > 0) { - rc->rc_abd = abd_get_offset_size(zio->io_abd, - abd_off, rc->rc_size); + rc->rc_abd = abd_get_offset_struct(&rc->rc_abdstruct, + zio->io_abd, abd_off, rc->rc_size); abd_off += rc->rc_size; } } @@ -1056,7 +1048,7 @@ ASSERT3P(rc->rc_abd, !=, NULL); ASSERT(!abd_is_gang(rc->rc_abd)); abd_t *read_abd = rc->rc_abd; - rc->rc_abd = abd_alloc_gang_abd(); + rc->rc_abd = abd_alloc_gang(); abd_gang_add(rc->rc_abd, read_abd, B_TRUE); abd_gang_add(rc->rc_abd, abd_get_offset_size( rr->rr_abd_empty, skip_off, skip_size), B_TRUE); diff --git a/sys/contrib/openzfs/module/zfs/vdev_indirect.c b/sys/contrib/openzfs/module/zfs/vdev_indirect.c --- a/sys/contrib/openzfs/module/zfs/vdev_indirect.c +++ b/sys/contrib/openzfs/module/zfs/vdev_indirect.c @@ -1187,7 +1187,7 @@ pio->io_error = zio_worst_error(pio->io_error, zio->io_error); mutex_exit(&pio->io_lock); - abd_put(zio->io_abd); + abd_free(zio->io_abd); } /* diff --git a/sys/contrib/openzfs/module/zfs/vdev_label.c b/sys/contrib/openzfs/module/zfs/vdev_label.c --- a/sys/contrib/openzfs/module/zfs/vdev_label.c +++ b/sys/contrib/openzfs/module/zfs/vdev_label.c @@ -754,16 +754,17 @@ { spa_t *spa = vd->vdev_spa; nvlist_t *config = NULL; - vdev_phys_t *vp; - abd_t *vp_abd; - zio_t *zio; + vdev_phys_t *vp[VDEV_LABELS]; + abd_t *vp_abd[VDEV_LABELS]; + zio_t *zio[VDEV_LABELS]; uint64_t best_txg = 0; uint64_t label_txg = 0; int error = 0; int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE; - ASSERT(spa_config_held(spa, SCL_STATE_ALL, RW_WRITER) == SCL_STATE_ALL); + ASSERT(vd->vdev_validate_thread == curthread || + spa_config_held(spa, SCL_STATE_ALL, RW_WRITER) == SCL_STATE_ALL); if (!vdev_readable(vd)) return (NULL); @@ -776,21 +777,24 @@ if (vd->vdev_ops == &vdev_draid_spare_ops) return (vdev_draid_read_config_spare(vd)); - vp_abd = abd_alloc_linear(sizeof (vdev_phys_t), B_TRUE); - vp = abd_to_buf(vp_abd); + for (int l = 0; l < VDEV_LABELS; l++) { + vp_abd[l] = abd_alloc_linear(sizeof (vdev_phys_t), B_TRUE); + vp[l] = abd_to_buf(vp_abd[l]); + } retry: for (int l = 0; l < VDEV_LABELS; l++) { - nvlist_t *label = NULL; - - zio = zio_root(spa, NULL, NULL, flags); + zio[l] = zio_root(spa, NULL, NULL, flags); - vdev_label_read(zio, vd, l, vp_abd, - offsetof(vdev_label_t, vl_vdev_phys), - sizeof (vdev_phys_t), NULL, NULL, flags); + vdev_label_read(zio[l], vd, l, vp_abd[l], + offsetof(vdev_label_t, vl_vdev_phys), sizeof (vdev_phys_t), + NULL, NULL, flags); + } + for (int l = 0; l < VDEV_LABELS; l++) { + nvlist_t *label = NULL; - if (zio_wait(zio) == 0 && - nvlist_unpack(vp->vp_nvlist, sizeof (vp->vp_nvlist), + if (zio_wait(zio[l]) == 0 && + nvlist_unpack(vp[l]->vp_nvlist, sizeof (vp[l]->vp_nvlist), &label, 0) == 0) { /* * Auxiliary vdevs won't have txg values in their @@ -803,6 +807,8 @@ ZPOOL_CONFIG_POOL_TXG, &label_txg); if ((error || label_txg == 0) && !config) { config = label; + for (l++; l < VDEV_LABELS; l++) + zio_wait(zio[l]); break; } else if (label_txg <= txg && label_txg > best_txg) { best_txg = label_txg; @@ -831,7 +837,9 @@ (u_longlong_t)txg); } - abd_free(vp_abd); + for (int l = 0; l < VDEV_LABELS; l++) { + abd_free(vp_abd[l]); + } return (config); } diff --git a/sys/contrib/openzfs/module/zfs/vdev_queue.c b/sys/contrib/openzfs/module/zfs/vdev_queue.c --- a/sys/contrib/openzfs/module/zfs/vdev_queue.c +++ b/sys/contrib/openzfs/module/zfs/vdev_queue.c @@ -789,7 +789,7 @@ size = IO_SPAN(first, last); ASSERT3U(size, <=, maxblocksize); - abd = abd_alloc_gang_abd(); + abd = abd_alloc_gang(); if (abd == NULL) return (NULL); diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz.c b/sys/contrib/openzfs/module/zfs/vdev_raidz.c --- a/sys/contrib/openzfs/module/zfs/vdev_raidz.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz.c @@ -138,30 +138,15 @@ static void vdev_raidz_row_free(raidz_row_t *rr) { - int c; - - for (c = 0; c < rr->rr_firstdatacol && c < rr->rr_cols; c++) { - abd_free(rr->rr_col[c].rc_abd); + for (int c = 0; c < rr->rr_cols; c++) { + raidz_col_t *rc = &rr->rr_col[c]; - if (rr->rr_col[c].rc_gdata != NULL) { - abd_free(rr->rr_col[c].rc_gdata); - } - if (rr->rr_col[c].rc_orig_data != NULL) { - zio_buf_free(rr->rr_col[c].rc_orig_data, - rr->rr_col[c].rc_size); - } - } - for (c = rr->rr_firstdatacol; c < rr->rr_cols; c++) { - if (rr->rr_col[c].rc_size != 0) { - if (abd_is_gang(rr->rr_col[c].rc_abd)) - abd_free(rr->rr_col[c].rc_abd); - else - abd_put(rr->rr_col[c].rc_abd); - } - if (rr->rr_col[c].rc_orig_data != NULL) { - zio_buf_free(rr->rr_col[c].rc_orig_data, - rr->rr_col[c].rc_size); - } + if (rc->rc_size != 0) + abd_free(rc->rc_abd); + if (rc->rc_gdata != NULL) + abd_free(rc->rc_gdata); + if (rc->rc_orig_data != NULL) + zio_buf_free(rc->rc_orig_data, rc->rc_size); } if (rr->rr_abd_copy != NULL) @@ -249,7 +234,7 @@ /* fill in the data columns from good_data */ offset = 0; for (; x < rr->rr_cols; x++) { - abd_put(rr->rr_col[x].rc_abd); + abd_free(rr->rr_col[x].rc_abd); rr->rr_col[x].rc_abd = abd_get_offset_size((abd_t *)good_data, @@ -268,7 +253,7 @@ offset = 0; for (x = rr->rr_firstdatacol; x < rr->rr_cols; x++) { - abd_put(rr->rr_col[x].rc_abd); + abd_free(rr->rr_col[x].rc_abd); rr->rr_col[x].rc_abd = abd_get_offset_size( rr->rr_abd_copy, offset, rr->rr_col[x].rc_size); @@ -291,7 +276,7 @@ /* we drop the ereport if it ends up that the data was good */ zfs_ereport_finish_checksum(zcr, good, bad, B_TRUE); - abd_put((abd_t *)good); + abd_free((abd_t *)good); } /* @@ -344,7 +329,7 @@ abd_copy(tmp, col->rc_abd, col->rc_size); - abd_put(col->rc_abd); + abd_free(col->rc_abd); col->rc_abd = tmp; offset += col->rc_size; @@ -379,7 +364,6 @@ /* The starting byte offset on each child vdev. */ uint64_t o = (b / dcols) << ashift; uint64_t q, r, c, bc, col, acols, scols, coff, devidx, asize, tot; - uint64_t off = 0; raidz_map_t *rm = kmem_zalloc(offsetof(raidz_map_t, rm_row[1]), KM_SLEEP); @@ -477,13 +461,10 @@ rr->rr_col[c].rc_abd = abd_alloc_linear(rr->rr_col[c].rc_size, B_FALSE); - rr->rr_col[c].rc_abd = abd_get_offset_size(zio->io_abd, 0, - rr->rr_col[c].rc_size); - off = rr->rr_col[c].rc_size; - - for (c = c + 1; c < acols; c++) { + for (uint64_t off = 0; c < acols; c++) { raidz_col_t *rc = &rr->rr_col[c]; - rc->rc_abd = abd_get_offset_size(zio->io_abd, off, rc->rc_size); + rc->rc_abd = abd_get_offset_struct(&rc->rc_abdstruct, + zio->io_abd, off, rc->rc_size); off += rc->rc_size; } diff --git a/sys/contrib/openzfs/module/zfs/vdev_removal.c b/sys/contrib/openzfs/module/zfs/vdev_removal.c --- a/sys/contrib/openzfs/module/zfs/vdev_removal.c +++ b/sys/contrib/openzfs/module/zfs/vdev_removal.c @@ -1207,6 +1207,11 @@ vd->vdev_mg = NULL; spa_log_sm_set_blocklimit(spa); } + if (vd->vdev_log_mg != NULL) { + ASSERT0(vd->vdev_ms_count); + metaslab_group_destroy(vd->vdev_log_mg); + vd->vdev_log_mg = NULL; + } ASSERT0(vd->vdev_stat.vs_space); ASSERT0(vd->vdev_stat.vs_dspace); @@ -1780,6 +1785,8 @@ spa_config_enter(spa, SCL_ALLOC | SCL_VDEV, FTAG, RW_WRITER); vdev_t *vd = vdev_lookup_top(spa, vdid); metaslab_group_activate(vd->vdev_mg); + ASSERT(!vd->vdev_islog); + metaslab_group_activate(vd->vdev_log_mg); spa_config_exit(spa, SCL_ALLOC | SCL_VDEV, FTAG); } @@ -1858,6 +1865,7 @@ ASSERT(vd->vdev_islog); ASSERT(vd == vd->vdev_top); + ASSERT3P(vd->vdev_log_mg, ==, NULL); ASSERT(MUTEX_HELD(&spa_namespace_lock)); /* @@ -1893,6 +1901,7 @@ if (error != 0) { metaslab_group_activate(mg); + ASSERT3P(vd->vdev_log_mg, ==, NULL); return (error); } ASSERT0(vd->vdev_stat.vs_alloc); @@ -2121,6 +2130,8 @@ */ metaslab_group_t *mg = vd->vdev_mg; metaslab_group_passivate(mg); + ASSERT(!vd->vdev_islog); + metaslab_group_passivate(vd->vdev_log_mg); /* * Wait for the youngest allocations and frees to sync, @@ -2157,6 +2168,8 @@ if (error != 0) { metaslab_group_activate(mg); + ASSERT(!vd->vdev_islog); + metaslab_group_activate(vd->vdev_log_mg); spa_async_request(spa, SPA_ASYNC_INITIALIZE_RESTART); spa_async_request(spa, SPA_ASYNC_TRIM_RESTART); spa_async_request(spa, SPA_ASYNC_AUTOTRIM_RESTART); diff --git a/sys/contrib/openzfs/module/zfs/zfs_ioctl.c b/sys/contrib/openzfs/module/zfs/zfs_ioctl.c --- a/sys/contrib/openzfs/module/zfs/zfs_ioctl.c +++ b/sys/contrib/openzfs/module/zfs/zfs_ioctl.c @@ -7418,6 +7418,7 @@ size_t saved_poolname_len = 0; nvlist_t *innvl = NULL; fstrans_cookie_t cookie; + hrtime_t start_time = gethrtime(); cmd = vecnum; error = 0; @@ -7576,6 +7577,8 @@ fnvlist_add_int64(lognv, ZPOOL_HIST_ERRNO, error); } + fnvlist_add_int64(lognv, ZPOOL_HIST_ELAPSED_NS, + gethrtime() - start_time); (void) spa_history_log_nvl(spa, lognv); spa_close(spa, FTAG); } diff --git a/sys/contrib/openzfs/module/zfs/zfs_sa.c b/sys/contrib/openzfs/module/zfs/zfs_sa.c --- a/sys/contrib/openzfs/module/zfs/zfs_sa.c +++ b/sys/contrib/openzfs/module/zfs/zfs_sa.c @@ -71,7 +71,7 @@ #ifdef _KERNEL int -zfs_sa_readlink(znode_t *zp, uio_t *uio) +zfs_sa_readlink(znode_t *zp, zfs_uio_t *uio) { dmu_buf_t *db = sa_get_db(zp->z_sa_hdl); size_t bufsz; @@ -79,15 +79,16 @@ bufsz = zp->z_size; if (bufsz + ZFS_OLD_ZNODE_PHYS_SIZE <= db->db_size) { - error = uiomove((caddr_t)db->db_data + + error = zfs_uiomove((caddr_t)db->db_data + ZFS_OLD_ZNODE_PHYS_SIZE, - MIN((size_t)bufsz, uio_resid(uio)), UIO_READ, uio); + MIN((size_t)bufsz, zfs_uio_resid(uio)), UIO_READ, uio); } else { dmu_buf_t *dbp; if ((error = dmu_buf_hold(ZTOZSB(zp)->z_os, zp->z_id, 0, FTAG, &dbp, DMU_READ_NO_PREFETCH)) == 0) { - error = uiomove(dbp->db_data, - MIN((size_t)bufsz, uio_resid(uio)), UIO_READ, uio); + error = zfs_uiomove(dbp->db_data, + MIN((size_t)bufsz, zfs_uio_resid(uio)), UIO_READ, + uio); dmu_buf_rele(dbp, FTAG); } } diff --git a/sys/contrib/openzfs/module/zfs/zfs_vnops.c b/sys/contrib/openzfs/module/zfs/zfs_vnops.c --- a/sys/contrib/openzfs/module/zfs/zfs_vnops.c +++ b/sys/contrib/openzfs/module/zfs/zfs_vnops.c @@ -187,7 +187,7 @@ */ /* ARGSUSED */ int -zfs_read(struct znode *zp, uio_t *uio, int ioflag, cred_t *cr) +zfs_read(struct znode *zp, zfs_uio_t *uio, int ioflag, cred_t *cr) { int error = 0; boolean_t frsync = B_FALSE; @@ -210,7 +210,7 @@ /* * Validate file offset */ - if (uio->uio_loffset < (offset_t)0) { + if (zfs_uio_offset(uio) < (offset_t)0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); } @@ -218,7 +218,7 @@ /* * Fasttrack empty reads */ - if (uio->uio_resid == 0) { + if (zfs_uio_resid(uio) == 0) { ZFS_EXIT(zfsvfs); return (0); } @@ -242,26 +242,26 @@ * Lock the range against changes. */ zfs_locked_range_t *lr = zfs_rangelock_enter(&zp->z_rangelock, - uio->uio_loffset, uio->uio_resid, RL_READER); + zfs_uio_offset(uio), zfs_uio_resid(uio), RL_READER); /* * If we are reading past end-of-file we can skip * to the end; but we might still need to set atime. */ - if (uio->uio_loffset >= zp->z_size) { + if (zfs_uio_offset(uio) >= zp->z_size) { error = 0; goto out; } - ASSERT(uio->uio_loffset < zp->z_size); - ssize_t n = MIN(uio->uio_resid, zp->z_size - uio->uio_loffset); + ASSERT(zfs_uio_offset(uio) < zp->z_size); + ssize_t n = MIN(zfs_uio_resid(uio), zp->z_size - zfs_uio_offset(uio)); ssize_t start_resid = n; while (n > 0) { ssize_t nbytes = MIN(n, zfs_vnops_read_chunk_size - - P2PHASE(uio->uio_loffset, zfs_vnops_read_chunk_size)); + P2PHASE(zfs_uio_offset(uio), zfs_vnops_read_chunk_size)); #ifdef UIO_NOCOPY - if (uio->uio_segflg == UIO_NOCOPY) + if (zfs_uio_segflg(uio) == UIO_NOCOPY) error = mappedread_sf(zp, nbytes, uio); else #endif @@ -314,10 +314,10 @@ /* ARGSUSED */ int -zfs_write(znode_t *zp, uio_t *uio, int ioflag, cred_t *cr) +zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr) { int error = 0; - ssize_t start_resid = uio->uio_resid; + ssize_t start_resid = zfs_uio_resid(uio); /* * Fasttrack empty write @@ -354,7 +354,7 @@ */ if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) || ((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & O_APPEND) && - (uio->uio_loffset < zp->z_size))) { + (zfs_uio_offset(uio) < zp->z_size))) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EPERM)); } @@ -362,7 +362,7 @@ /* * Validate file offset */ - offset_t woff = ioflag & O_APPEND ? zp->z_size : uio->uio_loffset; + offset_t woff = ioflag & O_APPEND ? zp->z_size : zfs_uio_offset(uio); if (woff < 0) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EINVAL)); @@ -375,7 +375,7 @@ * don't hold up txg. * Skip this if uio contains loaned arc_buf. */ - if (uio_prefaultpages(MIN(n, max_blksz), uio)) { + if (zfs_uio_prefaultpages(MIN(n, max_blksz), uio)) { ZFS_EXIT(zfsvfs); return (SET_ERROR(EFAULT)); } @@ -399,7 +399,7 @@ */ woff = zp->z_size; } - uio->uio_loffset = woff; + zfs_uio_setoffset(uio, woff); } else { /* * Note that if the file block size will change as a result of @@ -409,7 +409,7 @@ lr = zfs_rangelock_enter(&zp->z_rangelock, woff, n, RL_WRITER); } - if (zn_rlimit_fsize(zp, uio, uio->uio_td)) { + if (zn_rlimit_fsize(zp, uio)) { zfs_rangelock_exit(lr); ZFS_EXIT(zfsvfs); return (SET_ERROR(EFBIG)); @@ -439,7 +439,7 @@ * and allows us to do more fine-grained space accounting. */ while (n > 0) { - woff = uio->uio_loffset; + woff = zfs_uio_offset(uio); if (zfs_id_overblockquota(zfsvfs, DMU_USERUSED_OBJECT, uid) || zfs_id_overblockquota(zfsvfs, DMU_GROUPUSED_OBJECT, gid) || @@ -467,7 +467,7 @@ max_blksz); ASSERT(abuf != NULL); ASSERT(arc_buf_size(abuf) == max_blksz); - if ((error = uiocopy(abuf->b_data, max_blksz, + if ((error = zfs_uiocopy(abuf->b_data, max_blksz, UIO_WRITE, uio, &cbytes))) { dmu_return_arcbuf(abuf); break; @@ -528,11 +528,11 @@ ssize_t tx_bytes; if (abuf == NULL) { - tx_bytes = uio->uio_resid; - uio_fault_disable(uio, B_TRUE); + tx_bytes = zfs_uio_resid(uio); + zfs_uio_fault_disable(uio, B_TRUE); error = dmu_write_uio_dbuf(sa_get_db(zp->z_sa_hdl), uio, nbytes, tx); - uio_fault_disable(uio, B_FALSE); + zfs_uio_fault_disable(uio, B_FALSE); #ifdef __linux__ if (error == EFAULT) { dmu_tx_commit(tx); @@ -540,12 +540,13 @@ * Account for partial writes before * continuing the loop. * Update needs to occur before the next - * uio_prefaultpages, or prefaultpages may + * zfs_uio_prefaultpages, or prefaultpages may * error, and we may break the loop early. */ - if (tx_bytes != uio->uio_resid) - n -= tx_bytes - uio->uio_resid; - if (uio_prefaultpages(MIN(n, max_blksz), uio)) { + if (tx_bytes != zfs_uio_resid(uio)) + n -= tx_bytes - zfs_uio_resid(uio); + if (zfs_uio_prefaultpages(MIN(n, max_blksz), + uio)) { break; } continue; @@ -555,7 +556,7 @@ dmu_tx_commit(tx); break; } - tx_bytes -= uio->uio_resid; + tx_bytes -= zfs_uio_resid(uio); } else { /* Implied by abuf != NULL: */ ASSERT3S(n, >=, max_blksz); @@ -580,8 +581,8 @@ dmu_tx_commit(tx); break; } - ASSERT3S(nbytes, <=, uio->uio_resid); - uioskip(uio, nbytes); + ASSERT3S(nbytes, <=, zfs_uio_resid(uio)); + zfs_uioskip(uio, nbytes); tx_bytes = nbytes; } if (tx_bytes && zn_has_cached_data(zp) && @@ -632,9 +633,9 @@ * Update the file size (zp_size) if it has changed; * account for possible concurrent updates. */ - while ((end_size = zp->z_size) < uio->uio_loffset) { + while ((end_size = zp->z_size) < zfs_uio_offset(uio)) { (void) atomic_cas_64(&zp->z_size, end_size, - uio->uio_loffset); + zfs_uio_offset(uio)); ASSERT(error == 0); } /* @@ -657,14 +658,14 @@ n -= nbytes; if (n > 0) { - if (uio_prefaultpages(MIN(n, max_blksz), uio)) { + if (zfs_uio_prefaultpages(MIN(n, max_blksz), uio)) { error = SET_ERROR(EFAULT); break; } } } - zfs_inode_update(zp); + zfs_znode_update_vfs(zp); zfs_rangelock_exit(lr); /* @@ -672,7 +673,7 @@ * uio data is inaccessible return an error. Otherwise, it's * at least a partial write, so it's successful. */ - if (zfsvfs->z_replay || uio->uio_resid == start_resid || + if (zfsvfs->z_replay || zfs_uio_resid(uio) == start_resid || error == EFAULT) { ZFS_EXIT(zfsvfs); return (error); @@ -682,7 +683,7 @@ zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zilog, zp->z_id); - const int64_t nwritten = start_resid - uio->uio_resid; + const int64_t nwritten = start_resid - zfs_uio_resid(uio); dataset_kstats_update_write_kstats(&zfsvfs->z_kstat, nwritten); task_io_account_write(nwritten); diff --git a/sys/contrib/openzfs/module/zfs/zil.c b/sys/contrib/openzfs/module/zfs/zil.c --- a/sys/contrib/openzfs/module/zfs/zil.c +++ b/sys/contrib/openzfs/module/zfs/zil.c @@ -1230,7 +1230,7 @@ ASSERT(!BP_IS_HOLE(zio->io_bp)); ASSERT(BP_GET_FILL(zio->io_bp) == 0); - abd_put(zio->io_abd); + abd_free(zio->io_abd); mutex_enter(&zilog->zl_lock); ASSERT3S(lwb->lwb_state, ==, LWB_STATE_ISSUED); diff --git a/sys/contrib/openzfs/module/zfs/zio.c b/sys/contrib/openzfs/module/zfs/zio.c --- a/sys/contrib/openzfs/module/zfs/zio.c +++ b/sys/contrib/openzfs/module/zfs/zio.c @@ -2481,7 +2481,7 @@ static void zio_gang_issue_func_done(zio_t *zio) { - abd_put(zio->io_abd); + abd_free(zio->io_abd); } static zio_t * @@ -2525,7 +2525,7 @@ zio_checksum_compute(zio, BP_GET_CHECKSUM(bp), buf, BP_GET_PSIZE(bp)); - abd_put(buf); + abd_free(buf); } /* * If we are here to damage data for testing purposes, @@ -2653,7 +2653,7 @@ ASSERT(zio->io_size == SPA_GANGBLOCKSIZE); ASSERT(gn->gn_gbh->zg_tail.zec_magic == ZEC_MAGIC); - abd_put(zio->io_abd); + abd_free(zio->io_abd); for (int g = 0; g < SPA_GBH_NBLKPTRS; g++) { blkptr_t *gbp = &gn->gn_gbh->zg_blkptr[g]; @@ -2777,14 +2777,13 @@ * check for it here as it is cleared in zio_ready. */ if (zio->io_abd != NULL) - abd_put(zio->io_abd); + abd_free(zio->io_abd); } static zio_t * -zio_write_gang_block(zio_t *pio) +zio_write_gang_block(zio_t *pio, metaslab_class_t *mc) { spa_t *spa = pio->io_spa; - metaslab_class_t *mc = spa_normal_class(spa); blkptr_t *bp = pio->io_bp; zio_t *gio = pio->io_gang_leader; zio_t *zio; @@ -3501,6 +3500,17 @@ zio->io_metaslab_class = mc; } + /* + * Try allocating the block in the usual metaslab class. + * If that's full, allocate it in the normal class. + * If that's full, allocate as a gang block, + * and if all are full, the allocation fails (which shouldn't happen). + * + * Note that we do not fall back on embedded slog (ZIL) space, to + * preserve unfragmented slog space, which is critical for decent + * sync write performance. If a log allocation fails, we will fall + * back to spa_sync() which is abysmal for performance. + */ error = metaslab_alloc(spa, mc, zio->io_size, bp, zio->io_prop.zp_copies, zio->io_txg, NULL, flags, &zio->io_alloc_list, zio, zio->io_allocator); @@ -3520,26 +3530,38 @@ zio->io_prop.zp_copies, zio->io_allocator, zio); zio->io_flags &= ~ZIO_FLAG_IO_ALLOCATING; - mc = spa_normal_class(spa); - VERIFY(metaslab_class_throttle_reserve(mc, + VERIFY(metaslab_class_throttle_reserve( + spa_normal_class(spa), zio->io_prop.zp_copies, zio->io_allocator, zio, flags | METASLAB_MUST_RESERVE)); - } else { - mc = spa_normal_class(spa); } - zio->io_metaslab_class = mc; + zio->io_metaslab_class = mc = spa_normal_class(spa); + if (zfs_flags & ZFS_DEBUG_METASLAB_ALLOC) { + zfs_dbgmsg("%s: metaslab allocation failure, " + "trying normal class: zio %px, size %llu, error %d", + spa_name(spa), zio, zio->io_size, error); + } error = metaslab_alloc(spa, mc, zio->io_size, bp, zio->io_prop.zp_copies, zio->io_txg, NULL, flags, &zio->io_alloc_list, zio, zio->io_allocator); } + if (error == ENOSPC && zio->io_size > SPA_MINBLOCKSIZE) { + if (zfs_flags & ZFS_DEBUG_METASLAB_ALLOC) { + zfs_dbgmsg("%s: metaslab allocation failure, " + "trying ganging: zio %px, size %llu, error %d", + spa_name(spa), zio, zio->io_size, error); + } + return (zio_write_gang_block(zio, mc)); + } if (error != 0) { - zfs_dbgmsg("%s: metaslab allocation failure: zio %px, " - "size %llu, error %d", spa_name(spa), zio, zio->io_size, - error); - if (error == ENOSPC && zio->io_size > SPA_MINBLOCKSIZE) - return (zio_write_gang_block(zio)); + if (error != ENOSPC || + (zfs_flags & ZFS_DEBUG_METASLAB_ALLOC)) { + zfs_dbgmsg("%s: metaslab allocation failure: zio %px, " + "size %llu, error %d", + spa_name(spa), zio, zio->io_size, error); + } zio->io_error = error; } @@ -3619,15 +3641,18 @@ int flags = METASLAB_FASTWRITE | METASLAB_ZIL; int allocator = cityhash4(0, 0, 0, os->os_dsl_dataset->ds_object) % spa->spa_alloc_count; - error = metaslab_alloc(spa, spa_log_class(spa), size, new_bp, - 1, txg, NULL, flags, &io_alloc_list, NULL, allocator); - if (error == 0) { - *slog = TRUE; - } else { - error = metaslab_alloc(spa, spa_normal_class(spa), size, new_bp, - 1, txg, NULL, flags, &io_alloc_list, NULL, allocator); - if (error == 0) - *slog = FALSE; + error = metaslab_alloc(spa, spa_log_class(spa), size, new_bp, 1, + txg, NULL, flags, &io_alloc_list, NULL, allocator); + *slog = (error == 0); + if (error != 0) { + error = metaslab_alloc(spa, spa_embedded_log_class(spa), size, + new_bp, 1, txg, NULL, flags, + &io_alloc_list, NULL, allocator); + } + if (error != 0) { + error = metaslab_alloc(spa, spa_normal_class(spa), size, + new_bp, 1, txg, NULL, flags, + &io_alloc_list, NULL, allocator); } metaslab_trace_fini(&io_alloc_list); diff --git a/sys/contrib/openzfs/rpm/generic/zfs.spec.in b/sys/contrib/openzfs/rpm/generic/zfs.spec.in --- a/sys/contrib/openzfs/rpm/generic/zfs.spec.in +++ b/sys/contrib/openzfs/rpm/generic/zfs.spec.in @@ -442,7 +442,7 @@ # Core utilities %{_sbindir}/* %{_bindir}/raidz_test -%{_bindir}/zgenhostid +%{_sbindir}/zgenhostid %{_bindir}/zvol_wait # Optional Python 2/3 scripts %{_bindir}/arc_summary diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run --- a/sys/contrib/openzfs/tests/runfiles/common.run +++ b/sys/contrib/openzfs/tests/runfiles/common.run @@ -119,7 +119,7 @@ 'zdb_006_pos', 'zdb_args_neg', 'zdb_args_pos', 'zdb_block_size_histogram', 'zdb_checksum', 'zdb_decompress', 'zdb_display_block', 'zdb_object_range_neg', 'zdb_object_range_pos', - 'zdb_objset_id', 'zdb_decompress_zstd'] + 'zdb_objset_id', 'zdb_decompress_zstd', 'zdb_recover', 'zdb_recover_2'] pre = post = tags = ['functional', 'cli_root', 'zdb'] diff --git a/sys/contrib/openzfs/tests/runfiles/linux.run b/sys/contrib/openzfs/tests/runfiles/linux.run --- a/sys/contrib/openzfs/tests/runfiles/linux.run +++ b/sys/contrib/openzfs/tests/runfiles/linux.run @@ -115,7 +115,7 @@ tags = ['functional', 'features', 'large_dnode'] [tests/functional/io:Linux] -tests = ['libaio'] +tests = ['libaio', 'io_uring'] tags = ['functional', 'io'] [tests/functional/mmap:Linux] diff --git a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in --- a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in +++ b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in @@ -127,6 +127,11 @@ # na_reason = "Not applicable" +# +# Some test cases doesn't have all requirements to run on Github actions CI. +# +ci_reason = 'CI runner doesn\'t have all requirements' + summary = { 'total': float(0), 'passed': float(0), @@ -263,6 +268,7 @@ '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], + 'io/io_uring': ['SKIP', 'io_uring support required'], 'limits/filesystem_limit': ['SKIP', known_reason], 'limits/snapshot_limit': ['SKIP', known_reason], 'mmp/mmp_exported_import': ['FAIL', known_reason], @@ -275,6 +281,35 @@ }) +# Not all Github actions runners have scsi_debug module, so we may skip +# some tests which use it. +if os.environ.get('CI') == 'true': + known.update({ + 'cli_root/zpool_expand/zpool_expand_001_pos': ['SKIP', ci_reason], + 'cli_root/zpool_expand/zpool_expand_003_neg': ['SKIP', ci_reason], + 'cli_root/zpool_expand/zpool_expand_005_pos': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/setup': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/zpool_reopen_001_pos': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/zpool_reopen_002_pos': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/zpool_reopen_003_pos': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/zpool_reopen_004_pos': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/zpool_reopen_005_pos': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/zpool_reopen_006_neg': ['SKIP', ci_reason], + 'cli_root/zpool_reopen/zpool_reopen_007_pos': ['SKIP', ci_reason], + 'cli_root/zpool_split/zpool_split_wholedisk': ['SKIP', ci_reason], + 'fault/auto_offline_001_pos': ['SKIP', ci_reason], + 'fault/auto_online_001_pos': ['SKIP', ci_reason], + 'fault/auto_replace_001_pos': ['SKIP', ci_reason], + 'fault/auto_spare_ashift': ['SKIP', ci_reason], + 'fault/auto_spare_shared': ['SKIP', ci_reason], + 'procfs/pool_state': ['SKIP', ci_reason], + }) + + maybe.update({ + 'events/events_002_pos': ['FAIL', '11546'], + }) + + def usage(s): print(s) sys.exit(1) diff --git a/sys/contrib/openzfs/tests/test-runner/include/logapi.shlib b/sys/contrib/openzfs/tests/test-runner/include/logapi.shlib --- a/sys/contrib/openzfs/tests/test-runner/include/logapi.shlib +++ b/sys/contrib/openzfs/tests/test-runner/include/logapi.shlib @@ -105,7 +105,7 @@ " assertion failure exited $status" status=1 else - [[ -n $LOGAPI_DEBUG ]] && print $($out) + [[ -n $LOGAPI_DEBUG ]] && cat $logfile _printsuccess "$@" fi break @@ -244,7 +244,7 @@ fi if (( $ret == 0 )); then - [[ -n $LOGAPI_DEBUG ]] && print $($out) + [[ -n $LOGAPI_DEBUG ]] && cat $logfile _printsuccess "$@" "exited $status" fi fi @@ -284,7 +284,7 @@ " exited $status" status=1 else - [[ -n $LOGAPI_DEBUG ]] && print $($out) + [[ -n $LOGAPI_DEBUG ]] && cat $logfile _printsuccess "$@" fi fi diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite/mmapwrite.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite/mmapwrite.c --- a/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite/mmapwrite.c +++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite/mmapwrite.c @@ -42,8 +42,8 @@ * 2. In the same process, context #2, mmap page fault (which means the mm_sem * is hold) occurred, zfs_dirty_inode open a txg failed, and wait previous * txg "n" completed. - * 3. context #1 call uiomove to write, however page fault is occurred in - * uiomove, which means it needs mm_sem, but mm_sem is hold by + * 3. context #1 call zfs_uiomove to write, however page fault is occurred in + * zfs_uiomove, which means it needs mm_sem, but mm_sem is hold by * context #2, so it stuck and can't complete, then txg "n" will not * complete. * diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh old mode 100644 new mode 100755 diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_001_pos.ksh old mode 100644 new mode 120000 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_001_pos.ksh @@ -0,0 +1 @@ +../posix/posix_001_pos.ksh \ No newline at end of file diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_002_pos.ksh old mode 100644 new mode 120000 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_002_pos.ksh @@ -0,0 +1 @@ +../posix/posix_002_pos.ksh \ No newline at end of file diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_003_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_003_pos.ksh old mode 100644 new mode 120000 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_003_pos.ksh @@ -0,0 +1 @@ +../posix/posix_003_pos.ksh \ No newline at end of file diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_004_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_004_pos.ksh old mode 100644 new mode 120000 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/posix_004_pos.ksh @@ -0,0 +1 @@ +../posix/posix_004_pos.ksh \ No newline at end of file diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/setup.ksh old mode 100644 new mode 100755 diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix/posix_004_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix/posix_004_pos.ksh old mode 100644 new mode 100755 diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am @@ -14,4 +14,6 @@ zdb_object_range_neg.ksh \ zdb_object_range_pos.ksh \ zdb_display_block.ksh \ - zdb_objset_id.ksh + zdb_objset_id.ksh \ + zdb_recover.ksh \ + zdb_recover_2.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh @@ -56,7 +56,7 @@ "add mirror fakepool" "add raidz fakepool" \ "add raidz1 fakepool" "add raidz2 fakepool" \ "setvprop" "blah blah" "-%" "--?" "-*" "-=" \ - "-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" "-r" \ + "-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" \ "-t" "-w" "-z" "-E" "-H" "-I" "-J" "-K" \ "-N" "-Q" "-R" "-T" "-W" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_recover.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_recover.ksh new file mode 100755 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_recover.ksh @@ -0,0 +1,55 @@ +#!/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) 2021 by Allan Jude. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -r +# Will extract (relative to ) to the file +# Similar to -R, except it does the work for you to find each record +# +# Strategy: +# 1. Create a pool +# 2. Write some data to a file +# 3. Extract the file +# 4. Compare the file to the original +# + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL + rm $tmpfile +} + +log_assert "Verify zdb -r extract the correct data." +log_onexit cleanup +init_data=$TESTDIR/file1 +tmpfile="$TEST_BASE_DIR/zdb-recover" +write_count=8 +blksize=131072 +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS +file_write -o create -w -f $init_data -b $blksize -c $write_count +log_must zpool sync $TESTPOOL + +output=$(zdb -r $TESTPOOL/$TESTFS file1 $tmpfile) +log_must cmp $init_data $tmpfile + +log_pass "zdb -r extracts the correct data." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_recover_2.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_recover_2.ksh new file mode 100755 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_recover_2.ksh @@ -0,0 +1,57 @@ +#!/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) 2021 by Allan Jude. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -r +# Will extract (relative to ) to the file +# Similar to -R, except it does the work for you to find each record +# +# Strategy: +# 1. Create a pool +# 2. Write some data to a file +# 3. Append to the file so it isn't an divisible by 2 +# 4. Extract the file +# 5. Compare the file to the original +# + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL + rm $tmpfile +} + +log_assert "Verify zdb -r extract the correct data." +log_onexit cleanup +init_data=$TESTDIR/file1 +tmpfile="$TEST_BASE_DIR/zdb-recover" +write_count=8 +blksize=131072 +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS +file_write -o create -w -f $init_data -b $blksize -c $write_count +log_must echo "zfs" >> $init_data +log_must zpool sync $TESTPOOL + +output=$(zdb -r $TESTPOOL/$TESTFS file1 $tmpfile) +log_must cmp $init_data $tmpfile + +log_pass "zdb -r extracts the correct data." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh @@ -32,7 +32,9 @@ function cleanup { cd $STF_SUITE - [[ -d $TESTDIR/$$ ]] && (rm -rf $TESTDIR/$$ || log_fail) + if [[ -d $TESTDIR/$$ ]]; then + log_must rm -rf $TESTDIR/$$ + fi mounted && zfs $mountcmd $TESTPOOL return 0 } @@ -50,13 +52,25 @@ log_note "Verify mount(8) does not canonicalize before calling helper" # Canonicalization is confused by files in PWD matching [device|mountpoint] -mkdir -p $TESTDIR/$$/$TESTPOOL && cd $TESTDIR/$$ || log_fail +log_must mkdir -p $TESTDIR/$$/$TESTPOOL +log_must cd $TESTDIR/$$ # The env flag directs zfs to exec /bin/mount, which then calls helper log_must eval ZFS_MOUNT_HELPER=1 zfs $mountcmd -v $TESTPOOL # mount (2.35.2) still suffers from a cosmetic PWD prefix bug log_must mounted $TESTPOOL force_unmount $TESTPOOL +log_note "Verify CWD prefix filter " +log_must cd / +log_must zfs set mountpoint=legacy $TESTPOOL +log_must mkdir -p $mntpoint +log_must mount -t zfs $TESTPOOL $mntpoint +log_must ismounted $TESTPOOL +log_must umount $mntpoint +log_must zfs set mountpoint=$mntpoint $TESTPOOL +log_must cd - +force_unmount $TESTPOOL + log_note "Verify '-f ' fakemount" log_must $helper -f $fs $mntpoint log_mustnot ismounted $fs @@ -75,4 +89,4 @@ log_must $helper ${vdevs[0]} $mntpoint log_must mounted $mntpoint -log_pass "zfs mount helper correctly handles both device and pool strings" \ No newline at end of file +log_pass "zfs mount helper correctly handles both device and pool strings" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_005_neg.ksh @@ -82,8 +82,8 @@ log_must eval "zfs send $init_snap > $full_bkup" log_note "'zfs receive' fails with invalid send streams." -log_mustnot eval "zfs receive $rst_init_snap < /dev/zero" -log_mustnot eval "zfs receive -d $rst_root /dev/null" - log_must eval "zfs send -b$opt -i $SENDFS@s1 $SENDFS@s2 > /dev/null" - log_must eval "zfs send -b$opt -I $SENDFS@s1 $SENDFS@s2 > /dev/null" + log_must eval "zfs send -b$opt $SENDFS@s1 >$TEST_BASE_DIR/devnull" + log_must eval "zfs send -b$opt -i $SENDFS@s1 $SENDFS@s2 >$TEST_BASE_DIR/devnull" + log_must eval "zfs send -b$opt -I $SENDFS@s1 $SENDFS@s2 >$TEST_BASE_DIR/devnull" done for opt in ${opts[@]}; do - log_mustnot eval "zfs send -b$opt $SENDFS > /dev/null" - log_mustnot eval "zfs send -b$opt $SENDFS#bm > /dev/null" + log_mustnot eval "zfs send -b$opt $SENDFS >$TEST_BASE_DIR/devnull" + log_mustnot eval "zfs send -b$opt $SENDFS#bm >$TEST_BASE_DIR/devnull" done # Do 3..6 in a loop to verify various combination of "zfs send" options diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_003_pos.ksh @@ -61,7 +61,7 @@ typeset -i i=0 while (( i < ${#args[*]} )); do - log_must eval "zfs send -i ${args[i]} > /dev/null" + log_must eval "zfs send -i ${args[i]} >$TEST_BASE_DIR/devnull" (( i += 1 )) done diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_004_neg.ksh @@ -96,7 +96,7 @@ typeset -i i=0 while (( i < ${#badargs[*]} )) do - log_mustnot eval "zfs send ${badargs[i]} >/dev/null" + log_mustnot eval "zfs send ${badargs[i]} >$TEST_BASE_DIR/devnull" (( i = i + 1 )) done diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos.ksh @@ -61,6 +61,6 @@ log_must zpool export $TESTPOOL log_must zpool import -o readonly=on $TESTPOOL -log_must eval "zfs send -R $TESTPOOL@snap >/dev/null" +log_must eval "zfs send -R $TESTPOOL@snap >$TEST_BASE_DIR/devnull" log_pass "'zfs send -R' can send from read-only pools" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted.ksh @@ -62,15 +62,15 @@ log_must zfs snapshot -r $snap -log_must eval "zfs send $snap > /dev/null" -log_mustnot eval "zfs send -p $snap > /dev/null" -log_mustnot eval "zfs send -R $snap > /dev/null" +log_must eval "zfs send $snap >$TEST_BASE_DIR/devnull" +log_mustnot eval "zfs send -p $snap >$TEST_BASE_DIR/devnull" +log_mustnot eval "zfs send -R $snap >$TEST_BASE_DIR/devnull" log_must zfs unmount $TESTPOOL/$TESTFS1 log_must zfs unload-key $TESTPOOL/$TESTFS1 -log_mustnot eval "zfs send $snap > /dev/null" -log_must eval "zfs send $TESTPOOL/$TESTFS1/child@snap > /dev/null" +log_mustnot eval "zfs send $snap >$TEST_BASE_DIR/devnull" +log_must eval "zfs send $TESTPOOL/$TESTFS1/child@snap >$TEST_BASE_DIR/devnull" log_pass "ZFS performs unencrypted sends of encrypted datasets, unless the" \ "'-p' or '-R' options are specified" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_encrypted_unloaded.ksh @@ -53,7 +53,7 @@ log_must zfs snapshot $snap log_must zfs unmount $TESTPOOL/$TESTFS1 log_must zfs unload-key $TESTPOOL/$TESTFS1 -log_mustnot eval "zfs send $snap > /dev/null" +log_mustnot eval "zfs send $snap >$TEST_BASE_DIR/devnull" log_pass "ZFS does not perform unencrypted sends from encrypted datasets" \ "with unloaded keys." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_raw.ksh @@ -59,21 +59,21 @@ log_must zfs snapshot $snap log_must zfs snapshot $snap1 -log_must eval "zfs send -w $snap > /dev/null" -log_must eval "zfs send -w $snap1 > /dev/null" +log_must eval "zfs send -w $snap >$TEST_BASE_DIR/devnull" +log_must eval "zfs send -w $snap1 >$TEST_BASE_DIR/devnull" log_note "Verify ZFS can perform raw sends with properties" -log_must eval "zfs send -wp $snap > /dev/null" -log_must eval "zfs send -wp $snap1 > /dev/null" +log_must eval "zfs send -wp $snap >$TEST_BASE_DIR/devnull" +log_must eval "zfs send -wp $snap1 >$TEST_BASE_DIR/devnull" log_note "Verify ZFS can perform raw replication sends" -log_must eval "zfs send -wR $snap > /dev/null" -log_must eval "zfs send -wR $snap1 > /dev/null" +log_must eval "zfs send -wR $snap >$TEST_BASE_DIR/devnull" +log_must eval "zfs send -wR $snap1 >$TEST_BASE_DIR/devnull" log_note "Verify ZFS can perform a raw send of an encrypted datasets with" \ "its key unloaded" log_must zfs unmount $TESTPOOL/$TESTFS1 log_must zfs unload-key $TESTPOOL/$TESTFS1 -log_must eval "zfs send -w $snap1 > /dev/null" +log_must eval "zfs send -w $snap1 >$TEST_BASE_DIR/devnull" log_pass "ZFS performs raw sends of datasets" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib @@ -287,12 +287,14 @@ typeset chk_value=$(get_prop "$prop" "$dataset") typeset chk_source=$(get_source "$prop" "$dataset") - if [[ "$chk_value" != "$value" || "$chk_source" != "$4" ]] - then - return 1 - else - return 0 - fi + if [[ "$chk_value" != "$value" || "$chk_source" != "$source" ]] + then + log_note "expected (value '$value', source '$source'), got \ + (value '$chk_value', source '$chk_source')" + return 1 + else + return 0 + fi } # diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/draidcfg.gz b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/draidcfg.gz new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@$DISK_ARRAY_LIMIT )) && break - done - export DISK_ARRAY_NUM=$i - export DISKSARRAY - fi -} - -set_disks -set_device_dir +if is_linux; then + set_slice_prefix + set_device_dir + devs_id[0]=$(get_persistent_disk_name $DISK1) + devs_id[1]=$(get_persistent_disk_name $DISK2) +else + DEV_DSKDIR="/dev" +fi diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib copy from sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh copy to sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/acl/posix-sa/cleanup.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export.kshlib @@ -1,4 +1,3 @@ -#!/bin/ksh -p # # CDDL HEADER START # @@ -21,13 +20,13 @@ # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2020, Klara Systems, Inc. All rights reserved. # -. $STF_SUITE/include/libtest.shlib -. $STF_SUITE/tests/functional/acl/acl_common.kshlib +. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.cfg -cleanup_user_group - -default_cleanup +function zpool_export_cleanup +{ + [[ -d $TESTDIR0 ]] && log_must rm -rf $TESTDIR0 + default_cleanup +} diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_001_pos.ksh @@ -29,8 +29,7 @@ # Copyright (c) 2016 by Delphix. All rights reserved. # -. $STF_SUITE/include/libtest.shlib -. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.cfg +. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.kshlib # # DESCRIPTION: @@ -46,19 +45,7 @@ verify_runnable "global" -function cleanup -{ - typeset dir=$(get_device_dir $DISKS) - - datasetexists "$TESTPOOL/$TESTFS" || \ - log_must zpool import -d $dir $TESTPOOL - - ismounted "$TESTPOOL/$TESTFS" - (( $? != 0 )) && \ - log_must zfs mount $TESTPOOL/$TESTFS -} - -log_onexit cleanup +log_onexit zpool_export_cleanup log_assert "Verify a pool can be exported." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_002_pos.ksh @@ -29,7 +29,7 @@ # Copyright (c) 2016 by Delphix. All rights reserved. # -. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.kshlib # # DESCRIPTION: @@ -45,19 +45,10 @@ function cleanup { - typeset dir=$(get_device_dir $DISKS) cd $olddir || \ log_fail "Couldn't cd back to $olddir" - datasetexists "$TESTPOOL/$TESTFS" || \ - log_must zpool import -d $dir $TESTPOOL - - ismounted "$TESTPOOL/$TESTFS" - (( $? != 0 )) && \ - log_must zfs mount $TESTPOOL/$TESTFS - - [[ -e $TESTDIR/$TESTFILE0 ]] && \ - log_must rm -rf $TESTDIR/$TESTFILE0 + zpool_export_cleanup } olddir=$PWD diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_003_neg.ksh @@ -29,7 +29,7 @@ # Copyright (c) 2016 by Delphix. All rights reserved. # -. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.kshlib # # DESCRIPTION: @@ -43,18 +43,7 @@ verify_runnable "global" -function cleanup -{ - typeset dir=$(get_device_dir $DISKS) - datasetexists "$TESTPOOL/$TESTFS" || \ - log_must zpool import -d $dir $TESTPOOL - - ismounted "$TESTPOOL/$TESTFS" - (( $? != 0 )) && \ - log_must zfs mount $TESTPOOL/$TESTFS -} - -log_onexit cleanup +log_onexit zpool_export_cleanup set -A args "" "-f" "-? $TESTPOOL" "-QWERTYUIO $TESTPOOL" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_004_pos.ksh @@ -29,7 +29,7 @@ # Copyright (c) 2012, 2016 by Delphix. All rights reserved. # -. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.kshlib # # DESCRIPTION: @@ -50,25 +50,8 @@ verify_runnable "global" -function cleanup -{ - mntpnt=$TESTDIR0 - datasetexists $TESTPOOL1 || log_must zpool import -d $mntpnt $TESTPOOL1 - datasetexists $TESTPOOL1 && destroy_pool $TESTPOOL1 - datasetexists $TESTPOOL2 && destroy_pool $TESTPOOL2 - typeset -i i=0 - while ((i < 5)); do - if [[ -e $mntpnt/vdev$i ]]; then - log_must rm -f $mntpnt/vdev$i - fi - ((i += 1)) - done - log_must rmdir $mntpnt -} - - log_assert "Verify zpool export succeed or fail with spare." -log_onexit cleanup +log_onexit zpool_export_cleanup mntpnt=$TESTDIR0 log_must mkdir -p $mntpnt diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/Makefile.am --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/Makefile.am +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/Makefile.am @@ -5,6 +5,7 @@ sync.ksh \ psync.ksh \ libaio.ksh \ + io_uring.ksh \ posixaio.ksh \ mmap.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh new file mode 100755 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh @@ -0,0 +1,72 @@ +#! /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) 2018 by Lawrence Livermore National Security, LLC. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/io/io.cfg + +# +# DESCRIPTION: +# Verify Linux io_uring. +# +# STRATEGY: +# 1. Use fio(1) in verify mode to perform write, read, +# random read, and random write workloads. +# 2. Repeat the test with additional fio(1) options. +# + +verify_runnable "global" + + +if [[ $(linux_version) -lt $(linux_version "5.1") ]]; then + log_unsupported "Requires io_uring support" +fi + +fio --ioengine=io_uring --parse-only || log_unsupported "io_uring support required" + +function cleanup +{ + log_must rm -f "$mntpnt/rw*" +} + +log_assert "Verify Linux io_uring" + +log_onexit cleanup + +ioengine="--ioengine=io_uring" +mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS) +dir="--directory=$mntpnt" + +set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1" + +for arg in "${fio_arg[@]}"; do + log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS + log_must fio $dir $ioengine $arg $FIO_READ_ARGS + log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS + log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS + log_must rm -f "$mntpnt/rw*" +done + +log_pass "Verified Linux io_uring" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/Makefile.am rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/Makefile.am rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/Makefile.am diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/cleanup.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/cleanup.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/cleanup.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc.cfg b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc.cfg rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc.cfg rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/l2arc.cfg diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_001_pos.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_001_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_001_pos.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_002_pos.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_002_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_002_pos.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_003_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_003_neg.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_003_neg.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_003_neg.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_004_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_004_pos.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_004_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_004_pos.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_005_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_005_pos.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_005_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_005_pos.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_006_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_006_pos.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_006_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_006_pos.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_007_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_007_pos.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_007_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_007_pos.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_008_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_008_pos.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_008_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/persist_l2arc_008_pos.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/setup.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/persist_l2arc/setup.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/l2arc/setup.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/procfs/pool_state.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/procfs/pool_state.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/procfs/pool_state.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/procfs/pool_state.ksh @@ -61,16 +61,18 @@ log_must rm -f $BACKUP fi - # Our disk is back. Now we can clear errors and destroy the - # pool cleanly. - log_must zpool clear $TESTPOOL2 + if poolexists $TESTPOOL2 ; then + # Our disk is back. Now we can clear errors and destroy the + # pool cleanly. + log_must zpool clear $TESTPOOL2 - # Now that the disk is back and errors cleared, wait for our - # hung 'zpool scrub' to finish. - wait + # Now that the disk is back and errors cleared, wait for our + # hung 'zpool scrub' to finish. + wait - destroy_pool $TESTPOOL2 - log_must rm $REALDISK + destroy_pool $TESTPOOL2 + fi + log_must rm -f $REALDISK unload_scsi_debug fi } diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh @@ -45,11 +45,11 @@ # Incompatible flags log_must zfs redact $sendfs@snap2 book $clone1@snap -log_mustnot eval "zfs send -R --redact book $sendfs@snap2 >/dev/null" +log_mustnot eval "zfs send -R --redact book $sendfs@snap2 >$TEST_BASE_DIR/devnull" typeset arg for arg in "$sendfs" "$clone1#book"; do - log_mustnot eval "zfs send --redact book $arg >/dev/null" + log_mustnot eval "zfs send --redact book $arg >$TEST_BASE_DIR/devnull" done # Bad redaction list arguments @@ -58,7 +58,7 @@ log_mustnot zfs redact $sendfs#book1 book4 $clone1 log_mustnot zfs redact $sendfs@snap1 book snap2 snap3 log_mustnot zfs redact $sendfs@snap1 book @snap2 @snap3 -log_mustnot eval "zfs send --redact $sendfs#book $sendfs@snap >/dev/null" +log_mustnot eval "zfs send --redact $sendfs#book $sendfs@snap >$TEST_BASE_DIR/devnull" # Redaction snapshots not a descendant of tosnap log_mustnot zfs redact $sendfs@snap2 book $sendfs@snap2 @@ -66,7 +66,7 @@ log_must eval "zfs send --redact book2 $sendfs@snap2 >$stream" log_must zfs redact $sendfs@snap2 book3 $clone1@snap $clone2@snap log_must eval "zfs send -i $sendfs@snap1 --redact book3 $sendfs@snap2 \ - >/dev/null" + >$TEST_BASE_DIR/devnull" log_mustnot zfs redact $sendfs@snap3 $sendfs@snap3 $clone1@snap # Full redacted sends of redacted datasets are not allowed. diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh @@ -81,7 +81,7 @@ dd if=$stream bs=64k count=1 | log_mustnot zfs receive -s $recvfs [[ "-" = $(get_prop receive_resume_token $recvfs) ]] && \ log_fail "Receive token not found." -log_mustnot eval "zfs send --saved --redact book1 $recvfs > /dev/null" +log_mustnot eval "zfs send --saved --redact book1 $recvfs >$TEST_BASE_DIR/devnull" log_must zfs recv -A $recvfs log_must datasetnonexists $recvfs diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_003_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_mirror.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_003_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_mirror.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz1.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_001_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz1.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz2.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_002_pos.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_raidz2.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_004_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_stripe.ksh rename from sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_004_neg.ksh rename to sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_stripe.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/removal/removal_with_send.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/removal/removal_with_send.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/removal/removal_with_send.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/removal/removal_with_send.ksh @@ -28,7 +28,7 @@ { create_snapshot $TESTPOOL/$TESTFS $TESTSNAP log_must ksh -c \ - "zfs send $TESTPOOL/$TESTFS@$TESTSNAP >/dev/null" + "zfs send $TESTPOOL/$TESTFS@$TESTSNAP >$TEST_BASE_DIR/devnull" return 0 } diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_invalid.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_invalid.ksh old mode 100644 new mode 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_invalid.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_invalid.ksh @@ -44,7 +44,7 @@ log_must zfs snap $testfs@snap1 # Test bad send with the CLI -log_mustnot eval "zfs send -i $testfs@snap1 $testfs@snap0 >/dev/null" +log_mustnot eval "zfs send -i $testfs@snap1 $testfs@snap0 >$TEST_BASE_DIR/devnull" # Test bad send with libzfs/libzfs_core log_must badsend $testfs@snap0 $testfs@snap1 diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh @@ -103,7 +103,7 @@ while (( i < ${#badargs[*]} )) do - log_mustnot eval "zfs send --saved ${badargs[i]} >/dev/null" + log_mustnot eval "zfs send --saved ${badargs[i]} >$TEST_BASE_DIR/devnull" (( i = i + 1 )) done diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/userquota/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/userquota/Makefile.am --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/userquota/Makefile.am +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/userquota/Makefile.am @@ -21,7 +21,8 @@ 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 \ diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg @@ -35,6 +35,8 @@ # if is_linux; then SAVESWAPDEVS=$(swapon -s | nawk '(NR != 1) {print $1}') +elif is_freebsd; then + SAVESWAPDEVS=$(swapctl -l | nawk '(NR != 1) {print $1}') else SAVESWAPDEVS=$(swap -l | nawk '(NR != 1) {print $1}') fi diff --git a/sys/modules/zfs/zfs_config.h b/sys/modules/zfs/zfs_config.h --- a/sys/modules/zfs/zfs_config.h +++ b/sys/modules/zfs/zfs_config.h @@ -734,7 +734,7 @@ /* #undef ZFS_IS_GPL_COMPATIBLE */ /* Define the project alias string. */ -#define ZFS_META_ALIAS "zfs-2.0.0-FreeBSD_gf11b09dec" +#define ZFS_META_ALIAS "zfs-2.0.0-FreeBSD_g436ab35a5" /* Define the project author. */ #define ZFS_META_AUTHOR "OpenZFS" @@ -743,7 +743,7 @@ /* #undef ZFS_META_DATA */ /* Define the maximum compatible kernel version. */ -#define ZFS_META_KVER_MAX "5.10" +#define ZFS_META_KVER_MAX "5.11" /* Define the minimum compatible kernel version. */ #define ZFS_META_KVER_MIN "3.10" @@ -764,7 +764,7 @@ #define ZFS_META_NAME "zfs" /* Define the project release. */ -#define ZFS_META_RELEASE "FreeBSD_gf11b09dec" +#define ZFS_META_RELEASE "FreeBSD_g436ab35a5" /* Define the project version. */ #define ZFS_META_VERSION "2.0.0"