Compare commits
No commits in common. "zfs-2.1-release" and "zfs-2.1.0-rc3" have entirely different histories.
zfs-2.1-re
...
zfs-2.1.0-
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
|
@ -1,2 +0,0 @@
|
||||||
pax-utils
|
|
||||||
shellcheck
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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 /
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
6
META
|
@ -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
|
||||||
|
|
79
Makefile.am
79
Makefile.am
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 $< $@
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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:
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 ))
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -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 "
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
include $(top_srcdir)/config/Shellcheck.am
|
|
||||||
|
|
||||||
dist_udev_SCRIPTS = vdev_id
|
dist_udev_SCRIPTS = vdev_id
|
||||||
|
|
|
@ -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
|
||||||
|
|
273
cmd/zdb/zdb.c
273
cmd/zdb/zdb.c
|
@ -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, ¤t, &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, ¤t);
|
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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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}"'
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}"
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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}"
|
||||||
|
|
||||||
|
|
|
@ -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"
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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-
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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": {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
dist_sbin_SCRIPTS = zstreamdump
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec zstream dump "$@"
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
include $(top_srcdir)/config/Shellcheck.am
|
|
||||||
|
|
||||||
dist_bin_SCRIPTS = zvol_wait
|
dist_bin_SCRIPTS = zvol_wait
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)\"
|
||||||
|
|
|
@ -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
|
|
|
@ -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)
|
||||||
|
|
|
@ -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])
|
|
||||||
])
|
|
||||||
|
|
|
@ -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"])
|
|
||||||
])
|
|
|
@ -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.
|
||||||
|
|
|
@ -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")]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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"])
|
|
||||||
])
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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; \
|
||||||
|
|
|
@ -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])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
||||||
])
|
|
||||||
])
|
|
|
@ -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
Loading…
Reference in New Issue