Compare commits

..

No commits in common. "zfs-2.1-release" and "zfs-2.1.0-rc3" have entirely different histories.

1176 changed files with 42358 additions and 54386 deletions

View File

@ -2,7 +2,7 @@
name: Bug report name: Bug report
about: Create a report to help us improve OpenZFS about: Create a report to help us improve OpenZFS
title: '' title: ''
labels: 'Type: Defect' labels: 'Type: Defect, Status: Triage Needed'
assignees: '' assignees: ''
--- ---
@ -25,16 +25,14 @@ Type | Version/Name
--- | --- --- | ---
Distribution Name | Distribution Name |
Distribution Version | Distribution Version |
Kernel Version | Linux Kernel |
Architecture | Architecture |
OpenZFS Version | ZFS Version |
SPL Version |
<!-- <!--
Command to find OpenZFS version: Commands to find ZFS/SPL versions:
zfs version modinfo zfs | grep -iw version
modinfo spl | grep -iw version
Commands to find kernel version:
uname -r # Linux
freebsd-version -r # FreeBSD
--> -->
### Describe the problem you're observing ### Describe the problem you're observing

View File

@ -10,5 +10,5 @@ contact_links:
url: https://lists.freebsd.org/mailman/listinfo/freebsd-fs url: https://lists.freebsd.org/mailman/listinfo/freebsd-fs
about: Get community support for OpenZFS on FreeBSD about: Get community support for OpenZFS on FreeBSD
- name: OpenZFS on IRC - name: OpenZFS on IRC
url: https://web.libera.chat/#openzfs url: https://webchat.freenode.net/#openzfs
about: Use IRC to get community support for OpenZFS about: Use IRC to get community support for OpenZFS

View File

@ -1,57 +0,0 @@
acl
alien
attr
autoconf
bc
build-essential
curl
dbench
debhelper-compat
dh-python
dkms
fakeroot
fio
gdb
gdebi
git
ksh
lcov
libacl1-dev
libaio-dev
libattr1-dev
libblkid-dev
libcurl4-openssl-dev
libdevmapper-dev
libelf-dev
libffi-dev
libmount-dev
libpam0g-dev
libselinux1-dev
libssl-dev
libtool
libudev-dev
linux-headers-generic
lsscsi
mdadm
nfs-kernel-server
pamtester
parted
po-debconf
python3
python3-all-dev
python3-cffi
python3-dev
python3-packaging
python3-pip
python3-setuptools
python3-sphinx
rng-tools-debian
rsync
samba
sysstat
uuid-dev
watchdog
wget
xfslibs-dev
xz-utils
zlib1g-dev

View File

@ -1,2 +0,0 @@
pax-utils
shellcheck

View File

@ -6,27 +6,20 @@ on:
jobs: jobs:
checkstyle: checkstyle:
runs-on: ubuntu-22.04 runs-on: ubuntu-18.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Install dependencies - name: Install dependencies
run: | run: |
# https://github.com/orgs/community/discussions/47863 sudo apt-get update
sudo apt-mark hold grub-efi-amd64-signed sudo apt-get install --yes -qq build-essential autoconf libtool gawk alien fakeroot linux-headers-$(uname -r)
sudo apt-get update --fix-missing sudo apt-get install --yes -qq zlib1g-dev uuid-dev libattr1-dev libblkid-dev libselinux-dev libudev-dev libssl-dev python-dev python-setuptools python-cffi python3 python3-dev python3-setuptools python3-cffi
sudo apt-get upgrade # packages for tests
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq sudo apt-get install --yes -qq parted lsscsi ksh attr acl nfs-kernel-server fio
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/checkstyle-dependencies.txt apt-get install -qq sudo apt-get install --yes -qq mandoc cppcheck pax-utils devscripts abigail-tools
sudo python3 -m pip install --quiet flake8 sudo -E pip --quiet install flake8
sudo apt-get clean
# confirm that the tools are installed
# the build system doesn't fail when they are not
flake8 --version
scanelf --version
shellcheck --version
- name: Prepare - name: Prepare
run: | run: |
sh ./autogen.sh sh ./autogen.sh
@ -39,19 +32,5 @@ jobs:
run: | run: |
make lint make lint
- name: CheckABI - name: CheckABI
id: CheckABI
run: | run: |
sudo docker run -v $(pwd):/source ghcr.io/openzfs/libabigail make checkabi make checkabi
- name: StoreABI
if: failure() && steps.CheckABI.outcome == 'failure'
run: |
sudo docker run -v $(pwd):/source ghcr.io/openzfs/libabigail make storeabi
- name: Prepare artifacts
if: failure() && steps.CheckABI.outcome == 'failure'
run: |
find -name *.abi | tar -cf abi_files.tar -T -
- uses: actions/upload-artifact@v3
if: failure() && steps.CheckABI.outcome == 'failure'
with:
name: New ABI files (use only if you're sure about interface changes)
path: abi_files.tar

View File

@ -1,23 +0,0 @@
#!/bin/sh
set -eu
# remove 4GiB of images
sudo systemd-run docker system prune --force --all --volumes
# remove unused software
sudo systemd-run --wait rm -rf \
"$AGENT_TOOLSDIRECTORY" \
/opt/* \
/usr/local/* \
/usr/share/az* \
/usr/share/dotnet \
/usr/share/gradle* \
/usr/share/miniconda \
/usr/share/swift \
/var/lib/gems \
/var/lib/mysql \
/var/lib/snapd
# trim the cleaned space
sudo fstrim /

View File

@ -9,20 +9,24 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [20.04, 22.04] os: [18.04, 20.04]
runs-on: ubuntu-${{ matrix.os }} runs-on: ubuntu-${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Install dependencies - name: Install dependencies
run: | run: |
# https://github.com/orgs/community/discussions/47863 sudo apt-get update
sudo apt-mark hold grub-efi-amd64-signed sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
sudo apt-get update --fix-missing git alien fakeroot wget curl bc fio acl \
sudo apt-get upgrade sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq nfs-kernel-server samba rng-tools xz-utils \
sudo apt-get clean 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 - name: Autogen.sh
run: | run: |
sh autogen.sh sh autogen.sh
@ -40,42 +44,27 @@ jobs:
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
sudo depmod sudo depmod
sudo modprobe zfs sudo modprobe zfs
# Workaround for cloud-init bug # Workaround to provide additional free space for testing.
# see https://github.com/openzfs/zfs/issues/12644 # https://github.com/actions/virtual-environments/issues/2840
FILE=/lib/udev/rules.d/10-cloud-init-hook-hotplug.rules sudo rm -rf /usr/share/dotnet
if [ -r "${FILE}" ]; then sudo rm -rf /opt/ghc
HASH=$(md5sum "${FILE}" | awk '{ print $1 }') sudo rm -rf "/usr/local/share/boost"
if [ "${HASH}" = "121ff0ef1936cd2ef65aec0458a35772" ]; then sudo rm -rf "$AGENT_TOOLSDIRECTORY"
# Just shove a zd* exclusion right above the hotplug hook...
sudo sed -i -e s/'LABEL="cloudinit_hook"'/'KERNEL=="zd*", GOTO="cloudinit_end"\n&'/ "${FILE}"
sudo udevadm control --reload-rules
fi
fi
- name: Clear the kernel ring buffer
run: |
sudo dmesg -c >/var/tmp/dmesg-prerun
- name: Reclaim and report disk space
run: |
${{ github.workspace }}/.github/workflows/scripts/reclaim_disk_space.sh
df -h /
- name: Tests - name: Tests
run: | run: |
/usr/share/zfs/zfs-tests.sh -vR -s 3G /usr/share/zfs/zfs-tests.sh -v -s 3G
timeout-minutes: 330
- name: Prepare artifacts - name: Prepare artifacts
if: failure() if: failure()
run: | run: |
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current) RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
sudo dmesg > $RESULTS_PATH/dmesg sudo dmesg > $RESULTS_PATH/dmesg
sudo cp /var/log/syslog /var/tmp/dmesg-prerun $RESULTS_PATH/ sudo cp /var/log/syslog $RESULTS_PATH/
sudo chmod +r $RESULTS_PATH/* sudo chmod +r $RESULTS_PATH/*
# Replace ':' in dir names, actions/upload-artifact doesn't support it # Replace ':' in dir names, actions/upload-artifact doesn't support it
for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v2
if: failure() if: failure()
with: with:
name: Test logs Ubuntu-${{ matrix.os }} name: Test logs Ubuntu-${{ matrix.os }}
path: | path: /var/tmp/test_results/20*/
/var/tmp/test_results/*
!/var/tmp/test_results/current
if-no-files-found: ignore if-no-files-found: ignore

View File

@ -6,19 +6,23 @@ on:
jobs: jobs:
tests: tests:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Install dependencies - name: Install dependencies
run: | run: |
# https://github.com/orgs/community/discussions/47863 sudo apt-get update
sudo apt-mark hold grub-efi-amd64-signed sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
sudo apt-get update --fix-missing git alien fakeroot wget curl bc fio acl \
sudo apt-get upgrade sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq nfs-kernel-server samba rng-tools xz-utils \
sudo apt-get clean 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 - name: Autogen.sh
run: | run: |
sh autogen.sh sh autogen.sh
@ -36,42 +40,27 @@ jobs:
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
sudo depmod sudo depmod
sudo modprobe zfs sudo modprobe zfs
# Workaround for cloud-init bug # Workaround to provide additional free space for testing.
# see https://github.com/openzfs/zfs/issues/12644 # https://github.com/actions/virtual-environments/issues/2840
FILE=/lib/udev/rules.d/10-cloud-init-hook-hotplug.rules sudo rm -rf /usr/share/dotnet
if [ -r "${FILE}" ]; then sudo rm -rf /opt/ghc
HASH=$(md5sum "${FILE}" | awk '{ print $1 }') sudo rm -rf "/usr/local/share/boost"
if [ "${HASH}" = "121ff0ef1936cd2ef65aec0458a35772" ]; then sudo rm -rf "$AGENT_TOOLSDIRECTORY"
# Just shove a zd* exclusion right above the hotplug hook...
sudo sed -i -e s/'LABEL="cloudinit_hook"'/'KERNEL=="zd*", GOTO="cloudinit_end"\n&'/ "${FILE}"
sudo udevadm control --reload-rules
fi
fi
- name: Clear the kernel ring buffer
run: |
sudo dmesg -c >/var/tmp/dmesg-prerun
- name: Reclaim and report disk space
run: |
${{ github.workspace }}/.github/workflows/scripts/reclaim_disk_space.sh
df -h /
- name: Tests - name: Tests
run: | run: |
/usr/share/zfs/zfs-tests.sh -vR -s 3G -r sanity /usr/share/zfs/zfs-tests.sh -v -s 3G -r sanity
timeout-minutes: 330
- name: Prepare artifacts - name: Prepare artifacts
if: failure() if: failure()
run: | run: |
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current) RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
sudo dmesg > $RESULTS_PATH/dmesg sudo dmesg > $RESULTS_PATH/dmesg
sudo cp /var/log/syslog /var/tmp/dmesg-prerun $RESULTS_PATH/ sudo cp /var/log/syslog $RESULTS_PATH/
sudo chmod +r $RESULTS_PATH/* sudo chmod +r $RESULTS_PATH/*
# Replace ':' in dir names, actions/upload-artifact doesn't support it # Replace ':' in dir names, actions/upload-artifact doesn't support it
for f in $(find /var/tmp/test_results -name '*:*'); do mv "$f" "${f//:/__}"; done for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v2
if: failure() if: failure()
with: with:
name: Test logs Ubuntu-${{ matrix.os }} name: Test logs
path: | path: /var/tmp/test_results/20*/
/var/tmp/test_results/*
!/var/tmp/test_results/current
if-no-files-found: ignore if-no-files-found: ignore

View File

@ -6,21 +6,24 @@ on:
jobs: jobs:
tests: tests:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
env: env:
TEST_DIR: /var/tmp/zloop TEST_DIR: /var/tmp/zloop
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Install dependencies - name: Install dependencies
run: | run: |
# https://github.com/orgs/community/discussions/47863 sudo apt-get update
sudo apt-mark hold grub-efi-amd64-signed sudo apt-get install --yes -qq build-essential autoconf libtool gdb \
sudo apt-get update --fix-missing git alien fakeroot \
sudo apt-get upgrade zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
sudo xargs --arg-file=${{ github.workspace }}/.github/workflows/build-dependencies.txt apt-get install -qq xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
sudo apt-get clean libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
libpam0g-dev \
python-dev python-setuptools python-cffi \
python3 python3-dev python3-setuptools python3-cffi
- name: Autogen.sh - name: Autogen.sh
run: | run: |
sh autogen.sh sh autogen.sh
@ -41,14 +44,13 @@ jobs:
- name: Tests - name: Tests
run: | run: |
sudo mkdir -p $TEST_DIR sudo mkdir -p $TEST_DIR
# run for 10 minutes or at most 2 iterations for a maximum runner # run for 20 minutes to have a total runner time of 30 minutes
# time of 20 minutes. sudo /usr/share/zfs/zloop.sh -t 1200 -l -m1
sudo /usr/share/zfs/zloop.sh -t 600 -I 2 -l -m1 -- -T 120 -P 60
- name: Prepare artifacts - name: Prepare artifacts
if: failure() if: failure()
run: | run: |
sudo chmod +r -R $TEST_DIR/ sudo chmod +r -R $TEST_DIR/
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v2
if: failure() if: failure()
with: with:
name: Logs name: Logs
@ -56,7 +58,7 @@ jobs:
/var/tmp/zloop/*/ /var/tmp/zloop/*/
!/var/tmp/zloop/*/vdev/ !/var/tmp/zloop/*/vdev/
if-no-files-found: ignore if-no-files-found: ignore
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v2
if: failure() if: failure()
with: with:
name: Pool files name: Pool files

View File

@ -1,2 +1,2 @@
The [OpenZFS Code of Conduct](https://openzfs.org/wiki/Code_of_Conduct) The [OpenZFS Code of Conduct](http://www.open-zfs.org/wiki/Code_of_Conduct)
applies to spaces associated with the OpenZFS project, including GitHub. applies to spaces associated with the OpenZFS project, including GitHub.

6
META
View File

@ -1,10 +1,10 @@
Meta: 1 Meta: 1
Name: zfs Name: zfs
Branch: 1.0 Branch: 1.0
Version: 2.1.15 Version: 2.1.0
Release: 1 Release: rc3
Release-Tags: relext Release-Tags: relext
License: CDDL License: CDDL
Author: OpenZFS Author: OpenZFS
Linux-Maximum: 6.7 Linux-Maximum: 5.11
Linux-Minimum: 3.10 Linux-Minimum: 3.10

View File

@ -1,5 +1,3 @@
include $(top_srcdir)/config/Shellcheck.am
ACLOCAL_AMFLAGS = -I config ACLOCAL_AMFLAGS = -I config
SUBDIRS = include SUBDIRS = include
@ -8,7 +6,7 @@ SUBDIRS += rpm
endif endif
if CONFIG_USER if CONFIG_USER
SUBDIRS += man scripts lib tests cmd etc contrib SUBDIRS += etc man scripts lib tests cmd contrib
if BUILD_LINUX if BUILD_LINUX
SUBDIRS += udev SUBDIRS += udev
endif endif
@ -103,7 +101,7 @@ endif
endif endif
PHONY += codecheck PHONY += codecheck
codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck zstdcheck codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck
PHONY += checkstyle PHONY += checkstyle
checkstyle: codecheck commitcheck checkstyle: codecheck commitcheck
@ -114,47 +112,70 @@ commitcheck:
${top_srcdir}/scripts/commitcheck.sh; \ ${top_srcdir}/scripts/commitcheck.sh; \
fi fi
if HAVE_PARALLEL
cstyle_line = -print0 | parallel -X0 ${top_srcdir}/scripts/cstyle.pl -cpP {}
else
cstyle_line = -exec ${top_srcdir}/scripts/cstyle.pl -cpP {} +
endif
PHONY += cstyle PHONY += cstyle
cstyle: cstyle:
@find ${top_srcdir} -name build -prune \ @find ${top_srcdir} -name build -prune \
-o -type f -name '*.[hc]' \ -o -type f -name '*.[hc]' \
! -name 'zfs_config.*' ! -name '*.mod.c' \ ! -name 'zfs_config.*' ! -name '*.mod.c' \
! -name 'opt_global.h' ! -name '*_if*.h' \ ! -name 'opt_global.h' ! -name '*_if*.h' \
! -name 'zstd_compat_wrapper.h' \
! -path './module/zstd/lib/*' \ ! -path './module/zstd/lib/*' \
$(cstyle_line) -exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
filter_executable = -exec test -x '{}' \; -print filter_executable = -exec test -x '{}' \; -print
SHELLCHECKDIRS = cmd contrib etc scripts tests PHONY += shellcheck
SHELLCHECKSCRIPTS = autogen.sh shellcheck:
@if type shellcheck > /dev/null 2>&1; then \
shellcheck --exclude=SC1090 --exclude=SC1117 --format=gcc \
$$(find ${top_srcdir}/scripts/*.sh -type f) \
$$(find ${top_srcdir}/cmd/zed/zed.d/*.sh -type f) \
$$(find ${top_srcdir}/cmd/zpool/zpool.d/* \
-type f ${filter_executable}); \
else \
echo "skipping shellcheck because shellcheck is not installed"; \
fi
PHONY += checkabi storeabi PHONY += checkabi storeabi
checkabi: lib
checklibabiversion:
libabiversion=`abidw -v | $(SED) 's/[^0-9]//g'`; \
if test $$libabiversion -lt "200"; then \
/bin/echo -e "\n" \
"*** Please use libabigail 2.0.0 version or newer;\n" \
"*** otherwise results are not consistent!\n" \
"(or see https://github.com/openzfs/libabigail-docker )\n"; \
exit 1; \
fi;
checkabi: checklibabiversion lib
$(MAKE) -C lib checkabi $(MAKE) -C lib checkabi
storeabi: checklibabiversion lib storeabi: lib
$(MAKE) -C lib storeabi $(MAKE) -C lib storeabi
PHONY += checkbashisms
checkbashisms:
@if type checkbashisms > /dev/null 2>&1; then \
checkbashisms -n -p -x \
$$(find ${top_srcdir} \
-name '.git' -prune \
-o -name 'build' -prune \
-o -name 'tests' -prune \
-o -name 'config' -prune \
-o -name 'zed-functions.sh*' -prune \
-o -name 'zfs-import*' -prune \
-o -name 'zfs-mount*' -prune \
-o -name 'zfs-zed*' -prune \
-o -name 'smart' -prune \
-o -name 'paxcheck.sh' -prune \
-o -name 'make_gitrev.sh' -prune \
-o -name '90zfs' -prune \
-o -type f ! -name 'config*' \
! -name 'libtool' \
-exec sh -c 'awk "NR==1 && /\#\!.*bin\/sh.*/ {print FILENAME;}" "{}"' \;); \
else \
echo "skipping checkbashisms because checkbashisms is not installed"; \
fi
PHONY += mancheck PHONY += mancheck
mancheck: mancheck:
${top_srcdir}/scripts/mancheck.sh ${top_srcdir}/man ${top_srcdir}/tests/test-runner/man @if type mandoc > /dev/null 2>&1; then \
find ${top_srcdir}/man/man8 -type f -name 'zfs.8' \
-o -name 'zpool.8' -o -name 'zdb.8' \
-o -name 'zgenhostid.8' | \
xargs mandoc -Tlint -Werror; \
else \
echo "skipping mancheck because mandoc is not installed"; \
fi
if BUILD_LINUX if BUILD_LINUX
stat_fmt = -c '%A %n' stat_fmt = -c '%A %n'
@ -179,10 +200,6 @@ vcscheck:
awk '{c++; print} END {if(c>0) exit 1}' ; \ awk '{c++; print} END {if(c>0) exit 1}' ; \
fi fi
PHONY += zstdcheck
zstdcheck:
@$(MAKE) -C module/zstd checksymbols
PHONY += lint PHONY += lint
lint: cppcheck paxcheck lint: cppcheck paxcheck

View File

@ -12,7 +12,7 @@ This repository contains the code for running OpenZFS on Linux and FreeBSD.
* [Documentation](https://openzfs.github.io/openzfs-docs/) - for using and developing this repo * [Documentation](https://openzfs.github.io/openzfs-docs/) - for using and developing this repo
* [ZoL Site](https://zfsonlinux.org) - Linux release info & links * [ZoL Site](https://zfsonlinux.org) - Linux release info & links
* [Mailing lists](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html) * [Mailing lists](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html)
* [OpenZFS site](https://openzfs.org/) - for conference videos and info on other platforms (illumos, OSX, Windows, etc) * [OpenZFS site](http://open-zfs.org/) - for conference videos and info on other platforms (illumos, OSX, Windows, etc)
# Installation # Installation

View File

@ -1,15 +1,10 @@
include $(top_srcdir)/config/Shellcheck.am SUBDIRS = zfs zpool zdb zhack zinject zstream zstreamdump ztest
SUBDIRS = zfs zpool zdb zhack zinject zstream ztest
SUBDIRS += fsck_zfs vdev_id raidz_test zfs_ids_to_path SUBDIRS += fsck_zfs vdev_id raidz_test zfs_ids_to_path
SUBDIRS += zpool_influxdb SUBDIRS += zpool_influxdb
CPPCHECKDIRS = zfs zpool zdb zhack zinject zstream ztest CPPCHECKDIRS = zfs zpool zdb zhack zinject zstream ztest
CPPCHECKDIRS += raidz_test zfs_ids_to_path zpool_influxdb CPPCHECKDIRS += raidz_test zfs_ids_to_path zpool_influxdb
# TODO: #12084: SHELLCHECKDIRS = fsck_zfs vdev_id zpool
SHELLCHECKDIRS = fsck_zfs zpool
if USING_PYTHON if USING_PYTHON
SUBDIRS += arcstat arc_summary dbufstat SUBDIRS += arcstat arc_summary dbufstat
endif endif
@ -17,7 +12,6 @@ endif
if BUILD_LINUX if BUILD_LINUX
SUBDIRS += mount_zfs zed zgenhostid zvol_id zvol_wait SUBDIRS += mount_zfs zed zgenhostid zvol_id zvol_wait
CPPCHECKDIRS += mount_zfs zed zgenhostid zvol_id CPPCHECKDIRS += mount_zfs zed zgenhostid zvol_id
SHELLCHECKDIRS += zed
endif endif
PHONY = cppcheck PHONY = cppcheck

View File

@ -1,8 +1,13 @@
bin_SCRIPTS = arc_summary bin_SCRIPTS = arc_summary
CLEANFILES = arc_summary CLEANFILES = arc_summary
EXTRA_DIST = arc_summary3 EXTRA_DIST = arc_summary2 arc_summary3
if USING_PYTHON_2
SCRIPT = arc_summary2
else
SCRIPT = arc_summary3 SCRIPT = arc_summary3
endif
arc_summary: $(SCRIPT) arc_summary: $(SCRIPT)
cp $< $@ cp $< $@

1185
cmd/arc_summary/arc_summary2 Executable file

File diff suppressed because it is too large Load Diff

View File

@ -42,13 +42,6 @@ import os
import subprocess import subprocess
import sys import sys
import time import time
import errno
# We can't use env -S portably, and we need python3 -u to handle pipes in
# the shell abruptly closing the way we want to, so...
import io
if isinstance(sys.__stderr__.buffer, io.BufferedWriter):
os.execv(sys.executable, [sys.executable, "-u"] + sys.argv)
DESCRIPTION = 'Print ARC and other statistics for OpenZFS' DESCRIPTION = 'Print ARC and other statistics for OpenZFS'
INDENT = ' '*8 INDENT = ' '*8
@ -191,13 +184,21 @@ elif sys.platform.startswith('linux'):
# there, so we fall back on modinfo # there, so we fall back on modinfo
command = ["/sbin/modinfo", request, "-0"] command = ["/sbin/modinfo", request, "-0"]
# The recommended way to do this is with subprocess.run(). However,
# some installed versions of Python are < 3.5, so we offer them
# the option of doing it the old way (for now)
info = '' info = ''
try: try:
info = subprocess.run(command, stdout=subprocess.PIPE, if 'run' in dir(subprocess):
check=True, universal_newlines=True) info = subprocess.run(command, stdout=subprocess.PIPE,
raw_output = info.stdout.split('\0') universal_newlines=True)
raw_output = info.stdout.split('\0')
else:
info = subprocess.check_output(command,
universal_newlines=True)
raw_output = info.split('\0')
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
print("Error: Descriptions not available", print("Error: Descriptions not available",
@ -220,29 +221,6 @@ elif sys.platform.startswith('linux'):
return descs return descs
def handle_unraisableException(exc_type, exc_value=None, exc_traceback=None,
err_msg=None, object=None):
handle_Exception(exc_type, object, exc_traceback)
def handle_Exception(ex_cls, ex, tb):
if ex_cls is KeyboardInterrupt:
sys.exit()
if ex_cls is BrokenPipeError:
# It turns out that while sys.exit() triggers an exception
# not handled message on Python 3.8+, os._exit() does not.
os._exit(0)
if ex_cls is OSError:
if ex.errno == errno.ENOTCONN:
sys.exit()
raise ex
if hasattr(sys,'unraisablehook'): # Python 3.8+
sys.unraisablehook = handle_unraisableException
sys.excepthook = handle_Exception
def cleanup_line(single_line): def cleanup_line(single_line):
"""Format a raw line of data from /proc and isolate the name value """Format a raw line of data from /proc and isolate the name value
@ -678,9 +656,9 @@ def section_archits(kstats_dict):
print() print()
print('Cache hits by data type:') print('Cache hits by data type:')
dt_todo = (('Demand data:', arc_stats['demand_data_hits']), dt_todo = (('Demand data:', arc_stats['demand_data_hits']),
('Prefetch data:', arc_stats['prefetch_data_hits']), ('Demand prefetch data:', arc_stats['prefetch_data_hits']),
('Demand metadata:', arc_stats['demand_metadata_hits']), ('Demand metadata:', arc_stats['demand_metadata_hits']),
('Prefetch metadata:', ('Demand prefetch metadata:',
arc_stats['prefetch_metadata_hits'])) arc_stats['prefetch_metadata_hits']))
for title, value in dt_todo: for title, value in dt_todo:
@ -689,10 +667,10 @@ def section_archits(kstats_dict):
print() print()
print('Cache misses by data type:') print('Cache misses by data type:')
dm_todo = (('Demand data:', arc_stats['demand_data_misses']), dm_todo = (('Demand data:', arc_stats['demand_data_misses']),
('Prefetch data:', ('Demand prefetch data:',
arc_stats['prefetch_data_misses']), arc_stats['prefetch_data_misses']),
('Demand metadata:', arc_stats['demand_metadata_misses']), ('Demand metadata:', arc_stats['demand_metadata_misses']),
('Prefetch metadata:', ('Demand prefetch metadata:',
arc_stats['prefetch_metadata_misses'])) arc_stats['prefetch_metadata_misses']))
for title, value in dm_todo: for title, value in dm_todo:

View File

@ -47,7 +47,7 @@
# @hdr is the array of fields that needs to be printed, so we # @hdr is the array of fields that needs to be printed, so we
# just iterate over this array and print the values using our pretty printer. # just iterate over this array and print the values using our pretty printer.
# #
# This script must remain compatible with Python 3.6+. # This script must remain compatible with Python 2.6+ and Python 3.4+.
# #
import sys import sys
@ -271,7 +271,7 @@ def print_values():
if pretty_print: if pretty_print:
fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col]) fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col])
else: else:
fmt = lambda col: str(v[col]) fmt = lambda col: v[col]
sys.stdout.write(sep.join(fmt(col) for col in hdr)) sys.stdout.write(sep.join(fmt(col) for col in hdr))
sys.stdout.write("\n") sys.stdout.write("\n")

View File

@ -27,7 +27,7 @@
# Copyright (C) 2013 Lawrence Livermore National Security, LLC. # Copyright (C) 2013 Lawrence Livermore National Security, LLC.
# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). # Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
# #
# This script must remain compatible with and Python 3.6+. # This script must remain compatible with Python 2.6+ and Python 3.4+.
# #
import sys import sys

View File

@ -1,5 +1,4 @@
include $(top_srcdir)/config/Substfiles.am include $(top_srcdir)/config/Substfiles.am
include $(top_srcdir)/config/Shellcheck.am
dist_sbin_SCRIPTS = fsck.zfs dist_sbin_SCRIPTS = fsck.zfs

View File

@ -26,15 +26,15 @@ for dataset in "$@"; do
case "$(@sbindir@/zpool list -Ho health "$pool")" in case "$(@sbindir@/zpool list -Ho health "$pool")" in
DEGRADED) DEGRADED)
ret=$(( ret | 4 )) ret=$(( $ret | 4 ))
;; ;;
FAULTED) FAULTED)
awk '!/^([[:space:]]*#.*)?$/ && $1 == "'"$dataset"'" && $3 == "zfs" {exit 1}' /etc/fstab || \ awk '!/^([[:space:]]*#.*)?$/ && $1 == "'"$dataset"'" && $3 == "zfs" {exit 1}' /etc/fstab || \
ret=$(( ret | 8 )) ret=$(( $ret | 8 ))
;; ;;
"") "")
# Pool not found, error printed by zpool(8) # Pool not found, error printed by zpool(8)
ret=$(( ret | 8 )) ret=$(( $ret | 8 ))
;; ;;
*) *)
;; ;;

View File

@ -185,11 +185,10 @@ main(int argc, char **argv)
break; break;
case 'h': case 'h':
case '?': case '?':
if (optopt) (void) fprintf(stderr, gettext("Invalid option '%c'\n"),
(void) fprintf(stderr, optopt);
gettext("Invalid option '%c'\n"), optopt);
(void) fprintf(stderr, gettext("Usage: mount.zfs " (void) fprintf(stderr, gettext("Usage: mount.zfs "
"[-sfnvh] [-o options] <dataset> <mountpoint>\n")); "[-sfnv] [-o options] <dataset> <mountpoint>\n"));
return (MOUNT_USAGE); return (MOUNT_USAGE);
} }
} }
@ -246,6 +245,13 @@ main(int argc, char **argv)
} }
} }
if (verbose)
(void) fprintf(stdout, gettext("mount.zfs:\n"
" dataset: \"%s\"\n mountpoint: \"%s\"\n"
" mountflags: 0x%lx\n zfsflags: 0x%lx\n"
" mountopts: \"%s\"\n mtabopts: \"%s\"\n"),
dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt);
if (mntflags & MS_REMOUNT) { if (mntflags & MS_REMOUNT) {
nomtab = 1; nomtab = 1;
remount = 1; remount = 1;
@ -268,10 +274,7 @@ main(int argc, char **argv)
return (MOUNT_USAGE); return (MOUNT_USAGE);
} }
if (!zfsutil || sloppy || zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt);
libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt);
}
/* treat all snapshots as legacy mount points */ /* treat all snapshots as legacy mount points */
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT)
@ -289,11 +292,12 @@ main(int argc, char **argv)
if (zfs_version == 0) { if (zfs_version == 0) {
fprintf(stderr, gettext("unable to fetch " fprintf(stderr, gettext("unable to fetch "
"ZFS version for filesystem '%s'\n"), dataset); "ZFS version for filesystem '%s'\n"), dataset);
zfs_close(zhp);
libzfs_fini(g_zfs);
return (MOUNT_SYSERR); return (MOUNT_SYSERR);
} }
zfs_close(zhp);
libzfs_fini(g_zfs);
/* /*
* Legacy mount points may only be mounted using 'mount', never using * Legacy mount points may only be mounted using 'mount', never using
* 'zfs mount'. However, since 'zfs mount' actually invokes 'mount' * 'zfs mount'. However, since 'zfs mount' actually invokes 'mount'
@ -311,8 +315,6 @@ main(int argc, char **argv)
"Use 'zfs set mountpoint=%s' or 'mount -t zfs %s %s'.\n" "Use 'zfs set mountpoint=%s' or 'mount -t zfs %s %s'.\n"
"See zfs(8) for more information.\n"), "See zfs(8) for more information.\n"),
dataset, mntpoint, dataset, mntpoint); dataset, mntpoint, dataset, mntpoint);
zfs_close(zhp);
libzfs_fini(g_zfs);
return (MOUNT_USAGE); return (MOUNT_USAGE);
} }
@ -323,38 +325,14 @@ main(int argc, char **argv)
"Use 'zfs set mountpoint=%s' or 'zfs mount %s'.\n" "Use 'zfs set mountpoint=%s' or 'zfs mount %s'.\n"
"See zfs(8) for more information.\n"), "See zfs(8) for more information.\n"),
dataset, "legacy", dataset); dataset, "legacy", dataset);
zfs_close(zhp);
libzfs_fini(g_zfs);
return (MOUNT_USAGE); return (MOUNT_USAGE);
} }
if (verbose)
(void) fprintf(stdout, gettext("mount.zfs:\n"
" dataset: \"%s\"\n mountpoint: \"%s\"\n"
" mountflags: 0x%lx\n zfsflags: 0x%lx\n"
" mountopts: \"%s\"\n mtabopts: \"%s\"\n"),
dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt);
if (!fake) { if (!fake) {
if (zfsutil && !sloppy && error = mount(dataset, mntpoint, MNTTYPE_ZFS,
!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) { mntflags, mntopts);
error = zfs_mount_at(zhp, mntopts, mntflags, mntpoint);
if (error) {
(void) fprintf(stderr, "zfs_mount_at() failed: "
"%s", libzfs_error_description(g_zfs));
zfs_close(zhp);
libzfs_fini(g_zfs);
return (MOUNT_SYSERR);
}
} else {
error = mount(dataset, mntpoint, MNTTYPE_ZFS,
mntflags, mntopts);
}
} }
zfs_close(zhp);
libzfs_fini(g_zfs);
if (error) { if (error) {
switch (errno) { switch (errno) {
case ENOENT: case ENOENT:
@ -389,7 +367,7 @@ main(int argc, char **argv)
"mount the filesystem again.\n"), dataset); "mount the filesystem again.\n"), dataset);
return (MOUNT_SYSERR); return (MOUNT_SYSERR);
} }
fallthrough; /* fallthru */
#endif #endif
default: default:
(void) fprintf(stderr, gettext("filesystem " (void) fprintf(stderr, gettext("filesystem "

View File

@ -1,3 +1 @@
include $(top_srcdir)/config/Shellcheck.am
dist_udev_SCRIPTS = vdev_id dist_udev_SCRIPTS = vdev_id

View File

@ -140,17 +140,15 @@ Usage: vdev_id [-h]
-p number of phy's per switch port [default=$PHYS_PER_PORT] -p number of phy's per switch port [default=$PHYS_PER_PORT]
-h show this summary -h show this summary
EOF EOF
exit 1 exit 0
# exit with error to avoid processing usage message by a udev rule
} }
map_slot() { map_slot() {
LINUX_SLOT=$1 LINUX_SLOT=$1
CHANNEL=$2 CHANNEL=$2
MAPPED_SLOT=$(awk -v linux_slot="$LINUX_SLOT" -v channel="$CHANNEL" \ MAPPED_SLOT=$(awk '$1 == "slot" && $2 == "${LINUX_SLOT}" && \
'$1 == "slot" && $2 == linux_slot && \ $4 ~ /^${CHANNEL}$|^$/ { print $3; exit}' $CONFIG)
($4 ~ "^"channel"$" || $4 ~ /^$/) { print $3; exit}' $CONFIG)
if [ -z "$MAPPED_SLOT" ] ; then if [ -z "$MAPPED_SLOT" ] ; then
MAPPED_SLOT=$LINUX_SLOT MAPPED_SLOT=$LINUX_SLOT
fi fi
@ -165,7 +163,7 @@ map_channel() {
case $TOPOLOGY in case $TOPOLOGY in
"sas_switch") "sas_switch")
MAPPED_CHAN=$(awk -v port="$PORT" \ MAPPED_CHAN=$(awk -v port="$PORT" \
'$1 == "channel" && $2 == port \ '$1 == "channel" && $2 == ${PORT} \
{ print $3; exit }' $CONFIG) { print $3; exit }' $CONFIG)
;; ;;
"sas_direct"|"scsi") "sas_direct"|"scsi")
@ -375,7 +373,7 @@ sas_handler() {
i=$((i + 1)) i=$((i + 1))
done done
PHY=$(ls -vd "$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 if [ -z "$PHY" ] ; then
PHY=0 PHY=0
fi fi
@ -596,9 +594,7 @@ enclosure_handler () {
# DEVPATH=/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/subsystem/devices/0:0:0:0/scsi_generic/sg0 # DEVPATH=/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/subsystem/devices/0:0:0:0/scsi_generic/sg0
# Get the enclosure ID ("0:0:0:0") # Get the enclosure ID ("0:0:0:0")
ENC="${DEVPATH%/*}" ENC=$(basename $(readlink -m "/sys/$DEVPATH/../.."))
ENC="${ENC%/*}"
ENC="${ENC##*/}"
if [ ! -d "/sys/class/enclosure/$ENC" ] ; then if [ ! -d "/sys/class/enclosure/$ENC" ] ; then
# Not an enclosure, bail out # Not an enclosure, bail out
return return
@ -618,15 +614,14 @@ enclosure_handler () {
# The PCI directory is two directories up from the port directory # The PCI directory is two directories up from the port directory
# /sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0 # /sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0
PCI_ID_LONG="$(readlink -m "/sys/$PORT_DIR/../..")" PCI_ID_LONG=$(basename $(readlink -m "/sys/$PORT_DIR/../.."))
PCI_ID_LONG="${PCI_ID_LONG##*/}"
# Strip down the PCI address from 0000:05:00.0 to 05:00.0 # Strip down the PCI address from 0000:05:00.0 to 05:00.0
PCI_ID="${PCI_ID_LONG#[0-9]*:}" 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 our device according to vdev_id.conf (like "L0" or "U1").
NAME=$(awk "/channel/{if (\$1 == \"channel\" && \$2 == \"$PCI_ID\" && \ NAME=$(awk '/channel/{if ($1 == "channel" && $2 == "$PCI_ID" && \
\$3 == \"$PORT_ID\") {print \$4\$3}}" $CONFIG) $3 == "$PORT_ID") {print ${4}int(count[$4])}; count[$4]++}' $CONFIG)
echo "${NAME}" echo "${NAME}"
} }
@ -677,7 +672,7 @@ alias_handler () {
link=$(echo "$link" | sed 's/p[0-9][0-9]*$//') link=$(echo "$link" | sed 's/p[0-9][0-9]*$//')
fi fi
# Check both the fully qualified and the base name of link. # Check both the fully qualified and the base name of link.
for l in $link ${link##*/} ; do for l in $link $(basename "$link") ; do
if [ ! -z "$l" ]; then if [ ! -z "$l" ]; then
alias=$(awk -v var="$l" '($1 == "alias") && \ alias=$(awk -v var="$l" '($1 == "alias") && \
($3 == var) \ ($3 == var) \
@ -732,7 +727,7 @@ done
if [ ! -r "$CONFIG" ] ; then if [ ! -r "$CONFIG" ] ; then
echo "Error: Config file \"$CONFIG\" not found" echo "Error: Config file \"$CONFIG\" not found"
exit 1 exit 0
fi fi
if [ -z "$DEV" ] && [ -z "$ENCLOSURE_MODE" ] ; then if [ -z "$DEV" ] && [ -z "$ENCLOSURE_MODE" ] ; then

View File

@ -110,9 +110,8 @@ extern int zfs_recover;
extern unsigned long zfs_arc_meta_min, zfs_arc_meta_limit; extern unsigned long zfs_arc_meta_min, zfs_arc_meta_limit;
extern int zfs_vdev_async_read_max_active; extern int zfs_vdev_async_read_max_active;
extern boolean_t spa_load_verify_dryrun; extern boolean_t spa_load_verify_dryrun;
extern boolean_t spa_mode_readable_spacemaps;
extern int zfs_reconstruct_indirect_combinations_max; extern int zfs_reconstruct_indirect_combinations_max;
extern uint_t zfs_btree_verify_intensity; extern int zfs_btree_verify_intensity;
static const char cmdname[] = "zdb"; static const char cmdname[] = "zdb";
uint8_t dump_opt[256]; uint8_t dump_opt[256];
@ -163,6 +162,12 @@ static int dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t free,
dmu_tx_t *tx); dmu_tx_t *tx);
typedef struct sublivelist_verify { typedef struct sublivelist_verify {
/* all ALLOC'd blkptr_t in one sub-livelist */
zfs_btree_t sv_all_allocs;
/* all FREE'd blkptr_t in one sub-livelist */
zfs_btree_t sv_all_frees;
/* FREE's that haven't yet matched to an ALLOC, in one sub-livelist */ /* FREE's that haven't yet matched to an ALLOC, in one sub-livelist */
zfs_btree_t sv_pair; zfs_btree_t sv_pair;
@ -221,68 +226,29 @@ typedef struct sublivelist_verify_block {
static void zdb_print_blkptr(const blkptr_t *bp, int flags); static void zdb_print_blkptr(const blkptr_t *bp, int flags);
typedef struct sublivelist_verify_block_refcnt {
/* block pointer entry in livelist being verified */
blkptr_t svbr_blk;
/*
* Refcount gets incremented to 1 when we encounter the first
* FREE entry for the svfbr block pointer and a node for it
* is created in our ZDB verification/tracking metadata.
*
* As we encounter more FREE entries we increment this counter
* and similarly decrement it whenever we find the respective
* ALLOC entries for this block.
*
* When the refcount gets to 0 it means that all the FREE and
* ALLOC entries of this block have paired up and we no longer
* need to track it in our verification logic (e.g. the node
* containing this struct in our verification data structure
* should be freed).
*
* [refer to sublivelist_verify_blkptr() for the actual code]
*/
uint32_t svbr_refcnt;
} sublivelist_verify_block_refcnt_t;
static int
sublivelist_block_refcnt_compare(const void *larg, const void *rarg)
{
const sublivelist_verify_block_refcnt_t *l = larg;
const sublivelist_verify_block_refcnt_t *r = rarg;
return (livelist_compare(&l->svbr_blk, &r->svbr_blk));
}
static int static int
sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free, sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
dmu_tx_t *tx) dmu_tx_t *tx)
{ {
ASSERT3P(tx, ==, NULL); ASSERT3P(tx, ==, NULL);
struct sublivelist_verify *sv = arg; struct sublivelist_verify *sv = arg;
sublivelist_verify_block_refcnt_t current = { char blkbuf[BP_SPRINTF_LEN];
.svbr_blk = *bp,
/*
* Start with 1 in case this is the first free entry.
* This field is not used for our B-Tree comparisons
* anyway.
*/
.svbr_refcnt = 1,
};
zfs_btree_index_t where; zfs_btree_index_t where;
sublivelist_verify_block_refcnt_t *pair =
zfs_btree_find(&sv->sv_pair, &current, &where);
if (free) { if (free) {
if (pair == NULL) { zfs_btree_add(&sv->sv_pair, bp);
/* first free entry for this block pointer */ /* Check if the FREE is a duplicate */
zfs_btree_add(&sv->sv_pair, &current); if (zfs_btree_find(&sv->sv_all_frees, bp, &where) != NULL) {
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp,
free);
(void) printf("\tERROR: Duplicate FREE: %s\n", blkbuf);
} else { } else {
pair->svbr_refcnt++; zfs_btree_add_idx(&sv->sv_all_frees, bp, &where);
} }
} else { } else {
if (pair == NULL) { /* Check if the ALLOC has been freed */
/* block that is currently marked as allocated */ if (zfs_btree_find(&sv->sv_pair, bp, &where) != NULL) {
zfs_btree_remove_idx(&sv->sv_pair, &where);
} else {
for (int i = 0; i < SPA_DVAS_PER_BP; i++) { for (int i = 0; i < SPA_DVAS_PER_BP; i++) {
if (DVA_IS_EMPTY(&bp->blk_dva[i])) if (DVA_IS_EMPTY(&bp->blk_dva[i]))
break; break;
@ -297,16 +263,16 @@ sublivelist_verify_blkptr(void *arg, const blkptr_t *bp, boolean_t free,
&svb, &where); &svb, &where);
} }
} }
}
/* Check if the ALLOC is a duplicate */
if (zfs_btree_find(&sv->sv_all_allocs, bp, &where) != NULL) {
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp,
free);
(void) printf("\tERROR: Duplicate ALLOC: %s\n", blkbuf);
} else { } else {
/* alloc matches a free entry */ zfs_btree_add_idx(&sv->sv_all_allocs, bp, &where);
pair->svbr_refcnt--;
if (pair->svbr_refcnt == 0) {
/* all allocs and frees have been matched */
zfs_btree_remove_idx(&sv->sv_pair, &where);
}
} }
} }
return (0); return (0);
} }
@ -314,22 +280,32 @@ static int
sublivelist_verify_func(void *args, dsl_deadlist_entry_t *dle) sublivelist_verify_func(void *args, dsl_deadlist_entry_t *dle)
{ {
int err; int err;
char blkbuf[BP_SPRINTF_LEN];
struct sublivelist_verify *sv = args; struct sublivelist_verify *sv = args;
zfs_btree_create(&sv->sv_pair, sublivelist_block_refcnt_compare, zfs_btree_create(&sv->sv_all_allocs, livelist_compare,
sizeof (sublivelist_verify_block_refcnt_t)); sizeof (blkptr_t));
zfs_btree_create(&sv->sv_all_frees, livelist_compare,
sizeof (blkptr_t));
zfs_btree_create(&sv->sv_pair, livelist_compare,
sizeof (blkptr_t));
err = bpobj_iterate_nofree(&dle->dle_bpobj, sublivelist_verify_blkptr, err = bpobj_iterate_nofree(&dle->dle_bpobj, sublivelist_verify_blkptr,
sv, NULL); sv, NULL);
sublivelist_verify_block_refcnt_t *e; zfs_btree_clear(&sv->sv_all_allocs);
zfs_btree_destroy(&sv->sv_all_allocs);
zfs_btree_clear(&sv->sv_all_frees);
zfs_btree_destroy(&sv->sv_all_frees);
blkptr_t *e;
zfs_btree_index_t *cookie = NULL; zfs_btree_index_t *cookie = NULL;
while ((e = zfs_btree_destroy_nodes(&sv->sv_pair, &cookie)) != NULL) { while ((e = zfs_btree_destroy_nodes(&sv->sv_pair, &cookie)) != NULL) {
char blkbuf[BP_SPRINTF_LEN]; snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), e, B_TRUE);
snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), (void) printf("\tERROR: Unmatched FREE: %s\n", blkbuf);
&e->svbr_blk, B_TRUE);
(void) printf("\tERROR: %d unmatched FREE(s): %s\n",
e->svbr_refcnt, blkbuf);
} }
zfs_btree_destroy(&sv->sv_pair); zfs_btree_destroy(&sv->sv_pair);
@ -638,14 +614,10 @@ mv_populate_livelist_allocs(metaslab_verify_t *mv, sublivelist_verify_t *sv)
/* /*
* [Livelist Check] * [Livelist Check]
* Iterate through all the sublivelists and: * Iterate through all the sublivelists and:
* - report leftover frees (**) * - report leftover frees
* - report double ALLOCs/FREEs
* - record leftover ALLOCs together with their TXG [see Cross Check] * - record leftover ALLOCs together with their TXG [see Cross Check]
* *
* (**) Note: Double ALLOCs are valid in datasets that have dedup
* enabled. Similarly double FREEs are allowed as well but
* only if they pair up with a corresponding ALLOC entry once
* we our done with our sublivelist iteration.
*
* [Spacemap Check] * [Spacemap Check]
* for each metaslab: * for each metaslab:
* - iterate over spacemap and then the metaslab's entries in the * - iterate over spacemap and then the metaslab's entries in the
@ -2219,8 +2191,7 @@ snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
(void) snprintf(blkbuf + strlen(blkbuf), (void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), buflen - strlen(blkbuf),
" ZSTD:size=%u:version=%u:level=%u:EMBEDDED", " ZSTD:size=%u:version=%u:level=%u:EMBEDDED",
zstd_hdr.c_len, zfs_get_hdrversion(&zstd_hdr), zstd_hdr.c_len, zstd_hdr.version, zstd_hdr.level);
zfs_get_hdrlevel(&zstd_hdr));
return; return;
} }
@ -2244,8 +2215,7 @@ snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
(void) snprintf(blkbuf + strlen(blkbuf), (void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), buflen - strlen(blkbuf),
" ZSTD:size=%u:version=%u:level=%u:NORMAL", " ZSTD:size=%u:version=%u:level=%u:NORMAL",
zstd_hdr.c_len, zfs_get_hdrversion(&zstd_hdr), zstd_hdr.c_len, zstd_hdr.version, zstd_hdr.level);
zfs_get_hdrlevel(&zstd_hdr));
abd_return_buf_copy(pabd, buf, BP_GET_LSIZE(bp)); abd_return_buf_copy(pabd, buf, BP_GET_LSIZE(bp));
} }
@ -2995,7 +2965,7 @@ open_objset(const char *path, void *tag, objset_t **osp)
} }
sa_os = *osp; sa_os = *osp;
return (err); return (0);
} }
static void static void
@ -3102,22 +3072,13 @@ dump_znode_sa_xattr(sa_handle_t *hdl)
(void) printf("\tSA xattrs: %d bytes, %d entries\n\n", (void) printf("\tSA xattrs: %d bytes, %d entries\n\n",
sa_xattr_size, sa_xattr_entries); sa_xattr_size, sa_xattr_entries);
while ((elem = nvlist_next_nvpair(sa_xattr, elem)) != NULL) { while ((elem = nvlist_next_nvpair(sa_xattr, elem)) != NULL) {
boolean_t can_print = !dump_opt['P'];
uchar_t *value; uchar_t *value;
uint_t cnt, idx; uint_t cnt, idx;
(void) printf("\t\t%s = ", nvpair_name(elem)); (void) printf("\t\t%s = ", nvpair_name(elem));
nvpair_value_byte_array(elem, &value, &cnt); nvpair_value_byte_array(elem, &value, &cnt);
for (idx = 0; idx < cnt; ++idx) { for (idx = 0; idx < cnt; ++idx) {
if (!isprint(value[idx])) { if (isprint(value[idx]))
can_print = B_FALSE;
break;
}
}
for (idx = 0; idx < cnt; ++idx) {
if (can_print)
(void) putchar(value[idx]); (void) putchar(value[idx]);
else else
(void) printf("\\%3.3o", value[idx]); (void) printf("\\%3.3o", value[idx]);
@ -3134,18 +3095,13 @@ dump_znode_symlink(sa_handle_t *hdl)
{ {
int sa_symlink_size = 0; int sa_symlink_size = 0;
char linktarget[MAXPATHLEN]; char linktarget[MAXPATHLEN];
linktarget[0] = '\0';
int error; int error;
error = sa_size(hdl, sa_attr_table[ZPL_SYMLINK], &sa_symlink_size); error = sa_size(hdl, sa_attr_table[ZPL_SYMLINK], &sa_symlink_size);
if (error || sa_symlink_size == 0) { if (error || sa_symlink_size == 0) {
return; return;
} }
if (sa_symlink_size >= sizeof (linktarget)) {
(void) printf("symlink size %d is too large\n",
sa_symlink_size);
return;
}
linktarget[sa_symlink_size] = '\0';
if (sa_lookup(hdl, sa_attr_table[ZPL_SYMLINK], if (sa_lookup(hdl, sa_attr_table[ZPL_SYMLINK],
&linktarget, sa_symlink_size) == 0) &linktarget, sa_symlink_size) == 0)
(void) printf("\ttarget %s\n", linktarget); (void) printf("\ttarget %s\n", linktarget);
@ -4111,7 +4067,7 @@ cksum_record_compare(const void *x1, const void *x2)
const cksum_record_t *l = (cksum_record_t *)x1; const cksum_record_t *l = (cksum_record_t *)x1;
const cksum_record_t *r = (cksum_record_t *)x2; const cksum_record_t *r = (cksum_record_t *)x2;
int arraysize = ARRAY_SIZE(l->cksum.zc_word); int arraysize = ARRAY_SIZE(l->cksum.zc_word);
int difference = 0; int difference;
for (int i = 0; i < arraysize; i++) { for (int i = 0; i < arraysize; i++) {
difference = TREE_CMP(l->cksum.zc_word[i], r->cksum.zc_word[i]); difference = TREE_CMP(l->cksum.zc_word[i], r->cksum.zc_word[i]);
@ -4588,7 +4544,7 @@ dump_path_impl(objset_t *os, uint64_t obj, char *name, uint64_t *retobj)
case DMU_OT_DIRECTORY_CONTENTS: case DMU_OT_DIRECTORY_CONTENTS:
if (s != NULL && *(s + 1) != '\0') if (s != NULL && *(s + 1) != '\0')
return (dump_path_impl(os, child_obj, s + 1, retobj)); return (dump_path_impl(os, child_obj, s + 1, retobj));
fallthrough; /*FALLTHROUGH*/
case DMU_OT_PLAIN_FILE_CONTENTS: case DMU_OT_PLAIN_FILE_CONTENTS:
if (retobj != NULL) { if (retobj != NULL) {
*retobj = child_obj; *retobj = child_obj;
@ -4815,7 +4771,7 @@ dump_label(const char *dev)
if (nvlist_size(config, &size, NV_ENCODE_XDR) != 0) if (nvlist_size(config, &size, NV_ENCODE_XDR) != 0)
size = buflen; size = buflen;
/* If the device is a cache device read the header. */ /* If the device is a cache device clear the header. */
if (!read_l2arc_header) { if (!read_l2arc_header) {
if (nvlist_lookup_uint64(config, if (nvlist_lookup_uint64(config,
ZPOOL_CONFIG_POOL_STATE, &l2cache) == 0 && ZPOOL_CONFIG_POOL_STATE, &l2cache) == 0 &&
@ -5976,8 +5932,7 @@ zdb_leak_init_prepare_indirect_vdevs(spa_t *spa, zdb_cb_t *zcb)
vdev_metaslab_group_create(vd); vdev_metaslab_group_create(vd);
VERIFY0(vdev_metaslab_init(vd, 0)); VERIFY0(vdev_metaslab_init(vd, 0));
vdev_indirect_mapping_t *vim __maybe_unused = vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping;
vd->vdev_indirect_mapping;
uint64_t vim_idx = 0; uint64_t vim_idx = 0;
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) { for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
@ -7086,7 +7041,7 @@ verify_checkpoint_vdev_spacemaps(spa_t *checkpoint, spa_t *current)
for (uint64_t c = ckpoint_rvd->vdev_children; for (uint64_t c = ckpoint_rvd->vdev_children;
c < current_rvd->vdev_children; c++) { c < current_rvd->vdev_children; c++) {
vdev_t *current_vd = current_rvd->vdev_child[c]; vdev_t *current_vd = current_rvd->vdev_child[c];
VERIFY3P(current_vd->vdev_checkpoint_sm, ==, NULL); ASSERT3P(current_vd->vdev_checkpoint_sm, ==, NULL);
} }
} }
@ -8281,23 +8236,6 @@ zdb_embedded_block(char *thing)
free(buf); free(buf);
} }
/* check for valid hex or decimal numeric string */
static boolean_t
zdb_numeric(char *str)
{
int i = 0;
if (strlen(str) == 0)
return (B_FALSE);
if (strncmp(str, "0x", 2) == 0 || strncmp(str, "0X", 2) == 0)
i = 2;
for (; i < strlen(str); i++) {
if (!isxdigit(str[i]))
return (B_FALSE);
}
return (B_TRUE);
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -8343,7 +8281,7 @@ main(int argc, char **argv)
zfs_btree_verify_intensity = 3; zfs_btree_verify_intensity = 3;
while ((c = getopt(argc, argv, while ((c = getopt(argc, argv,
"AbcCdDeEFGhiI:klLmMNo:Op:PqrRsSt:uU:vVx:XYyZ")) != -1) { "AbcCdDeEFGhiI:klLmMo:Op:PqrRsSt:uU:vVx:XYyZ")) != -1) {
switch (c) { switch (c) {
case 'b': case 'b':
case 'c': case 'c':
@ -8357,7 +8295,6 @@ main(int argc, char **argv)
case 'l': case 'l':
case 'm': case 'm':
case 'M': case 'M':
case 'N':
case 'O': case 'O':
case 'r': case 'r':
case 'R': case 'R':
@ -8449,6 +8386,31 @@ main(int argc, char **argv)
(void) fprintf(stderr, "-p option requires use of -e\n"); (void) fprintf(stderr, "-p option requires use of -e\n");
usage(); usage();
} }
if (dump_opt['d'] || dump_opt['r']) {
/* <pool>[/<dataset | objset id> is accepted */
if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL &&
objset_str++ != NULL) {
char *endptr;
errno = 0;
objset_id = strtoull(objset_str, &endptr, 0);
/* dataset 0 is the same as opening the pool */
if (errno == 0 && endptr != objset_str &&
objset_id != 0) {
target_is_spa = B_FALSE;
dataset_lookup = B_TRUE;
} else if (objset_id != 0) {
printf("failed to open objset %s "
"%llu %s", objset_str,
(u_longlong_t)objset_id,
strerror(errno));
exit(1);
}
/* normal dataset name not an objset ID */
if (endptr == objset_str) {
objset_id = -1;
}
}
}
#if defined(_LP64) #if defined(_LP64)
/* /*
@ -8477,18 +8439,13 @@ main(int argc, char **argv)
*/ */
spa_load_verify_dryrun = B_TRUE; spa_load_verify_dryrun = B_TRUE;
/*
* ZDB should have ability to read spacemaps.
*/
spa_mode_readable_spacemaps = B_TRUE;
kernel_init(SPA_MODE_READ); kernel_init(SPA_MODE_READ);
if (dump_all) if (dump_all)
verbose = MAX(verbose, 1); verbose = MAX(verbose, 1);
for (c = 0; c < 256; c++) { for (c = 0; c < 256; c++) {
if (dump_all && strchr("AeEFklLNOPrRSXy", c) == NULL) if (dump_all && strchr("AeEFklLOPrRSXy", c) == NULL)
dump_opt[c] = 1; dump_opt[c] = 1;
if (dump_opt[c]) if (dump_opt[c])
dump_opt[c] += verbose; dump_opt[c] += verbose;
@ -8527,7 +8484,6 @@ main(int argc, char **argv)
return (dump_path(argv[0], argv[1], NULL)); return (dump_path(argv[0], argv[1], NULL));
} }
if (dump_opt['r']) { if (dump_opt['r']) {
target_is_spa = B_FALSE;
if (argc != 3) if (argc != 3)
usage(); usage();
dump_opt['v'] = verbose; dump_opt['v'] = verbose;
@ -8538,10 +8494,6 @@ main(int argc, char **argv)
rewind = ZPOOL_DO_REWIND | rewind = ZPOOL_DO_REWIND |
(dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0); (dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0);
/* -N implies -d */
if (dump_opt['N'] && dump_opt['d'] == 0)
dump_opt['d'] = dump_opt['N'];
if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 || if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 ||
nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, max_txg) != 0 || nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, max_txg) != 0 ||
nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, rewind) != 0) nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, rewind) != 0)
@ -8560,34 +8512,6 @@ main(int argc, char **argv)
targetlen = strlen(target); targetlen = strlen(target);
if (targetlen && target[targetlen - 1] == '/') if (targetlen && target[targetlen - 1] == '/')
target[targetlen - 1] = '\0'; target[targetlen - 1] = '\0';
/*
* See if an objset ID was supplied (-d <pool>/<objset ID>).
* To disambiguate tank/100, consider the 100 as objsetID
* if -N was given, otherwise 100 is an objsetID iff
* tank/100 as a named dataset fails on lookup.
*/
objset_str = strchr(target, '/');
if (objset_str && strlen(objset_str) > 1 &&
zdb_numeric(objset_str + 1)) {
char *endptr;
errno = 0;
objset_str++;
objset_id = strtoull(objset_str, &endptr, 0);
/* dataset 0 is the same as opening the pool */
if (errno == 0 && endptr != objset_str &&
objset_id != 0) {
if (dump_opt['N'])
dataset_lookup = B_TRUE;
}
/* normal dataset name not an objset ID */
if (endptr == objset_str) {
objset_id = -1;
}
} else if (objset_str && !zdb_numeric(objset_str + 1) &&
dump_opt['N']) {
printf("Supply a numeric objset ID with -N\n");
exit(1);
}
} else { } else {
target_pool = target; target_pool = target;
} }
@ -8705,27 +8629,13 @@ main(int argc, char **argv)
} }
return (error); return (error);
} else { } else {
target_pool = strdup(target);
if (strpbrk(target, "/@") != NULL)
*strpbrk(target_pool, "/@") = '\0';
zdb_set_skip_mmp(target); zdb_set_skip_mmp(target);
/*
* If -N was supplied, the user has indicated that
* zdb -d <pool>/<objsetID> is in effect. Otherwise
* we first assume that the dataset string is the
* dataset name. If dmu_objset_hold fails with the
* dataset string, and we have an objset_id, retry the
* lookup with the objsetID.
*/
boolean_t retry = B_TRUE;
retry_lookup:
if (dataset_lookup == B_TRUE) { if (dataset_lookup == B_TRUE) {
/* /*
* Use the supplied id to get the name * Use the supplied id to get the name
* for open_objset. * for open_objset.
*/ */
error = spa_open(target_pool, &spa, FTAG); error = spa_open(target, &spa, FTAG);
if (error == 0) { if (error == 0) {
error = name_from_objset_id(spa, error = name_from_objset_id(spa,
objset_id, dsname); objset_id, dsname);
@ -8734,23 +8644,10 @@ retry_lookup:
target = dsname; target = dsname;
} }
} }
if (error == 0) { if (error == 0)
if (objset_id > 0 && retry) {
int err = dmu_objset_hold(target, FTAG,
&os);
if (err) {
dataset_lookup = B_TRUE;
retry = B_FALSE;
goto retry_lookup;
} else {
dmu_objset_rele(os, FTAG);
}
}
error = open_objset(target, FTAG, &os); error = open_objset(target, FTAG, &os);
}
if (error == 0) if (error == 0)
spa = dmu_objset_spa(os); spa = dmu_objset_spa(os);
free(target_pool);
} }
} }
nvlist_free(policy); nvlist_free(policy);

View File

@ -1,10 +1,8 @@
include $(top_srcdir)/config/Rules.am include $(top_srcdir)/config/Rules.am
include $(top_srcdir)/config/Shellcheck.am
AM_CFLAGS += $(LIBUDEV_CFLAGS) $(LIBUUID_CFLAGS) AM_CFLAGS += $(LIBUDEV_CFLAGS) $(LIBUUID_CFLAGS)
SUBDIRS = zed.d SUBDIRS = zed.d
SHELLCHECKDIRS = $(SUBDIRS)
sbin_PROGRAMS = zed sbin_PROGRAMS = zed
@ -45,7 +43,7 @@ zed_LDADD = \
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \ $(abs_top_builddir)/lib/libnvpair/libnvpair.la \
$(abs_top_builddir)/lib/libuutil/libuutil.la $(abs_top_builddir)/lib/libuutil/libuutil.la
zed_LDADD += -lrt $(LIBATOMIC_LIBS) $(LIBUDEV_LIBS) $(LIBUUID_LIBS) zed_LDADD += -lrt $(LIBUDEV_LIBS) $(LIBUUID_LIBS)
zed_LDFLAGS = -pthread zed_LDFLAGS = -pthread
EXTRA_DIST = agents/README.md EXTRA_DIST = agents/README.md

View File

@ -599,7 +599,6 @@ fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta)
sev.sigev_notify_function = _timer_notify; sev.sigev_notify_function = _timer_notify;
sev.sigev_notify_attributes = NULL; sev.sigev_notify_attributes = NULL;
sev.sigev_value.sival_ptr = ftp; sev.sigev_value.sival_ptr = ftp;
sev.sigev_signo = 0;
timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid); timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid);
timer_settime(ftp->ft_tid, 0, &its, NULL); timer_settime(ftp->ft_tid, 0, &its, NULL);

View File

@ -80,7 +80,6 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
char *path = NULL; char *path = NULL;
uint_t c, children; uint_t c, children;
nvlist_t **child; nvlist_t **child;
uint64_t vdev_guid;
/* /*
* First iterate over any children. * First iterate over any children.
@ -101,7 +100,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
&child, &children) == 0) { &child, &children) == 0) {
for (c = 0; c < children; c++) { for (c = 0; c < children; c++) {
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) { if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
gsp->gs_vdev_type = DEVICE_TYPE_SPARE; gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
return (B_TRUE); return (B_TRUE);
} }
} }
@ -110,7 +109,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
&child, &children) == 0) { &child, &children) == 0) {
for (c = 0; c < children; c++) { for (c = 0; c < children; c++) {
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) { if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
gsp->gs_vdev_type = DEVICE_TYPE_L2ARC; gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
return (B_TRUE); return (B_TRUE);
} }
} }
@ -127,21 +126,6 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
&gsp->gs_vdev_expandtime); &gsp->gs_vdev_expandtime);
return (B_TRUE); return (B_TRUE);
} }
/*
* Otherwise, on a vdev guid match, grab the devid and expansion
* time. The devid might be missing on removal since its not part
* of blkid cache and L2ARC VDEV does not contain pool guid in its
* blkid, so this is a special case for L2ARC VDEV.
*/
else if (gsp->gs_vdev_guid != 0 && gsp->gs_devid == NULL &&
nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &vdev_guid) == 0 &&
gsp->gs_vdev_guid == vdev_guid) {
(void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
&gsp->gs_devid);
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
&gsp->gs_vdev_expandtime);
return (B_TRUE);
}
return (B_FALSE); return (B_FALSE);
} }
@ -164,13 +148,13 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
/* /*
* if a match was found then grab the pool guid * if a match was found then grab the pool guid
*/ */
if (gsp->gs_vdev_guid && gsp->gs_devid) { if (gsp->gs_vdev_guid) {
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
&gsp->gs_pool_guid); &gsp->gs_pool_guid);
} }
zpool_close(zhp); zpool_close(zhp);
return (gsp->gs_devid != NULL && gsp->gs_vdev_guid != 0); return (gsp->gs_vdev_guid != 0);
} }
void void
@ -211,13 +195,11 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
uint64_t pool_guid = 0, vdev_guid = 0; uint64_t pool_guid = 0, vdev_guid = 0;
guid_search_t search = { 0 }; guid_search_t search = { 0 };
device_type_t devtype = DEVICE_TYPE_PRIMARY; device_type_t devtype = DEVICE_TYPE_PRIMARY;
char *devid = NULL;
class = "resource.fs.zfs.removed"; class = "resource.fs.zfs.removed";
subclass = ""; subclass = "";
(void) nvlist_add_string(payload, FM_CLASS, class); (void) nvlist_add_string(payload, FM_CLASS, class);
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid);
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid); (void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
(void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid); (void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid);
@ -227,24 +209,20 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2); (void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
/* /*
* If devid is missing but vdev_guid is available, find devid
* and pool_guid from vdev_guid.
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or * For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
* ZFS_EV_POOL_GUID may be missing so find them. * ZFS_EV_POOL_GUID may be missing so find them.
*/ */
if (devid == NULL || pool_guid == 0 || vdev_guid == 0) { if (pool_guid == 0 || vdev_guid == 0) {
if (devid == NULL) if ((nvlist_lookup_string(nvl, DEV_IDENTIFIER,
search.gs_vdev_guid = vdev_guid; &search.gs_devid) == 0) &&
else (zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search)
search.gs_devid = devid; == 1)) {
zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search); if (pool_guid == 0)
if (devid == NULL) pool_guid = search.gs_pool_guid;
devid = search.gs_devid; if (vdev_guid == 0)
if (pool_guid == 0) vdev_guid = search.gs_vdev_guid;
pool_guid = search.gs_pool_guid; devtype = search.gs_vdev_type;
if (vdev_guid == 0) }
vdev_guid = search.gs_vdev_guid;
devtype = search.gs_vdev_type;
} }
/* /*
@ -257,9 +235,7 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
search.gs_vdev_expandtime + 10 > tv.tv_sec) { search.gs_vdev_expandtime + 10 > tv.tv_sec) {
zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' " zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' "
"for recently expanded device '%s'", EC_DEV_REMOVE, "for recently expanded device '%s'", EC_DEV_REMOVE,
devid); search.gs_devid);
fnvlist_free(payload);
free(event);
goto out; goto out;
} }

View File

@ -35,7 +35,6 @@
#include <sys/fs/zfs.h> #include <sys/fs/zfs.h>
#include <sys/fm/protocol.h> #include <sys/fm/protocol.h>
#include <sys/fm/fs/zfs.h> #include <sys/fm/fs/zfs.h>
#include <sys/zio.h>
#include "zfs_agents.h" #include "zfs_agents.h"
#include "fmd_api.h" #include "fmd_api.h"
@ -774,8 +773,6 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) { ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
char *failmode = NULL; char *failmode = NULL;
boolean_t checkremove = B_FALSE; boolean_t checkremove = B_FALSE;
uint32_t pri = 0;
int32_t flags = 0;
/* /*
* If this is a checksum or I/O error, then toss it into the * If this is a checksum or I/O error, then toss it into the
@ -798,23 +795,6 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
checkremove = B_TRUE; checkremove = B_TRUE;
} else if (fmd_nvl_class_match(hdl, nvl, } else if (fmd_nvl_class_match(hdl, nvl,
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CHECKSUM))) { ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CHECKSUM))) {
/*
* We ignore ereports for checksum errors generated by
* scrub/resilver I/O to avoid potentially further
* degrading the pool while it's being repaired.
*/
if (((nvlist_lookup_uint32(nvl,
FM_EREPORT_PAYLOAD_ZFS_ZIO_PRIORITY, &pri) == 0) &&
(pri == ZIO_PRIORITY_SCRUB ||
pri == ZIO_PRIORITY_REBUILD)) ||
((nvlist_lookup_int32(nvl,
FM_EREPORT_PAYLOAD_ZFS_ZIO_FLAGS, &flags) == 0) &&
(flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER)))) {
fmd_hdl_debug(hdl, "ignoring '%s' for "
"scrub/resilver I/O", class);
return;
}
if (zcp->zc_data.zc_serd_checksum[0] == '\0') { if (zcp->zc_data.zc_serd_checksum[0] == '\0') {
zfs_serd_name(zcp->zc_data.zc_serd_checksum, zfs_serd_name(zcp->zc_data.zc_serd_checksum,
pool_guid, vdev_guid, "checksum"); pool_guid, vdev_guid, "checksum");

View File

@ -141,17 +141,6 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
return (0); return (0);
} }
/*
* Write an array of strings to the zed log
*/
static void lines_to_zed_log_msg(char **lines, int lines_cnt)
{
int i;
for (i = 0; i < lines_cnt; i++) {
zed_log_msg(LOG_INFO, "%s", lines[i]);
}
}
/* /*
* Two stage replace on Linux * Two stage replace on Linux
* since we get disk notifications * since we get disk notifications
@ -194,20 +183,16 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
nvlist_t *nvroot, *newvd; nvlist_t *nvroot, *newvd;
pendingdev_t *device; pendingdev_t *device;
uint64_t wholedisk = 0ULL; uint64_t wholedisk = 0ULL;
uint64_t offline = 0ULL, faulted = 0ULL; uint64_t offline = 0ULL;
uint64_t guid = 0ULL; uint64_t guid = 0ULL;
uint64_t is_spare = 0;
char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL; char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL;
char rawpath[PATH_MAX], fullpath[PATH_MAX]; char rawpath[PATH_MAX], fullpath[PATH_MAX];
char devpath[PATH_MAX]; char devpath[PATH_MAX];
int ret; int ret;
int online_flag = ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE; boolean_t is_dm = B_FALSE;
boolean_t is_sd = B_FALSE; boolean_t is_sd = B_FALSE;
boolean_t is_mpath_wholedisk = B_FALSE;
uint_t c; uint_t c;
vdev_stat_t *vs; vdev_stat_t *vs;
char **lines = NULL;
int lines_cnt = 0;
if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0) if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0)
return; return;
@ -222,82 +207,19 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
} }
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_PHYS_PATH, &physpath); (void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_PHYS_PATH, &physpath);
update_vdev_config_dev_sysfs_path(vdev, path,
ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH, (void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
&enc_sysfs_path); &enc_sysfs_path);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk); (void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_OFFLINE, &offline); (void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_OFFLINE, &offline);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_FAULTED, &faulted);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &guid); (void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &guid);
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_IS_SPARE, &is_spare);
/* if (offline)
* Special case: return; /* don't intervene if it was taken offline */
*
* We've seen times where a disk won't have a ZPOOL_CONFIG_PHYS_PATH
* entry in their config. For example, on this force-faulted disk:
*
* children[0]:
* type: 'disk'
* id: 0
* guid: 14309659774640089719
* path: '/dev/disk/by-vdev/L28'
* whole_disk: 0
* DTL: 654
* create_txg: 4
* com.delphix:vdev_zap_leaf: 1161
* faulted: 1
* aux_state: 'external'
* children[1]:
* type: 'disk'
* id: 1
* guid: 16002508084177980912
* path: '/dev/disk/by-vdev/L29'
* devid: 'dm-uuid-mpath-35000c500a61d68a3'
* phys_path: 'L29'
* vdev_enc_sysfs_path: '/sys/class/enclosure/0:0:1:0/SLOT 30 32'
* whole_disk: 0
* DTL: 1028
* create_txg: 4
* com.delphix:vdev_zap_leaf: 131
*
* If the disk's path is a /dev/disk/by-vdev/ path, then we can infer
* the ZPOOL_CONFIG_PHYS_PATH from the by-vdev disk name.
*/
if (physpath == NULL && path != NULL) {
/* If path begins with "/dev/disk/by-vdev/" ... */
if (strncmp(path, DEV_BYVDEV_PATH,
strlen(DEV_BYVDEV_PATH)) == 0) {
/* Set physpath to the char after "/dev/disk/by-vdev" */
physpath = &path[strlen(DEV_BYVDEV_PATH)];
}
}
/* is_dm = zfs_dev_is_dm(path);
* We don't want to autoreplace offlined disks. However, we do want to
* replace force-faulted disks (`zpool offline -f`). Force-faulted
* disks have both offline=1 and faulted=1 in the nvlist.
*/
if (offline && !faulted) {
zed_log_msg(LOG_INFO, "%s: %s is offline, skip autoreplace",
__func__, path);
return;
}
is_mpath_wholedisk = is_mpath_whole_disk(path);
zed_log_msg(LOG_INFO, "zfs_process_add: pool '%s' vdev '%s', phys '%s'" zed_log_msg(LOG_INFO, "zfs_process_add: pool '%s' vdev '%s', phys '%s'"
" %s blank disk, %s mpath blank disk, %s labeled, enc sysfs '%s', " " wholedisk %d, %s dm (guid %llu)", zpool_get_name(zhp), path,
"(guid %llu)", physpath ? physpath : "NULL", wholedisk, is_dm ? "is" : "not",
zpool_get_name(zhp), path,
physpath ? physpath : "NULL",
wholedisk ? "is" : "not",
is_mpath_wholedisk? "is" : "not",
labeled ? "is" : "not",
enc_sysfs_path,
(long long unsigned int)guid); (long long unsigned int)guid);
/* /*
@ -324,18 +246,15 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
} }
} }
if (is_spare)
online_flag |= ZFS_ONLINE_SPARE;
/* /*
* Attempt to online the device. * Attempt to online the device.
*/ */
if (zpool_vdev_online(zhp, fullpath, online_flag, &newstate) == 0 && if (zpool_vdev_online(zhp, fullpath,
ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE, &newstate) == 0 &&
(newstate == VDEV_STATE_HEALTHY || (newstate == VDEV_STATE_HEALTHY ||
newstate == VDEV_STATE_DEGRADED)) { newstate == VDEV_STATE_DEGRADED)) {
zed_log_msg(LOG_INFO, zed_log_msg(LOG_INFO, " zpool_vdev_online: vdev %s is %s",
" zpool_vdev_online: vdev '%s' ('%s') is " fullpath, (newstate == VDEV_STATE_HEALTHY) ?
"%s", fullpath, physpath, (newstate == VDEV_STATE_HEALTHY) ?
"HEALTHY" : "DEGRADED"); "HEALTHY" : "DEGRADED");
return; return;
} }
@ -352,12 +271,11 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
* vdev online to trigger a FMA fault by posting an ereport. * vdev online to trigger a FMA fault by posting an ereport.
*/ */
if (!zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOREPLACE, NULL) || if (!zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOREPLACE, NULL) ||
!(wholedisk || is_mpath_wholedisk) || (physpath == NULL)) { !(wholedisk || is_dm) || (physpath == NULL)) {
(void) zpool_vdev_online(zhp, fullpath, ZFS_ONLINE_FORCEFAULT, (void) zpool_vdev_online(zhp, fullpath, ZFS_ONLINE_FORCEFAULT,
&newstate); &newstate);
zed_log_msg(LOG_INFO, "Pool's autoreplace is not enabled or " zed_log_msg(LOG_INFO, "Pool's autoreplace is not enabled or "
"not a blank disk for '%s' ('%s')", fullpath, "not a whole disk for '%s'", fullpath);
physpath);
return; return;
} }
@ -369,7 +287,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
(void) snprintf(rawpath, sizeof (rawpath), "%s%s", (void) snprintf(rawpath, sizeof (rawpath), "%s%s",
is_sd ? DEV_BYVDEV_PATH : DEV_BYPATH_PATH, physpath); is_sd ? DEV_BYVDEV_PATH : DEV_BYPATH_PATH, physpath);
if (realpath(rawpath, devpath) == NULL && !is_mpath_wholedisk) { if (realpath(rawpath, devpath) == NULL && !is_dm) {
zed_log_msg(LOG_INFO, " realpath: %s failed (%s)", zed_log_msg(LOG_INFO, " realpath: %s failed (%s)",
rawpath, strerror(errno)); rawpath, strerror(errno));
@ -385,31 +303,13 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
if ((vs->vs_state != VDEV_STATE_DEGRADED) && if ((vs->vs_state != VDEV_STATE_DEGRADED) &&
(vs->vs_state != VDEV_STATE_FAULTED) && (vs->vs_state != VDEV_STATE_FAULTED) &&
(vs->vs_state != VDEV_STATE_CANT_OPEN)) { (vs->vs_state != VDEV_STATE_CANT_OPEN)) {
zed_log_msg(LOG_INFO, " not autoreplacing since disk isn't in "
"a bad state (currently %d)", vs->vs_state);
return; return;
} }
nvlist_lookup_string(vdev, "new_devid", &new_devid); nvlist_lookup_string(vdev, "new_devid", &new_devid);
if (is_mpath_wholedisk) { if (is_dm) {
/* Don't label device mapper or multipath disks. */ /* Don't label device mapper or multipath disks. */
zed_log_msg(LOG_INFO,
" it's a multipath wholedisk, don't label");
if (zpool_prepare_disk(zhp, vdev, "autoreplace", &lines,
&lines_cnt) != 0) {
zed_log_msg(LOG_INFO,
" zpool_prepare_disk: could not "
"prepare '%s' (%s)", fullpath,
libzfs_error_description(g_zfshdl));
if (lines_cnt > 0) {
zed_log_msg(LOG_INFO,
" zfs_prepare_disk output:");
lines_to_zed_log_msg(lines, lines_cnt);
}
libzfs_free_str_array(lines, lines_cnt);
return;
}
} else if (!labeled) { } else if (!labeled) {
/* /*
* we're auto-replacing a raw disk, so label it first * we're auto-replacing a raw disk, so label it first
@ -432,18 +332,10 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
* If this is a request to label a whole disk, then attempt to * If this is a request to label a whole disk, then attempt to
* write out the label. * write out the label.
*/ */
if (zpool_prepare_and_label_disk(g_zfshdl, zhp, leafname, if (zpool_label_disk(g_zfshdl, zhp, leafname) != 0) {
vdev, "autoreplace", &lines, &lines_cnt) != 0) { zed_log_msg(LOG_INFO, " zpool_label_disk: could not "
zed_log_msg(LOG_INFO,
" zpool_prepare_and_label_disk: could not "
"label '%s' (%s)", leafname, "label '%s' (%s)", leafname,
libzfs_error_description(g_zfshdl)); libzfs_error_description(g_zfshdl));
if (lines_cnt > 0) {
zed_log_msg(LOG_INFO,
" zfs_prepare_disk output:");
lines_to_zed_log_msg(lines, lines_cnt);
}
libzfs_free_str_array(lines, lines_cnt);
(void) zpool_vdev_online(zhp, fullpath, (void) zpool_vdev_online(zhp, fullpath,
ZFS_ONLINE_FORCEFAULT, &newstate); ZFS_ONLINE_FORCEFAULT, &newstate);
@ -498,8 +390,6 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
DEV_BYID_PATH, new_devid); DEV_BYID_PATH, new_devid);
} }
libzfs_free_str_array(lines, lines_cnt);
/* /*
* Construct the root vdev to pass to zpool_vdev_attach(). While adding * Construct the root vdev to pass to zpool_vdev_attach(). While adding
* the entire vdev structure is harmless, we construct a reduced set of * the entire vdev structure is harmless, we construct a reduced set of
@ -573,9 +463,7 @@ typedef struct dev_data {
boolean_t dd_islabeled; boolean_t dd_islabeled;
uint64_t dd_pool_guid; uint64_t dd_pool_guid;
uint64_t dd_vdev_guid; uint64_t dd_vdev_guid;
uint64_t dd_new_vdev_guid;
const char *dd_new_devid; const char *dd_new_devid;
uint64_t dd_num_spares;
} dev_data_t; } dev_data_t;
static void static void
@ -585,8 +473,6 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
char *path = NULL; char *path = NULL;
uint_t c, children; uint_t c, children;
nvlist_t **child; nvlist_t **child;
uint64_t guid = 0;
uint64_t isspare = 0;
/* /*
* First iterate over any children. * First iterate over any children.
@ -612,16 +498,19 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
} }
/* once a vdev was matched and processed there is nothing left to do */ /* once a vdev was matched and processed there is nothing left to do */
if (dp->dd_found && dp->dd_num_spares == 0) if (dp->dd_found)
return; return;
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &guid);
/* /*
* Match by GUID if available otherwise fallback to devid or physical * Match by GUID if available otherwise fallback to devid or physical
*/ */
if (dp->dd_vdev_guid != 0) { if (dp->dd_vdev_guid != 0) {
if (guid != dp->dd_vdev_guid) uint64_t guid;
if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
&guid) != 0 || guid != dp->dd_vdev_guid) {
return; return;
}
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched on %llu", guid); zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched on %llu", guid);
dp->dd_found = B_TRUE; dp->dd_found = B_TRUE;
@ -631,23 +520,10 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
* illumos, substring matching is not required to accommodate * illumos, substring matching is not required to accommodate
* the partition suffix. An exact match will be present in * the partition suffix. An exact match will be present in
* the dp->dd_compare value. * the dp->dd_compare value.
* If the attached disk already contains a vdev GUID, it means
* the disk is not clean. In such a scenario, the physical path
* would be a match that makes the disk faulted when trying to
* online it. So, we would only want to proceed if either GUID
* matches with the last attached disk or the disk is in clean
* state.
*/ */
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 || if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
strcmp(dp->dd_compare, path) != 0) { strcmp(dp->dd_compare, path) != 0)
return; return;
}
if (dp->dd_new_vdev_guid != 0 && dp->dd_new_vdev_guid != guid) {
zed_log_msg(LOG_INFO, " %s: no match (GUID:%llu"
" != vdev GUID:%llu)", __func__,
dp->dd_new_vdev_guid, guid);
return;
}
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched %s on %s", zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched %s on %s",
dp->dd_prop, path); dp->dd_prop, path);
@ -660,10 +536,6 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
} }
} }
if (dp->dd_found == B_TRUE && nvlist_lookup_uint64(nvl,
ZPOOL_CONFIG_IS_SPARE, &isspare) == 0 && isspare)
dp->dd_num_spares++;
(dp->dd_func)(zhp, nvl, dp->dd_islabeled); (dp->dd_func)(zhp, nvl, dp->dd_islabeled);
} }
@ -699,8 +571,6 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
ZPOOL_CONFIG_VDEV_TREE, &nvl); ZPOOL_CONFIG_VDEV_TREE, &nvl);
zfs_iter_vdev(zhp, nvl, data); zfs_iter_vdev(zhp, nvl, data);
} }
} else {
zed_log_msg(LOG_INFO, "%s: no config\n", __func__);
} }
/* /*
@ -724,9 +594,7 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
} }
zpool_close(zhp); zpool_close(zhp);
return (dp->dd_found); /* cease iteration after a match */
/* cease iteration after a match */
return (dp->dd_found && dp->dd_num_spares == 0);
} }
/* /*
@ -735,7 +603,7 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
*/ */
static boolean_t static boolean_t
devphys_iter(const char *physical, const char *devid, zfs_process_func_t func, devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
boolean_t is_slice, uint64_t new_vdev_guid) boolean_t is_slice)
{ {
dev_data_t data = { 0 }; dev_data_t data = { 0 };
@ -745,73 +613,6 @@ devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
data.dd_found = B_FALSE; data.dd_found = B_FALSE;
data.dd_islabeled = is_slice; data.dd_islabeled = is_slice;
data.dd_new_devid = devid; /* used by auto replace code */ data.dd_new_devid = devid; /* used by auto replace code */
data.dd_new_vdev_guid = new_vdev_guid;
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
return (data.dd_found);
}
/*
* Given a device identifier, find any vdevs with a matching by-vdev
* path. Normally we shouldn't need this as the comparison would be
* made earlier in the devphys_iter(). For example, if we were replacing
* /dev/disk/by-vdev/L28, normally devphys_iter() would match the
* ZPOOL_CONFIG_PHYS_PATH of "L28" from the old disk config to "L28"
* of the new disk config. However, we've seen cases where
* ZPOOL_CONFIG_PHYS_PATH was not in the config for the old disk. Here's
* an example of a real 2-disk mirror pool where one disk was force
* faulted:
*
* com.delphix:vdev_zap_top: 129
* children[0]:
* type: 'disk'
* id: 0
* guid: 14309659774640089719
* path: '/dev/disk/by-vdev/L28'
* whole_disk: 0
* DTL: 654
* create_txg: 4
* com.delphix:vdev_zap_leaf: 1161
* faulted: 1
* aux_state: 'external'
* children[1]:
* type: 'disk'
* id: 1
* guid: 16002508084177980912
* path: '/dev/disk/by-vdev/L29'
* devid: 'dm-uuid-mpath-35000c500a61d68a3'
* phys_path: 'L29'
* vdev_enc_sysfs_path: '/sys/class/enclosure/0:0:1:0/SLOT 30 32'
* whole_disk: 0
* DTL: 1028
* create_txg: 4
* com.delphix:vdev_zap_leaf: 131
*
* So in the case above, the only thing we could compare is the path.
*
* We can do this because we assume by-vdev paths are authoritative as physical
* paths. We could not assume this for normal paths like /dev/sda since the
* physical location /dev/sda points to could change over time.
*/
static boolean_t
by_vdev_path_iter(const char *by_vdev_path, const char *devid,
zfs_process_func_t func, boolean_t is_slice)
{
dev_data_t data = { 0 };
data.dd_compare = by_vdev_path;
data.dd_func = func;
data.dd_prop = ZPOOL_CONFIG_PATH;
data.dd_found = B_FALSE;
data.dd_islabeled = is_slice;
data.dd_new_devid = devid;
if (strncmp(by_vdev_path, DEV_BYVDEV_PATH,
strlen(DEV_BYVDEV_PATH)) != 0) {
/* by_vdev_path doesn't start with "/dev/disk/by-vdev/" */
return (B_FALSE);
}
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data); (void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
@ -839,27 +640,6 @@ devid_iter(const char *devid, zfs_process_func_t func, boolean_t is_slice)
return (data.dd_found); return (data.dd_found);
} }
/*
* Given a device guid, find any vdevs with a matching guid.
*/
static boolean_t
guid_iter(uint64_t pool_guid, uint64_t vdev_guid, const char *devid,
zfs_process_func_t func, boolean_t is_slice)
{
dev_data_t data = { 0 };
data.dd_func = func;
data.dd_found = B_FALSE;
data.dd_pool_guid = pool_guid;
data.dd_vdev_guid = vdev_guid;
data.dd_islabeled = is_slice;
data.dd_new_devid = devid;
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
return (data.dd_found);
}
/* /*
* Handle a EC_DEV_ADD.ESC_DISK event. * Handle a EC_DEV_ADD.ESC_DISK event.
* *
@ -882,21 +662,16 @@ guid_iter(uint64_t pool_guid, uint64_t vdev_guid, const char *devid,
static int static int
zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi) zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
{ {
char *devpath = NULL, *devid = NULL; char *devpath = NULL, *devid;
uint64_t pool_guid = 0, vdev_guid = 0;
boolean_t is_slice; boolean_t is_slice;
/* /*
* Expecting a devid string and an optional physical location and guid * Expecting a devid string and an optional physical location
*/ */
if (nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid) != 0) { if (nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid) != 0)
zed_log_msg(LOG_INFO, "%s: no dev identifier\n", __func__);
return (-1); return (-1);
}
(void) nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devpath); (void) nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devpath);
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
(void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid);
is_slice = (nvlist_lookup_boolean(nvl, DEV_IS_PART) == 0); is_slice = (nvlist_lookup_boolean(nvl, DEV_IS_PART) == 0);
@ -907,28 +682,12 @@ zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
* Iterate over all vdevs looking for a match in the following order: * Iterate over all vdevs looking for a match in the following order:
* 1. ZPOOL_CONFIG_DEVID (identifies the unique disk) * 1. ZPOOL_CONFIG_DEVID (identifies the unique disk)
* 2. ZPOOL_CONFIG_PHYS_PATH (identifies disk physical location). * 2. ZPOOL_CONFIG_PHYS_PATH (identifies disk physical location).
* 3. ZPOOL_CONFIG_GUID (identifies unique vdev). *
* 4. ZPOOL_CONFIG_PATH for /dev/disk/by-vdev devices only (since * For disks, we only want to pay attention to vdevs marked as whole
* by-vdev paths represent physical paths). * disks or are a multipath device.
*/ */
if (devid_iter(devid, zfs_process_add, is_slice)) if (!devid_iter(devid, zfs_process_add, is_slice) && devpath != NULL)
return (0); (void) devphys_iter(devpath, devid, zfs_process_add, is_slice);
if (devpath != NULL && devphys_iter(devpath, devid, zfs_process_add,
is_slice, vdev_guid))
return (0);
if (vdev_guid != 0)
(void) guid_iter(pool_guid, vdev_guid, devid, zfs_process_add,
is_slice);
if (devpath != NULL) {
/* Can we match a /dev/disk/by-vdev/ path? */
char by_vdev_path[MAXPATHLEN];
snprintf(by_vdev_path, sizeof (by_vdev_path),
"/dev/disk/by-vdev/%s", devpath);
if (by_vdev_path_iter(by_vdev_path, devid, zfs_process_add,
is_slice))
return (0);
}
return (0); return (0);
} }
@ -960,96 +719,21 @@ zfs_deliver_check(nvlist_t *nvl)
return (0); return (0);
} }
/*
* Given a path to a vdev, lookup the vdev's physical size from its
* config nvlist.
*
* Returns the vdev's physical size in bytes on success, 0 on error.
*/
static uint64_t
vdev_size_from_config(zpool_handle_t *zhp, const char *vdev_path)
{
nvlist_t *nvl = NULL;
boolean_t avail_spare, l2cache, log;
vdev_stat_t *vs = NULL;
uint_t c;
nvl = zpool_find_vdev(zhp, vdev_path, &avail_spare, &l2cache, &log);
if (!nvl)
return (0);
verify(nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) == 0);
if (!vs) {
zed_log_msg(LOG_INFO, "%s: no nvlist for '%s'", __func__,
vdev_path);
return (0);
}
return (vs->vs_pspace);
}
/*
* Given a path to a vdev, lookup if the vdev is a "whole disk" in the
* config nvlist. "whole disk" means that ZFS was passed a whole disk
* at pool creation time, which it partitioned up and has full control over.
* Thus a partition with wholedisk=1 set tells us that zfs created the
* partition at creation time. A partition without whole disk set would have
* been created by externally (like with fdisk) and passed to ZFS.
*
* Returns the whole disk value (either 0 or 1).
*/
static uint64_t
vdev_whole_disk_from_config(zpool_handle_t *zhp, const char *vdev_path)
{
nvlist_t *nvl = NULL;
boolean_t avail_spare, l2cache, log;
uint64_t wholedisk = 0;
nvl = zpool_find_vdev(zhp, vdev_path, &avail_spare, &l2cache, &log);
if (!nvl)
return (0);
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
return (wholedisk);
}
/*
* If the device size grew more than 1% then return true.
*/
#define DEVICE_GREW(oldsize, newsize) \
((newsize > oldsize) && \
((newsize / (newsize - oldsize)) <= 100))
static int static int
zfsdle_vdev_online(zpool_handle_t *zhp, void *data) zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
{ {
char *devname = data;
boolean_t avail_spare, l2cache; boolean_t avail_spare, l2cache;
nvlist_t *udev_nvl = data;
nvlist_t *tgt; nvlist_t *tgt;
int error; int error;
char *tmp_devname, devname[MAXPATHLEN] = "";
uint64_t guid;
if (nvlist_lookup_uint64(udev_nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
sprintf(devname, "%llu", (u_longlong_t)guid);
} else if (nvlist_lookup_string(udev_nvl, DEV_PHYS_PATH,
&tmp_devname) == 0) {
strlcpy(devname, tmp_devname, MAXPATHLEN);
zfs_append_partition(devname, MAXPATHLEN);
} else {
zed_log_msg(LOG_INFO, "%s: no guid or physpath", __func__);
}
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: searching for '%s' in '%s'", zed_log_msg(LOG_INFO, "zfsdle_vdev_online: searching for '%s' in '%s'",
devname, zpool_get_name(zhp)); devname, zpool_get_name(zhp));
if ((tgt = zpool_find_vdev_by_physpath(zhp, devname, if ((tgt = zpool_find_vdev_by_physpath(zhp, devname,
&avail_spare, &l2cache, NULL)) != NULL) { &avail_spare, &l2cache, NULL)) != NULL) {
char *path, fullpath[MAXPATHLEN]; char *path, fullpath[MAXPATHLEN];
uint64_t wholedisk = 0; uint64_t wholedisk;
error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path); error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path);
if (error) { if (error) {
@ -1057,8 +741,10 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
return (0); return (0);
} }
(void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK, error = nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
&wholedisk); &wholedisk);
if (error)
wholedisk = 0;
if (wholedisk) { if (wholedisk) {
path = strrchr(path, '/'); path = strrchr(path, '/');
@ -1092,75 +778,12 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
vdev_state_t newstate; vdev_state_t newstate;
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) { if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
/* error = zpool_vdev_online(zhp, fullpath, 0,
* If this disk size has not changed, then &newstate);
* there's no need to do an autoexpand. To zed_log_msg(LOG_INFO, "zfsdle_vdev_online: "
* check we look at the disk's size in its "setting device '%s' to ONLINE state "
* config, and compare it to the disk size "in pool '%s': %d", fullpath,
* that udev is reporting. zpool_get_name(zhp), error);
*/
uint64_t udev_size = 0, conf_size = 0,
wholedisk = 0, udev_parent_size = 0;
/*
* Get the size of our disk that udev is
* reporting.
*/
if (nvlist_lookup_uint64(udev_nvl, DEV_SIZE,
&udev_size) != 0) {
udev_size = 0;
}
/*
* Get the size of our disk's parent device
* from udev (where sda1's parent is sda).
*/
if (nvlist_lookup_uint64(udev_nvl,
DEV_PARENT_SIZE, &udev_parent_size) != 0) {
udev_parent_size = 0;
}
conf_size = vdev_size_from_config(zhp,
fullpath);
wholedisk = vdev_whole_disk_from_config(zhp,
fullpath);
/*
* Only attempt an autoexpand if the vdev size
* changed. There are two different cases
* to consider.
*
* 1. wholedisk=1
* If you do a 'zpool create' on a whole disk
* (like /dev/sda), then zfs will create
* partitions on the disk (like /dev/sda1). In
* that case, wholedisk=1 will be set in the
* partition's nvlist config. So zed will need
* to see if your parent device (/dev/sda)
* expanded in size, and if so, then attempt
* the autoexpand.
*
* 2. wholedisk=0
* If you do a 'zpool create' on an existing
* partition, or a device that doesn't allow
* partitions, then wholedisk=0, and you will
* simply need to check if the device itself
* expanded in size.
*/
if (DEVICE_GREW(conf_size, udev_size) ||
(wholedisk && DEVICE_GREW(conf_size,
udev_parent_size))) {
error = zpool_vdev_online(zhp, fullpath,
0, &newstate);
zed_log_msg(LOG_INFO,
"%s: autoexpanding '%s' from %llu"
" to %llu bytes in pool '%s': %d",
__func__, fullpath, conf_size,
MAX(udev_size, udev_parent_size),
zpool_get_name(zhp), error);
}
} }
} }
zpool_close(zhp); zpool_close(zhp);
@ -1188,11 +811,10 @@ zfs_deliver_dle(nvlist_t *nvl)
strlcpy(name, devname, MAXPATHLEN); strlcpy(name, devname, MAXPATHLEN);
zfs_append_partition(name, MAXPATHLEN); zfs_append_partition(name, MAXPATHLEN);
} else { } else {
sprintf(name, "unknown");
zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath"); zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath");
} }
if (zpool_iter(g_zfshdl, zfsdle_vdev_online, nvl) != 1) { if (zpool_iter(g_zfshdl, zfsdle_vdev_online, name) != 1) {
zed_log_msg(LOG_INFO, "zfs_deliver_dle: device '%s' not " zed_log_msg(LOG_INFO, "zfs_deliver_dle: device '%s' not "
"found", name); "found", name);
return (1); return (1);
@ -1278,7 +900,7 @@ zfs_enum_pools(void *arg)
* For now, each agent has its own libzfs instance * For now, each agent has its own libzfs instance
*/ */
int int
zfs_slm_init(void) zfs_slm_init()
{ {
if ((g_zfshdl = libzfs_init()) == NULL) if ((g_zfshdl = libzfs_init()) == NULL)
return (-1); return (-1);
@ -1304,7 +926,7 @@ zfs_slm_init(void)
} }
void void
zfs_slm_fini(void) zfs_slm_fini()
{ {
unavailpool_t *pool; unavailpool_t *pool;
pendingdev_t *device; pendingdev_t *device;

View File

@ -40,7 +40,6 @@
#include <sys/fm/fs/zfs.h> #include <sys/fm/fs/zfs.h>
#include <libzfs.h> #include <libzfs.h>
#include <string.h> #include <string.h>
#include <libgen.h>
#include "zfs_agents.h" #include "zfs_agents.h"
#include "fmd_api.h" #include "fmd_api.h"
@ -75,8 +74,6 @@ typedef struct find_cbdata {
uint64_t cb_guid; uint64_t cb_guid;
zpool_handle_t *cb_zhp; zpool_handle_t *cb_zhp;
nvlist_t *cb_vdev; nvlist_t *cb_vdev;
uint64_t cb_vdev_guid;
uint64_t cb_num_spares;
} find_cbdata_t; } find_cbdata_t;
static int static int
@ -142,64 +139,6 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
return (NULL); return (NULL);
} }
static int
remove_spares(zpool_handle_t *zhp, void *data)
{
nvlist_t *config, *nvroot;
nvlist_t **spares;
uint_t nspares;
char *devname;
find_cbdata_t *cbp = data;
uint64_t spareguid = 0;
vdev_stat_t *vs;
unsigned int c;
config = zpool_get_config(zhp, NULL);
if (nvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE, &nvroot) != 0) {
zpool_close(zhp);
return (0);
}
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
&spares, &nspares) != 0) {
zpool_close(zhp);
return (0);
}
for (int i = 0; i < nspares; i++) {
if (nvlist_lookup_uint64(spares[i], ZPOOL_CONFIG_GUID,
&spareguid) == 0 && spareguid == cbp->cb_vdev_guid) {
devname = zpool_vdev_name(NULL, zhp, spares[i],
B_FALSE);
nvlist_lookup_uint64_array(spares[i],
ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c);
if (vs->vs_state != VDEV_STATE_REMOVED &&
zpool_vdev_remove_wanted(zhp, devname) == 0)
cbp->cb_num_spares++;
break;
}
}
zpool_close(zhp);
return (0);
}
/*
* Given a vdev guid, find and remove all spares associated with it.
*/
static int
find_and_remove_spares(libzfs_handle_t *zhdl, uint64_t vdev_guid)
{
find_cbdata_t cb;
cb.cb_num_spares = 0;
cb.cb_vdev_guid = vdev_guid;
zpool_iter(zhdl, remove_spares, &cb);
return (cb.cb_num_spares);
}
/* /*
* Given a (pool, vdev) GUID pair, find the matching pool and vdev. * Given a (pool, vdev) GUID pair, find the matching pool and vdev.
*/ */
@ -375,8 +314,6 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
libzfs_handle_t *zhdl = zdp->zrd_hdl; libzfs_handle_t *zhdl = zdp->zrd_hdl;
boolean_t fault_device, degrade_device; boolean_t fault_device, degrade_device;
boolean_t is_repair; boolean_t is_repair;
boolean_t l2arc = B_FALSE;
boolean_t spare = B_FALSE;
char *scheme; char *scheme;
nvlist_t *vdev = NULL; nvlist_t *vdev = NULL;
char *uuid; char *uuid;
@ -385,8 +322,6 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
boolean_t is_disk; boolean_t is_disk;
vdev_aux_t aux; vdev_aux_t aux;
uint64_t state = 0; uint64_t state = 0;
vdev_stat_t *vs;
unsigned int c;
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class); fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
@ -403,31 +338,10 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
char *devtype; char *devtype;
char *devname; char *devname;
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
&devtype) == 0) {
if (strcmp(devtype, VDEV_TYPE_SPARE) == 0)
spare = B_TRUE;
else if (strcmp(devtype, VDEV_TYPE_L2CACHE) == 0)
l2arc = B_TRUE;
}
if (nvlist_lookup_uint64(nvl,
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
return;
if (vdev_guid == 0) {
fmd_hdl_debug(hdl, "Got a zero GUID");
return;
}
if (spare) {
int nspares = find_and_remove_spares(zhdl, vdev_guid);
fmd_hdl_debug(hdl, "%d spares removed", nspares);
return;
}
if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID, if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
&pool_guid) != 0) &pool_guid) != 0 ||
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID,
&vdev_guid) != 0)
return; return;
if ((zhp = find_by_guid(zhdl, pool_guid, vdev_guid, if ((zhp = find_by_guid(zhdl, pool_guid, vdev_guid,
@ -436,30 +350,13 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE); devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE);
nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS, /* Can't replace l2arc with a spare: offline the device */
(uint64_t **)&vs, &c); if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
&devtype) == 0 && strcmp(devtype, VDEV_TYPE_L2CACHE) == 0) {
/* fmd_hdl_debug(hdl, "zpool_vdev_offline '%s'", devname);
* If state removed is requested for already removed vdev, zpool_vdev_offline(zhp, devname, B_TRUE);
* its a loopback event from spa_async_remove(). Just } else if (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
* ignore it. replace_with_spare(hdl, zhp, vdev) == B_FALSE) {
*/
if (vs->vs_state == VDEV_STATE_REMOVED &&
state == VDEV_STATE_REMOVED)
return;
/* Remove the vdev since device is unplugged */
int remove_status = 0;
if (l2arc || (strcmp(class, "resource.fs.zfs.removed") == 0)) {
remove_status = zpool_vdev_remove_wanted(zhp, devname);
fmd_hdl_debug(hdl, "zpool_vdev_remove_wanted '%s'"
", err:%d", devname, libzfs_errno(zhdl));
}
/* Replace the vdev with a spare if its not a l2arc */
if (!l2arc && !remove_status &&
(!fmd_prop_get_int32(hdl, "spare_on_remove") ||
replace_with_spare(hdl, zhp, vdev) == B_FALSE)) {
/* Could not handle with spare */ /* Could not handle with spare */
fmd_hdl_debug(hdl, "no spare for '%s'", devname); fmd_hdl_debug(hdl, "no spare for '%s'", devname);
} }

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).
@ -291,7 +291,7 @@ idle:
rv = zed_event_service(&zcp); rv = zed_event_service(&zcp);
/* ENODEV: When kernel module is unloaded (osx) */ /* ENODEV: When kernel module is unloaded (osx) */
if (rv != 0) if (rv == ENODEV)
break; break;
} }

View File

@ -1,6 +1,5 @@
include $(top_srcdir)/config/Rules.am include $(top_srcdir)/config/Rules.am
include $(top_srcdir)/config/Substfiles.am include $(top_srcdir)/config/Substfiles.am
include $(top_srcdir)/config/Shellcheck.am
EXTRA_DIST += README EXTRA_DIST += README
@ -21,7 +20,6 @@ dist_zedexec_SCRIPTS = \
scrub_finish-notify.sh \ scrub_finish-notify.sh \
statechange-led.sh \ statechange-led.sh \
statechange-notify.sh \ statechange-notify.sh \
statechange-slot_off.sh \
vdev_clear-led.sh \ vdev_clear-led.sh \
vdev_attach-led.sh \ vdev_attach-led.sh \
pool_import-led.sh \ pool_import-led.sh \
@ -40,7 +38,6 @@ zedconfdefaults = \
scrub_finish-notify.sh \ scrub_finish-notify.sh \
statechange-led.sh \ statechange-led.sh \
statechange-notify.sh \ statechange-notify.sh \
statechange-slot_off.sh \
vdev_clear-led.sh \ vdev_clear-led.sh \
vdev_attach-led.sh \ vdev_attach-led.sh \
pool_import-led.sh \ pool_import-led.sh \
@ -54,6 +51,3 @@ install-data-hook:
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \ ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
done done
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc" chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
# False positive: 1>&"${ZED_FLOCK_FD}" looks suspiciously similar to a >&filename bash extension
CHECKBASHISMS_IGNORE = -e 'should be >word 2>&1' -e '&"$${ZED_FLOCK_FD}"'

View File

@ -12,11 +12,15 @@
zed_exit_if_ignoring_this_event zed_exit_if_ignoring_this_event
zed_lock "${ZED_DEBUG_LOG}" lockfile="$(basename -- "${ZED_DEBUG_LOG}").lock"
{
printenv | sort
echo
} 1>&"${ZED_FLOCK_FD}"
zed_unlock "${ZED_DEBUG_LOG}"
umask 077
zed_lock "${lockfile}"
exec >> "${ZED_DEBUG_LOG}"
printenv | sort
echo
exec >&-
zed_unlock "${lockfile}"
exit 0 exit 0

View File

@ -21,7 +21,7 @@ if [ "${ZED_SYSLOG_DISPLAY_GUIDS}" = "1" ]; then
[ -n "${ZEVENT_VDEV_GUID}" ] && msg="${msg} vdev_guid=${ZEVENT_VDEV_GUID}" [ -n "${ZEVENT_VDEV_GUID}" ] && msg="${msg} vdev_guid=${ZEVENT_VDEV_GUID}"
else else
[ -n "${ZEVENT_POOL}" ] && msg="${msg} pool='${ZEVENT_POOL}'" [ -n "${ZEVENT_POOL}" ] && msg="${msg} pool='${ZEVENT_POOL}'"
[ -n "${ZEVENT_VDEV_PATH}" ] && msg="${msg} vdev=${ZEVENT_VDEV_PATH##*/}" [ -n "${ZEVENT_VDEV_PATH}" ] && msg="${msg} vdev=$(basename "${ZEVENT_VDEV_PATH}")"
fi fi
# log pool state if state is anything other than 'ACTIVE' # log pool state if state is anything other than 'ACTIVE'
@ -42,7 +42,6 @@ fi
msg="${msg} delay=$((ZEVENT_ZIO_DELAY / 1000000))ms" msg="${msg} delay=$((ZEVENT_ZIO_DELAY / 1000000))ms"
# list the bookmark data together # list the bookmark data together
# shellcheck disable=SC2153
[ -n "${ZEVENT_ZIO_OBJSET}" ] && \ [ -n "${ZEVENT_ZIO_OBJSET}" ] && \
msg="${msg} bookmark=${ZEVENT_ZIO_OBJSET}:${ZEVENT_ZIO_OBJECT}:${ZEVENT_ZIO_LEVEL}:${ZEVENT_ZIO_BLKID}" msg="${msg} bookmark=${ZEVENT_ZIO_OBJSET}:${ZEVENT_ZIO_OBJECT}:${ZEVENT_ZIO_LEVEL}:${ZEVENT_ZIO_BLKID}"

View File

@ -25,7 +25,7 @@ zed_rate_limit "${rate_limit_tag}" || exit 3
umask 077 umask 077
note_subject="ZFS ${ZEVENT_SUBCLASS} error for ${ZEVENT_POOL} on $(hostname)" note_subject="ZFS ${ZEVENT_SUBCLASS} error for ${ZEVENT_POOL} on $(hostname)"
note_pathname="$(mktemp)" note_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$"
{ {
echo "ZFS has detected a data error:" echo "ZFS has detected a data error:"
echo echo

View File

@ -23,7 +23,7 @@
# Rate-limit the notification based in part on the filename. # Rate-limit the notification based in part on the filename.
# #
rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};${0##*/}" rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};$(basename -- "$0")"
rate_limit_interval="${ZED_NOTIFY_INTERVAL_SECS}" rate_limit_interval="${ZED_NOTIFY_INTERVAL_SECS}"
zed_rate_limit "${rate_limit_tag}" "${rate_limit_interval}" || exit 3 zed_rate_limit "${rate_limit_tag}" "${rate_limit_interval}" || exit 3
@ -31,7 +31,7 @@ umask 077
pool_str="${ZEVENT_POOL:+" for ${ZEVENT_POOL}"}" pool_str="${ZEVENT_POOL:+" for ${ZEVENT_POOL}"}"
host_str=" on $(hostname)" host_str=" on $(hostname)"
note_subject="ZFS ${ZEVENT_SUBCLASS} event${pool_str}${host_str}" note_subject="ZFS ${ZEVENT_SUBCLASS} event${pool_str}${host_str}"
note_pathname="$(mktemp)" note_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$"
{ {
echo "ZFS has posted the following event:" echo "ZFS has posted the following event:"
echo echo

View File

@ -3,8 +3,9 @@
# Track changes to enumerated pools for use in early-boot # Track changes to enumerated pools for use in early-boot
set -ef set -ef
FSLIST="@sysconfdir@/zfs/zfs-list.cache/${ZEVENT_POOL}" FSLIST_DIR="@sysconfdir@/zfs/zfs-list.cache"
FSLIST_TMP="@runstatedir@/zfs-list.cache@${ZEVENT_POOL}" FSLIST_TMP="@runstatedir@/zfs-list.cache.new"
FSLIST="${FSLIST_DIR}/${ZEVENT_POOL}"
# If the pool specific cache file is not writeable, abort # If the pool specific cache file is not writeable, abort
[ -w "${FSLIST}" ] || exit 0 [ -w "${FSLIST}" ] || exit 0
@ -13,20 +14,20 @@ FSLIST_TMP="@runstatedir@/zfs-list.cache@${ZEVENT_POOL}"
. "${ZED_ZEDLET_DIR}/zed-functions.sh" . "${ZED_ZEDLET_DIR}/zed-functions.sh"
[ "$ZEVENT_SUBCLASS" != "history_event" ] && exit 0 [ "$ZEVENT_SUBCLASS" != "history_event" ] && exit 0
zed_check_cmd "${ZFS}" sort diff zed_check_cmd "${ZFS}" sort diff grep
# If we are acting on a snapshot, we have nothing to do # If we are acting on a snapshot, we have nothing to do
[ "${ZEVENT_HISTORY_DSNAME%@*}" = "${ZEVENT_HISTORY_DSNAME}" ] || exit 0 printf '%s' "${ZEVENT_HISTORY_DSNAME}" | grep '@' && exit 0
# We lock the output file to avoid simultaneous writes. # We obtain a lock on zfs-list to avoid any simultaneous writes.
# If we run into trouble, log and drop the lock # If we run into trouble, log and drop the lock
abort_alter() { abort_alter() {
zed_log_msg "Error updating zfs-list.cache for ${ZEVENT_POOL}!" zed_log_msg "Error updating zfs-list.cache!"
zed_unlock "${FSLIST}" zed_unlock zfs-list
} }
finished() { finished() {
zed_unlock "${FSLIST}" zed_unlock zfs-list
trap - EXIT trap - EXIT
exit 0 exit 0
} }
@ -36,7 +37,7 @@ case "${ZEVENT_HISTORY_INTERNAL_NAME}" in
;; ;;
export) export)
zed_lock "${FSLIST}" zed_lock zfs-list
trap abort_alter EXIT trap abort_alter EXIT
echo > "${FSLIST}" echo > "${FSLIST}"
finished finished
@ -62,7 +63,7 @@ case "${ZEVENT_HISTORY_INTERNAL_NAME}" in
;; ;;
esac esac
zed_lock "${FSLIST}" zed_lock zfs-list
trap abort_alter EXIT trap abort_alter EXIT
PROPS="name,mountpoint,canmount,atime,relatime,devices,exec\ PROPS="name,mountpoint,canmount,atime,relatime,devices,exec\
@ -78,7 +79,7 @@ PROPS="name,mountpoint,canmount,atime,relatime,devices,exec\
sort "${FSLIST_TMP}" -o "${FSLIST_TMP}" sort "${FSLIST_TMP}" -o "${FSLIST_TMP}"
# Don't modify the file if it hasn't changed # Don't modify the file if it hasn't changed
diff -q "${FSLIST_TMP}" "${FSLIST}" || cat "${FSLIST_TMP}" > "${FSLIST}" diff -q "${FSLIST_TMP}" "${FSLIST}" || mv "${FSLIST_TMP}" "${FSLIST}"
rm -f "${FSLIST_TMP}" rm -f "${FSLIST_TMP}"
finished finished

View File

@ -41,7 +41,7 @@ fi
umask 077 umask 077
note_subject="ZFS ${ZEVENT_SUBCLASS} event for ${ZEVENT_POOL} on $(hostname)" note_subject="ZFS ${ZEVENT_SUBCLASS} event for ${ZEVENT_POOL} on $(hostname)"
note_pathname="$(mktemp)" note_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$"
{ {
echo "ZFS has finished a ${action}:" echo "ZFS has finished a ${action}:"
echo echo

View File

@ -1,21 +1,21 @@
#!/bin/sh #!/bin/sh
# #
# Turn off/on vdevs' enclosure fault LEDs when their pool's state changes. # Turn off/on the VDEV's enclosure fault LEDs when the pool's state changes.
# #
# Turn a vdev's fault LED on if it becomes FAULTED, DEGRADED or UNAVAIL. # Turn the VDEV's fault LED on if it becomes FAULTED, DEGRADED or UNAVAIL.
# Turn its LED off when it's back ONLINE again. # Turn the LED off when it's back ONLINE again.
# #
# This script run in two basic modes: # This script run in two basic modes:
# #
# 1. If $ZEVENT_VDEV_ENC_SYSFS_PATH and $ZEVENT_VDEV_STATE_STR are set, then # 1. If $ZEVENT_VDEV_ENC_SYSFS_PATH and $ZEVENT_VDEV_STATE_STR are set, then
# only set the LED for that particular vdev. This is the case for statechange # only set the LED for that particular VDEV. This is the case for statechange
# events and some vdev_* events. # events and some vdev_* events.
# #
# 2. If those vars are not set, then check the state of all vdevs in the pool # 2. If those vars are not set, then check the state of all VDEVs in the pool
# and set the LEDs accordingly. This is the case for pool_import events. # and set the LEDs accordingly. This is the case for pool_import events.
# #
# Note that this script requires that your enclosure be supported by the # Note that this script requires that your enclosure be supported by the
# Linux SCSI Enclosure services (SES) driver. The script will do nothing # Linux SCSI enclosure services (ses) driver. The script will do nothing
# if you have no enclosure, or if your enclosure isn't supported. # if you have no enclosure, or if your enclosure isn't supported.
# #
# Exit codes: # Exit codes:
@ -29,8 +29,7 @@
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc" [ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
. "${ZED_ZEDLET_DIR}/zed-functions.sh" . "${ZED_ZEDLET_DIR}/zed-functions.sh"
if [ ! -d /sys/class/enclosure ] && [ ! -d /sys/bus/pci/slots ] ; then if [ ! -d /sys/class/enclosure ] ; then
# No JBOD enclosure or NVMe slots
exit 1 exit 1
fi fi
@ -60,10 +59,6 @@ check_and_set_led()
file="$1" file="$1"
val="$2" val="$2"
if [ -z "$val" ]; then
return 0
fi
if [ ! -e "$file" ] ; then if [ ! -e "$file" ] ; then
return 3 return 3
fi fi
@ -71,11 +66,11 @@ check_and_set_led()
# If another process is accessing the LED when we attempt to update it, # If another process is accessing the LED when we attempt to update it,
# the update will be lost so retry until the LED actually changes or we # the update will be lost so retry until the LED actually changes or we
# timeout. # timeout.
for _ in 1 2 3 4 5; do for _ in $(seq 1 5); do
# We want to check the current state first, since writing to the # We want to check the current state first, since writing to the
# 'fault' entry always causes a SES command, even if the # 'fault' entry always causes a SES command, even if the
# current state is already what you want. # current state is already what you want.
read -r current < "${file}" current=$(cat "${file}")
# On some enclosures if you write 1 to fault, and read it back, # On some enclosures if you write 1 to fault, and read it back,
# it will return 2. Treat all non-zero values as 1 for # it will return 2. Treat all non-zero values as 1 for
@ -90,84 +85,27 @@ check_and_set_led()
else else
break break
fi fi
done done
}
# Fault LEDs for JBODs and NVMe drives are handled a little differently.
#
# On JBODs the fault LED is called 'fault' and on a path like this:
#
# /sys/class/enclosure/0:0:1:0/SLOT 10/fault
#
# On NVMe it's called 'attention' and on a path like this:
#
# /sys/bus/pci/slot/0/attention
#
# This function returns the full path to the fault LED file for a given
# enclosure/slot directory.
#
path_to_led()
{
dir=$1
if [ -f "$dir/fault" ] ; then
echo "$dir/fault"
elif [ -f "$dir/attention" ] ; then
echo "$dir/attention"
fi
} }
state_to_val() state_to_val()
{ {
state="$1" state="$1"
case "$state" in if [ "$state" = "FAULTED" ] || [ "$state" = "DEGRADED" ] || \
FAULTED|DEGRADED|UNAVAIL) [ "$state" = "UNAVAIL" ] ; then
echo 1 echo 1
;; elif [ "$state" = "ONLINE" ] ; then
ONLINE) echo 0
echo 0 fi
;;
esac
} }
# process_pool ([pool])
# #
# Given a nvme name like 'nvme0n1', pass back its slot directory # Iterate through a pool (or pools) and set the VDEV's enclosure slot LEDs to
# like "/sys/bus/pci/slots/0" # the VDEV's state.
#
nvme_dev_to_slot()
{
dev="$1"
# Get the address "0000:01:00.0"
address=$(cat "/sys/class/block/$dev/device/address")
# For each /sys/bus/pci/slots subdir that is an actual number
# (rather than weird directories like "1-3/").
# shellcheck disable=SC2010
for i in $(ls /sys/bus/pci/slots/ | grep -E "^[0-9]+$") ; do
this_address=$(cat "/sys/bus/pci/slots/$i/address")
# The format of address is a little different between
# /sys/class/block/$dev/device/address and
# /sys/bus/pci/slots/
#
# address= "0000:01:00.0"
# this_address = "0000:01:00"
#
if echo "$address" | grep -Eq ^"$this_address" ; then
echo "/sys/bus/pci/slots/$i"
break
fi
done
}
# process_pool (pool)
#
# Iterate through a pool and set the vdevs' enclosure slot LEDs to
# those vdevs' state.
# #
# Arguments # Arguments
# pool: Pool name. # pool: Optional pool name. If not specified, iterate though all pools.
# #
# Return # Return
# 0 on success, 3 on missing sysfs path # 0 on success, 3 on missing sysfs path
@ -175,27 +113,19 @@ nvme_dev_to_slot()
process_pool() process_pool()
{ {
pool="$1" pool="$1"
# The output will be the vdevs only (from "grep '/dev/'"):
#
# U45 ONLINE 0 0 0 /dev/sdk 0
# U46 ONLINE 0 0 0 /dev/sdm 0
# U47 ONLINE 0 0 0 /dev/sdn 0
# U50 ONLINE 0 0 0 /dev/sdbn 0
#
ZPOOL_SCRIPTS_AS_ROOT=1 $ZPOOL status -c upath,fault_led "$pool" | grep '/dev/' | (
rc=0 rc=0
while read -r vdev state _ _ _ therest; do
# Read out current LED value and path
# Get dev name (like 'sda')
dev=$(basename "$(echo "$therest" | awk '{print $(NF-1)}')")
vdev_enc_sysfs_path=$(realpath "/sys/class/block/$dev/device/enclosure_device"*)
if [ ! -d "$vdev_enc_sysfs_path" ] ; then
# This is not a JBOD disk, but it could be a PCI NVMe drive
vdev_enc_sysfs_path=$(nvme_dev_to_slot "$dev")
fi
current_val=$(echo "$therest" | awk '{print $NF}') # Lookup all the current LED values and paths in parallel
#shellcheck disable=SC2016
cmd='echo led_token=$(cat "$VDEV_ENC_SYSFS_PATH/fault"),"$VDEV_ENC_SYSFS_PATH",'
out=$($ZPOOL status -vc "$cmd" "$pool" | grep 'led_token=')
#shellcheck disable=SC2034
echo "$out" | while read -r vdev state read write chksum therest; do
# Read out current LED value and path
tmp=$(echo "$therest" | sed 's/^.*led_token=//g')
vdev_enc_sysfs_path=$(echo "$tmp" | awk -F ',' '{print $2}')
current_val=$(echo "$tmp" | awk -F ',' '{print $1}')
if [ "$current_val" != "0" ] ; then if [ "$current_val" != "0" ] ; then
current_val=1 current_val=1
@ -206,33 +136,40 @@ process_pool()
continue continue
fi fi
led_path=$(path_to_led "$vdev_enc_sysfs_path") if [ ! -e "$vdev_enc_sysfs_path/fault" ] ; then
if [ ! -e "$led_path" ] ; then #shellcheck disable=SC2030
rc=3 rc=1
zed_log_msg "vdev $vdev '$led_path' doesn't exist" zed_log_msg "vdev $vdev '$file/fault' doesn't exist"
continue continue;
fi fi
val=$(state_to_val "$state") val=$(state_to_val "$state")
if [ "$current_val" = "$val" ] ; then if [ "$current_val" = "$val" ] ; then
# LED is already set correctly # LED is already set correctly
continue continue;
fi fi
if ! check_and_set_led "$led_path" "$val"; then if ! check_and_set_led "$vdev_enc_sysfs_path/fault" "$val"; then
rc=3 rc=1
fi fi
done done
exit "$rc"; )
#shellcheck disable=SC2031
if [ "$rc" = "0" ] ; then
return 0
else
# We didn't see a sysfs entry that we wanted to set
return 3
fi
} }
if [ -n "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ -n "$ZEVENT_VDEV_STATE_STR" ] ; then if [ -n "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ -n "$ZEVENT_VDEV_STATE_STR" ] ; then
# Got a statechange for an individual vdev # Got a statechange for an individual VDEV
val=$(state_to_val "$ZEVENT_VDEV_STATE_STR") val=$(state_to_val "$ZEVENT_VDEV_STATE_STR")
vdev=$(basename "$ZEVENT_VDEV_PATH") vdev=$(basename "$ZEVENT_VDEV_PATH")
ledpath=$(path_to_led "$ZEVENT_VDEV_ENC_SYSFS_PATH") check_and_set_led "$ZEVENT_VDEV_ENC_SYSFS_PATH/fault" "$val"
check_and_set_led "$ledpath" "$val"
else else
# Process the entire pool # Process the entire pool
poolname=$(zed_guid_to_pool "$ZEVENT_POOL_GUID") poolname=$(zed_guid_to_pool "$ZEVENT_POOL_GUID")

View File

@ -15,7 +15,7 @@
# Send notification in response to a fault induced statechange # Send notification in response to a fault induced statechange
# #
# ZEVENT_SUBCLASS: 'statechange' # ZEVENT_SUBCLASS: 'statechange'
# ZEVENT_VDEV_STATE_STR: 'DEGRADED', 'FAULTED', 'REMOVED', or 'UNAVAIL' # ZEVENT_VDEV_STATE_STR: 'DEGRADED', 'FAULTED' or 'REMOVED'
# #
# Exit codes: # Exit codes:
# 0: notification sent # 0: notification sent
@ -31,14 +31,13 @@
if [ "${ZEVENT_VDEV_STATE_STR}" != "FAULTED" ] \ if [ "${ZEVENT_VDEV_STATE_STR}" != "FAULTED" ] \
&& [ "${ZEVENT_VDEV_STATE_STR}" != "DEGRADED" ] \ && [ "${ZEVENT_VDEV_STATE_STR}" != "DEGRADED" ] \
&& [ "${ZEVENT_VDEV_STATE_STR}" != "REMOVED" ] \ && [ "${ZEVENT_VDEV_STATE_STR}" != "REMOVED" ]; then
&& [ "${ZEVENT_VDEV_STATE_STR}" != "UNAVAIL" ]; then
exit 3 exit 3
fi fi
umask 077 umask 077
note_subject="ZFS device fault for pool ${ZEVENT_POOL} on $(hostname)" note_subject="ZFS device fault for pool ${ZEVENT_POOL_GUID} on $(hostname)"
note_pathname="$(mktemp)" note_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$"
{ {
if [ "${ZEVENT_VDEV_STATE_STR}" = "FAULTED" ] ; then if [ "${ZEVENT_VDEV_STATE_STR}" = "FAULTED" ] ; then
echo "The number of I/O errors associated with a ZFS device exceeded" echo "The number of I/O errors associated with a ZFS device exceeded"
@ -65,7 +64,7 @@ note_pathname="$(mktemp)"
[ -n "${ZEVENT_VDEV_GUID}" ] && echo " vguid: ${ZEVENT_VDEV_GUID}" [ -n "${ZEVENT_VDEV_GUID}" ] && echo " vguid: ${ZEVENT_VDEV_GUID}"
[ -n "${ZEVENT_VDEV_DEVID}" ] && echo " devid: ${ZEVENT_VDEV_DEVID}" [ -n "${ZEVENT_VDEV_DEVID}" ] && echo " devid: ${ZEVENT_VDEV_DEVID}"
echo " pool: ${ZEVENT_POOL} (${ZEVENT_POOL_GUID})" echo " pool: ${ZEVENT_POOL_GUID}"
} > "${note_pathname}" } > "${note_pathname}"

View File

@ -1,64 +0,0 @@
#!/bin/sh
# shellcheck disable=SC3014,SC2154,SC2086,SC2034
#
# Turn off disk's enclosure slot if it becomes FAULTED.
#
# Bad SCSI disks can often "disappear and reappear" causing all sorts of chaos
# as they flip between FAULTED and ONLINE. If
# ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT is set in zed.rc, and the disk gets
# FAULTED, then power down the slot via sysfs:
#
# /sys/class/enclosure/<enclosure>/<slot>/power_status
#
# We assume the user will be responsible for turning the slot back on again.
#
# Note that this script requires that your enclosure be supported by the
# Linux SCSI Enclosure services (SES) driver. The script will do nothing
# if you have no enclosure, or if your enclosure isn't supported.
#
# Exit codes:
# 0: slot successfully powered off
# 1: enclosure not available
# 2: ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT disabled
# 3: vdev was not FAULTED
# 4: The enclosure sysfs path passed from ZFS does not exist
# 5: Enclosure slot didn't actually turn off after we told it to
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
if [ ! -d /sys/class/enclosure ] ; then
# No JBOD enclosure or NVMe slots
exit 1
fi
if [ "${ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT}" != "1" ] ; then
exit 2
fi
if [ "$ZEVENT_VDEV_STATE_STR" != "FAULTED" ] ; then
exit 3
fi
if [ ! -f "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" ] ; then
exit 4
fi
# Turn off the slot and wait for sysfs to report that the slot is off.
# It can take ~400ms on some enclosures and multiple retries may be needed.
for i in $(seq 1 20) ; do
echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status"
for j in $(seq 1 5) ; do
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then
break 2
fi
sleep 0.1
done
done
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" != "off" ] ; then
exit 5
fi
zed_log_msg "powered down slot $ZEVENT_VDEV_ENC_SYSFS_PATH for $ZEVENT_VDEV_PATH"

View File

@ -19,7 +19,7 @@ zed_check_cmd "${ZPOOL}" || exit 9
umask 077 umask 077
note_subject="ZFS ${ZEVENT_SUBCLASS} event for ${ZEVENT_POOL} on $(hostname)" note_subject="ZFS ${ZEVENT_SUBCLASS} event for ${ZEVENT_POOL} on $(hostname)"
note_pathname="$(mktemp)" note_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$"
{ {
echo "ZFS has finished a trim:" echo "ZFS has finished a trim:"
echo echo

View File

@ -77,7 +77,7 @@ zed_log_msg()
zed_log_err() zed_log_err()
{ {
logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "error:" \ logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "error:" \
"${0##*/}:""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@" "$(basename -- "$0"):""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"
} }
@ -126,8 +126,10 @@ zed_lock()
# Obtain a lock on the file bound to the given file descriptor. # Obtain a lock on the file bound to the given file descriptor.
# #
eval "exec ${fd}>> '${lockfile}'" eval "exec ${fd}> '${lockfile}'"
if ! err="$(flock --exclusive "${fd}" 2>&1)"; then err="$(flock --exclusive "${fd}" 2>&1)"
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
zed_log_err "failed to lock \"${lockfile}\": ${err}" zed_log_err "failed to lock \"${lockfile}\": ${err}"
fi fi
@ -163,7 +165,9 @@ zed_unlock()
fi fi
# Release the lock and close the file descriptor. # Release the lock and close the file descriptor.
if ! err="$(flock --unlock "${fd}" 2>&1)"; then err="$(flock --unlock "${fd}" 2>&1)"
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
zed_log_err "failed to unlock \"${lockfile}\": ${err}" zed_log_err "failed to unlock \"${lockfile}\": ${err}"
fi fi
eval "exec ${fd}>&-" eval "exec ${fd}>&-"
@ -202,10 +206,6 @@ zed_notify()
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) [ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
zed_notify_pushover "${subject}" "${pathname}"; rv=$?
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
[ "${num_success}" -gt 0 ] && return 0 [ "${num_success}" -gt 0 ] && return 0
[ "${num_failure}" -gt 0 ] && return 1 [ "${num_failure}" -gt 0 ] && return 1
return 2 return 2
@ -224,8 +224,6 @@ zed_notify()
# ZED_EMAIL_OPTS. This undergoes the following keyword substitutions: # ZED_EMAIL_OPTS. This undergoes the following keyword substitutions:
# - @ADDRESS@ is replaced with the space-delimited recipient email address(es) # - @ADDRESS@ is replaced with the space-delimited recipient email address(es)
# - @SUBJECT@ is replaced with the notification subject # - @SUBJECT@ is replaced with the notification subject
# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification
#
# #
# Arguments # Arguments
# subject: notification subject # subject: notification subject
@ -243,7 +241,7 @@ zed_notify()
# #
zed_notify_email() zed_notify_email()
{ {
local subject="${1:-"ZED notification"}" local subject="$1"
local pathname="${2:-"/dev/null"}" local pathname="${2:-"/dev/null"}"
: "${ZED_EMAIL_PROG:="mail"}" : "${ZED_EMAIL_PROG:="mail"}"
@ -260,30 +258,19 @@ zed_notify_email()
[ -n "${subject}" ] || return 1 [ -n "${subject}" ] || return 1
if [ ! -r "${pathname}" ]; then if [ ! -r "${pathname}" ]; then
zed_log_err \ zed_log_err \
"${ZED_EMAIL_PROG##*/} cannot read \"${pathname}\"" "$(basename "${ZED_EMAIL_PROG}") cannot read \"${pathname}\""
return 1 return 1
fi fi
# construct cmdline options ZED_EMAIL_OPTS="$(echo "${ZED_EMAIL_OPTS}" \
ZED_EMAIL_OPTS_PARSED="$(echo "${ZED_EMAIL_OPTS}" \
| sed -e "s/@ADDRESS@/${ZED_EMAIL_ADDR}/g" \ | sed -e "s/@ADDRESS@/${ZED_EMAIL_ADDR}/g" \
-e "s/@SUBJECT@/${subject}/g")" -e "s/@SUBJECT@/${subject}/g")"
# pipe message to email prog # shellcheck disable=SC2086
# shellcheck disable=SC2086,SC2248 eval "${ZED_EMAIL_PROG}" ${ZED_EMAIL_OPTS} < "${pathname}" >/dev/null 2>&1
{
# no subject passed as option?
if [ "${ZED_EMAIL_OPTS%@SUBJECT@*}" = "${ZED_EMAIL_OPTS}" ] ; then
# inject subject header
printf "Subject: %s\n" "${subject}"
fi
# output message
cat "${pathname}"
} |
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS_PARSED} >/dev/null 2>&1
rv=$? rv=$?
if [ "${rv}" -ne 0 ]; then if [ "${rv}" -ne 0 ]; then
zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}" zed_log_err "$(basename "${ZED_EMAIL_PROG}") exit=${rv}"
return 1 return 1
fi fi
return 0 return 0
@ -430,7 +417,7 @@ zed_notify_slack_webhook()
# Construct the JSON message for posting. # Construct the JSON message for posting.
# #
msg_json="$(printf '{"text": "*%s*\\n%s"}' "${subject}" "${msg_body}" )" msg_json="$(printf '{"text": "*%s*\n%s"}' "${subject}" "${msg_body}" )"
# Send the POST request and check for errors. # Send the POST request and check for errors.
# #
@ -450,84 +437,6 @@ zed_notify_slack_webhook()
return 0 return 0
} }
# zed_notify_pushover (subject, pathname)
#
# Send a notification via Pushover <https://pushover.net/>.
# The access token (ZED_PUSHOVER_TOKEN) identifies this client to the
# Pushover server. The user token (ZED_PUSHOVER_USER) defines the user or
# group to which the notification will be sent.
#
# Requires curl and sed executables to be installed in the standard PATH.
#
# References
# https://pushover.net/api
#
# Arguments
# subject: notification subject
# pathname: pathname containing the notification message (OPTIONAL)
#
# Globals
# ZED_PUSHOVER_TOKEN
# ZED_PUSHOVER_USER
#
# Return
# 0: notification sent
# 1: notification failed
# 2: not configured
#
zed_notify_pushover()
{
local subject="$1"
local pathname="${2:-"/dev/null"}"
local msg_body
local msg_out
local msg_err
local url="https://api.pushover.net/1/messages.json"
[ -n "${ZED_PUSHOVER_TOKEN}" ] && [ -n "${ZED_PUSHOVER_USER}" ] || return 2
if [ ! -r "${pathname}" ]; then
zed_log_err "pushover cannot read \"${pathname}\""
return 1
fi
zed_check_cmd "curl" "sed" || return 1
# Read the message body in.
#
msg_body="$(cat "${pathname}")"
if [ -z "${msg_body}" ]
then
msg_body=$subject
subject=""
fi
# Send the POST request and check for errors.
#
msg_out="$( \
curl \
--form-string "token=${ZED_PUSHOVER_TOKEN}" \
--form-string "user=${ZED_PUSHOVER_USER}" \
--form-string "message=${msg_body}" \
--form-string "title=${subject}" \
"${url}" \
2>/dev/null \
)"; rv=$?
if [ "${rv}" -ne 0 ]; then
zed_log_err "curl exit=${rv}"
return 1
fi
msg_err="$(echo "${msg_out}" \
| sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"
if [ -n "${msg_err}" ]; then
zed_log_err "pushover \"${msg_err}"\"
return 1
fi
return 0
}
# zed_rate_limit (tag, [interval]) # zed_rate_limit (tag, [interval])
# #
# Check whether an event of a given type [tag] has already occurred within the # Check whether an event of a given type [tag] has already occurred within the
@ -602,8 +511,10 @@ zed_guid_to_pool()
return return
fi fi
guid="$(printf "%u" "$1")" guid=$(printf "%llu" "$1")
$ZPOOL get -H -ovalue,name guid | awk '$1 == '"$guid"' {print $2; exit}' if [ -n "$guid" ] ; then
$ZPOOL get -H -ovalue,name guid | awk '$1=='"$guid"' {print $2}'
fi
} }
# zed_exit_if_ignoring_this_event # zed_exit_if_ignoring_this_event

View File

@ -13,9 +13,9 @@
# Email address of the zpool administrator for receipt of notifications; # Email address of the zpool administrator for receipt of notifications;
# multiple addresses can be specified if they are delimited by whitespace. # multiple addresses can be specified if they are delimited by whitespace.
# Email will only be sent if ZED_EMAIL_ADDR is defined. # Email will only be sent if ZED_EMAIL_ADDR is defined.
# Enabled by default; comment to disable. # Disabled by default; uncomment to enable.
# #
ZED_EMAIL_ADDR="root" #ZED_EMAIL_ADDR="root"
## ##
# Name or path of executable responsible for sending notifications via email; # Name or path of executable responsible for sending notifications via email;
@ -30,7 +30,6 @@ ZED_EMAIL_ADDR="root"
# The string @SUBJECT@ will be replaced with the notification subject; # The string @SUBJECT@ will be replaced with the notification subject;
# this should be protected with quotes to prevent word-splitting. # this should be protected with quotes to prevent word-splitting.
# Email will only be sent if ZED_EMAIL_ADDR is defined. # Email will only be sent if ZED_EMAIL_ADDR is defined.
# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification
# #
#ZED_EMAIL_OPTS="-s '@SUBJECT@' @ADDRESS@" #ZED_EMAIL_OPTS="-s '@SUBJECT@' @ADDRESS@"
@ -83,23 +82,6 @@ ZED_EMAIL_ADDR="root"
# #
#ZED_SLACK_WEBHOOK_URL="" #ZED_SLACK_WEBHOOK_URL=""
##
# Pushover token.
# This defines the application from which the notification will be sent.
# <https://pushover.net/api#registration>
# Disabled by default; uncomment to enable.
# ZED_PUSHOVER_USER, below, must also be configured.
#
#ZED_PUSHOVER_TOKEN=""
##
# Pushover user key.
# This defines which user or group will receive Pushover notifications.
# <https://pushover.net/api#identifiers>
# Disabled by default; uncomment to enable.
# ZED_PUSHOVER_TOKEN, above, must also be configured.
#ZED_PUSHOVER_USER=""
## ##
# Default directory for zed state files. # Default directory for zed state files.
# #
@ -107,8 +89,8 @@ ZED_EMAIL_ADDR="root"
## ##
# Turn on/off enclosure LEDs when drives get DEGRADED/FAULTED. This works for # Turn on/off enclosure LEDs when drives get DEGRADED/FAULTED. This works for
# device mapper and multipath devices as well. This works with JBOD enclosures # device mapper and multipath devices as well. Your enclosure must be
# and NVMe PCI drives (assuming they're supported by Linux in sysfs). # supported by the Linux SES driver for this to work.
# #
ZED_USE_ENCLOSURE_LEDS=1 ZED_USE_ENCLOSURE_LEDS=1
@ -143,8 +125,3 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
# Disabled by default, 1 to enable and 0 to disable. # Disabled by default, 1 to enable and 0 to disable.
#ZED_SYSLOG_DISPLAY_GUIDS=1 #ZED_SYSLOG_DISPLAY_GUIDS=1
##
# Power off the drive's slot in the enclosure if it becomes FAULTED. This can
# help silence misbehaving drives. This assumes your drive enclosure fully
# supports slot power control via sysfs.
#ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT=1

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).
@ -22,7 +22,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
@ -426,6 +425,8 @@ zed_conf_scan_dir(struct zed_conf *zcp)
int int
zed_conf_write_pid(struct zed_conf *zcp) zed_conf_write_pid(struct zed_conf *zcp)
{ {
const mode_t dirmode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
const mode_t filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
char buf[PATH_MAX]; char buf[PATH_MAX];
int n; int n;
char *p; char *p;
@ -453,7 +454,7 @@ zed_conf_write_pid(struct zed_conf *zcp)
if (p) if (p)
*p = '\0'; *p = '\0';
if ((mkdirp(buf, 0755) < 0) && (errno != EEXIST)) { if ((mkdirp(buf, dirmode) < 0) && (errno != EEXIST)) {
zed_log_msg(LOG_ERR, "Failed to create directory \"%s\": %s", zed_log_msg(LOG_ERR, "Failed to create directory \"%s\": %s",
buf, strerror(errno)); buf, strerror(errno));
goto err; goto err;
@ -463,7 +464,7 @@ zed_conf_write_pid(struct zed_conf *zcp)
*/ */
mask = umask(0); mask = umask(0);
umask(mask | 022); umask(mask | 022);
zcp->pid_fd = open(zcp->pid_file, O_RDWR | O_CREAT | O_CLOEXEC, 0644); zcp->pid_fd = open(zcp->pid_file, (O_RDWR | O_CREAT), filemode);
umask(mask); umask(mask);
if (zcp->pid_fd < 0) { if (zcp->pid_fd < 0) {
zed_log_msg(LOG_ERR, "Failed to open PID file \"%s\": %s", zed_log_msg(LOG_ERR, "Failed to open PID file \"%s\": %s",
@ -528,6 +529,7 @@ int
zed_conf_open_state(struct zed_conf *zcp) zed_conf_open_state(struct zed_conf *zcp)
{ {
char dirbuf[PATH_MAX]; char dirbuf[PATH_MAX];
mode_t dirmode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
int n; int n;
char *p; char *p;
int rv; int rv;
@ -549,7 +551,7 @@ zed_conf_open_state(struct zed_conf *zcp)
if (p) if (p)
*p = '\0'; *p = '\0';
if ((mkdirp(dirbuf, 0755) < 0) && (errno != EEXIST)) { if ((mkdirp(dirbuf, dirmode) < 0) && (errno != EEXIST)) {
zed_log_msg(LOG_WARNING, zed_log_msg(LOG_WARNING,
"Failed to create directory \"%s\": %s", "Failed to create directory \"%s\": %s",
dirbuf, strerror(errno)); dirbuf, strerror(errno));
@ -567,7 +569,7 @@ zed_conf_open_state(struct zed_conf *zcp)
(void) unlink(zcp->state_file); (void) unlink(zcp->state_file);
zcp->state_fd = open(zcp->state_file, zcp->state_fd = open(zcp->state_file,
O_RDWR | O_CREAT | O_CLOEXEC, 0644); (O_RDWR | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
if (zcp->state_fd < 0) { if (zcp->state_fd < 0) {
zed_log_msg(LOG_WARNING, "Failed to open state file \"%s\": %s", zed_log_msg(LOG_WARNING, "Failed to open state file \"%s\": %s",
zcp->state_file, strerror(errno)); zcp->state_file, strerror(errno));

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -72,14 +72,10 @@ zed_udev_event(const char *class, const char *subclass, nvlist_t *nvl)
zed_log_msg(LOG_INFO, "\t%s: %s", DEV_PATH, strval); zed_log_msg(LOG_INFO, "\t%s: %s", DEV_PATH, strval);
if (nvlist_lookup_string(nvl, DEV_IDENTIFIER, &strval) == 0) if (nvlist_lookup_string(nvl, DEV_IDENTIFIER, &strval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %s", DEV_IDENTIFIER, strval); zed_log_msg(LOG_INFO, "\t%s: %s", DEV_IDENTIFIER, strval);
if (nvlist_lookup_boolean(nvl, DEV_IS_PART) == B_TRUE)
zed_log_msg(LOG_INFO, "\t%s: B_TRUE", DEV_IS_PART);
if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &strval) == 0) if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &strval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %s", DEV_PHYS_PATH, strval); zed_log_msg(LOG_INFO, "\t%s: %s", DEV_PHYS_PATH, strval);
if (nvlist_lookup_uint64(nvl, DEV_SIZE, &numval) == 0) if (nvlist_lookup_uint64(nvl, DEV_SIZE, &numval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_SIZE, numval); zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_SIZE, numval);
if (nvlist_lookup_uint64(nvl, DEV_PARENT_SIZE, &numval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_PARENT_SIZE, numval);
if (nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &numval) == 0) if (nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &numval) == 0)
zed_log_msg(LOG_INFO, "\t%s: %llu", ZFS_EV_POOL_GUID, numval); zed_log_msg(LOG_INFO, "\t%s: %llu", ZFS_EV_POOL_GUID, numval);
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &numval) == 0) if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &numval) == 0)
@ -132,20 +128,6 @@ dev_event_nvlist(struct udev_device *dev)
numval *= strtoull(value, NULL, 10); numval *= strtoull(value, NULL, 10);
(void) nvlist_add_uint64(nvl, DEV_SIZE, numval); (void) nvlist_add_uint64(nvl, DEV_SIZE, numval);
/*
* If the device has a parent, then get the parent block
* device's size as well. For example, /dev/sda1's parent
* is /dev/sda.
*/
struct udev_device *parent_dev = udev_device_get_parent(dev);
if ((value = udev_device_get_sysattr_value(parent_dev, "size"))
!= NULL) {
uint64_t numval = DEV_BSIZE;
numval *= strtoull(value, NULL, 10);
(void) nvlist_add_uint64(nvl, DEV_PARENT_SIZE, numval);
}
} }
/* /*
@ -185,7 +167,7 @@ zed_udev_monitor(void *arg)
while (1) { while (1) {
struct udev_device *dev; struct udev_device *dev;
const char *action, *type, *part, *sectors; const char *action, *type, *part, *sectors;
const char *bus, *uuid, *devpath; const char *bus, *uuid;
const char *class, *subclass; const char *class, *subclass;
nvlist_t *nvl; nvlist_t *nvl;
boolean_t is_zfs = B_FALSE; boolean_t is_zfs = B_FALSE;
@ -224,12 +206,6 @@ zed_udev_monitor(void *arg)
* if this is a disk and it is partitioned, then the * if this is a disk and it is partitioned, then the
* zfs label will reside in a DEVTYPE=partition and * zfs label will reside in a DEVTYPE=partition and
* we can skip passing this event * we can skip passing this event
*
* Special case: Blank disks are sometimes reported with
* an erroneous 'atari' partition, and should not be
* excluded from being used as an autoreplace disk:
*
* https://github.com/openzfs/zfs/issues/13497
*/ */
type = udev_device_get_property_value(dev, "DEVTYPE"); type = udev_device_get_property_value(dev, "DEVTYPE");
part = udev_device_get_property_value(dev, part = udev_device_get_property_value(dev,
@ -237,23 +213,9 @@ zed_udev_monitor(void *arg)
if (type != NULL && type[0] != '\0' && if (type != NULL && type[0] != '\0' &&
strcmp(type, "disk") == 0 && strcmp(type, "disk") == 0 &&
part != NULL && part[0] != '\0') { part != NULL && part[0] != '\0') {
const char *devname = /* skip and wait for partition event */
udev_device_get_property_value(dev, "DEVNAME"); udev_device_unref(dev);
continue;
if (strcmp(part, "atari") == 0) {
zed_log_msg(LOG_INFO,
"%s: %s is reporting an atari partition, "
"but we're going to assume it's a false "
"positive and still use it (issue #13497)",
__func__, devname);
} else {
zed_log_msg(LOG_INFO,
"%s: skip %s since it has a %s partition "
"already", __func__, devname, part);
/* skip and wait for partition event */
udev_device_unref(dev);
continue;
}
} }
/* /*
@ -265,11 +227,6 @@ zed_udev_monitor(void *arg)
sectors = udev_device_get_sysattr_value(dev, "size"); sectors = udev_device_get_sysattr_value(dev, "size");
if (sectors != NULL && if (sectors != NULL &&
strtoull(sectors, NULL, 10) < MINIMUM_SECTORS) { strtoull(sectors, NULL, 10) < MINIMUM_SECTORS) {
zed_log_msg(LOG_INFO,
"%s: %s sectors %s < %llu (minimum)",
__func__,
udev_device_get_property_value(dev, "DEVNAME"),
sectors, MINIMUM_SECTORS);
udev_device_unref(dev); udev_device_unref(dev);
continue; continue;
} }
@ -279,19 +236,10 @@ zed_udev_monitor(void *arg)
* device id string is required in the message schema * device id string is required in the message schema
* for matching with vdevs. Preflight here for expected * for matching with vdevs. Preflight here for expected
* udev information. * udev information.
*
* Special case:
* NVMe devices don't have ID_BUS set (at least on RHEL 7-8),
* but they are valid for autoreplace. Add a special case for
* them by searching for "/nvme/" in the udev DEVPATH:
*
* DEVPATH=/devices/pci0000:00/0000:00:1e.0/nvme/nvme2/nvme2n1
*/ */
bus = udev_device_get_property_value(dev, "ID_BUS"); bus = udev_device_get_property_value(dev, "ID_BUS");
uuid = udev_device_get_property_value(dev, "DM_UUID"); uuid = udev_device_get_property_value(dev, "DM_UUID");
devpath = udev_device_get_devpath(dev); if (!is_zfs && (bus == NULL && uuid == NULL)) {
if (!is_zfs && (bus == NULL && uuid == NULL &&
strstr(devpath, "/nvme/") == NULL)) {
zed_log_msg(LOG_INFO, "zed_udev_monitor: %s no devid " zed_log_msg(LOG_INFO, "zed_udev_monitor: %s no devid "
"source", udev_device_get_devnode(dev)); "source", udev_device_get_devnode(dev));
udev_device_unref(dev); udev_device_unref(dev);
@ -402,7 +350,7 @@ zed_udev_monitor(void *arg)
} }
int int
zed_disk_event_init(void) zed_disk_event_init()
{ {
int fd, fflags; int fd, fflags;
@ -438,7 +386,7 @@ zed_disk_event_init(void)
} }
void void
zed_disk_event_fini(void) zed_disk_event_fini()
{ {
/* cancel monitor thread at recvmsg() */ /* cancel monitor thread at recvmsg() */
(void) pthread_cancel(g_mon_tid); (void) pthread_cancel(g_mon_tid);
@ -456,13 +404,13 @@ zed_disk_event_fini(void)
#include "zed_disk_event.h" #include "zed_disk_event.h"
int int
zed_disk_event_init(void) zed_disk_event_init()
{ {
return (0); return (0);
} }
void void
zed_disk_event_fini(void) zed_disk_event_fini()
{ {
} }

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).
@ -35,7 +35,6 @@
#include "zed_strings.h" #include "zed_strings.h"
#include "agents/zfs_agents.h" #include "agents/zfs_agents.h"
#include <libzutil.h>
#define MAXBUF 4096 #define MAXBUF 4096
@ -55,7 +54,7 @@ zed_event_init(struct zed_conf *zcp)
zed_log_die("Failed to initialize libzfs"); zed_log_die("Failed to initialize libzfs");
} }
zcp->zevent_fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC); zcp->zevent_fd = open(ZFS_DEV, O_RDWR);
if (zcp->zevent_fd < 0) { if (zcp->zevent_fd < 0) {
if (zcp->do_idle) if (zcp->do_idle)
return (-1); return (-1);
@ -908,25 +907,6 @@ _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
} }
} }
static void
_zed_event_update_enc_sysfs_path(nvlist_t *nvl)
{
char *vdev_path;
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_PATH,
&vdev_path) != 0) {
return; /* some other kind of event, ignore it */
}
if (vdev_path == NULL) {
return;
}
update_vdev_config_dev_sysfs_path(nvl, vdev_path,
FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH);
}
/* /*
* Service the next zevent, blocking until one is available. * Service the next zevent, blocking until one is available.
*/ */
@ -974,17 +954,6 @@ zed_event_service(struct zed_conf *zcp)
zed_log_msg(LOG_WARNING, zed_log_msg(LOG_WARNING,
"Failed to lookup zevent class (eid=%llu)", eid); "Failed to lookup zevent class (eid=%llu)", eid);
} else { } else {
/*
* Special case: If we can dynamically detect an enclosure sysfs
* path, then use that value rather than the one stored in the
* vd->vdev_enc_sysfs_path. There have been rare cases where
* vd->vdev_enc_sysfs_path becomes outdated. However, there
* will be other times when we can not dynamically detect the
* sysfs path (like if a disk disappears) and have to rely on
* the old value for things like turning on the fault LED.
*/
_zed_event_update_enc_sysfs_path(nvl);
/* let internal modules see this event first */ /* let internal modules see this event first */
zfs_agent_post_event(class, NULL, nvl); zfs_agent_post_event(class, NULL, nvl);

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).
@ -26,9 +26,8 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h>
#include "zed_exec.h" #include "zed_exec.h"
#include "zed_file.h"
#include "zed_log.h" #include "zed_log.h"
#include "zed_strings.h" #include "zed_strings.h"
@ -117,7 +116,7 @@ _zed_exec_create_env(zed_strings_t *zsp)
*/ */
static void static void
_zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog, _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog,
char *env[], int zfd, boolean_t in_foreground) char *env[], int zfd)
{ {
char path[PATH_MAX]; char path[PATH_MAX];
int n; int n;
@ -144,10 +143,8 @@ _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog,
prog, eid, strerror(ENAMETOOLONG)); prog, eid, strerror(ENAMETOOLONG));
return; return;
} }
(void) pthread_mutex_lock(&_launched_processes_lock);
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
(void) pthread_mutex_unlock(&_launched_processes_lock);
zed_log_msg(LOG_WARNING, zed_log_msg(LOG_WARNING,
"Failed to fork \"%s\" for eid=%llu: %s", "Failed to fork \"%s\" for eid=%llu: %s",
prog, eid, strerror(errno)); prog, eid, strerror(errno));
@ -157,32 +154,33 @@ _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog,
(void) sigprocmask(SIG_SETMASK, &mask, NULL); (void) sigprocmask(SIG_SETMASK, &mask, NULL);
(void) umask(022); (void) umask(022);
if (in_foreground && /* we're already devnulled if daemonised */ if ((fd = open("/dev/null", O_RDWR)) != -1) {
(fd = open("/dev/null", O_RDWR | O_CLOEXEC)) != -1) {
(void) dup2(fd, STDIN_FILENO); (void) dup2(fd, STDIN_FILENO);
(void) dup2(fd, STDOUT_FILENO); (void) dup2(fd, STDOUT_FILENO);
(void) dup2(fd, STDERR_FILENO); (void) dup2(fd, STDERR_FILENO);
} }
(void) dup2(zfd, ZEVENT_FILENO); (void) dup2(zfd, ZEVENT_FILENO);
zed_file_close_from(ZEVENT_FILENO + 1);
execle(path, prog, NULL, env); execle(path, prog, NULL, env);
_exit(127); _exit(127);
} }
/* parent process */ /* parent process */
__atomic_sub_fetch(&_launched_processes_limit, 1, __ATOMIC_SEQ_CST);
zed_log_msg(LOG_INFO, "Invoking \"%s\" eid=%llu pid=%d",
prog, eid, pid);
node = calloc(1, sizeof (*node)); node = calloc(1, sizeof (*node));
if (node) { if (node) {
node->pid = pid; node->pid = pid;
node->eid = eid; node->eid = eid;
node->name = strdup(prog); node->name = strdup(prog);
(void) pthread_mutex_lock(&_launched_processes_lock);
avl_add(&_launched_processes, node); avl_add(&_launched_processes, node);
(void) pthread_mutex_unlock(&_launched_processes_lock);
} }
(void) pthread_mutex_unlock(&_launched_processes_lock);
__atomic_sub_fetch(&_launched_processes_limit, 1, __ATOMIC_SEQ_CST);
zed_log_msg(LOG_INFO, "Invoking \"%s\" eid=%llu pid=%d",
prog, eid, pid);
} }
static void static void
@ -208,12 +206,10 @@ _reap_children(void *arg)
(void) sigaction(SIGCHLD, &sa, NULL); (void) sigaction(SIGCHLD, &sa, NULL);
for (_reap_children_stop = B_FALSE; !_reap_children_stop; ) { for (_reap_children_stop = B_FALSE; !_reap_children_stop; ) {
(void) pthread_mutex_lock(&_launched_processes_lock); pid = wait4(0, &status, 0, &usage);
pid = wait4(0, &status, WNOHANG, &usage);
if (pid == 0 || pid == (pid_t)-1) { if (pid == (pid_t)-1) {
(void) pthread_mutex_unlock(&_launched_processes_lock); if (errno == ECHILD)
if (pid == 0 || errno == ECHILD)
pause(); pause();
else if (errno != EINTR) else if (errno != EINTR)
zed_log_msg(LOG_WARNING, zed_log_msg(LOG_WARNING,
@ -222,6 +218,7 @@ _reap_children(void *arg)
} else { } else {
memset(&node, 0, sizeof (node)); memset(&node, 0, sizeof (node));
node.pid = pid; node.pid = pid;
(void) pthread_mutex_lock(&_launched_processes_lock);
pnode = avl_find(&_launched_processes, &node, NULL); pnode = avl_find(&_launched_processes, &node, NULL);
if (pnode) { if (pnode) {
memcpy(&node, pnode, sizeof (node)); memcpy(&node, pnode, sizeof (node));
@ -362,7 +359,7 @@ zed_exec_process(uint64_t eid, const char *class, const char *subclass,
n = strlen(*csp); n = strlen(*csp);
if ((strncmp(z, *csp, n) == 0) && !isalpha(z[n])) if ((strncmp(z, *csp, n) == 0) && !isalpha(z[n]))
_zed_exec_fork_child(eid, zcp->zedlet_dir, _zed_exec_fork_child(eid, zcp->zedlet_dir,
z, e, zcp->zevent_fd, zcp->do_foreground); z, e, zcp->zevent_fd);
} }
} }
free(e); free(e);

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -3,7 +3,7 @@
* *
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
* Refer to the OpenZFS git commit log for authoritative copyright attribution. * Refer to the ZoL git commit log for authoritative copyright attribution.
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License Version 1.0 (CDDL-1.0). * Common Development and Distribution License Version 1.0 (CDDL-1.0).

View File

@ -315,14 +315,14 @@ get_usage(zfs_help_t idx)
case HELP_ROLLBACK: case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n")); return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND: case HELP_SEND:
return (gettext("\tsend [-DnPpRVvLecwhb] [-[i|I] snapshot] " return (gettext("\tsend [-DnPpRvLecwhb] [-[i|I] snapshot] "
"<snapshot>\n" "<snapshot>\n"
"\tsend [-DnVvPLecw] [-i snapshot|bookmark] " "\tsend [-nvPLecw] [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n" "<filesystem|volume|snapshot>\n"
"\tsend [-DnPpVvLec] [-i bookmark|snapshot] " "\tsend [-DnPpvLec] [-i bookmark|snapshot] "
"--redact <bookmark> <snapshot>\n" "--redact <bookmark> <snapshot>\n"
"\tsend [-nVvPe] -t <receive_resume_token>\n" "\tsend [-nvPe] -t <receive_resume_token>\n"
"\tsend [-PnVv] --saved filesystem\n")); "\tsend [-Pnv] --saved filesystem\n"));
case HELP_SET: case HELP_SET:
return (gettext("\tset <property=value> ... " return (gettext("\tset <property=value> ... "
"<filesystem|volume|snapshot> ...\n")); "<filesystem|volume|snapshot> ...\n"));
@ -535,7 +535,7 @@ usage(boolean_t requested)
show_properties = B_TRUE; show_properties = B_TRUE;
if (show_properties) { if (show_properties) {
(void) fprintf(fp, "%s", (void) fprintf(fp,
gettext("\nThe following properties are supported:\n")); gettext("\nThe following properties are supported:\n"));
(void) fprintf(fp, "\n\t%-14s %s %s %s\n\n", (void) fprintf(fp, "\n\t%-14s %s %s %s\n\n",
@ -728,32 +728,6 @@ finish_progress(char *done)
pt_header = NULL; pt_header = NULL;
} }
/* This function checks if the passed fd refers to /dev/null or /dev/zero */
#ifdef __linux__
static boolean_t
is_dev_nullzero(int fd)
{
struct stat st;
fstat(fd, &st);
return (major(st.st_rdev) == 1 && (minor(st.st_rdev) == 3 /* null */ ||
minor(st.st_rdev) == 5 /* zero */));
}
#endif
static void
note_dev_error(int err, int fd)
{
#ifdef __linux__
if (err == EINVAL && is_dev_nullzero(fd)) {
(void) fprintf(stderr,
gettext("Error: Writing directly to /dev/{null,zero} files"
" on certain kernels is not currently implemented.\n"
"(As a workaround, "
"try \"zfs send [...] | cat > /dev/null\")\n"));
}
#endif
}
static int static int
zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type) zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type)
{ {
@ -2480,7 +2454,7 @@ upgrade_set_callback(zfs_handle_t *zhp, void *data)
/* upgrade */ /* upgrade */
if (version < cb->cb_version) { if (version < cb->cb_version) {
char verstr[24]; char verstr[16];
(void) snprintf(verstr, sizeof (verstr), (void) snprintf(verstr, sizeof (verstr),
"%llu", (u_longlong_t)cb->cb_version); "%llu", (u_longlong_t)cb->cb_version);
if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) { if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) {
@ -3474,8 +3448,6 @@ print_header(list_cbdata_t *cb)
boolean_t first = B_TRUE; boolean_t first = B_TRUE;
boolean_t right_justify; boolean_t right_justify;
color_start(ANSI_BOLD);
for (; pl != NULL; pl = pl->pl_next) { for (; pl != NULL; pl = pl->pl_next) {
if (!first) { if (!first) {
(void) printf(" "); (void) printf(" ");
@ -3502,31 +3474,9 @@ print_header(list_cbdata_t *cb)
(void) printf("%-*s", (int)pl->pl_width, header); (void) printf("%-*s", (int)pl->pl_width, header);
} }
color_end();
(void) printf("\n"); (void) printf("\n");
} }
/*
* Decides on the color that the avail value should be printed in.
* > 80% used = yellow
* > 90% used = red
*/
static const char *
zfs_list_avail_color(zfs_handle_t *zhp)
{
uint64_t used = zfs_prop_get_int(zhp, ZFS_PROP_USED);
uint64_t avail = zfs_prop_get_int(zhp, ZFS_PROP_AVAILABLE);
int percentage = (int)((double)avail / MAX(avail + used, 1) * 100);
if (percentage > 20)
return (NULL);
else if (percentage > 10)
return (ANSI_YELLOW);
else
return (ANSI_RED);
}
/* /*
* Given a dataset and a list of fields, print out all the properties according * Given a dataset and a list of fields, print out all the properties according
* to the described layout. * to the described layout.
@ -3589,22 +3539,6 @@ print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
right_justify = B_FALSE; right_justify = B_FALSE;
} }
/*
* zfs_list_avail_color() needs ZFS_PROP_AVAILABLE + USED
* - so we need another for() search for the USED part
* - when no colors wanted, we can skip the whole thing
*/
if (use_color() && pl->pl_prop == ZFS_PROP_AVAILABLE) {
zprop_list_t *pl2 = cb->cb_proplist;
for (; pl2 != NULL; pl2 = pl2->pl_next) {
if (pl2->pl_prop == ZFS_PROP_USED) {
color_start(zfs_list_avail_color(zhp));
/* found it, no need for more loops */
break;
}
}
}
/* /*
* If this is being called in scripted mode, or if this is the * If this is being called in scripted mode, or if this is the
* last column and it is left-justified, don't include a width * last column and it is left-justified, don't include a width
@ -3616,9 +3550,6 @@ print_dataset(zfs_handle_t *zhp, list_cbdata_t *cb)
(void) printf("%*s", (int)pl->pl_width, propstr); (void) printf("%*s", (int)pl->pl_width, propstr);
else else
(void) printf("%-*s", (int)pl->pl_width, propstr); (void) printf("%-*s", (int)pl->pl_width, propstr);
if (pl->pl_prop == ZFS_PROP_AVAILABLE)
color_end();
} }
(void) printf("\n"); (void) printf("\n");
@ -4450,7 +4381,6 @@ zfs_do_send(int argc, char **argv)
{"props", no_argument, NULL, 'p'}, {"props", no_argument, NULL, 'p'},
{"parsable", no_argument, NULL, 'P'}, {"parsable", no_argument, NULL, 'P'},
{"dedup", no_argument, NULL, 'D'}, {"dedup", no_argument, NULL, 'D'},
{"proctitle", no_argument, NULL, 'V'},
{"verbose", no_argument, NULL, 'v'}, {"verbose", no_argument, NULL, 'v'},
{"dryrun", no_argument, NULL, 'n'}, {"dryrun", no_argument, NULL, 'n'},
{"large-block", no_argument, NULL, 'L'}, {"large-block", no_argument, NULL, 'L'},
@ -4465,7 +4395,7 @@ zfs_do_send(int argc, char **argv)
}; };
/* check options */ /* check options */
while ((c = getopt_long(argc, argv, ":i:I:RsDpVvnPLeht:cwbd:S", while ((c = getopt_long(argc, argv, ":i:I:RsDpvnPLeht:cwbd:S",
long_options, NULL)) != -1) { long_options, NULL)) != -1) {
switch (c) { switch (c) {
case 'i': case 'i':
@ -4500,9 +4430,6 @@ zfs_do_send(int argc, char **argv)
case 'P': case 'P':
flags.parsable = B_TRUE; flags.parsable = B_TRUE;
break; break;
case 'V':
flags.progressastitle = B_TRUE;
break;
case 'v': case 'v':
flags.verbosity++; flags.verbosity++;
flags.progress = B_TRUE; flags.progress = B_TRUE;
@ -4578,7 +4505,7 @@ zfs_do_send(int argc, char **argv)
} }
} }
if ((flags.parsable || flags.progressastitle) && flags.verbosity == 0) if (flags.parsable && flags.verbosity == 0)
flags.verbosity = 1; flags.verbosity = 1;
argc -= optind; argc -= optind;
@ -4645,16 +4572,11 @@ zfs_do_send(int argc, char **argv)
err = zfs_send_saved(zhp, &flags, STDOUT_FILENO, err = zfs_send_saved(zhp, &flags, STDOUT_FILENO,
resume_token); resume_token);
if (err != 0)
note_dev_error(errno, STDOUT_FILENO);
zfs_close(zhp); zfs_close(zhp);
return (err != 0); return (err != 0);
} else if (resume_token != NULL) { } else if (resume_token != NULL) {
err = zfs_send_resume(g_zfs, &flags, STDOUT_FILENO, return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
resume_token); resume_token));
if (err != 0)
note_dev_error(errno, STDOUT_FILENO);
return (err);
} }
if (flags.skipmissing && !flags.replicate) { if (flags.skipmissing && !flags.replicate) {
@ -4705,8 +4627,6 @@ zfs_do_send(int argc, char **argv)
err = zfs_send_one(zhp, fromname, STDOUT_FILENO, &flags, err = zfs_send_one(zhp, fromname, STDOUT_FILENO, &flags,
redactbook); redactbook);
zfs_close(zhp); zfs_close(zhp);
if (err != 0)
note_dev_error(errno, STDOUT_FILENO);
return (err != 0); return (err != 0);
} }
@ -4783,7 +4703,6 @@ zfs_do_send(int argc, char **argv)
nvlist_free(dbgnv); nvlist_free(dbgnv);
} }
zfs_close(zhp); zfs_close(zhp);
note_dev_error(errno, STDOUT_FILENO);
return (err != 0); return (err != 0);
} }
@ -6640,7 +6559,7 @@ zfs_do_holds(int argc, char **argv)
/* /*
* 1. collect holds data, set format options * 1. collect holds data, set format options
*/ */
ret = zfs_for_each(1, argv + i, flags, types, NULL, NULL, limit, ret = zfs_for_each(argc, argv, flags, types, NULL, NULL, limit,
holds_callback, &cb); holds_callback, &cb);
if (ret != 0) if (ret != 0)
++errors; ++errors;
@ -7522,7 +7441,6 @@ unshare_unmount(int op, int argc, char **argv)
if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) ==
ZFS_CANMOUNT_NOAUTO) ZFS_CANMOUNT_NOAUTO)
continue; continue;
break;
default: default:
break; break;
} }
@ -7719,7 +7637,7 @@ zfs_do_diff(int argc, char **argv)
int c; int c;
struct sigaction sa; struct sigaction sa;
while ((c = getopt(argc, argv, "FHth")) != -1) { while ((c = getopt(argc, argv, "FHt")) != -1) {
switch (c) { switch (c) {
case 'F': case 'F':
flags |= ZFS_DIFF_CLASSIFY; flags |= ZFS_DIFF_CLASSIFY;
@ -7730,9 +7648,6 @@ zfs_do_diff(int argc, char **argv)
case 't': case 't':
flags |= ZFS_DIFF_TIMESTAMP; flags |= ZFS_DIFF_TIMESTAMP;
break; break;
case 'h':
flags |= ZFS_DIFF_NO_MANGLE;
break;
default: default:
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("invalid option '%c'\n"), optopt); gettext("invalid option '%c'\n"), optopt);
@ -8582,7 +8497,7 @@ static int
zfs_do_wait(int argc, char **argv) zfs_do_wait(int argc, char **argv)
{ {
boolean_t enabled[ZFS_WAIT_NUM_ACTIVITIES]; boolean_t enabled[ZFS_WAIT_NUM_ACTIVITIES];
int error = 0, i; int error, i;
int c; int c;
/* By default, wait for all types of activity. */ /* By default, wait for all types of activity. */
@ -8740,8 +8655,6 @@ main(int argc, char **argv)
libzfs_print_on_error(g_zfs, B_TRUE); libzfs_print_on_error(g_zfs, B_TRUE);
zfs_setproctitle_init(argc, argv, environ);
/* /*
* Many commands modify input strings for string parsing reasons. * Many commands modify input strings for string parsing reasons.
* We create a copy to protect the original argv. * We create a copy to protect the original argv.

View File

@ -207,6 +207,7 @@ static int
zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc, zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
list_t *head) list_t *head)
{ {
char fullname[PATH_MAX];
struct dirent *ent; struct dirent *ent;
DIR *dir; DIR *dir;
int ret = 0; int ret = 0;
@ -226,28 +227,21 @@ zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
zpc->zpc_ignore_noent = B_TRUE; zpc->zpc_ignore_noent = B_TRUE;
errno = 0; errno = 0;
while (!ret && (ent = readdir(dir)) != NULL) { while (!ret && (ent = readdir(dir)) != NULL) {
char *fullname;
/* skip "." and ".." */ /* skip "." and ".." */
if (strcmp(ent->d_name, ".") == 0 || if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0) strcmp(ent->d_name, "..") == 0)
continue; continue;
if (strlen(ent->d_name) + strlen(name) + 1 >= PATH_MAX) { if (strlen(ent->d_name) + strlen(name) >=
sizeof (fullname) + 1) {
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
break; break;
} }
if (asprintf(&fullname, "%s/%s", name, ent->d_name) == -1) { sprintf(fullname, "%s/%s", name, ent->d_name);
errno = ENOMEM;
break;
}
ret = zfs_project_handle_one(fullname, zpc); ret = zfs_project_handle_one(fullname, zpc);
if (!ret && zpc->zpc_recursive && ent->d_type == DT_DIR) if (!ret && zpc->zpc_recursive && ent->d_type == DT_DIR)
zfs_project_item_alloc(head, fullname); zfs_project_item_alloc(head, fullname);
free(fullname);
} }
if (errno && !ret) { if (errno && !ret) {

View File

@ -36,6 +36,8 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
static void usage(void);
static void static void
usage(void) usage(void)
{ {
@ -58,11 +60,12 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
/* default file path, can be optionally set by user */ /* default file path, can be optionally set by user */
const char *path = "/etc/hostid"; char path[PATH_MAX] = "/etc/hostid";
/* holds converted user input or lrand48() generated value */ /* holds converted user input or lrand48() generated value */
unsigned long input_i = 0; unsigned long input_i = 0;
int opt; int opt;
int pathlen;
int force_fwrite = 0; int force_fwrite = 0;
while ((opt = getopt_long(argc, argv, "fo:h?", 0, 0)) != -1) { while ((opt = getopt_long(argc, argv, "fo:h?", 0, 0)) != -1) {
switch (opt) { switch (opt) {
@ -70,7 +73,14 @@ main(int argc, char **argv)
force_fwrite = 1; force_fwrite = 1;
break; break;
case 'o': case 'o':
path = optarg; pathlen = snprintf(path, sizeof (path), "%s", optarg);
if (pathlen >= sizeof (path)) {
fprintf(stderr, "%s\n", strerror(EOVERFLOW));
exit(EXIT_FAILURE);
} else if (pathlen < 1) {
fprintf(stderr, "%s\n", strerror(EINVAL));
exit(EXIT_FAILURE);
}
break; break;
case 'h': case 'h':
case '?': case '?':
@ -108,7 +118,7 @@ main(int argc, char **argv)
if (force_fwrite == 0 && stat(path, &fstat) == 0 && if (force_fwrite == 0 && stat(path, &fstat) == 0 &&
S_ISREG(fstat.st_mode)) { S_ISREG(fstat.st_mode)) {
fprintf(stderr, "%s: %s\n", path, strerror(EEXIST)); fprintf(stderr, "%s: %s\n", path, strerror(EEXIST));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* /*

View File

@ -1,5 +1,4 @@
include $(top_srcdir)/config/Rules.am include $(top_srcdir)/config/Rules.am
include $(top_srcdir)/config/Shellcheck.am
AM_CFLAGS += $(LIBBLKID_CFLAGS) $(LIBUUID_CFLAGS) AM_CFLAGS += $(LIBBLKID_CFLAGS) $(LIBUUID_CFLAGS)
@ -26,8 +25,7 @@ zpool_LDADD = \
$(abs_top_builddir)/lib/libzfs/libzfs.la \ $(abs_top_builddir)/lib/libzfs/libzfs.la \
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \ $(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \ $(abs_top_builddir)/lib/libnvpair/libnvpair.la \
$(abs_top_builddir)/lib/libuutil/libuutil.la \ $(abs_top_builddir)/lib/libuutil/libuutil.la
$(abs_top_builddir)/lib/libzutil/libzutil.la
zpool_LDADD += $(LTLIBINTL) zpool_LDADD += $(LTLIBINTL)

View File

@ -101,39 +101,3 @@ check_sector_size_database(char *path, int *sector_size)
{ {
return (0); return (0);
} }
void
after_zpool_upgrade(zpool_handle_t *zhp)
{
char bootfs[ZPOOL_MAXPROPLEN];
if (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
sizeof (bootfs), NULL, B_FALSE) == 0 &&
strcmp(bootfs, "-") != 0) {
(void) printf(gettext("Pool '%s' has the bootfs "
"property set, you might need to update\nthe boot "
"code. See gptzfsboot(8) and loader.efi(8) for "
"details.\n"), zpool_get_name(zhp));
}
}
int
zpool_power_current_state(zpool_handle_t *zhp, char *vdev)
{
(void) zhp;
(void) vdev;
/* Enclosure slot power not supported on FreeBSD yet */
return (-1);
}
int
zpool_power(zpool_handle_t *zhp, char *vdev, boolean_t turn_on)
{
(void) zhp;
(void) vdev;
(void) turn_on;
/* Enclosure slot power not supported on FreeBSD yet */
return (ENOTSUP);
}

View File

@ -405,263 +405,3 @@ check_device(const char *path, boolean_t force,
return (error); return (error);
} }
void
after_zpool_upgrade(zpool_handle_t *zhp)
{
}
/*
* Read from a sysfs file and return an allocated string. Removes
* the newline from the end of the string if there is one.
*
* Returns a string on success (which must be freed), or NULL on error.
*/
static char *zpool_sysfs_gets(char *path)
{
int fd;
struct stat statbuf;
char *buf = NULL;
ssize_t count = 0;
fd = open(path, O_RDONLY);
if (fd < 0)
return (NULL);
if (fstat(fd, &statbuf) != 0) {
close(fd);
return (NULL);
}
buf = calloc(sizeof (*buf), statbuf.st_size + 1);
if (buf == NULL) {
close(fd);
return (NULL);
}
/*
* Note, we can read less bytes than st_size, and that's ok. Sysfs
* files will report their size is 4k even if they only return a small
* string.
*/
count = read(fd, buf, statbuf.st_size);
if (count < 0) {
/* Error doing read() or we overran the buffer */
close(fd);
free(buf);
return (NULL);
}
/* Remove trailing newline */
if (buf[count - 1] == '\n')
buf[count - 1] = 0;
close(fd);
return (buf);
}
/*
* Write a string to a sysfs file.
*
* Returns 0 on success, non-zero otherwise.
*/
static int zpool_sysfs_puts(char *path, char *str)
{
FILE *file;
file = fopen(path, "w");
if (!file) {
return (-1);
}
if (fputs(str, file) < 0) {
fclose(file);
return (-2);
}
fclose(file);
return (0);
}
/* Given a vdev nvlist_t, rescan its enclosure sysfs path */
static void
rescan_vdev_config_dev_sysfs_path(nvlist_t *vdev_nv)
{
update_vdev_config_dev_sysfs_path(vdev_nv,
fnvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_PATH),
ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
}
/*
* Given a power string: "on", "off", "1", or "0", return 0 if it's an
* off value, 1 if it's an on value, and -1 if the value is unrecognized.
*/
static int zpool_power_parse_value(char *str)
{
if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0))
return (0);
if ((strcmp(str, "on") == 0) || (strcmp(str, "1") == 0))
return (1);
return (-1);
}
/*
* Given a vdev string return an allocated string containing the sysfs path to
* its power control file. Also do a check if the power control file really
* exists and has correct permissions.
*
* Example returned strings:
*
* /sys/class/enclosure/0:0:122:0/10/power_status
* /sys/bus/pci/slots/10/power
*
* Returns allocated string on success (which must be freed), NULL on failure.
*/
static char *
zpool_power_sysfs_path(zpool_handle_t *zhp, char *vdev)
{
char *enc_sysfs_dir = NULL;
char *path = NULL;
nvlist_t *vdev_nv = zpool_find_vdev(zhp, vdev, NULL, NULL, NULL);
if (vdev_nv == NULL) {
return (NULL);
}
/* Make sure we're getting the updated enclosure sysfs path */
rescan_vdev_config_dev_sysfs_path(vdev_nv);
if (nvlist_lookup_string(vdev_nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
&enc_sysfs_dir) != 0) {
return (NULL);
}
if (asprintf(&path, "%s/power_status", enc_sysfs_dir) == -1)
return (NULL);
if (access(path, W_OK) != 0) {
free(path);
path = NULL;
/* No HDD 'power_control' file, maybe it's NVMe? */
if (asprintf(&path, "%s/power", enc_sysfs_dir) == -1) {
return (NULL);
}
if (access(path, R_OK | W_OK) != 0) {
/* Not NVMe either */
free(path);
return (NULL);
}
}
return (path);
}
/*
* Given a path to a sysfs power control file, return B_TRUE if you should use
* "on/off" words to control it, or B_FALSE otherwise ("0/1" to control).
*/
static boolean_t
zpool_power_use_word(char *sysfs_path)
{
if (strcmp(&sysfs_path[strlen(sysfs_path) - strlen("power_status")],
"power_status") == 0) {
return (B_TRUE);
}
return (B_FALSE);
}
/*
* Check the sysfs power control value for a vdev.
*
* Returns:
* 0 - Power is off
* 1 - Power is on
* -1 - Error or unsupported
*/
int
zpool_power_current_state(zpool_handle_t *zhp, char *vdev)
{
char *val;
int rc;
char *path = zpool_power_sysfs_path(zhp, vdev);
if (path == NULL)
return (-1);
val = zpool_sysfs_gets(path);
if (val == NULL) {
free(path);
return (-1);
}
rc = zpool_power_parse_value(val);
free(val);
free(path);
return (rc);
}
/*
* Turn on or off the slot to a device
*
* Device path is the full path to the device (like /dev/sda or /dev/sda1).
*
* Return code:
* 0: Success
* ENOTSUP: Power control not supported for OS
* EBADSLT: Couldn't read current power state
* ENOENT: No sysfs path to power control
* EIO: Couldn't write sysfs power value
* EBADE: Sysfs power value didn't change
*/
int
zpool_power(zpool_handle_t *zhp, char *vdev, boolean_t turn_on)
{
char *sysfs_path;
const char *val;
int rc;
int timeout_ms;
rc = zpool_power_current_state(zhp, vdev);
if (rc == -1) {
return (EBADSLT);
}
/* Already correct value? */
if (rc == (int)turn_on)
return (0);
sysfs_path = zpool_power_sysfs_path(zhp, vdev);
if (sysfs_path == NULL)
return (ENOENT);
if (zpool_power_use_word(sysfs_path)) {
val = turn_on ? "on" : "off";
} else {
val = turn_on ? "1" : "0";
}
rc = zpool_sysfs_puts(sysfs_path, (char *)val);
free(sysfs_path);
if (rc != 0) {
return (EIO);
}
/*
* Wait up to 30 seconds for sysfs power value to change after
* writing it.
*/
timeout_ms = zpool_getenv_int("ZPOOL_POWER_ON_SLOT_TIMEOUT_MS", 30000);
for (int i = 0; i < MAX(1, timeout_ms / 200); i++) {
rc = zpool_power_current_state(zhp, vdev);
if (rc == (int)turn_on)
return (0); /* success */
fsleep(0.200); /* 200ms */
}
/* sysfs value never changed */
return (EBADE);
}

View File

@ -16,12 +16,14 @@ if [ -L "$dev" ] ; then
dev=$(readlink "$dev") dev=$(readlink "$dev")
fi fi
dev="${dev##*/}" dev=$(basename "$dev")
val="" val=""
if [ -d "/sys/class/block/$dev/slaves" ] ; then if [ -d "/sys/class/block/$dev/slaves" ] ; then
# ls -C: output in columns, no newlines, two spaces (change to one) # ls -C: output in columns, no newlines
# shellcheck disable=SC2012 val=$(ls -C "/sys/class/block/$dev/slaves")
val=$(ls -C "/sys/class/block/$dev/slaves" | tr -s '[:space:]' ' ')
# ls -C will print two spaces between files; change to one space.
val=$(echo "$val" | sed -r 's/[[:blank:]]+/ /g')
fi fi
echo "dm-deps=$val" echo "dm-deps=$val"

View File

@ -9,7 +9,7 @@ iostat: Show iostat values since boot (summary page).
iostat-1s: Do a single 1-second iostat sample and show values. iostat-1s: Do a single 1-second iostat sample and show values.
iostat-10s: Do a single 10-second iostat sample and show values." iostat-10s: Do a single 10-second iostat sample and show values."
script="${0##*/}" script=$(basename "$0")
if [ "$1" = "-h" ] ; then if [ "$1" = "-h" ] ; then
echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2- echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2-
exit exit
@ -42,7 +42,7 @@ else
${brief:+"-y"} \ ${brief:+"-y"} \
${interval:+"$interval"} \ ${interval:+"$interval"} \
${interval:+"1"} \ ${interval:+"1"} \
"$VDEV_UPATH" | grep -v '^$' | tail -n 2) "$VDEV_UPATH" | awk NF | tail -n 2)
fi fi
@ -61,7 +61,7 @@ fi
cols=$(echo "$out" | head -n 1) cols=$(echo "$out" | head -n 1)
# Get the values and tab separate them to make them cut-able. # Get the values and tab separate them to make them cut-able.
vals=$(echo "$out" | tail -n 1 | tr -s '[:space:]' '\t') vals=$(echo "$out" | tail -n 1 | sed -r 's/[[:blank:]]+/\t/g')
i=0 i=0
for col in $cols ; do for col in $cols ; do

View File

@ -48,7 +48,7 @@ size: Show the disk capacity.
vendor: Show the disk vendor. vendor: Show the disk vendor.
lsblk: Show the disk size, vendor, and model number." lsblk: Show the disk size, vendor, and model number."
script="${0##*/}" script=$(basename "$0")
if [ "$1" = "-h" ] ; then if [ "$1" = "-h" ] ; then
echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2- echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2-

View File

@ -4,23 +4,19 @@
# #
if [ "$1" = "-h" ] ; then if [ "$1" = "-h" ] ; then
echo "Show whether a vdev is a file, hdd, ssd, or iscsi." echo "Show whether a vdev is a file, hdd, or ssd."
exit exit
fi fi
if [ -b "$VDEV_UPATH" ]; then if [ -b "$VDEV_UPATH" ]; then
device="${VDEV_UPATH##*/}" device=$(basename "$VDEV_UPATH")
read -r val 2>/dev/null < "/sys/block/$device/queue/rotational" val=$(cat "/sys/block/$device/queue/rotational" 2>/dev/null)
case "$val" in if [ "$val" = "0" ]; then
0) MEDIA="ssd" ;; MEDIA="ssd"
1) MEDIA="hdd" ;; fi
esac
vpd_pg83="/sys/block/$device/device/vpd_pg83" if [ "$val" = "1" ]; then
if [ -f "$vpd_pg83" ]; then MEDIA="hdd"
if grep -q --binary "iqn." "$vpd_pg83"; then
MEDIA="iscsi"
fi
fi fi
else else
if [ -f "$VDEV_UPATH" ]; then if [ -f "$VDEV_UPATH" ]; then

View File

@ -11,7 +11,7 @@ fault_led: Show value of the disk enclosure slot fault LED.
locate_led: Show value of the disk enclosure slot locate LED. locate_led: Show value of the disk enclosure slot locate LED.
ses: Show disk's enc, enc device, slot, and fault/locate LED values." ses: Show disk's enc, enc device, slot, and fault/locate LED values."
script="${0##*/}" script=$(basename "$0")
if [ "$1" = "-h" ] ; then if [ "$1" = "-h" ] ; then
echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2- echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2-
exit exit
@ -32,30 +32,16 @@ for i in $scripts ; do
val="" val=""
case $i in case $i in
enc) enc)
if echo "$VDEV_ENC_SYSFS_PATH" | grep -q '/sys/bus/pci/slots' ; then val=$(ls "$VDEV_ENC_SYSFS_PATH/../../" 2>/dev/null)
val="$VDEV_ENC_SYSFS_PATH"
else
val="$(ls """$VDEV_ENC_SYSFS_PATH/../../""" 2>/dev/null)"
fi
;; ;;
slot) slot)
if echo "$VDEV_ENC_SYSFS_PATH" | grep -q '/sys/bus/pci/slots' ; then val=$(cat "$VDEV_ENC_SYSFS_PATH/slot" 2>/dev/null)
val="$(basename """$VDEV_ENC_SYSFS_PATH""")"
else
val="$(cat """$VDEV_ENC_SYSFS_PATH/slot""" 2>/dev/null)"
fi
;; ;;
encdev) encdev)
val=$(ls "$VDEV_ENC_SYSFS_PATH/../device/scsi_generic" 2>/dev/null) val=$(ls "$VDEV_ENC_SYSFS_PATH/../device/scsi_generic" 2>/dev/null)
;; ;;
fault_led) fault_led)
# JBODs fault LED is called 'fault', NVMe fault LED is called val=$(cat "$VDEV_ENC_SYSFS_PATH/fault" 2>/dev/null)
# 'attention'.
if [ -f "$VDEV_ENC_SYSFS_PATH/fault" ] ; then
val=$(cat "$VDEV_ENC_SYSFS_PATH/fault" 2>/dev/null)
elif [ -f "$VDEV_ENC_SYSFS_PATH/attention" ] ; then
val=$(cat "$VDEV_ENC_SYSFS_PATH/attention" 2>/dev/null)
fi
;; ;;
locate_led) locate_led)
val=$(cat "$VDEV_ENC_SYSFS_PATH/locate" 2>/dev/null) val=$(cat "$VDEV_ENC_SYSFS_PATH/locate" 2>/dev/null)

View File

@ -53,7 +53,7 @@ get_filename_from_dir()
num_files=$(find "$dir" -maxdepth 1 -type f | wc -l) num_files=$(find "$dir" -maxdepth 1 -type f | wc -l)
mod=$((pid % num_files)) mod=$((pid % num_files))
i=0 i=0
find "$dir" -type f -printf '%f\n' | while read -r file ; do find "$dir" -type f -printf "%f\n" | while read -r file ; do
if [ "$mod" = "$i" ] ; then if [ "$mod" = "$i" ] ; then
echo "$file" echo "$file"
break break
@ -62,14 +62,17 @@ get_filename_from_dir()
done done
} }
script="${0##*/}" script=$(basename "$0")
if [ "$1" = "-h" ] ; then if [ "$1" = "-h" ] ; then
echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2- echo "$helpstr" | grep "$script:" | tr -s '\t' | cut -f 2-
exit exit
fi fi
if [ -b "$VDEV_UPATH" ] && PATH="/usr/sbin:$PATH" command -v smartctl > /dev/null || [ -n "$samples" ] ; then smartctl_path=$(command -v smartctl)
# shellcheck disable=SC2015
if [ -b "$VDEV_UPATH" ] && [ -x "$smartctl_path" ] || [ -n "$samples" ] ; then
if [ -n "$samples" ] ; then if [ -n "$samples" ] ; then
# cat a smartctl output text file instead of running smartctl # cat a smartctl output text file instead of running smartctl
# on a vdev (only used for developer testing). # on a vdev (only used for developer testing).
@ -77,7 +80,7 @@ if [ -b "$VDEV_UPATH" ] && PATH="/usr/sbin:$PATH" command -v smartctl > /dev/nul
echo "file=$file" echo "file=$file"
raw_out=$(cat "$samples/$file") raw_out=$(cat "$samples/$file")
else else
raw_out=$(sudo smartctl -a "$VDEV_UPATH") raw_out=$(eval "sudo $smartctl_path -a $VDEV_UPATH")
fi fi
# What kind of drive are we? Look for the right line in smartctl: # What kind of drive are we? Look for the right line in smartctl:
@ -228,11 +231,11 @@ esac
with_vals=$(echo "$out" | grep -E "$scripts") with_vals=$(echo "$out" | grep -E "$scripts")
if [ -n "$with_vals" ]; then if [ -n "$with_vals" ]; then
echo "$with_vals" echo "$with_vals"
without_vals=$(echo "$scripts" | tr '|' '\n' | without_vals=$(echo "$scripts" | tr "|" "\n" |
grep -v -E "$(echo "$with_vals" | grep -v -E "$(echo "$with_vals" |
awk -F "=" '{print $1}')" | awk '{print $0"="}') awk -F "=" '{print $1}')" | awk '{print $0"="}')
else else
without_vals=$(echo "$scripts" | tr '|' '\n' | awk '{print $0"="}') without_vals=$(echo "$scripts" | tr "|" "\n" | awk '{print $0"="}')
fi fi
if [ -n "$without_vals" ]; then if [ -n "$without_vals" ]; then

View File

@ -264,6 +264,51 @@ for_each_pool(int argc, char **argv, boolean_t unavail,
return (ret); return (ret);
} }
static int
for_each_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, pool_vdev_iter_f func,
void *data)
{
nvlist_t **child;
uint_t c, children;
int ret = 0;
int i;
char *type;
const char *list[] = {
ZPOOL_CONFIG_SPARES,
ZPOOL_CONFIG_L2CACHE,
ZPOOL_CONFIG_CHILDREN
};
for (i = 0; i < ARRAY_SIZE(list); i++) {
if (nvlist_lookup_nvlist_array(nv, list[i], &child,
&children) == 0) {
for (c = 0; c < children; c++) {
uint64_t ishole = 0;
(void) nvlist_lookup_uint64(child[c],
ZPOOL_CONFIG_IS_HOLE, &ishole);
if (ishole)
continue;
ret |= for_each_vdev_cb(zhp, child[c], func,
data);
}
}
}
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
return (ret);
/* Don't run our function on root vdevs */
if (strcmp(type, VDEV_TYPE_ROOT) != 0) {
ret |= func(zhp, nv, data);
}
return (ret);
}
/* /*
* This is the equivalent of for_each_pool() for vdevs. It iterates thorough * This is the equivalent of for_each_pool() for vdevs. It iterates thorough
* all vdevs in the pool, ignoring root vdevs and holes, calling func() on * all vdevs in the pool, ignoring root vdevs and holes, calling func() on
@ -282,7 +327,7 @@ for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func, void *data)
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvroot) == 0); &nvroot) == 0);
} }
return (for_each_vdev_cb((void *) zhp, nvroot, func, data)); return (for_each_vdev_cb(zhp, nvroot, func, data));
} }
/* /*
@ -439,23 +484,33 @@ static void
vdev_run_cmd(vdev_cmd_data_t *data, char *cmd) vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
{ {
int rc; int rc;
char *argv[2] = {cmd}; char *argv[2] = {cmd, 0};
char **env; char *env[5] = {"PATH=/bin:/sbin:/usr/bin:/usr/sbin", NULL, NULL, NULL,
NULL};
char **lines = NULL; char **lines = NULL;
int lines_cnt = 0; int lines_cnt = 0;
int i; int i;
env = zpool_vdev_script_alloc_env(data->pool, data->path, data->upath, /* Setup our custom environment variables */
data->vdev_enc_sysfs_path, NULL, NULL); rc = asprintf(&env[1], "VDEV_PATH=%s",
if (env == NULL) data->path ? data->path : "");
if (rc == -1)
goto out;
rc = asprintf(&env[2], "VDEV_UPATH=%s",
data->upath ? data->upath : "");
if (rc == -1)
goto out;
rc = asprintf(&env[3], "VDEV_ENC_SYSFS_PATH=%s",
data->vdev_enc_sysfs_path ?
data->vdev_enc_sysfs_path : "");
if (rc == -1)
goto out; goto out;
/* Run the command */ /* Run the command */
rc = libzfs_run_process_get_stdout_nopath(cmd, argv, env, &lines, rc = libzfs_run_process_get_stdout_nopath(cmd, argv, env, &lines,
&lines_cnt); &lines_cnt);
zpool_vdev_script_free_env(env);
if (rc != 0) if (rc != 0)
goto out; goto out;
@ -467,6 +522,11 @@ vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
out: out:
if (lines != NULL) if (lines != NULL)
libzfs_free_str_array(lines, lines_cnt); libzfs_free_str_array(lines, lines_cnt);
/* Start with i = 1 since env[0] was statically allocated */
for (i = 1; i < ARRAY_SIZE(env); i++)
if (env[i] != NULL)
free(env[i]);
} }
/* /*
@ -538,7 +598,7 @@ vdev_run_cmd_thread(void *cb_cmd_data)
/* For each vdev in the pool run a command */ /* For each vdev in the pool run a command */
static int static int
for_each_vdev_run_cb(void *zhp_data, nvlist_t *nv, void *cb_vcdl) for_each_vdev_run_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_vcdl)
{ {
vdev_cmd_data_list_t *vcdl = cb_vcdl; vdev_cmd_data_list_t *vcdl = cb_vcdl;
vdev_cmd_data_t *data; vdev_cmd_data_t *data;
@ -546,15 +606,10 @@ for_each_vdev_run_cb(void *zhp_data, nvlist_t *nv, void *cb_vcdl)
char *vname = NULL; char *vname = NULL;
char *vdev_enc_sysfs_path = NULL; char *vdev_enc_sysfs_path = NULL;
int i, match = 0; int i, match = 0;
zpool_handle_t *zhp = zhp_data;
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0) if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
return (1); return (1);
/* Make sure we're getting the updated enclosure sysfs path */
update_vdev_config_dev_sysfs_path(nv, path,
ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
nvlist_lookup_string(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH, nvlist_lookup_string(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
&vdev_enc_sysfs_path); &vdev_enc_sysfs_path);

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,6 @@
#include <libnvpair.h> #include <libnvpair.h>
#include <libzfs.h> #include <libzfs.h>
#include <libzutil.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -68,6 +67,7 @@ int for_each_pool(int, char **, boolean_t unavail, zprop_list_t **,
boolean_t, zpool_iter_f, void *); boolean_t, zpool_iter_f, void *);
/* Vdev list functions */ /* Vdev list functions */
typedef int (*pool_vdev_iter_f)(zpool_handle_t *, nvlist_t *, void *);
int for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func, void *data); int for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func, void *data);
typedef struct zpool_list zpool_list_t; typedef struct zpool_list zpool_list_t;
@ -124,19 +124,11 @@ vdev_cmd_data_list_t *all_pools_for_each_vdev_run(int argc, char **argv,
void free_vdev_cmd_data_list(vdev_cmd_data_list_t *vcdl); void free_vdev_cmd_data_list(vdev_cmd_data_list_t *vcdl);
void free_vdev_cmd_data(vdev_cmd_data_t *data);
int vdev_run_cmd_simple(char *path, char *cmd);
int check_device(const char *path, boolean_t force, int check_device(const char *path, boolean_t force,
boolean_t isspare, boolean_t iswholedisk); boolean_t isspare, boolean_t iswholedisk);
boolean_t check_sector_size_database(char *path, int *sector_size); boolean_t check_sector_size_database(char *path, int *sector_size);
void vdev_error(const char *fmt, ...); void vdev_error(const char *fmt, ...);
int check_file(const char *file, boolean_t force, boolean_t isspare); int check_file(const char *file, boolean_t force, boolean_t isspare);
void after_zpool_upgrade(zpool_handle_t *zhp);
int zpool_power(zpool_handle_t *zhp, char *vdev, boolean_t turn_on);
int zpool_power_current_state(zpool_handle_t *zhp, char *vdev);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -373,10 +373,6 @@ make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0); verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0); verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
/* Lookup and add the enclosure sysfs path (if exists) */
update_vdev_config_dev_sysfs_path(vdev, path,
ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
if (strcmp(type, VDEV_TYPE_DISK) == 0) if (strcmp(type, VDEV_TYPE_DISK) == 0)
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
(uint64_t)wholedisk) == 0); (uint64_t)wholedisk) == 0);
@ -925,15 +921,6 @@ zero_label(char *path)
return (0); return (0);
} }
static void
lines_to_stderr(char *lines[], int lines_cnt)
{
int i;
for (i = 0; i < lines_cnt; i++) {
fprintf(stderr, "%s\n", lines[i]);
}
}
/* /*
* Go through and find any whole disks in the vdev specification, labelling them * Go through and find any whole disks in the vdev specification, labelling them
* as appropriate. When constructing the vdev spec, we were unable to open this * as appropriate. When constructing the vdev spec, we were unable to open this
@ -945,7 +932,7 @@ lines_to_stderr(char *lines[], int lines_cnt)
* need to get the devid after we label the disk. * need to get the devid after we label the disk.
*/ */
static int static int
make_disks(zpool_handle_t *zhp, nvlist_t *nv, boolean_t replacing) make_disks(zpool_handle_t *zhp, nvlist_t *nv)
{ {
nvlist_t **child; nvlist_t **child;
uint_t c, children; uint_t c, children;
@ -1030,8 +1017,6 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv, boolean_t replacing)
*/ */
if (!is_exclusive && !is_spare(NULL, udevpath)) { if (!is_exclusive && !is_spare(NULL, udevpath)) {
char *devnode = strrchr(devpath, '/') + 1; char *devnode = strrchr(devpath, '/') + 1;
char **lines = NULL;
int lines_cnt = 0;
ret = strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT)); ret = strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT));
if (ret == 0) { if (ret == 0) {
@ -1043,27 +1028,9 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv, boolean_t replacing)
/* /*
* When labeling a pool the raw device node name * When labeling a pool the raw device node name
* is provided as it appears under /dev/. * is provided as it appears under /dev/.
*
* Note that 'zhp' will be NULL when we're creating a
* pool.
*/ */
if (zpool_prepare_and_label_disk(g_zfs, zhp, devnode, if (zpool_label_disk(g_zfs, zhp, devnode) == -1)
nv, zhp == NULL ? "create" :
replacing ? "replace" : "add", &lines,
&lines_cnt) != 0) {
(void) fprintf(stderr,
gettext(
"Error preparing/labeling disk.\n"));
if (lines_cnt > 0) {
(void) fprintf(stderr,
gettext("zfs_prepare_disk output:\n"));
lines_to_stderr(lines, lines_cnt);
}
libzfs_free_str_array(lines, lines_cnt);
return (-1); return (-1);
}
libzfs_free_str_array(lines, lines_cnt);
/* /*
* Wait for udev to signal the device is available * Wait for udev to signal the device is available
@ -1100,19 +1067,19 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv, boolean_t replacing)
} }
for (c = 0; c < children; c++) for (c = 0; c < children; c++)
if ((ret = make_disks(zhp, child[c], replacing)) != 0) if ((ret = make_disks(zhp, child[c])) != 0)
return (ret); return (ret);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
&child, &children) == 0) &child, &children) == 0)
for (c = 0; c < children; c++) for (c = 0; c < children; c++)
if ((ret = make_disks(zhp, child[c], replacing)) != 0) if ((ret = make_disks(zhp, child[c])) != 0)
return (ret); return (ret);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
&child, &children) == 0) &child, &children) == 0)
for (c = 0; c < children; c++) for (c = 0; c < children; c++)
if ((ret = make_disks(zhp, child[c], replacing)) != 0) if ((ret = make_disks(zhp, child[c])) != 0)
return (ret); return (ret);
return (0); return (0);
@ -1773,7 +1740,7 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
return (NULL); return (NULL);
} }
if (!flags.dryrun && make_disks(zhp, newroot, B_FALSE) != 0) { if (!flags.dryrun && make_disks(zhp, newroot) != 0) {
nvlist_free(newroot); nvlist_free(newroot);
return (NULL); return (NULL);
} }
@ -1894,7 +1861,7 @@ make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep,
/* /*
* Run through the vdev specification and label any whole disks found. * Run through the vdev specification and label any whole disks found.
*/ */
if (!dryrun && make_disks(zhp, newroot, replacing) != 0) { if (!dryrun && make_disks(zhp, newroot) != 0) {
nvlist_free(newroot); nvlist_free(newroot);
return (NULL); return (NULL);
} }

View File

@ -1360,7 +1360,7 @@
"type": "row" "type": "row"
}, },
{ {
"content": "I/O requests that are satisfied by accessing pool devices are managed by the ZIO scheduler.\nThe total latency is measured from the start of the I/O to completion by the disk.\nLatency through each queue is shown prior to its submission to the disk queue.\n\nThis view is useful for observing the effects of tuning the ZIO scheduler min and max values\n(see zfs(4) and [ZFS on Linux Module Parameters](https://openzfs.github.io/openzfs-docs/Performance%20and%20tuning/ZFS%20on%20Linux%20Module%20Parameters.html)):\n+ *zfs_vdev_max_active* controls the ZIO scheduler's disk queue depth (do not confuse with the block device's nr_requests)\n+ *zfs_vdev_sync_read_min_active* and *zfs_vdev_sync_read_max_active* control the synchronous queue for reads: most reads are sync\n+ *zfs_vdev_sync_write_min_active* and *zfs_vdev_sync_write_max_active* control the synchronous queue for writes: \nusually metadata or user data depending on the \"sync\" property setting or I/Os that are requested to be flushed\n+ *zfs_vdev_async_read_min_active* and *zfs_vdev_async_read_max_active* control the asynchronous queue for reads: usually prefetches\n+ *zfs_vdev_async_write_min_active* and *zfs_vdev_async_write_max_active* control the asynchronous queue for writes: \nusually the bulk of all writes at transaction group (txg) commit\n+ *zfs_vdev_scrub_min_active* and *zfs_vdev_scrub_max_active* controls the scan reads: usually scrub or resilver\n\n", "content": "I/O requests that are satisfied by accessing pool devices are managed by the ZIO scheduler.\nThe total latency is measured from the start of the I/O to completion by the disk.\nLatency through each queue is shown prior to its submission to the disk queue.\n\nThis view is useful for observing the effects of tuning the ZIO scheduler min and max values\n(see zfs-module-parameters(5) and [ZFS on Linux Module Parameters](https://openzfs.github.io/openzfs-docs/Performance%20and%20tuning/ZFS%20on%20Linux%20Module%20Parameters.html)):\n+ *zfs_vdev_max_active* controls the ZIO scheduler's disk queue depth (do not confuse with the block device's nr_requests)\n+ *zfs_vdev_sync_read_min_active* and *zfs_vdev_sync_read_max_active* control the synchronous queue for reads: most reads are sync\n+ *zfs_vdev_sync_write_min_active* and *zfs_vdev_sync_write_max_active* control the synchronous queue for writes: \nusually metadata or user data depending on the \"sync\" property setting or I/Os that are requested to be flushed\n+ *zfs_vdev_async_read_min_active* and *zfs_vdev_async_read_max_active* control the asynchronous queue for reads: usually prefetches\n+ *zfs_vdev_async_write_min_active* and *zfs_vdev_async_write_max_active* control the asynchronous queue for writes: \nusually the bulk of all writes at transaction group (txg) commit\n+ *zfs_vdev_scrub_min_active* and *zfs_vdev_scrub_max_active* controls the scan reads: usually scrub or resilver\n\n",
"datasource": "${DS_MACBOOK-INFLUX}", "datasource": "${DS_MACBOOK-INFLUX}",
"fieldConfig": { "fieldConfig": {
"defaults": { "defaults": {

View File

@ -117,7 +117,6 @@ escape_string(char *s)
case '=': case '=':
case '\\': case '\\':
*d++ = '\\'; *d++ = '\\';
fallthrough;
default: default:
*d = *c; *d = *c;
} }
@ -684,8 +683,9 @@ print_recursive_stats(stat_printer_f func, nvlist_t *nvroot,
if (descend && nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, if (descend && nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&child, &children) == 0) { &child, &children) == 0) {
(void) strlcpy(vdev_name, get_vdev_name(nvroot, parent_name), (void) strncpy(vdev_name, get_vdev_name(nvroot, parent_name),
sizeof (vdev_name)); sizeof (vdev_name));
vdev_name[sizeof (vdev_name) - 1] = '\0';
for (c = 0; c < children; c++) { for (c = 0; c < children; c++) {
print_recursive_stats(func, child[c], pool_name, print_recursive_stats(func, child[c], pool_name,

View File

@ -15,6 +15,3 @@ zstream_LDADD = \
$(abs_top_builddir)/lib/libnvpair/libnvpair.la $(abs_top_builddir)/lib/libnvpair/libnvpair.la
include $(top_srcdir)/config/CppCheck.am include $(top_srcdir)/config/CppCheck.am
install-exec-hook:
cd $(DESTDIR)$(sbindir) && $(LN_S) -f zstream zstreamdump

View File

@ -49,11 +49,6 @@ zstream_usage(void)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *basename = strrchr(argv[0], '/');
basename = basename ? (basename + 1) : argv[0];
if (argc >= 1 && strcmp(basename, "zstreamdump") == 0)
return (zstream_do_dump(argc, argv));
if (argc < 2) if (argc < 2)
zstream_usage(); zstream_usage();

View File

@ -297,7 +297,6 @@ zstream_do_dump(int argc, char *argv[])
fletcher_4_init(); fletcher_4_init();
while (read_hdr(drr, &zc)) { while (read_hdr(drr, &zc)) {
uint64_t featureflags = 0;
/* /*
* If this is the first DMU record being processed, check for * If this is the first DMU record being processed, check for
@ -462,18 +461,6 @@ zstream_do_dump(int argc, char *argv[])
BSWAP_64(drro->drr_maxblkid); BSWAP_64(drro->drr_maxblkid);
} }
featureflags =
DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
if (featureflags & DMU_BACKUP_FEATURE_RAW &&
drro->drr_bonuslen > drro->drr_raw_bonuslen) {
(void) fprintf(stderr,
"Warning: Object %llu has bonuslen = "
"%u > raw_bonuslen = %u\n\n",
(u_longlong_t)drro->drr_object,
drro->drr_bonuslen, drro->drr_raw_bonuslen);
}
payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro); payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
if (verbose) { if (verbose) {

View File

@ -0,0 +1 @@
dist_sbin_SCRIPTS = zstreamdump

3
cmd/zstreamdump/zstreamdump Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
exec zstream dump "$@"

View File

@ -124,7 +124,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <getopt.h>
#include <signal.h> #include <signal.h>
#include <umem.h> #include <umem.h>
#include <ctype.h> #include <ctype.h>
@ -193,58 +192,30 @@ typedef struct ztest_shared_opts {
char zo_gvars[ZO_GVARS_MAX_COUNT][ZO_GVARS_MAX_ARGLEN]; char zo_gvars[ZO_GVARS_MAX_COUNT][ZO_GVARS_MAX_ARGLEN];
} ztest_shared_opts_t; } ztest_shared_opts_t;
/* Default values for command line options. */
#define DEFAULT_POOL "ztest"
#define DEFAULT_VDEV_DIR "/tmp"
#define DEFAULT_VDEV_COUNT 5
#define DEFAULT_VDEV_SIZE (SPA_MINDEVSIZE * 4) /* 256m default size */
#define DEFAULT_VDEV_SIZE_STR "256M"
#define DEFAULT_ASHIFT SPA_MINBLOCKSHIFT
#define DEFAULT_MIRRORS 2
#define DEFAULT_RAID_CHILDREN 4
#define DEFAULT_RAID_PARITY 1
#define DEFAULT_DRAID_DATA 4
#define DEFAULT_DRAID_SPARES 1
#define DEFAULT_DATASETS_COUNT 7
#define DEFAULT_THREADS 23
#define DEFAULT_RUN_TIME 300 /* 300 seconds */
#define DEFAULT_RUN_TIME_STR "300 sec"
#define DEFAULT_PASS_TIME 60 /* 60 seconds */
#define DEFAULT_PASS_TIME_STR "60 sec"
#define DEFAULT_KILL_RATE 70 /* 70% kill rate */
#define DEFAULT_KILLRATE_STR "70%"
#define DEFAULT_INITS 1
#define DEFAULT_MAX_LOOPS 50 /* 5 minutes */
#define DEFAULT_FORCE_GANGING (64 << 10)
#define DEFAULT_FORCE_GANGING_STR "64K"
/* Simplifying assumption: -1 is not a valid default. */
#define NO_DEFAULT -1
static const ztest_shared_opts_t ztest_opts_defaults = { static const ztest_shared_opts_t ztest_opts_defaults = {
.zo_pool = DEFAULT_POOL, .zo_pool = "ztest",
.zo_dir = DEFAULT_VDEV_DIR, .zo_dir = "/tmp",
.zo_alt_ztest = { '\0' }, .zo_alt_ztest = { '\0' },
.zo_alt_libpath = { '\0' }, .zo_alt_libpath = { '\0' },
.zo_vdevs = DEFAULT_VDEV_COUNT, .zo_vdevs = 5,
.zo_ashift = DEFAULT_ASHIFT, .zo_ashift = SPA_MINBLOCKSHIFT,
.zo_mirrors = DEFAULT_MIRRORS, .zo_mirrors = 2,
.zo_raid_children = DEFAULT_RAID_CHILDREN, .zo_raid_children = 4,
.zo_raid_parity = DEFAULT_RAID_PARITY, .zo_raid_parity = 1,
.zo_raid_type = VDEV_TYPE_RAIDZ, .zo_raid_type = VDEV_TYPE_RAIDZ,
.zo_vdev_size = DEFAULT_VDEV_SIZE, .zo_vdev_size = SPA_MINDEVSIZE * 4, /* 256m default size */
.zo_draid_data = DEFAULT_DRAID_DATA, /* data drives */ .zo_draid_data = 4, /* data drives */
.zo_draid_spares = DEFAULT_DRAID_SPARES, /* distributed spares */ .zo_draid_spares = 1, /* distributed spares */
.zo_datasets = DEFAULT_DATASETS_COUNT, .zo_datasets = 7,
.zo_threads = DEFAULT_THREADS, .zo_threads = 23,
.zo_passtime = DEFAULT_PASS_TIME, .zo_passtime = 60, /* 60 seconds */
.zo_killrate = DEFAULT_KILL_RATE, .zo_killrate = 70, /* 70% kill rate */
.zo_verbose = 0, .zo_verbose = 0,
.zo_mmp_test = 0, .zo_mmp_test = 0,
.zo_init = DEFAULT_INITS, .zo_init = 1,
.zo_time = DEFAULT_RUN_TIME, .zo_time = 300, /* 5 minutes */
.zo_maxloops = DEFAULT_MAX_LOOPS, /* max loops during spa_freeze() */ .zo_maxloops = 50, /* max loops during spa_freeze() */
.zo_metaslab_force_ganging = DEFAULT_FORCE_GANGING, .zo_metaslab_force_ganging = 64 << 10,
.zo_special_vdevs = ZTEST_VDEV_CLASS_RND, .zo_special_vdevs = ZTEST_VDEV_CLASS_RND,
.zo_gvars_count = 0, .zo_gvars_count = 0,
}; };
@ -713,154 +684,68 @@ nicenumtoull(const char *buf)
return (val); return (val);
} }
typedef struct ztest_option {
const char short_opt;
const char *long_opt;
const char *long_opt_param;
const char *comment;
unsigned int default_int;
char *default_str;
} ztest_option_t;
/*
* The following option_table is used for generating the usage info as well as
* the long and short option information for calling getopt_long().
*/
static ztest_option_t option_table[] = {
{ 'v', "vdevs", "INTEGER", "Number of vdevs", DEFAULT_VDEV_COUNT,
NULL},
{ 's', "vdev-size", "INTEGER", "Size of each vdev",
NO_DEFAULT, DEFAULT_VDEV_SIZE_STR},
{ 'a', "alignment-shift", "INTEGER",
"Alignment shift; use 0 for random", DEFAULT_ASHIFT, NULL},
{ 'm', "mirror-copies", "INTEGER", "Number of mirror copies",
DEFAULT_MIRRORS, NULL},
{ 'r', "raid-disks", "INTEGER", "Number of raidz/draid disks",
DEFAULT_RAID_CHILDREN, NULL},
{ 'R', "raid-parity", "INTEGER", "Raid parity",
DEFAULT_RAID_PARITY, NULL},
{ 'K', "raid-kind", "raidz|draid|random", "Raid kind",
NO_DEFAULT, "random"},
{ 'D', "draid-data", "INTEGER", "Number of draid data drives",
DEFAULT_DRAID_DATA, NULL},
{ 'S', "draid-spares", "INTEGER", "Number of draid spares",
DEFAULT_DRAID_SPARES, NULL},
{ 'd', "datasets", "INTEGER", "Number of datasets",
DEFAULT_DATASETS_COUNT, NULL},
{ 't', "threads", "INTEGER", "Number of ztest threads",
DEFAULT_THREADS, NULL},
{ 'g', "gang-block-threshold", "INTEGER",
"Metaslab gang block threshold",
NO_DEFAULT, DEFAULT_FORCE_GANGING_STR},
{ 'i', "init-count", "INTEGER", "Number of times to initialize pool",
DEFAULT_INITS, NULL},
{ 'k', "kill-percentage", "INTEGER", "Kill percentage",
NO_DEFAULT, DEFAULT_KILLRATE_STR},
{ 'p', "pool-name", "STRING", "Pool name",
NO_DEFAULT, DEFAULT_POOL},
{ 'f', "vdev-file-directory", "PATH", "File directory for vdev files",
NO_DEFAULT, DEFAULT_VDEV_DIR},
{ 'M', "multi-host", NULL,
"Multi-host; simulate pool imported on remote host",
NO_DEFAULT, NULL},
{ 'E', "use-existing-pool", NULL,
"Use existing pool instead of creating new one", NO_DEFAULT, NULL},
{ 'T', "run-time", "INTEGER", "Total run time",
NO_DEFAULT, DEFAULT_RUN_TIME_STR},
{ 'P', "pass-time", "INTEGER", "Time per pass",
NO_DEFAULT, DEFAULT_PASS_TIME_STR},
{ 'F', "freeze-loops", "INTEGER", "Max loops in spa_freeze()",
DEFAULT_MAX_LOOPS, NULL},
{ 'B', "alt-ztest", "PATH", "Alternate ztest path",
NO_DEFAULT, NULL},
{ 'C', "vdev-class-state", "on|off|random", "vdev class state",
NO_DEFAULT, "random"},
{ 'o', "option", "\"OPTION=INTEGER\"",
"Set global variable to an unsigned 32-bit integer value",
NO_DEFAULT, NULL},
{ 'G', "dump-debug-msg", NULL,
"Dump zfs_dbgmsg buffer before exiting due to an error",
NO_DEFAULT, NULL},
{ 'V', "verbose", NULL,
"Verbose (use multiple times for ever more verbosity)",
NO_DEFAULT, NULL},
{ 'h', "help", NULL, "Show this help",
NO_DEFAULT, NULL},
{0, 0, 0, 0, 0, 0}
};
static struct option *long_opts = NULL;
static char *short_opts = NULL;
static void
init_options(void)
{
ASSERT3P(long_opts, ==, NULL);
ASSERT3P(short_opts, ==, NULL);
int count = sizeof (option_table) / sizeof (option_table[0]);
long_opts = umem_alloc(sizeof (struct option) * count, UMEM_NOFAIL);
short_opts = umem_alloc(sizeof (char) * 2 * count, UMEM_NOFAIL);
int short_opt_index = 0;
for (int i = 0; i < count; i++) {
long_opts[i].val = option_table[i].short_opt;
long_opts[i].name = option_table[i].long_opt;
long_opts[i].has_arg = option_table[i].long_opt_param != NULL
? required_argument : no_argument;
long_opts[i].flag = NULL;
short_opts[short_opt_index++] = option_table[i].short_opt;
if (option_table[i].long_opt_param != NULL) {
short_opts[short_opt_index++] = ':';
}
}
}
static void
fini_options(void)
{
int count = sizeof (option_table) / sizeof (option_table[0]);
umem_free(long_opts, sizeof (struct option) * count);
umem_free(short_opts, sizeof (char) * 2 * count);
long_opts = NULL;
short_opts = NULL;
}
static void static void
usage(boolean_t requested) usage(boolean_t requested)
{ {
char option[80]; const ztest_shared_opts_t *zo = &ztest_opts_defaults;
char nice_vdev_size[NN_NUMBUF_SZ];
char nice_force_ganging[NN_NUMBUF_SZ];
FILE *fp = requested ? stdout : stderr; FILE *fp = requested ? stdout : stderr;
(void) fprintf(fp, "Usage: %s [OPTIONS...]\n", DEFAULT_POOL); nicenum(zo->zo_vdev_size, nice_vdev_size, sizeof (nice_vdev_size));
for (int i = 0; option_table[i].short_opt != 0; i++) { nicenum(zo->zo_metaslab_force_ganging, nice_force_ganging,
if (option_table[i].long_opt_param != NULL) { sizeof (nice_force_ganging));
(void) sprintf(option, " -%c --%s=%s",
option_table[i].short_opt,
option_table[i].long_opt,
option_table[i].long_opt_param);
} else {
(void) sprintf(option, " -%c --%s",
option_table[i].short_opt,
option_table[i].long_opt);
}
(void) fprintf(fp, " %-40s%s", option,
option_table[i].comment);
if (option_table[i].long_opt_param != NULL) { (void) fprintf(fp, "Usage: %s\n"
if (option_table[i].default_str != NULL) { "\t[-v vdevs (default: %llu)]\n"
(void) fprintf(fp, " (default: %s)", "\t[-s size_of_each_vdev (default: %s)]\n"
option_table[i].default_str); "\t[-a alignment_shift (default: %d)] use 0 for random\n"
} else if (option_table[i].default_int != NO_DEFAULT) { "\t[-m mirror_copies (default: %d)]\n"
(void) fprintf(fp, " (default: %u)", "\t[-r raidz_disks / draid_disks (default: %d)]\n"
option_table[i].default_int); "\t[-R raid_parity (default: %d)]\n"
} "\t[-K raid_kind (default: random)] raidz|draid|random\n"
} "\t[-D draid_data (default: %d)] in config\n"
(void) fprintf(fp, "\n"); "\t[-S draid_spares (default: %d)]\n"
} "\t[-d datasets (default: %d)]\n"
"\t[-t threads (default: %d)]\n"
"\t[-g gang_block_threshold (default: %s)]\n"
"\t[-i init_count (default: %d)] initialize pool i times\n"
"\t[-k kill_percentage (default: %llu%%)]\n"
"\t[-p pool_name (default: %s)]\n"
"\t[-f dir (default: %s)] file directory for vdev files\n"
"\t[-M] Multi-host simulate pool imported on remote host\n"
"\t[-V] verbose (use multiple times for ever more blather)\n"
"\t[-E] use existing pool instead of creating new one\n"
"\t[-T time (default: %llu sec)] total run time\n"
"\t[-F freezeloops (default: %llu)] max loops in spa_freeze()\n"
"\t[-P passtime (default: %llu sec)] time per pass\n"
"\t[-B alt_ztest (default: <none>)] alternate ztest path\n"
"\t[-C vdev class state (default: random)] special=on|off|random\n"
"\t[-o variable=value] ... set global variable to an unsigned\n"
"\t 32-bit integer value\n"
"\t[-G dump zfs_dbgmsg buffer before exiting due to an error\n"
"\t[-h] (print help)\n"
"",
zo->zo_pool,
(u_longlong_t)zo->zo_vdevs, /* -v */
nice_vdev_size, /* -s */
zo->zo_ashift, /* -a */
zo->zo_mirrors, /* -m */
zo->zo_raid_children, /* -r */
zo->zo_raid_parity, /* -R */
zo->zo_draid_data, /* -D */
zo->zo_draid_spares, /* -S */
zo->zo_datasets, /* -d */
zo->zo_threads, /* -t */
nice_force_ganging, /* -g */
zo->zo_init, /* -i */
(u_longlong_t)zo->zo_killrate, /* -k */
zo->zo_pool, /* -p */
zo->zo_dir, /* -f */
(u_longlong_t)zo->zo_time, /* -T */
(u_longlong_t)zo->zo_maxloops, /* -F */
(u_longlong_t)zo->zo_passtime);
exit(requested ? 0 : 1); exit(requested ? 0 : 1);
} }
@ -932,10 +817,8 @@ process_options(int argc, char **argv)
bcopy(&ztest_opts_defaults, zo, sizeof (*zo)); bcopy(&ztest_opts_defaults, zo, sizeof (*zo));
init_options(); while ((opt = getopt(argc, argv,
"v:s:a:m:r:R:K:D:S:d:t:g:i:k:p:f:MVET:P:hF:B:C:o:G")) != EOF) {
while ((opt = getopt_long(argc, argv, short_opts, long_opts,
NULL)) != EOF) {
value = 0; value = 0;
switch (opt) { switch (opt) {
case 'v': case 'v':
@ -1070,8 +953,6 @@ process_options(int argc, char **argv)
} }
} }
fini_options();
/* When raid choice is 'random' add a draid pool 50% of the time */ /* When raid choice is 'random' add a draid pool 50% of the time */
if (strcmp(raid_kind, "random") == 0) { if (strcmp(raid_kind, "random") == 0) {
(void) strlcpy(raid_kind, (ztest_random(2) == 0) ? (void) strlcpy(raid_kind, (ztest_random(2) == 0) ?
@ -1184,7 +1065,7 @@ ztest_kill(ztest_shared_t *zs)
* See comment above spa_write_cachefile(). * See comment above spa_write_cachefile().
*/ */
mutex_enter(&spa_namespace_lock); mutex_enter(&spa_namespace_lock);
spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE, B_FALSE); spa_write_cachefile(ztest_spa, B_FALSE, B_FALSE);
mutex_exit(&spa_namespace_lock); mutex_exit(&spa_namespace_lock);
(void) kill(getpid(), SIGKILL); (void) kill(getpid(), SIGKILL);
@ -2193,7 +2074,6 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap)
* but not always, because we also want to verify correct * but not always, because we also want to verify correct
* behavior when the data was not recently read into cache. * behavior when the data was not recently read into cache.
*/ */
ASSERT(doi.doi_data_block_size);
ASSERT0(offset % doi.doi_data_block_size); ASSERT0(offset % doi.doi_data_block_size);
if (ztest_random(4) != 0) { if (ztest_random(4) != 0) {
int prefetch = ztest_random(2) ? int prefetch = ztest_random(2) ?
@ -6670,7 +6550,7 @@ ztest_initialize(ztest_ds_t *zd, uint64_t id)
char *path = strdup(rand_vd->vdev_path); char *path = strdup(rand_vd->vdev_path);
boolean_t active = rand_vd->vdev_initialize_thread != NULL; boolean_t active = rand_vd->vdev_initialize_thread != NULL;
zfs_dbgmsg("vd %px, guid %llu", rand_vd, (u_longlong_t)guid); zfs_dbgmsg("vd %px, guid %llu", rand_vd, guid);
spa_config_exit(spa, SCL_VDEV, FTAG); spa_config_exit(spa, SCL_VDEV, FTAG);
uint64_t cmd = ztest_random(POOL_INITIALIZE_FUNCS); uint64_t cmd = ztest_random(POOL_INITIALIZE_FUNCS);
@ -6742,7 +6622,7 @@ ztest_trim(ztest_ds_t *zd, uint64_t id)
char *path = strdup(rand_vd->vdev_path); char *path = strdup(rand_vd->vdev_path);
boolean_t active = rand_vd->vdev_trim_thread != NULL; boolean_t active = rand_vd->vdev_trim_thread != NULL;
zfs_dbgmsg("vd %p, guid %llu", rand_vd, (u_longlong_t)guid); zfs_dbgmsg("vd %p, guid %llu", rand_vd, guid);
spa_config_exit(spa, SCL_VDEV, FTAG); spa_config_exit(spa, SCL_VDEV, FTAG);
uint64_t cmd = ztest_random(POOL_TRIM_FUNCS); uint64_t cmd = ztest_random(POOL_TRIM_FUNCS);

View File

@ -38,39 +38,40 @@
static int static int
ioctl_get_msg(char *var, int fd) ioctl_get_msg(char *var, int fd)
{ {
int ret; int error = 0;
char msg[ZFS_MAX_DATASET_NAME_LEN]; char msg[ZFS_MAX_DATASET_NAME_LEN];
ret = ioctl(fd, BLKZNAME, msg); error = ioctl(fd, BLKZNAME, msg);
if (ret < 0) { if (error < 0) {
return (ret); return (error);
} }
snprintf(var, ZFS_MAX_DATASET_NAME_LEN, "%s", msg); snprintf(var, ZFS_MAX_DATASET_NAME_LEN, "%s", msg);
return (ret); return (error);
} }
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int fd = -1, ret = 0, status = EXIT_FAILURE; int fd, error = 0;
char zvol_name[ZFS_MAX_DATASET_NAME_LEN]; char zvol_name[ZFS_MAX_DATASET_NAME_LEN];
char *zvol_name_part = NULL; char *zvol_name_part = NULL;
char *dev_name; char *dev_name;
struct stat64 statbuf; struct stat64 statbuf;
int dev_minor, dev_part; int dev_minor, dev_part;
int i; int i;
int rc;
if (argc < 2) { if (argc < 2) {
fprintf(stderr, "Usage: %s /dev/zvol_device_node\n", argv[0]); printf("Usage: %s /dev/zvol_device_node\n", argv[0]);
goto fail; return (EINVAL);
} }
dev_name = argv[1]; dev_name = argv[1];
ret = stat64(dev_name, &statbuf); error = stat64(dev_name, &statbuf);
if (ret != 0) { if (error != 0) {
fprintf(stderr, "Unable to access device file: %s\n", dev_name); printf("Unable to access device file: %s\n", dev_name);
goto fail; return (errno);
} }
dev_minor = minor(statbuf.st_rdev); dev_minor = minor(statbuf.st_rdev);
@ -78,23 +79,23 @@ main(int argc, char **argv)
fd = open(dev_name, O_RDONLY); fd = open(dev_name, O_RDONLY);
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "Unable to open device file: %s\n", dev_name); printf("Unable to open device file: %s\n", dev_name);
goto fail; return (errno);
} }
ret = ioctl_get_msg(zvol_name, fd); error = ioctl_get_msg(zvol_name, fd);
if (ret < 0) { if (error < 0) {
fprintf(stderr, "ioctl_get_msg failed: %s\n", strerror(errno)); printf("ioctl_get_msg failed:%s\n", strerror(errno));
goto fail; return (errno);
} }
if (dev_part > 0) if (dev_part > 0)
ret = asprintf(&zvol_name_part, "%s-part%d", zvol_name, rc = asprintf(&zvol_name_part, "%s-part%d", zvol_name,
dev_part); dev_part);
else else
ret = asprintf(&zvol_name_part, "%s", zvol_name); rc = asprintf(&zvol_name_part, "%s", zvol_name);
if (ret == -1 || zvol_name_part == NULL) if (rc == -1 || zvol_name_part == NULL)
goto fail; goto error;
for (i = 0; i < strlen(zvol_name_part); i++) { for (i = 0; i < strlen(zvol_name_part); i++) {
if (isblank(zvol_name_part[i])) if (isblank(zvol_name_part[i]))
@ -102,13 +103,8 @@ main(int argc, char **argv)
} }
printf("%s\n", zvol_name_part); printf("%s\n", zvol_name_part);
status = EXIT_SUCCESS; free(zvol_name_part);
error:
fail: close(fd);
if (zvol_name_part) return (error);
free(zvol_name_part);
if (fd >= 0)
close(fd);
return (status);
} }

View File

@ -1,3 +1 @@
include $(top_srcdir)/config/Shellcheck.am
dist_bin_SCRIPTS = zvol_wait dist_bin_SCRIPTS = zvol_wait

View File

@ -20,7 +20,6 @@ filter_out_deleted_zvols() {
OIFS="$IFS" OIFS="$IFS"
IFS=" IFS="
" "
# shellcheck disable=SC2086
zfs list -H -o name $zvols 2>/dev/null zfs list -H -o name $zvols 2>/dev/null
IFS="$OIFS" IFS="$OIFS"
} }
@ -28,17 +27,15 @@ filter_out_deleted_zvols() {
list_zvols() { list_zvols() {
read -r default_volmode < /sys/module/zfs/parameters/zvol_volmode read -r default_volmode < /sys/module/zfs/parameters/zvol_volmode
zfs list -t volume -H -o \ zfs list -t volume -H -o \
name,volmode,receive_resume_token,redact_snaps,keystatus | name,volmode,receive_resume_token,redact_snaps |
while IFS=" " read -r name volmode token redacted keystatus; do # IFS=\t here! while IFS=" " read -r name volmode token redacted; do # IFS=\t here!
# /dev links are not created for zvols with volmode = "none", # /dev links are not created for zvols with volmode = "none"
# redacted zvols, or encrypted zvols for which the key has not # or for redacted zvols.
# been loaded.
[ "$volmode" = "none" ] && continue [ "$volmode" = "none" ] && continue
[ "$volmode" = "default" ] && [ "$default_volmode" = "3" ] && [ "$volmode" = "default" ] && [ "$default_volmode" = "3" ] &&
continue continue
[ "$redacted" = "-" ] || continue [ "$redacted" = "-" ] || continue
[ "$keystatus" = "unavailable" ] && continue
# We also ignore partially received zvols if it is # We also ignore partially received zvols if it is
# not an incremental receive, as those won't even have a block # not an incremental receive, as those won't even have a block
@ -109,13 +106,6 @@ while [ "$outer_loop" -lt 20 ]; do
exit 0 exit 0
fi fi
fi fi
#
# zvol_count made some progress - let's stay in this loop.
#
if [ "$old_zvols_count" -gt "$zvols_count" ]; then
outer_loop=$((outer_loop - 1))
fi
done done
echo "Timed out waiting on zvol links" echo "Timed out waiting on zvol links"

View File

@ -25,9 +25,5 @@ checkabi:
storeabi: storeabi:
cd .libs ; \ cd .libs ; \
for lib in $(lib_LTLIBRARIES) ; do \ for lib in $(lib_LTLIBRARIES) ; do \
abidw --no-show-locs \ abidw $${lib%.la}.so > ../$${lib%.la}.abi ; \
--no-corpus-path \
--no-comp-dir-path \
--type-id-style hash \
$${lib%.la}.so > ../$${lib%.la}.abi ; \
done done

View File

@ -26,7 +26,6 @@ AM_LIBTOOLFLAGS = --silent
AM_CFLAGS = -std=gnu99 -Wall -Wstrict-prototypes -Wmissing-prototypes AM_CFLAGS = -std=gnu99 -Wall -Wstrict-prototypes -Wmissing-prototypes
AM_CFLAGS += -fno-strict-aliasing AM_CFLAGS += -fno-strict-aliasing
AM_CFLAGS += $(NO_OMIT_FRAME_POINTER) AM_CFLAGS += $(NO_OMIT_FRAME_POINTER)
AM_CFLAGS += $(IMPLICIT_FALLTHROUGH)
AM_CFLAGS += $(DEBUG_CFLAGS) AM_CFLAGS += $(DEBUG_CFLAGS)
AM_CFLAGS += $(ASAN_CFLAGS) AM_CFLAGS += $(ASAN_CFLAGS)
AM_CFLAGS += $(CODE_COVERAGE_CFLAGS) $(NO_FORMAT_ZERO_LENGTH) AM_CFLAGS += $(CODE_COVERAGE_CFLAGS) $(NO_FORMAT_ZERO_LENGTH)
@ -40,8 +39,8 @@ AM_CPPFLAGS = -D_GNU_SOURCE
AM_CPPFLAGS += -D_REENTRANT AM_CPPFLAGS += -D_REENTRANT
AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64 AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64
AM_CPPFLAGS += -D_LARGEFILE64_SOURCE AM_CPPFLAGS += -D_LARGEFILE64_SOURCE
AM_CPPFLAGS += -DHAVE_LARGE_STACKS=1
AM_CPPFLAGS += -DLIBEXECDIR=\"$(libexecdir)\" AM_CPPFLAGS += -DLIBEXECDIR=\"$(libexecdir)\"
AM_CPPFLAGS += -DZFSEXECDIR=\"$(zfsexecdir)\"
AM_CPPFLAGS += -DRUNSTATEDIR=\"$(runstatedir)\" AM_CPPFLAGS += -DRUNSTATEDIR=\"$(runstatedir)\"
AM_CPPFLAGS += -DSBINDIR=\"$(sbindir)\" AM_CPPFLAGS += -DSBINDIR=\"$(sbindir)\"
AM_CPPFLAGS += -DSYSCONFDIR=\"$(sysconfdir)\" AM_CPPFLAGS += -DSYSCONFDIR=\"$(sysconfdir)\"

View File

@ -1,22 +0,0 @@
.PHONY: shellcheck
shellcheck: $(SCRIPTS) $(SHELLCHECKSCRIPTS)
if HAVE_SHELLCHECK
[ -z "$(SCRIPTS)$(SHELLCHECKSCRIPTS)" ] && exit; shellcheck $$([ -n "$(SHELLCHECK_SHELL)" ] && echo "--shell=$(SHELLCHECK_SHELL)") --exclude=SC1090,SC1091$(SHELLCHECK_IGNORE) --format=gcc $(SCRIPTS) $(SHELLCHECKSCRIPTS)
else
@[ -z "$(SCRIPTS)$(SHELLCHECKSCRIPTS)" ] && exit; echo "skipping shellcheck of" $(SCRIPTS) $(SHELLCHECKSCRIPTS) "because shellcheck is not installed"
endif
@set -e; for dir in $(SHELLCHECKDIRS); do $(MAKE) -C $$dir shellcheck; done
# command -v *is* specified by POSIX and every shell in existence supports it
.PHONY: checkbashisms
checkbashisms: $(SCRIPTS) $(SHELLCHECKSCRIPTS)
if HAVE_CHECKBASHISMS
[ -z "$(SCRIPTS)$(SHELLCHECKSCRIPTS)" ] && exit; ! if [ -z "$(SHELLCHECK_SHELL)" ]; then \
checkbashisms -npx $(SCRIPTS) $(SHELLCHECKSCRIPTS); else \
for f in $(SCRIPTS) $(SHELLCHECKSCRIPTS); do echo $$f >&3; { echo '#!/bin/$(SHELLCHECK_SHELL)'; cat $$f; } | checkbashisms -npx; done; \
fi 3>&2 2>&1 | grep -vFe "'command' with option other than -p" -e 'command -v' $(CHECKBASHISMS_IGNORE) >&2
else
@[ -z "$(SCRIPTS)$(SHELLCHECKSCRIPTS)" ] && exit; echo "skipping checkbashisms of" $(SCRIPTS) $(SHELLCHECKSCRIPTS) "because checkbashisms is not installed"
endif
@set -e; for dir in $(SHELLCHECKDIRS); do $(MAKE) -C $$dir checkbashisms; done

View File

@ -15,9 +15,7 @@ subst_sed_cmd = \
-e 's|@PYTHON[@]|$(PYTHON)|g' \ -e 's|@PYTHON[@]|$(PYTHON)|g' \
-e 's|@PYTHON_SHEBANG[@]|$(PYTHON_SHEBANG)|g' \ -e 's|@PYTHON_SHEBANG[@]|$(PYTHON_SHEBANG)|g' \
-e 's|@DEFAULT_INIT_NFS_SERVER[@]|$(DEFAULT_INIT_NFS_SERVER)|g' \ -e 's|@DEFAULT_INIT_NFS_SERVER[@]|$(DEFAULT_INIT_NFS_SERVER)|g' \
-e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g' \ -e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g'
-e 's|@LIBFETCH_DYNAMIC[@]|$(LIBFETCH_DYNAMIC)|g' \
-e 's|@LIBFETCH_SONAME[@]|$(LIBFETCH_SONAME)|g'
SUBSTFILES = SUBSTFILES =
CLEANFILES = $(SUBSTFILES) CLEANFILES = $(SUBSTFILES)

View File

@ -88,7 +88,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_FORMAT_TRUNCATION], [
]) ])
dnl # dnl #
dnl # Check if gcc supports -Wno-format-zero-length option. dnl # Check if gcc supports -Wno-format-truncation option.
dnl # dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_FORMAT_ZERO_LENGTH], [ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_FORMAT_ZERO_LENGTH], [
AC_MSG_CHECKING([whether $CC supports -Wno-format-zero-length]) AC_MSG_CHECKING([whether $CC supports -Wno-format-zero-length])
@ -108,132 +108,57 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_FORMAT_ZERO_LENGTH], [
AC_SUBST([NO_FORMAT_ZERO_LENGTH]) AC_SUBST([NO_FORMAT_ZERO_LENGTH])
]) ])
dnl # dnl #
dnl # Check if gcc supports -Wno-clobbered option. dnl # Check if gcc supports -Wno-bool-compare option.
dnl # dnl #
dnl # We actually invoke gcc with the -Wclobbered option dnl # We actually invoke gcc with the -Wbool-compare option
dnl # and infer the 'no-' version does or doesn't exist based upon dnl # and infer the 'no-' version does or doesn't exist based upon
dnl # the results. This is required because when checking any of dnl # the results. This is required because when checking any of
dnl # no- prefixed options gcc always returns success. dnl # no- prefixed options gcc always returns success.
dnl # dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_CLOBBERED], [ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_BOOL_COMPARE], [
AC_MSG_CHECKING([whether $CC supports -Wno-clobbered]) AC_MSG_CHECKING([whether $CC supports -Wno-bool-compare])
saved_flags="$CFLAGS" saved_flags="$CFLAGS"
CFLAGS="$CFLAGS -Werror -Wclobbered" CFLAGS="$CFLAGS -Werror -Wbool-compare"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
NO_CLOBBERED=-Wno-clobbered NO_BOOL_COMPARE=-Wno-bool-compare
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
], [ ], [
NO_CLOBBERED= NO_BOOL_COMPARE=
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
]) ])
CFLAGS="$saved_flags" CFLAGS="$saved_flags"
AC_SUBST([NO_CLOBBERED]) AC_SUBST([NO_BOOL_COMPARE])
]) ])
dnl # dnl #
dnl # Check if gcc supports -Wimplicit-fallthrough option. dnl # Check if gcc supports -Wno-unused-but-set-variable option.
dnl # dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_IMPLICIT_FALLTHROUGH], [ dnl # We actually invoke gcc with the -Wunused-but-set-variable option
AC_MSG_CHECKING([whether $CC supports -Wimplicit-fallthrough]) dnl # and infer the 'no-' version does or doesn't exist based upon
dnl # the results. This is required because when checking any of
dnl # no- prefixed options gcc always returns success.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_UNUSED_BUT_SET_VARIABLE], [
AC_MSG_CHECKING([whether $CC supports -Wno-unused-but-set-variable])
saved_flags="$CFLAGS" saved_flags="$CFLAGS"
CFLAGS="$CFLAGS -Werror -Wimplicit-fallthrough" CFLAGS="$CFLAGS -Werror -Wunused-but-set-variable"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
IMPLICIT_FALLTHROUGH=-Wimplicit-fallthrough NO_UNUSED_BUT_SET_VARIABLE=-Wno-unused-but-set-variable
AC_DEFINE([HAVE_IMPLICIT_FALLTHROUGH], 1,
[Define if compiler supports -Wimplicit-fallthrough])
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
], [ ], [
IMPLICIT_FALLTHROUGH= NO_UNUSED_BUT_SET_VARIABLE=
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
]) ])
CFLAGS="$saved_flags" CFLAGS="$saved_flags"
AC_SUBST([IMPLICIT_FALLTHROUGH]) AC_SUBST([NO_UNUSED_BUT_SET_VARIABLE])
])
dnl #
dnl # Check if cc supports -Winfinite-recursion option.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_INFINITE_RECURSION], [
AC_MSG_CHECKING([whether $CC supports -Winfinite-recursion])
saved_flags="$CFLAGS"
CFLAGS="$CFLAGS -Werror -Winfinite-recursion"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
INFINITE_RECURSION=-Winfinite-recursion
AC_DEFINE([HAVE_INFINITE_RECURSION], 1,
[Define if compiler supports -Winfinite-recursion])
AC_MSG_RESULT([yes])
], [
INFINITE_RECURSION=
AC_MSG_RESULT([no])
])
CFLAGS="$saved_flags"
AC_SUBST([INFINITE_RECURSION])
])
dnl #
dnl # Check if kernel cc supports -Winfinite-recursion option.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_KERNEL_CC_INFINITE_RECURSION], [
AC_MSG_CHECKING([whether $KERNEL_CC supports -Winfinite-recursion])
saved_cc="$CC"
saved_flags="$CFLAGS"
CC="gcc"
CFLAGS="$CFLAGS -Werror -Winfinite-recursion"
AS_IF([ test -n "$KERNEL_CC" ], [
CC="$KERNEL_CC"
])
AS_IF([ test -n "$KERNEL_LLVM" ], [
CC="clang"
])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
KERNEL_INFINITE_RECURSION=-Winfinite-recursion
AC_DEFINE([HAVE_KERNEL_INFINITE_RECURSION], 1,
[Define if compiler supports -Winfinite-recursion])
AC_MSG_RESULT([yes])
], [
KERNEL_INFINITE_RECURSION=
AC_MSG_RESULT([no])
])
CC="$saved_cc"
CFLAGS="$saved_flags"
AC_SUBST([KERNEL_INFINITE_RECURSION])
])
dnl #
dnl # Check if cc supports -Wformat-overflow option.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_FORMAT_OVERFLOW], [
AC_MSG_CHECKING([whether $CC supports -Wformat-overflow])
saved_flags="$CFLAGS"
CFLAGS="$CFLAGS -Werror -Wformat-overflow"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
FORMAT_OVERFLOW=-Wformat-overflow
AC_DEFINE([HAVE_FORMAT_OVERFLOW], 1,
[Define if compiler supports -Wformat-overflow])
AC_MSG_RESULT([yes])
], [
FORMAT_OVERFLOW=
AC_MSG_RESULT([no])
])
CFLAGS="$saved_flags"
AC_SUBST([FORMAT_OVERFLOW])
]) ])
dnl # dnl #
@ -277,34 +202,3 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_IPA_SRA], [
CFLAGS="$saved_flags" CFLAGS="$saved_flags"
AC_SUBST([NO_IPA_SRA]) AC_SUBST([NO_IPA_SRA])
]) ])
dnl #
dnl # Check if kernel cc supports -fno-ipa-sra option.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_KERNEL_CC_NO_IPA_SRA], [
AC_MSG_CHECKING([whether $KERNEL_CC supports -fno-ipa-sra])
saved_cc="$CC"
saved_flags="$CFLAGS"
CC="gcc"
CFLAGS="$CFLAGS -Werror -fno-ipa-sra"
AS_IF([ test -n "$KERNEL_CC" ], [
CC="$KERNEL_CC"
])
AS_IF([ test -n "$KERNEL_LLVM" ], [
CC="clang"
])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
KERNEL_NO_IPA_SRA=-fno-ipa-sra
AC_MSG_RESULT([yes])
], [
KERNEL_NO_IPA_SRA=
AC_MSG_RESULT([no])
])
CC="$saved_cc"
CFLAGS="$saved_flags"
AC_SUBST([KERNEL_NO_IPA_SRA])
])

View File

@ -1,8 +0,0 @@
dnl #
dnl # Check if GNU parallel is available.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PARALLEL], [
AC_CHECK_PROG([PARALLEL], [parallel], [yes])
AM_CONDITIONAL([HAVE_PARALLEL], [test "x$PARALLEL" = "xyes"])
])

View File

@ -1,6 +1,7 @@
dnl # dnl #
dnl # The majority of the python scripts are written to be compatible dnl # The majority of the python scripts are written to be compatible
dnl # with Python 3.6. This option is intended to dnl # with Python 2.6 and Python 3.4. Therefore, they may be installed
dnl # and used with either interpreter. This option is intended to
dnl # to provide a method to specify the default system version, and dnl # to provide a method to specify the default system version, and
dnl # set the PYTHON environment variable accordingly. dnl # set the PYTHON environment variable accordingly.
dnl # dnl #
@ -12,7 +13,9 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYTHON], [
[with_python=check]) [with_python=check])
AS_CASE([$with_python], AS_CASE([$with_python],
[check], [AC_CHECK_PROGS([PYTHON], [python3], [:])], [check], [AC_CHECK_PROGS([PYTHON], [python3 python2], [:])],
[2*], [PYTHON="python${with_python}"],
[*python2*], [PYTHON="${with_python}"],
[3*], [PYTHON="python${with_python}"], [3*], [PYTHON="python${with_python}"],
[*python3*], [PYTHON="${with_python}"], [*python3*], [PYTHON="${with_python}"],
[no], [PYTHON=":"], [no], [PYTHON=":"],
@ -20,25 +23,35 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYTHON], [
) )
dnl # dnl #
dnl # Minimum supported Python versions for utilities: Python 3.6 dnl # Minimum supported Python versions for utilities:
dnl # Python 2.6 or Python 3.4
dnl # dnl #
AM_PATH_PYTHON([], [], [:]) AM_PATH_PYTHON([], [], [:])
AS_IF([test -z "$PYTHON_VERSION"], [ AS_IF([test -z "$PYTHON_VERSION"], [
PYTHON_VERSION=$(echo ${PYTHON##*/} | tr -cd 0-9.) PYTHON_VERSION=$(basename $PYTHON | tr -cd 0-9.)
]) ])
PYTHON_MINOR=${PYTHON_VERSION#*\.} PYTHON_MINOR=${PYTHON_VERSION#*\.}
AS_CASE([$PYTHON_VERSION], AS_CASE([$PYTHON_VERSION],
[3.*], [ [2.*], [
AS_IF([test $PYTHON_MINOR -lt 6], AS_IF([test $PYTHON_MINOR -lt 6],
[AC_MSG_ERROR("Python >= 3.6 is required")]) [AC_MSG_ERROR("Python >= 2.6 is required")])
],
[3.*], [
AS_IF([test $PYTHON_MINOR -lt 4],
[AC_MSG_ERROR("Python >= 3.4 is required")])
], ],
[:|2|3], [], [:|2|3], [],
[PYTHON_VERSION=3] [PYTHON_VERSION=3]
) )
AM_CONDITIONAL([USING_PYTHON], [test "$PYTHON" != :]) AM_CONDITIONAL([USING_PYTHON], [test "$PYTHON" != :])
AC_SUBST([PYTHON_SHEBANG], [python3]) AM_CONDITIONAL([USING_PYTHON_2], [test "x${PYTHON_VERSION%%\.*}" = x2])
AM_CONDITIONAL([USING_PYTHON_3], [test "x${PYTHON_VERSION%%\.*}" = x3])
AM_COND_IF([USING_PYTHON_2],
[AC_SUBST([PYTHON_SHEBANG], [python2])],
[AC_SUBST([PYTHON_SHEBANG], [python3])])
dnl # dnl #
dnl # Request that packages be built for a specific Python version. dnl # Request that packages be built for a specific Python version.

View File

@ -6,7 +6,7 @@ dnl # https://www.gnu.org/software/autoconf-archive/ax_python_module.html
dnl # Required by ZFS_AC_CONFIG_ALWAYS_PYZFS. dnl # Required by ZFS_AC_CONFIG_ALWAYS_PYZFS.
dnl # dnl #
AC_DEFUN([ZFS_AC_PYTHON_MODULE], [ AC_DEFUN([ZFS_AC_PYTHON_MODULE], [
PYTHON_NAME=${PYTHON##*/} PYTHON_NAME=$(basename $PYTHON)
AC_MSG_CHECKING([for $PYTHON_NAME module: $1]) AC_MSG_CHECKING([for $PYTHON_NAME module: $1])
AS_IF([$PYTHON -c "import $1" 2>/dev/null], [ AS_IF([$PYTHON -c "import $1" 2>/dev/null], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
@ -18,7 +18,7 @@ AC_DEFUN([ZFS_AC_PYTHON_MODULE], [
]) ])
dnl # dnl #
dnl # Determines if pyzfs can be built, requires Python 3.6 or later. dnl # Determines if pyzfs can be built, requires Python 2.7 or later.
dnl # dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
AC_ARG_ENABLE([pyzfs], AC_ARG_ENABLE([pyzfs],
@ -47,36 +47,12 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
AC_SUBST(DEFINE_PYZFS) AC_SUBST(DEFINE_PYZFS)
dnl # dnl #
dnl # Autodetection disables pyzfs if kernel or srpm config dnl # Require python-devel libraries
dnl #
AS_IF([test "x$enable_pyzfs" = xcheck], [
AS_IF([test "x$ZFS_CONFIG" = xkernel -o "x$ZFS_CONFIG" = xsrpm ], [
enable_pyzfs=no
AC_MSG_NOTICE([Disabling pyzfs for kernel/srpm config])
])
])
dnl #
dnl # Python "packaging" (or, failing that, "distlib") module is required to build and install pyzfs
dnl #
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
ZFS_AC_PYTHON_MODULE([packaging], [], [
ZFS_AC_PYTHON_MODULE([distlib], [], [
AS_IF([test "x$enable_pyzfs" = xyes], [
AC_MSG_ERROR("Python $PYTHON_VERSION packaging and distlib modules are not installed")
], [test "x$enable_pyzfs" != xno], [
enable_pyzfs=no
])
])
])
])
dnl #
dnl # Require python3-devel libraries
dnl # dnl #
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [ AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
AS_CASE([$PYTHON_VERSION], AS_CASE([$PYTHON_VERSION],
[3.*], [PYTHON_REQUIRED_VERSION=">= '3.6.0'"], [3.*], [PYTHON_REQUIRED_VERSION=">= '3.4.0'"],
[2.*], [PYTHON_REQUIRED_VERSION=">= '2.7.0'"],
[AC_MSG_ERROR("Python $PYTHON_VERSION unknown")] [AC_MSG_ERROR("Python $PYTHON_VERSION unknown")]
) )

View File

@ -1,10 +0,0 @@
dnl #
dnl # Check if shellcheck and/or checkbashisms are available.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_SHELLCHECK], [
AC_CHECK_PROG([SHELLCHECK], [shellcheck], [yes])
AC_CHECK_PROG([CHECKBASHISMS], [checkbashisms], [yes])
AM_CONDITIONAL([HAVE_SHELLCHECK], [test "x$SHELLCHECK" = "xyes"])
AM_CONDITIONAL([HAVE_CHECKBASHISMS], [test "x$CHECKBASHISMS" = "xyes"])
])

View File

@ -103,7 +103,8 @@ AC_DEFUN([AX_PYTHON_DEVEL],[
if test "$ac_supports_python_ver" != "True"; then if test "$ac_supports_python_ver" != "True"; then
if test -z "$PYTHON_NOVERSIONCHECK"; then if test -z "$PYTHON_NOVERSIONCHECK"; then
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
AC_MSG_FAILURE([ m4_ifvaln([$2],[$2],[
AC_MSG_FAILURE([
This version of the AC@&t@_PYTHON_DEVEL macro This version of the AC@&t@_PYTHON_DEVEL macro
doesn't work properly with versions of Python before doesn't work properly with versions of Python before
2.1.0. You may need to re-run configure, setting the 2.1.0. You may need to re-run configure, setting the
@ -112,6 +113,7 @@ PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
Moreover, to disable this check, set PYTHON_NOVERSIONCHECK Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
to something else than an empty string. to something else than an empty string.
]) ])
])
else else
AC_MSG_RESULT([skip at user request]) AC_MSG_RESULT([skip at user request])
fi fi
@ -120,47 +122,25 @@ to something else than an empty string.
fi fi
# #
# If the macro parameter ``version'' is set, honour it. # if the macro parameter ``version'' is set, honour it
# A Python shim class, VPy, is used to implement correct version comparisons via
# string expressions, since e.g. a naive textual ">= 2.7.3" won't work for
# Python 2.7.10 (the ".1" being evaluated as less than ".3").
# #
if test -n "$1"; then if test -n "$1"; then
AC_MSG_CHECKING([for a version of Python $1]) AC_MSG_CHECKING([for a version of Python $1])
cat << EOF > ax_python_devel_vpy.py ac_supports_python_ver=`$PYTHON -c "import sys; \
class VPy: ver = sys.version.split ()[[0]]; \
def vtup(self, s):
return tuple(map(int, s.strip().replace("rc", ".").split(".")))
def __init__(self):
import sys
self.vpy = tuple(sys.version_info)
def __eq__(self, s):
return self.vpy == self.vtup(s)
def __ne__(self, s):
return self.vpy != self.vtup(s)
def __lt__(self, s):
return self.vpy < self.vtup(s)
def __gt__(self, s):
return self.vpy > self.vtup(s)
def __le__(self, s):
return self.vpy <= self.vtup(s)
def __ge__(self, s):
return self.vpy >= self.vtup(s)
EOF
ac_supports_python_ver=`$PYTHON -c "import ax_python_devel_vpy; \
ver = ax_python_devel_vpy.VPy(); \
print (ver $1)"` print (ver $1)"`
rm -rf ax_python_devel_vpy*.py* __pycache__/ax_python_devel_vpy*.py*
if test "$ac_supports_python_ver" = "True"; then if test "$ac_supports_python_ver" = "True"; then
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
AC_MSG_ERROR([this package requires Python $1. m4_ifvaln([$2],[$2],[
AC_MSG_ERROR([this package requires Python $1.
If you have it installed, but it isn't the default Python If you have it installed, but it isn't the default Python
interpreter in your system path, please pass the PYTHON_VERSION interpreter in your system path, please pass the PYTHON_VERSION
variable to configure. See ``configure --help'' for reference. variable to configure. See ``configure --help'' for reference.
]) ])
PYTHON_VERSION="" PYTHON_VERSION=""
])
fi fi
fi fi
@ -168,7 +148,8 @@ variable to configure. See ``configure --help'' for reference.
# Check if you have distutils, else fail # Check if you have distutils, else fail
# #
AC_MSG_CHECKING([for the distutils Python package]) AC_MSG_CHECKING([for the distutils Python package])
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
if test $? -eq 0; then
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
@ -223,7 +204,7 @@ EOD`
ac_python_version=$PYTHON_VERSION ac_python_version=$PYTHON_VERSION
else else
ac_python_version=`$PYTHON -c "import sys; \ ac_python_version=`$PYTHON -c "import sys; \
print ('.'.join(sys.version.split('.')[[:2]]))"` print (sys.version[[:3]])"`
fi fi
fi fi

View File

@ -66,7 +66,7 @@ deb-utils: deb-local rpm-utils-initramfs
## to do this, so we install a shim onto the path which calls the real ## to do this, so we install a shim onto the path which calls the real
## dh_shlibdeps with the required arguments. ## dh_shlibdeps with the required arguments.
path_prepend=`mktemp -d /tmp/intercept.XXXXXX`; \ path_prepend=`mktemp -d /tmp/intercept.XXXXXX`; \
echo "#!$(SHELL)" > $${path_prepend}/dh_shlibdeps; \ echo "#$(SHELL)" > $${path_prepend}/dh_shlibdeps; \
echo "`which dh_shlibdeps` -- \ echo "`which dh_shlibdeps` -- \
-xlibuutil3linux -xlibnvpair3linux -xlibzfs5linux -xlibzpool5linux" \ -xlibuutil3linux -xlibnvpair3linux -xlibzfs5linux -xlibzpool5linux" \
>> $${path_prepend}/dh_shlibdeps; \ >> $${path_prepend}/dh_shlibdeps; \
@ -74,7 +74,7 @@ deb-utils: deb-local rpm-utils-initramfs
## Debianized packages from the auto-generated dependencies of the new debs, ## Debianized packages from the auto-generated dependencies of the new debs,
## which should NOT be mixed with the alien-generated debs created here ## which should NOT be mixed with the alien-generated debs created here
chmod +x $${path_prepend}/dh_shlibdeps; \ chmod +x $${path_prepend}/dh_shlibdeps; \
env "PATH=$${path_prepend}:$${PATH}" \ env PATH=$${path_prepend}:$${PATH} \
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch \ fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch \
$$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \ $$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \
$$pkg8 $$pkg9 $$pkg10 || exit 1; \ $$pkg8 $$pkg9 $$pkg10 || exit 1; \

View File

@ -162,17 +162,11 @@ dnl #
dnl # 3.1 API change, dnl # 3.1 API change,
dnl # Check if inode_operations contains the function get_acl dnl # Check if inode_operations contains the function get_acl
dnl # dnl #
dnl # 5.15 API change,
dnl # Added the bool rcu argument to get_acl for rcu path walk.
dnl #
dnl # 6.2 API change,
dnl # get_acl() was renamed to get_inode_acl()
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [ ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
#include <linux/fs.h> #include <linux/fs.h>
static struct posix_acl *get_acl_fn(struct inode *inode, int type) struct posix_acl *get_acl_fn(struct inode *inode, int type)
{ return NULL; } { return NULL; }
static const struct inode_operations static const struct inode_operations
@ -180,49 +174,14 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
.get_acl = get_acl_fn, .get_acl = get_acl_fn,
}; };
],[]) ],[])
ZFS_LINUX_TEST_SRC([inode_operations_get_acl_rcu], [
#include <linux/fs.h>
static struct posix_acl *get_acl_fn(struct inode *inode, int type,
bool rcu) { return NULL; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
.get_acl = get_acl_fn,
};
],[])
ZFS_LINUX_TEST_SRC([inode_operations_get_inode_acl], [
#include <linux/fs.h>
static struct posix_acl *get_inode_acl_fn(struct inode *inode, int type,
bool rcu) { return NULL; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
.get_inode_acl = get_inode_acl_fn,
};
],[])
]) ])
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
AC_MSG_CHECKING([whether iops->get_acl() exists]) AC_MSG_CHECKING([whether iops->get_acl() exists])
ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [ ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GET_ACL, 1, [iops->get_acl() exists])
],[ ],[
ZFS_LINUX_TEST_RESULT([inode_operations_get_acl_rcu], [ ZFS_LINUX_TEST_ERROR([iops->get_acl()])
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GET_ACL_RCU, 1, [iops->get_acl() takes rcu])
],[
ZFS_LINUX_TEST_RESULT([inode_operations_get_inode_acl], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GET_INODE_ACL, 1, [has iops->get_inode_acl()])
],[
ZFS_LINUX_TEST_ERROR([iops->get_acl() or iops->get_inode_acl()])
])
])
]) ])
]) ])
@ -230,56 +189,11 @@ dnl #
dnl # 3.14 API change, dnl # 3.14 API change,
dnl # Check if inode_operations contains the function set_acl dnl # Check if inode_operations contains the function set_acl
dnl # dnl #
dnl # 5.12 API change,
dnl # set_acl() added a user_namespace* parameter first
dnl #
dnl # 6.2 API change,
dnl # set_acl() second paramter changed to a struct dentry *
dnl #
dnl # 6.3 API change,
dnl # set_acl() first parameter changed to struct mnt_idmap *
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
ZFS_LINUX_TEST_SRC([inode_operations_set_acl_mnt_idmap_dentry], [
#include <linux/fs.h>
static int set_acl_fn(struct mnt_idmap *idmap,
struct dentry *dent, struct posix_acl *acl,
int type) { return 0; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
.set_acl = set_acl_fn,
};
],[])
ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns_dentry], [
#include <linux/fs.h>
static int set_acl_fn(struct user_namespace *userns,
struct dentry *dent, struct posix_acl *acl,
int type) { return 0; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
.set_acl = set_acl_fn,
};
],[])
ZFS_LINUX_TEST_SRC([inode_operations_set_acl_userns], [
#include <linux/fs.h>
static int set_acl_fn(struct user_namespace *userns,
struct inode *inode, struct posix_acl *acl,
int type) { return 0; }
static const struct inode_operations
iops __attribute__ ((unused)) = {
.set_acl = set_acl_fn,
};
],[])
ZFS_LINUX_TEST_SRC([inode_operations_set_acl], [ ZFS_LINUX_TEST_SRC([inode_operations_set_acl], [
#include <linux/fs.h> #include <linux/fs.h>
static int set_acl_fn(struct inode *inode, struct posix_acl *acl, int set_acl_fn(struct inode *inode, struct posix_acl *acl,
int type) { return 0; } int type) { return 0; }
static const struct inode_operations static const struct inode_operations
@ -291,31 +205,11 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
AC_MSG_CHECKING([whether iops->set_acl() exists]) AC_MSG_CHECKING([whether iops->set_acl() exists])
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_userns], [ ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists]) AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
AC_DEFINE(HAVE_SET_ACL_USERNS, 1, [iops->set_acl() takes 4 args])
],[ ],[
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_mnt_idmap_dentry], [ AC_MSG_RESULT(no)
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
AC_DEFINE(HAVE_SET_ACL_IDMAP_DENTRY, 1,
[iops->set_acl() takes 4 args, arg1 is struct mnt_idmap *])
],[
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl_userns_dentry], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
AC_DEFINE(HAVE_SET_ACL_USERNS_DENTRY_ARG2, 1,
[iops->set_acl() takes 4 args, arg2 is struct dentry *])
],[
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists, takes 3 args])
],[
ZFS_LINUX_REQUIRE_API([i_op->set_acl()], [3.14])
])
])
])
]) ])
]) ])

View File

@ -1,24 +0,0 @@
dnl #
dnl # 5.16 API change
dnl # add_disk grew a must-check return code
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_ADD_DISK], [
ZFS_LINUX_TEST_SRC([add_disk_ret], [
#include <linux/blkdev.h>
], [
struct gendisk *disk = NULL;
int error __attribute__ ((unused)) = add_disk(disk);
])
])
AC_DEFUN([ZFS_AC_KERNEL_ADD_DISK], [
AC_MSG_CHECKING([whether add_disk() returns int])
ZFS_LINUX_TEST_RESULT([add_disk_ret],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_ADD_DISK_RET, 1,
[add_disk() returns int])
], [
AC_MSG_RESULT(no)
])
])

View File

@ -8,7 +8,7 @@ dnl #
AC_DEFUN([ZFS_AC_KERNEL_SRC_AUTOMOUNT], [ AC_DEFUN([ZFS_AC_KERNEL_SRC_AUTOMOUNT], [
ZFS_LINUX_TEST_SRC([dentry_operations_d_automount], [ ZFS_LINUX_TEST_SRC([dentry_operations_d_automount], [
#include <linux/dcache.h> #include <linux/dcache.h>
static struct vfsmount *d_automount(struct path *p) { return NULL; } struct vfsmount *d_automount(struct path *p) { return NULL; }
struct dentry_operations dops __attribute__ ((unused)) = { struct dentry_operations dops __attribute__ ((unused)) = {
.d_automount = d_automount, .d_automount = d_automount,
}; };

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