mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-26 12:12:13 +03:00
Compare commits
213 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dcbf847493 | |||
| 2757204434 | |||
| 24a6f83847 | |||
| 2c36eb763f | |||
| a4ab0c607e | |||
| a3a4b8def7 | |||
| 14bdf57a99 | |||
| 45061cc797 | |||
| cb01817f22 | |||
| 1c4ccfb34e | |||
| 056287e3f7 | |||
| ccfa35c6f9 | |||
| 8471f71132 | |||
| 813185d141 | |||
| be12087783 | |||
| 4f9014b70b | |||
| 043ef5c25e | |||
| c06118e0b1 | |||
| 5f24bd11ee | |||
| f6f3089cf6 | |||
| a09aeb9fc4 | |||
| e4257ed76d | |||
| c4a5e3b90f | |||
| d02fc15ba1 | |||
| 435dc4baab | |||
| 04177b9c3f | |||
| 4a87c280dc | |||
| d237d9a918 | |||
| 2132ae465d | |||
| 87f01fc158 | |||
| 995b80fa3a | |||
| d842f99c6b | |||
| 8cad25a39c | |||
| c00bb5f4ea | |||
| d33cbbbf93 | |||
| a4efa59a94 | |||
| cb4d3fb737 | |||
| 4a2e9811e9 | |||
| 050dfc5045 | |||
| b49118220c | |||
| 806dda56ce | |||
| 97f5cfea77 | |||
| 5ecbea67eb | |||
| 957b4e9fbd | |||
| ef648fec0e | |||
| e518548e17 | |||
| 1f442afa41 | |||
| 62d549d757 | |||
| ab9011e79b | |||
| b42f36f0b0 | |||
| a30fed54f4 | |||
| e767b1cacc | |||
| d2090becab | |||
| 54f10674f3 | |||
| f8460e7e62 | |||
| 45479eb1de | |||
| aaeffd09bf | |||
| 0c270bb6c4 | |||
| c2c643256c | |||
| 896d0f0906 | |||
| ef525e0841 | |||
| 00a27515f0 | |||
| 52f1ef3b2d | |||
| c6b0680d9b | |||
| 2c37e1416b | |||
| 6e4845aee3 | |||
| 48cf7d674a | |||
| ca54e52122 | |||
| c3ae9321bf | |||
| 2dd2e49cc7 | |||
| 8a1b26eb54 | |||
| 7e76d21bc8 | |||
| e579a4ed0f | |||
| 6867d00403 | |||
| 0dc6fb730f | |||
| f5bffd3748 | |||
| 07c7899a37 | |||
| 79bfba2fa8 | |||
| 73511e3dde | |||
| 3b79394bc9 | |||
| 4df31aa98c | |||
| aeeada355c | |||
| 0905a4fe9b | |||
| 3ba6774e58 | |||
| 26e9c479b5 | |||
| db75854cbb | |||
| bd565f3e24 | |||
| 3c4e580e9a | |||
| b3f4436d37 | |||
| 05f8be3b49 | |||
| d8091c9294 | |||
| 05613fa7a3 | |||
| 725c9e22ca | |||
| fbfc7e843a | |||
| faa62966b1 | |||
| be28cdd1c3 | |||
| 7f0b3fa042 | |||
| f40a1ad9e0 | |||
| 9cf33c99fc | |||
| a51019f4ec | |||
| c71847b77b | |||
| 5c6d3c21b1 | |||
| 5e7198b873 | |||
| 46c71074ca | |||
| 35ba2ca5b7 | |||
| cbcb88dff8 | |||
| 0df5b5737c | |||
| 102a1db6b2 | |||
| 25e44a17ff | |||
| 718d20ed93 | |||
| 18fea82b89 | |||
| cfb602125e | |||
| 106627caa7 | |||
| d6bee967ed | |||
| 47e3dba972 | |||
| a09e3a8594 | |||
| 5573cbea9a | |||
| fc5966589b | |||
| 5d61d6e8dd | |||
| 775afc4dcd | |||
| 7ce9da0bea | |||
| e58dee8cae | |||
| 83b5a22d86 | |||
| 13c38c4c45 | |||
| fdbec0423b | |||
| 9f29a4d972 | |||
| ced5f71eec | |||
| e5a4f9cfc4 | |||
| 1579483a86 | |||
| edd23dba81 | |||
| 7b353d2c8c | |||
| b37efb872b | |||
| d8a81c3d3c | |||
| 875307b6a1 | |||
| 626abe164d | |||
| ba28919168 | |||
| c70c6e004e | |||
| 227273efa4 | |||
| b199e62d17 | |||
| b9d18bdbdc | |||
| e651a5b233 | |||
| 723726ae7d | |||
| aba5b019cb | |||
| f664153078 | |||
| 4ce06f940e | |||
| 5899ea5a77 | |||
| 56e69c1e9c | |||
| dacb4f6a61 | |||
| 66ccc9b75f | |||
| 7b86ad215e | |||
| aa7817c151 | |||
| 3902eaf9ed | |||
| 2cec08a1f0 | |||
| 0968d689a2 | |||
| 1ce90aa441 | |||
| c9eab8257d | |||
| df39626fdd | |||
| 083ddb7714 | |||
| 7bc2d04398 | |||
| 84d9492e52 | |||
| c8bbb0c93d | |||
| ae93e46716 | |||
| 645ca45a13 | |||
| 29bc31f62f | |||
| 17e2fd3bfd | |||
| 55de40fe47 | |||
| 9cea5f0d69 | |||
| 78d84f56d1 | |||
| 127daad223 | |||
| b155a243a6 | |||
| ac71835706 | |||
| 3625a0131a | |||
| 0b5a4c4d6b | |||
| ee73a8ff3d | |||
| c0234eab65 | |||
| dd34e6cdd9 | |||
| e9c1fa0cc1 | |||
| 18524b936d | |||
| 8afac5dc55 | |||
| bd724261d2 | |||
| a1e03186fd | |||
| e28635396a | |||
| 36f36610c3 | |||
| fd20a81b9a | |||
| ef8a6fe9fe | |||
| 7c36a9e24a | |||
| da81d91d48 | |||
| ecd3976f5b | |||
| 76a157f004 | |||
| 6512c18fe1 | |||
| f5ddb3b481 | |||
| d6a779a278 | |||
| bbba0b7f93 | |||
| 8a06356e24 | |||
| b73a8b1dc2 | |||
| baed4fbacb | |||
| f4c8e9c69b | |||
| 8639ca86da | |||
| c6ee83893e | |||
| 0fba4d138c | |||
| 6bf3f4dfe5 | |||
| fa0cd2d16f | |||
| a00c61db44 | |||
| c2068750d7 | |||
| af424d8a1a | |||
| 1ac6248312 | |||
| 77b01f53e7 | |||
| 57fc3987a0 | |||
| 4f6167deb5 | |||
| 79d6a1b1da | |||
| 510179f086 | |||
| cb16a5e043 | |||
| 3ca31bd0c6 |
@@ -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, Status: Triage Needed'
|
labels: 'Type: Defect'
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: OpenZFS Questions
|
|
||||||
url: https://github.com/openzfs/zfs/discussions/new
|
|
||||||
about: Ask the community for help
|
|
||||||
- name: OpenZFS Community Support Mailing list (Linux)
|
- name: OpenZFS Community Support Mailing list (Linux)
|
||||||
url: https://zfsonlinux.topicbox.com/groups/zfs-discuss
|
url: https://zfsonlinux.topicbox.com/groups/zfs-discuss
|
||||||
about: Get community support for OpenZFS on Linux
|
about: Get community support for OpenZFS on Linux
|
||||||
@@ -10,5 +7,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
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
name: Code Question
|
||||||
|
about: Ask a question about the code
|
||||||
|
title: ''
|
||||||
|
labels: 'Type: Question'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Thank you for taking an interest in the OpenZFS codebase.
|
||||||
|
|
||||||
|
Please be aware that most questions are preferably asked in the mailing list first.
|
||||||
|
This form is primarily meant for asking questions about the code itself.
|
||||||
|
|
||||||
|
Please also check our issue tracker before opening a new question.
|
||||||
|
Filling out the following template will help other contributors better understand your question.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Ask your question!
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please provide a clear and concise question.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Which portion of the codebase does your question involve?
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Optional: Please describe what portion of the codebase your issue involved.
|
||||||
|
Example: "Testsuite", "Buildbots", "CLI", a code snippet etc.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Any additional information you want to add?
|
||||||
|
-->
|
||||||
@@ -28,15 +28,14 @@ https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.
|
|||||||
- [ ] Performance enhancement (non-breaking change which improves efficiency)
|
- [ ] Performance enhancement (non-breaking change which improves efficiency)
|
||||||
- [ ] Code cleanup (non-breaking change which makes code smaller or more readable)
|
- [ ] Code cleanup (non-breaking change which makes code smaller or more readable)
|
||||||
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||||
- [ ] Library ABI change (libzfs, libzfs\_core, libnvpair, libuutil and libzfsbootenv)
|
|
||||||
- [ ] Documentation (a change to man pages or other documentation)
|
- [ ] Documentation (a change to man pages or other documentation)
|
||||||
|
|
||||||
### Checklist:
|
### Checklist:
|
||||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||||
- [ ] My code follows the OpenZFS [code style requirements](https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md#coding-conventions).
|
- [ ] My code follows the ZFS on Linux [code style requirements](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md#coding-conventions).
|
||||||
- [ ] I have updated the documentation accordingly.
|
- [ ] I have updated the documentation accordingly.
|
||||||
- [ ] I have read the [**contributing** document](https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md).
|
- [ ] I have read the [**contributing** document](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md).
|
||||||
- [ ] I have added [tests](https://github.com/openzfs/zfs/tree/master/tests) to cover my changes.
|
- [ ] I have added [tests](https://github.com/zfsonlinux/zfs/tree/master/tests) to cover my changes.
|
||||||
- [ ] I have run the ZFS Test Suite with this change applied.
|
- [ ] I have run the ZFS Test Suite with this change applied.
|
||||||
- [ ] All commit messages are properly formatted and contain [`Signed-off-by`](https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md#signed-off-by).
|
- [ ] All commit messages are properly formatted and contain [`Signed-off-by`](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md#signed-off-by).
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
# Configuration for probot-no-response - https://github.com/probot/no-response
|
|
||||||
|
|
||||||
# Number of days of inactivity before an Issue is closed for lack of response
|
|
||||||
daysUntilClose: 31
|
|
||||||
# Label requiring a response
|
|
||||||
responseRequiredLabel: "Status: Feedback requested"
|
|
||||||
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
|
||||||
closeComment: >
|
|
||||||
This issue has been automatically closed because there has been no response
|
|
||||||
to our request for more information from the original author. With only the
|
|
||||||
information that is currently in the issue, we don't have enough information
|
|
||||||
to take action. Please reach out if you have or find the answers we need so
|
|
||||||
that we can investigate further.
|
|
||||||
+1
-10
@@ -7,14 +7,7 @@ only: issues
|
|||||||
# Issues with these labels will never be considered stale
|
# Issues with these labels will never be considered stale
|
||||||
exemptLabels:
|
exemptLabels:
|
||||||
- "Type: Feature"
|
- "Type: Feature"
|
||||||
- "Bot: Not Stale"
|
- "Type: Understood"
|
||||||
- "Status: Work in Progress"
|
|
||||||
# Set to true to ignore issues in a project (defaults to false)
|
|
||||||
exemptProjects: true
|
|
||||||
# Set to true to ignore issues in a milestone (defaults to false)
|
|
||||||
exemptMilestones: true
|
|
||||||
# Set to true to ignore issues with an assignee (defaults to false)
|
|
||||||
exemptAssignees: true
|
|
||||||
# Label to use when marking an issue as stale
|
# Label to use when marking an issue as stale
|
||||||
staleLabel: "Status: Stale"
|
staleLabel: "Status: Stale"
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||||
@@ -22,5 +15,3 @@ markComment: >
|
|||||||
This issue has been automatically marked as "stale" because it has not had
|
This issue has been automatically marked as "stale" because it has not had
|
||||||
any activity for a while. It will be closed in 90 days if no further activity occurs.
|
any activity for a while. It will be closed in 90 days if no further activity occurs.
|
||||||
Thank you for your contributions.
|
Thank you for your contributions.
|
||||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
|
||||||
limitPerRun: 6
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ name: checkstyle
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request_target:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
checkstyle:
|
checkstyle:
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
@@ -18,13 +18,12 @@ jobs:
|
|||||||
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 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
|
||||||
# packages for tests
|
# packages for tests
|
||||||
sudo apt-get install --yes -qq parted lsscsi ksh attr acl nfs-kernel-server fio
|
sudo apt-get install --yes -qq parted lsscsi ksh attr acl nfs-kernel-server fio
|
||||||
sudo apt-get install --yes -qq mandoc cppcheck pax-utils devscripts abigail-tools
|
sudo apt-get install --yes -qq mandoc cppcheck pax-utils abigail-tools # devscripts - enable then bashisms fixed
|
||||||
sudo -E pip --quiet install flake8
|
sudo -E pip --quiet install flake8
|
||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
sh ./autogen.sh
|
sh ./autogen.sh
|
||||||
./configure
|
./configure
|
||||||
make -j$(nproc)
|
|
||||||
- name: Checkstyle
|
- name: Checkstyle
|
||||||
run: |
|
run: |
|
||||||
make checkstyle
|
make checkstyle
|
||||||
@@ -33,4 +32,5 @@ jobs:
|
|||||||
make lint
|
make lint
|
||||||
- name: CheckABI
|
- name: CheckABI
|
||||||
run: |
|
run: |
|
||||||
|
make -j$(nproc)
|
||||||
make checkabi
|
make checkabi
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
name: zfs-tests-functional
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests-functional-ubuntu:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [18.04, 20.04]
|
|
||||||
runs-on: ubuntu-${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
|
||||||
git alien fakeroot wget curl bc fio acl \
|
|
||||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
|
||||||
nfs-kernel-server samba rng-tools xz-utils \
|
|
||||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
|
||||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
|
||||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
|
||||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
|
||||||
python3 python3-dev python3-setuptools python3-cffi
|
|
||||||
- name: Autogen.sh
|
|
||||||
run: |
|
|
||||||
sh autogen.sh
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./configure --enable-debug --enable-debuginfo
|
|
||||||
- name: Make
|
|
||||||
run: |
|
|
||||||
make --no-print-directory -s pkg-utils pkg-kmod
|
|
||||||
- name: Install
|
|
||||||
run: |
|
|
||||||
sudo dpkg -i *.deb
|
|
||||||
# Update order of directories to search for modules, otherwise
|
|
||||||
# Ubuntu will load kernel-shipped ones.
|
|
||||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
|
||||||
sudo depmod
|
|
||||||
sudo modprobe zfs
|
|
||||||
# Workaround to provide additional free space for testing.
|
|
||||||
# https://github.com/actions/virtual-environments/issues/2840
|
|
||||||
sudo rm -rf /usr/share/dotnet
|
|
||||||
sudo rm -rf /opt/ghc
|
|
||||||
sudo rm -rf "/usr/local/share/boost"
|
|
||||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
|
||||||
- name: Tests
|
|
||||||
run: |
|
|
||||||
/usr/share/zfs/zfs-tests.sh -v -s 3G
|
|
||||||
- name: Prepare artifacts
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
|
||||||
sudo dmesg > $RESULTS_PATH/dmesg
|
|
||||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
|
||||||
sudo chmod +r $RESULTS_PATH/*
|
|
||||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
|
||||||
for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Test logs Ubuntu-${{ matrix.os }}
|
|
||||||
path: /var/tmp/test_results/20*/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
name: zfs-tests-sanity
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
|
||||||
git alien fakeroot wget curl bc fio acl \
|
|
||||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
|
||||||
nfs-kernel-server samba rng-tools xz-utils \
|
|
||||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
|
||||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
|
||||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
|
||||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
|
||||||
python3 python3-dev python3-setuptools python3-cffi
|
|
||||||
- name: Autogen.sh
|
|
||||||
run: |
|
|
||||||
sh autogen.sh
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./configure --enable-debug --enable-debuginfo
|
|
||||||
- name: Make
|
|
||||||
run: |
|
|
||||||
make --no-print-directory -s pkg-utils pkg-kmod
|
|
||||||
- name: Install
|
|
||||||
run: |
|
|
||||||
sudo dpkg -i *.deb
|
|
||||||
# Update order of directories to search for modules, otherwise
|
|
||||||
# Ubuntu will load kernel-shipped ones.
|
|
||||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
|
||||||
sudo depmod
|
|
||||||
sudo modprobe zfs
|
|
||||||
# Workaround to provide additional free space for testing.
|
|
||||||
# https://github.com/actions/virtual-environments/issues/2840
|
|
||||||
sudo rm -rf /usr/share/dotnet
|
|
||||||
sudo rm -rf /opt/ghc
|
|
||||||
sudo rm -rf "/usr/local/share/boost"
|
|
||||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
|
||||||
- name: Tests
|
|
||||||
run: |
|
|
||||||
/usr/share/zfs/zfs-tests.sh -v -s 3G -r sanity
|
|
||||||
- name: Prepare artifacts
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
|
||||||
sudo dmesg > $RESULTS_PATH/dmesg
|
|
||||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
|
||||||
sudo chmod +r $RESULTS_PATH/*
|
|
||||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
|
||||||
for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Test logs
|
|
||||||
path: /var/tmp/test_results/20*/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
name: zloop
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
TEST_DIR: /var/tmp/zloop
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb \
|
|
||||||
git alien fakeroot \
|
|
||||||
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 \
|
|
||||||
python-dev python-setuptools python-cffi \
|
|
||||||
python3 python3-dev python3-setuptools python3-cffi
|
|
||||||
- name: Autogen.sh
|
|
||||||
run: |
|
|
||||||
sh autogen.sh
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./configure --enable-debug --enable-debuginfo
|
|
||||||
- name: Make
|
|
||||||
run: |
|
|
||||||
make --no-print-directory -s pkg-utils pkg-kmod
|
|
||||||
- name: Install
|
|
||||||
run: |
|
|
||||||
sudo dpkg -i *.deb
|
|
||||||
# Update order of directories to search for modules, otherwise
|
|
||||||
# Ubuntu will load kernel-shipped ones.
|
|
||||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
|
||||||
sudo depmod
|
|
||||||
sudo modprobe zfs
|
|
||||||
- name: Tests
|
|
||||||
run: |
|
|
||||||
sudo mkdir -p $TEST_DIR
|
|
||||||
# run for 20 minutes to have a total runner time of 30 minutes
|
|
||||||
sudo /usr/share/zfs/zloop.sh -t 1200 -l -m1
|
|
||||||
- name: Prepare artifacts
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
sudo chmod +r -R $TEST_DIR/
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Logs
|
|
||||||
path: |
|
|
||||||
/var/tmp/zloop/*/
|
|
||||||
!/var/tmp/zloop/*/vdev/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Pool files
|
|
||||||
path: |
|
|
||||||
/var/tmp/zloop/*/vdev/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
[submodule "scripts/zfs-images"]
|
[submodule "scripts/zfs-images"]
|
||||||
path = scripts/zfs-images
|
path = scripts/zfs-images
|
||||||
url = https://github.com/openzfs/zfs-images
|
url = https://github.com/zfsonlinux/zfs-images
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
Meta: 1
|
Meta: 1
|
||||||
Name: zfs
|
Name: zfs
|
||||||
Branch: 1.0
|
Branch: 1.0
|
||||||
Version: 2.1.0
|
Version: 2.0.0
|
||||||
Release: 1
|
Release: 1
|
||||||
Release-Tags: relext
|
Release-Tags: relext
|
||||||
License: CDDL
|
License: CDDL
|
||||||
Author: OpenZFS
|
Author: OpenZFS
|
||||||
Linux-Maximum: 5.13
|
Linux-Maximum: 5.9
|
||||||
Linux-Minimum: 3.10
|
Linux-Minimum: 3.10
|
||||||
|
|||||||
+53
-14
@@ -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
|
||||||
@@ -27,9 +25,10 @@ endif
|
|||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign
|
AUTOMAKE_OPTIONS = foreign
|
||||||
EXTRA_DIST = autogen.sh copy-builtin
|
EXTRA_DIST = autogen.sh copy-builtin
|
||||||
|
EXTRA_DIST += cppcheck-suppressions.txt
|
||||||
EXTRA_DIST += config/config.awk config/rpm.am config/deb.am config/tgz.am
|
EXTRA_DIST += config/config.awk config/rpm.am config/deb.am config/tgz.am
|
||||||
EXTRA_DIST += AUTHORS CODE_OF_CONDUCT.md COPYRIGHT LICENSE META NEWS NOTICE
|
EXTRA_DIST += META AUTHORS COPYRIGHT LICENSE NEWS NOTICE README.md
|
||||||
EXTRA_DIST += README.md RELEASES.md
|
EXTRA_DIST += CODE_OF_CONDUCT.md
|
||||||
EXTRA_DIST += module/lua/README.zfs module/os/linux/spl/README.md
|
EXTRA_DIST += module/lua/README.zfs module/os/linux/spl/README.md
|
||||||
|
|
||||||
# Include all the extra licensing information for modules
|
# Include all the extra licensing information for modules
|
||||||
@@ -125,8 +124,17 @@ cstyle:
|
|||||||
|
|
||||||
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
|
checkabi: lib
|
||||||
@@ -135,9 +143,40 @@ checkabi: lib
|
|||||||
storeabi: 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'
|
||||||
@@ -165,13 +204,13 @@ vcscheck:
|
|||||||
PHONY += lint
|
PHONY += lint
|
||||||
lint: cppcheck paxcheck
|
lint: cppcheck paxcheck
|
||||||
|
|
||||||
CPPCHECKDIRS = cmd lib module
|
|
||||||
PHONY += cppcheck
|
PHONY += cppcheck
|
||||||
cppcheck: $(CPPCHECKDIRS)
|
cppcheck:
|
||||||
@if test -n "$(CPPCHECK)"; then \
|
@if type cppcheck > /dev/null 2>&1; then \
|
||||||
set -e ; for dir in $(CPPCHECKDIRS) ; do \
|
cppcheck --quiet --force --error-exitcode=2 --inline-suppr \
|
||||||
$(MAKE) -C $$dir cppcheck ; \
|
--suppressions-list=${top_srcdir}/cppcheck-suppressions.txt \
|
||||||
done \
|
-UHAVE_SSE2 -UHAVE_AVX512F -UHAVE_UIO_ZEROCOPY \
|
||||||
|
${top_srcdir}; \
|
||||||
else \
|
else \
|
||||||
echo "skipping cppcheck because cppcheck is not installed"; \
|
echo "skipping cppcheck because cppcheck is not installed"; \
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -32,4 +32,4 @@ For more details see the NOTICE, LICENSE and COPYRIGHT files; `UCRL-CODE-235197`
|
|||||||
|
|
||||||
# Supported Kernels
|
# Supported Kernels
|
||||||
* The `META` file contains the officially recognized supported Linux kernel versions.
|
* The `META` file contains the officially recognized supported Linux kernel versions.
|
||||||
* Supported FreeBSD versions are any supported branches and releases starting from 12.2-RELEASE.
|
* Supported FreeBSD versions are 12-STABLE and 13-CURRENT.
|
||||||
|
|||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
OpenZFS uses the MAJOR.MINOR.PATCH versioning scheme described here:
|
|
||||||
|
|
||||||
* MAJOR - Incremented at the discretion of the OpenZFS developers to indicate
|
|
||||||
a particularly noteworthy feature or change. An increase in MAJOR number
|
|
||||||
does not indicate any incompatible on-disk format change. The ability
|
|
||||||
to import a ZFS pool is controlled by the feature flags enabled on the
|
|
||||||
pool and the feature flags supported by the installed OpenZFS version.
|
|
||||||
Increasing the MAJOR version is expected to be an infrequent occurrence.
|
|
||||||
|
|
||||||
* MINOR - Incremented to indicate new functionality such as a new feature
|
|
||||||
flag, pool/dataset property, zfs/zpool sub-command, new user/kernel
|
|
||||||
interface, etc. MINOR releases may introduce incompatible changes to the
|
|
||||||
user space library APIs (libzfs.so). Existing user/kernel interfaces are
|
|
||||||
considered to be stable to maximize compatibility between OpenZFS releases.
|
|
||||||
Additions to the user/kernel interface are backwards compatible.
|
|
||||||
|
|
||||||
* PATCH - Incremented when applying documentation updates, important bug
|
|
||||||
fixes, minor performance improvements, and kernel compatibility patches.
|
|
||||||
The user space library APIs and user/kernel interface are considered to
|
|
||||||
be stable. PATCH releases for a MAJOR.MINOR are published as needed.
|
|
||||||
|
|
||||||
Two release branches are maintained for OpenZFS, they are:
|
|
||||||
|
|
||||||
* OpenZFS LTS - A designated MAJOR.MINOR release with periodic PATCH
|
|
||||||
releases that incorporate important changes backported from newer OpenZFS
|
|
||||||
releases. This branch is intended for use in environments using an
|
|
||||||
LTS, enterprise, or similarly managed kernel (RHEL, Ubuntu LTS, Debian).
|
|
||||||
Minor changes to support these distribution kernels will be applied as
|
|
||||||
needed. New kernel versions released after the OpenZFS LTS release are
|
|
||||||
not supported. LTS releases will receive patches for at least 2 years.
|
|
||||||
The current LTS release is OpenZFS 2.1.
|
|
||||||
|
|
||||||
* OpenZFS current - Tracks the newest MAJOR.MINOR release. This branch
|
|
||||||
includes support for the latest OpenZFS features and recently releases
|
|
||||||
kernels. When a new MINOR release is tagged the previous MINOR release
|
|
||||||
will no longer be maintained (unless it is an LTS release). New MINOR
|
|
||||||
releases are planned to occur roughly annually.
|
|
||||||
+1
-18
@@ -1,14 +1,5 @@
|
|||||||
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
|
|
||||||
|
|
||||||
CPPCHECKDIRS = zfs zpool zdb zhack zinject zstream ztest
|
|
||||||
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
|
||||||
@@ -16,12 +7,4 @@ 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
|
|
||||||
SHELLCHECKDIRS += zed
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PHONY = cppcheck
|
|
||||||
cppcheck: $(CPPCHECKDIRS)
|
|
||||||
set -e ; for dir in $(CPPCHECKDIRS) ; do \
|
|
||||||
$(MAKE) -C $$dir cppcheck ; \
|
|
||||||
done
|
|
||||||
|
|||||||
+60
-147
@@ -59,20 +59,14 @@ if sys.platform.startswith('freebsd'):
|
|||||||
# Requires py27-sysctl on FreeBSD
|
# Requires py27-sysctl on FreeBSD
|
||||||
import sysctl
|
import sysctl
|
||||||
|
|
||||||
def is_value(ctl):
|
|
||||||
return ctl.type != sysctl.CTLTYPE_NODE
|
|
||||||
|
|
||||||
def load_kstats(namespace):
|
def load_kstats(namespace):
|
||||||
"""Collect information on a specific subsystem of the ARC"""
|
"""Collect information on a specific subsystem of the ARC"""
|
||||||
|
|
||||||
base = 'kstat.zfs.misc.%s.' % namespace
|
base = 'kstat.zfs.misc.%s.' % namespace
|
||||||
fmt = lambda kstat: (kstat.name, D(kstat.value))
|
return [(kstat.name, D(kstat.value)) for kstat in sysctl.filter(base)]
|
||||||
kstats = sysctl.filter(base)
|
|
||||||
return [fmt(kstat) for kstat in kstats if is_value(kstat)]
|
|
||||||
|
|
||||||
def load_tunables():
|
def load_tunables():
|
||||||
ctls = sysctl.filter('vfs.zfs')
|
return dict((ctl.name, ctl.value) for ctl in sysctl.filter('vfs.zfs'))
|
||||||
return dict((ctl.name, ctl.value) for ctl in ctls if is_value(ctl))
|
|
||||||
|
|
||||||
elif sys.platform.startswith('linux'):
|
elif sys.platform.startswith('linux'):
|
||||||
|
|
||||||
@@ -102,6 +96,18 @@ show_tunable_descriptions = False
|
|||||||
alternate_tunable_layout = False
|
alternate_tunable_layout = False
|
||||||
|
|
||||||
|
|
||||||
|
def handle_Exception(ex_cls, ex, tb):
|
||||||
|
if ex is IOError:
|
||||||
|
if ex.errno == errno.EPIPE:
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
if ex is KeyboardInterrupt:
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
|
sys.excepthook = handle_Exception
|
||||||
|
|
||||||
|
|
||||||
def get_Kstat():
|
def get_Kstat():
|
||||||
"""Collect information on the ZFS subsystem from the /proc virtual
|
"""Collect information on the ZFS subsystem from the /proc virtual
|
||||||
file system. The name "kstat" is a holdover from the Solaris utility
|
file system. The name "kstat" is a holdover from the Solaris utility
|
||||||
@@ -213,30 +219,12 @@ def get_arc_summary(Kstat):
|
|||||||
deleted = Kstat["kstat.zfs.misc.arcstats.deleted"]
|
deleted = Kstat["kstat.zfs.misc.arcstats.deleted"]
|
||||||
mutex_miss = Kstat["kstat.zfs.misc.arcstats.mutex_miss"]
|
mutex_miss = Kstat["kstat.zfs.misc.arcstats.mutex_miss"]
|
||||||
evict_skip = Kstat["kstat.zfs.misc.arcstats.evict_skip"]
|
evict_skip = Kstat["kstat.zfs.misc.arcstats.evict_skip"]
|
||||||
evict_l2_cached = Kstat["kstat.zfs.misc.arcstats.evict_l2_cached"]
|
|
||||||
evict_l2_eligible = Kstat["kstat.zfs.misc.arcstats.evict_l2_eligible"]
|
|
||||||
evict_l2_eligible_mfu = Kstat["kstat.zfs.misc.arcstats.evict_l2_eligible_mfu"]
|
|
||||||
evict_l2_eligible_mru = Kstat["kstat.zfs.misc.arcstats.evict_l2_eligible_mru"]
|
|
||||||
evict_l2_ineligible = Kstat["kstat.zfs.misc.arcstats.evict_l2_ineligible"]
|
|
||||||
evict_l2_skip = Kstat["kstat.zfs.misc.arcstats.evict_l2_skip"]
|
|
||||||
|
|
||||||
# ARC Misc.
|
# ARC Misc.
|
||||||
output["arc_misc"] = {}
|
output["arc_misc"] = {}
|
||||||
output["arc_misc"]["deleted"] = fHits(deleted)
|
output["arc_misc"]["deleted"] = fHits(deleted)
|
||||||
output["arc_misc"]["mutex_miss"] = fHits(mutex_miss)
|
output["arc_misc"]['mutex_miss'] = fHits(mutex_miss)
|
||||||
output["arc_misc"]["evict_skips"] = fHits(evict_skip)
|
output["arc_misc"]['evict_skips'] = fHits(evict_skip)
|
||||||
output["arc_misc"]["evict_l2_skip"] = fHits(evict_l2_skip)
|
|
||||||
output["arc_misc"]["evict_l2_cached"] = fBytes(evict_l2_cached)
|
|
||||||
output["arc_misc"]["evict_l2_eligible"] = fBytes(evict_l2_eligible)
|
|
||||||
output["arc_misc"]["evict_l2_eligible_mfu"] = {
|
|
||||||
'per': fPerc(evict_l2_eligible_mfu, evict_l2_eligible),
|
|
||||||
'num': fBytes(evict_l2_eligible_mfu),
|
|
||||||
}
|
|
||||||
output["arc_misc"]["evict_l2_eligible_mru"] = {
|
|
||||||
'per': fPerc(evict_l2_eligible_mru, evict_l2_eligible),
|
|
||||||
'num': fBytes(evict_l2_eligible_mru),
|
|
||||||
}
|
|
||||||
output["arc_misc"]["evict_l2_ineligible"] = fBytes(evict_l2_ineligible)
|
|
||||||
|
|
||||||
# ARC Sizing
|
# ARC Sizing
|
||||||
arc_size = Kstat["kstat.zfs.misc.arcstats.size"]
|
arc_size = Kstat["kstat.zfs.misc.arcstats.size"]
|
||||||
@@ -352,26 +340,8 @@ def _arc_summary(Kstat):
|
|||||||
sys.stdout.write("\tDeleted:\t\t\t\t%s\n" % arc['arc_misc']['deleted'])
|
sys.stdout.write("\tDeleted:\t\t\t\t%s\n" % arc['arc_misc']['deleted'])
|
||||||
sys.stdout.write("\tMutex Misses:\t\t\t\t%s\n" %
|
sys.stdout.write("\tMutex Misses:\t\t\t\t%s\n" %
|
||||||
arc['arc_misc']['mutex_miss'])
|
arc['arc_misc']['mutex_miss'])
|
||||||
sys.stdout.write("\tEviction Skips:\t\t\t\t%s\n" %
|
sys.stdout.write("\tEvict Skips:\t\t\t\t%s\n" %
|
||||||
arc['arc_misc']['evict_skips'])
|
arc['arc_misc']['evict_skips'])
|
||||||
sys.stdout.write("\tEviction Skips Due to L2 Writes:\t%s\n" %
|
|
||||||
arc['arc_misc']['evict_l2_skip'])
|
|
||||||
sys.stdout.write("\tL2 Cached Evictions:\t\t\t%s\n" %
|
|
||||||
arc['arc_misc']['evict_l2_cached'])
|
|
||||||
sys.stdout.write("\tL2 Eligible Evictions:\t\t\t%s\n" %
|
|
||||||
arc['arc_misc']['evict_l2_eligible'])
|
|
||||||
sys.stdout.write("\tL2 Eligible MFU Evictions:\t%s\t%s\n" % (
|
|
||||||
arc['arc_misc']['evict_l2_eligible_mfu']['per'],
|
|
||||||
arc['arc_misc']['evict_l2_eligible_mfu']['num'],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tL2 Eligible MRU Evictions:\t%s\t%s\n" % (
|
|
||||||
arc['arc_misc']['evict_l2_eligible_mru']['per'],
|
|
||||||
arc['arc_misc']['evict_l2_eligible_mru']['num'],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tL2 Ineligible Evictions:\t\t%s\n" %
|
|
||||||
arc['arc_misc']['evict_l2_ineligible'])
|
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
# ARC Sizing
|
# ARC Sizing
|
||||||
@@ -707,11 +677,6 @@ def get_l2arc_summary(Kstat):
|
|||||||
l2_writes_done = Kstat["kstat.zfs.misc.arcstats.l2_writes_done"]
|
l2_writes_done = Kstat["kstat.zfs.misc.arcstats.l2_writes_done"]
|
||||||
l2_writes_error = Kstat["kstat.zfs.misc.arcstats.l2_writes_error"]
|
l2_writes_error = Kstat["kstat.zfs.misc.arcstats.l2_writes_error"]
|
||||||
l2_writes_sent = Kstat["kstat.zfs.misc.arcstats.l2_writes_sent"]
|
l2_writes_sent = Kstat["kstat.zfs.misc.arcstats.l2_writes_sent"]
|
||||||
l2_mfu_asize = Kstat["kstat.zfs.misc.arcstats.l2_mfu_asize"]
|
|
||||||
l2_mru_asize = Kstat["kstat.zfs.misc.arcstats.l2_mru_asize"]
|
|
||||||
l2_prefetch_asize = Kstat["kstat.zfs.misc.arcstats.l2_prefetch_asize"]
|
|
||||||
l2_bufc_data_asize = Kstat["kstat.zfs.misc.arcstats.l2_bufc_data_asize"]
|
|
||||||
l2_bufc_metadata_asize = Kstat["kstat.zfs.misc.arcstats.l2_bufc_metadata_asize"]
|
|
||||||
|
|
||||||
l2_access_total = (l2_hits + l2_misses)
|
l2_access_total = (l2_hits + l2_misses)
|
||||||
output['l2_health_count'] = (l2_writes_error + l2_cksum_bad + l2_io_error)
|
output['l2_health_count'] = (l2_writes_error + l2_cksum_bad + l2_io_error)
|
||||||
@@ -734,7 +699,7 @@ def get_l2arc_summary(Kstat):
|
|||||||
output["io_errors"] = fHits(l2_io_error)
|
output["io_errors"] = fHits(l2_io_error)
|
||||||
|
|
||||||
output["l2_arc_size"] = {}
|
output["l2_arc_size"] = {}
|
||||||
output["l2_arc_size"]["adaptive"] = fBytes(l2_size)
|
output["l2_arc_size"]["adative"] = fBytes(l2_size)
|
||||||
output["l2_arc_size"]["actual"] = {
|
output["l2_arc_size"]["actual"] = {
|
||||||
'per': fPerc(l2_asize, l2_size),
|
'per': fPerc(l2_asize, l2_size),
|
||||||
'num': fBytes(l2_asize)
|
'num': fBytes(l2_asize)
|
||||||
@@ -743,26 +708,6 @@ def get_l2arc_summary(Kstat):
|
|||||||
'per': fPerc(l2_hdr_size, l2_size),
|
'per': fPerc(l2_hdr_size, l2_size),
|
||||||
'num': fBytes(l2_hdr_size),
|
'num': fBytes(l2_hdr_size),
|
||||||
}
|
}
|
||||||
output["l2_arc_size"]["mfu_asize"] = {
|
|
||||||
'per': fPerc(l2_mfu_asize, l2_asize),
|
|
||||||
'num': fBytes(l2_mfu_asize),
|
|
||||||
}
|
|
||||||
output["l2_arc_size"]["mru_asize"] = {
|
|
||||||
'per': fPerc(l2_mru_asize, l2_asize),
|
|
||||||
'num': fBytes(l2_mru_asize),
|
|
||||||
}
|
|
||||||
output["l2_arc_size"]["prefetch_asize"] = {
|
|
||||||
'per': fPerc(l2_prefetch_asize, l2_asize),
|
|
||||||
'num': fBytes(l2_prefetch_asize),
|
|
||||||
}
|
|
||||||
output["l2_arc_size"]["bufc_data_asize"] = {
|
|
||||||
'per': fPerc(l2_bufc_data_asize, l2_asize),
|
|
||||||
'num': fBytes(l2_bufc_data_asize),
|
|
||||||
}
|
|
||||||
output["l2_arc_size"]["bufc_metadata_asize"] = {
|
|
||||||
'per': fPerc(l2_bufc_metadata_asize, l2_asize),
|
|
||||||
'num': fBytes(l2_bufc_metadata_asize),
|
|
||||||
}
|
|
||||||
|
|
||||||
output["l2_arc_evicts"] = {}
|
output["l2_arc_evicts"] = {}
|
||||||
output["l2_arc_evicts"]['lock_retries'] = fHits(l2_evict_lock_retry)
|
output["l2_arc_evicts"]['lock_retries'] = fHits(l2_evict_lock_retry)
|
||||||
@@ -827,7 +772,7 @@ def _l2arc_summary(Kstat):
|
|||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
sys.stdout.write("L2 ARC Size: (Adaptive)\t\t\t\t%s\n" %
|
sys.stdout.write("L2 ARC Size: (Adaptive)\t\t\t\t%s\n" %
|
||||||
arc["l2_arc_size"]["adaptive"])
|
arc["l2_arc_size"]["adative"])
|
||||||
sys.stdout.write("\tCompressed:\t\t\t%s\t%s\n" % (
|
sys.stdout.write("\tCompressed:\t\t\t%s\t%s\n" % (
|
||||||
arc["l2_arc_size"]["actual"]["per"],
|
arc["l2_arc_size"]["actual"]["per"],
|
||||||
arc["l2_arc_size"]["actual"]["num"],
|
arc["l2_arc_size"]["actual"]["num"],
|
||||||
@@ -838,36 +783,11 @@ def _l2arc_summary(Kstat):
|
|||||||
arc["l2_arc_size"]["head_size"]["num"],
|
arc["l2_arc_size"]["head_size"]["num"],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
sys.stdout.write("\tMFU Alloc. Size:\t\t%s\t%s\n" % (
|
|
||||||
arc["l2_arc_size"]["mfu_asize"]["per"],
|
|
||||||
arc["l2_arc_size"]["mfu_asize"]["num"],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tMRU Alloc. Size:\t\t%s\t%s\n" % (
|
|
||||||
arc["l2_arc_size"]["mru_asize"]["per"],
|
|
||||||
arc["l2_arc_size"]["mru_asize"]["num"],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tPrefetch Alloc. Size:\t\t%s\t%s\n" % (
|
|
||||||
arc["l2_arc_size"]["prefetch_asize"]["per"],
|
|
||||||
arc["l2_arc_size"]["prefetch_asize"]["num"],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tData (buf content) Alloc. Size:\t%s\t%s\n" % (
|
|
||||||
arc["l2_arc_size"]["bufc_data_asize"]["per"],
|
|
||||||
arc["l2_arc_size"]["bufc_data_asize"]["num"],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tMetadata (buf content) Size:\t%s\t%s\n" % (
|
|
||||||
arc["l2_arc_size"]["bufc_metadata_asize"]["per"],
|
|
||||||
arc["l2_arc_size"]["bufc_metadata_asize"]["num"],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
if arc["l2_arc_evicts"]['lock_retries'] != '0' or \
|
if arc["l2_arc_evicts"]['lock_retries'] != '0' or \
|
||||||
arc["l2_arc_evicts"]["reading"] != '0':
|
arc["l2_arc_evicts"]["reading"] != '0':
|
||||||
sys.stdout.write("L2 ARC Evictions:\n")
|
sys.stdout.write("L2 ARC Evicts:\n")
|
||||||
sys.stdout.write("\tLock Retries:\t\t\t\t%s\n" %
|
sys.stdout.write("\tLock Retries:\t\t\t\t%s\n" %
|
||||||
arc["l2_arc_evicts"]['lock_retries'])
|
arc["l2_arc_evicts"]['lock_retries'])
|
||||||
sys.stdout.write("\tUpon Reading:\t\t\t\t%s\n" %
|
sys.stdout.write("\tUpon Reading:\t\t\t\t%s\n" %
|
||||||
@@ -1125,55 +1045,48 @@ def main():
|
|||||||
global alternate_tunable_layout
|
global alternate_tunable_layout
|
||||||
|
|
||||||
try:
|
try:
|
||||||
try:
|
opts, args = getopt.getopt(
|
||||||
opts, args = getopt.getopt(
|
sys.argv[1:],
|
||||||
sys.argv[1:],
|
"adp:h", ["alternate", "description", "page=", "help"]
|
||||||
"adp:h", ["alternate", "description", "page=", "help"]
|
)
|
||||||
)
|
except getopt.error as e:
|
||||||
except getopt.error as e:
|
sys.stderr.write("Error: %s\n" % e.msg)
|
||||||
sys.stderr.write("Error: %s\n" % e.msg)
|
usage()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
args = {}
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt in ('-a', '--alternate'):
|
||||||
|
args['a'] = True
|
||||||
|
if opt in ('-d', '--description'):
|
||||||
|
args['d'] = True
|
||||||
|
if opt in ('-p', '--page'):
|
||||||
|
args['p'] = arg
|
||||||
|
if opt in ('-h', '--help'):
|
||||||
usage()
|
usage()
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
args = {}
|
|
||||||
for opt, arg in opts:
|
|
||||||
if opt in ('-a', '--alternate'):
|
|
||||||
args['a'] = True
|
|
||||||
if opt in ('-d', '--description'):
|
|
||||||
args['d'] = True
|
|
||||||
if opt in ('-p', '--page'):
|
|
||||||
args['p'] = arg
|
|
||||||
if opt in ('-h', '--help'):
|
|
||||||
usage()
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
Kstat = get_Kstat()
|
|
||||||
|
|
||||||
alternate_tunable_layout = 'a' in args
|
|
||||||
show_tunable_descriptions = 'd' in args
|
|
||||||
|
|
||||||
pages = []
|
|
||||||
|
|
||||||
if 'p' in args:
|
|
||||||
try:
|
|
||||||
pages.append(unSub[int(args['p']) - 1])
|
|
||||||
except IndexError:
|
|
||||||
sys.stderr.write('the argument to -p must be between 1 and ' +
|
|
||||||
str(len(unSub)) + '\n')
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
pages = unSub
|
|
||||||
|
|
||||||
zfs_header()
|
|
||||||
for page in pages:
|
|
||||||
page(Kstat)
|
|
||||||
sys.stdout.write("\n")
|
|
||||||
except IOError as ex:
|
|
||||||
if (ex.errno == errno.EPIPE):
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
raise
|
|
||||||
except KeyboardInterrupt:
|
Kstat = get_Kstat()
|
||||||
sys.exit(0)
|
|
||||||
|
alternate_tunable_layout = 'a' in args
|
||||||
|
show_tunable_descriptions = 'd' in args
|
||||||
|
|
||||||
|
pages = []
|
||||||
|
|
||||||
|
if 'p' in args:
|
||||||
|
try:
|
||||||
|
pages.append(unSub[int(args['p']) - 1])
|
||||||
|
except IndexError:
|
||||||
|
sys.stderr.write('the argument to -p must be between 1 and ' +
|
||||||
|
str(len(unSub)) + '\n')
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
pages = unSub
|
||||||
|
|
||||||
|
zfs_header()
|
||||||
|
for page in pages:
|
||||||
|
page(Kstat)
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -65,6 +58,7 @@ SECTION_PATHS = {'arc': 'arcstats',
|
|||||||
'dmu': 'dmu_tx',
|
'dmu': 'dmu_tx',
|
||||||
'l2arc': 'arcstats', # L2ARC stuff lives in arcstats
|
'l2arc': 'arcstats', # L2ARC stuff lives in arcstats
|
||||||
'vdev': 'vdev_cache_stats',
|
'vdev': 'vdev_cache_stats',
|
||||||
|
'xuio': 'xuio_stats',
|
||||||
'zfetch': 'zfetchstats',
|
'zfetch': 'zfetchstats',
|
||||||
'zil': 'zil'}
|
'zil': 'zil'}
|
||||||
|
|
||||||
@@ -92,24 +86,16 @@ if sys.platform.startswith('freebsd'):
|
|||||||
|
|
||||||
VDEV_CACHE_SIZE = 'vdev.cache_size'
|
VDEV_CACHE_SIZE = 'vdev.cache_size'
|
||||||
|
|
||||||
def is_value(ctl):
|
|
||||||
return ctl.type != sysctl.CTLTYPE_NODE
|
|
||||||
|
|
||||||
def namefmt(ctl, base='vfs.zfs.'):
|
|
||||||
# base is removed from the name
|
|
||||||
cut = len(base)
|
|
||||||
return ctl.name[cut:]
|
|
||||||
|
|
||||||
def load_kstats(section):
|
def load_kstats(section):
|
||||||
base = 'kstat.zfs.misc.{section}.'.format(section=section)
|
base = 'kstat.zfs.misc.{section}.'.format(section=section)
|
||||||
fmt = lambda kstat: '{name} : {value}'.format(name=namefmt(kstat, base),
|
# base is removed from the name
|
||||||
|
fmt = lambda kstat: '{name} : {value}'.format(name=kstat.name[len(base):],
|
||||||
value=kstat.value)
|
value=kstat.value)
|
||||||
kstats = sysctl.filter(base)
|
return [fmt(kstat) for kstat in sysctl.filter(base)]
|
||||||
return [fmt(kstat) for kstat in kstats if is_value(kstat)]
|
|
||||||
|
|
||||||
def get_params(base):
|
def get_params(base):
|
||||||
ctls = sysctl.filter(base)
|
cut = 8 # = len('vfs.zfs.')
|
||||||
return {namefmt(ctl): str(ctl.value) for ctl in ctls if is_value(ctl)}
|
return {ctl.name[cut:]: str(ctl.value) for ctl in sysctl.filter(base)}
|
||||||
|
|
||||||
def get_tunable_params():
|
def get_tunable_params():
|
||||||
return get_params('vfs.zfs')
|
return get_params('vfs.zfs')
|
||||||
@@ -126,8 +112,25 @@ if sys.platform.startswith('freebsd'):
|
|||||||
return '{} version {}'.format(name, version)
|
return '{} version {}'.format(name, version)
|
||||||
|
|
||||||
def get_descriptions(_request):
|
def get_descriptions(_request):
|
||||||
ctls = sysctl.filter('vfs.zfs')
|
# py-sysctl doesn't give descriptions, so we have to shell out.
|
||||||
return {namefmt(ctl): ctl.description for ctl in ctls if is_value(ctl)}
|
command = ['sysctl', '-d', 'vfs.zfs']
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
if 'run' in dir(subprocess):
|
||||||
|
info = subprocess.run(command, stdout=subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
|
lines = info.stdout.split('\n')
|
||||||
|
else:
|
||||||
|
info = subprocess.check_output(command, universal_newlines=True)
|
||||||
|
lines = info.split('\n')
|
||||||
|
|
||||||
|
def fmt(line):
|
||||||
|
name, desc = line.split(':', 1)
|
||||||
|
return (name.strip(), desc.strip())
|
||||||
|
|
||||||
|
return dict([fmt(line) for line in lines if len(line) > 0])
|
||||||
|
|
||||||
|
|
||||||
elif sys.platform.startswith('linux'):
|
elif sys.platform.startswith('linux'):
|
||||||
@@ -168,11 +171,21 @@ elif sys.platform.startswith('linux'):
|
|||||||
# The original arc_summary called /sbin/modinfo/{spl,zfs} to get
|
# The original arc_summary called /sbin/modinfo/{spl,zfs} to get
|
||||||
# the version information. We switch to /sys/module/{spl,zfs}/version
|
# the version information. We switch to /sys/module/{spl,zfs}/version
|
||||||
# to make sure we get what is really loaded in the kernel
|
# to make sure we get what is really loaded in the kernel
|
||||||
try:
|
command = ["cat", "/sys/module/{0}/version".format(request)]
|
||||||
with open("/sys/module/{}/version".format(request)) as f:
|
req = request.upper()
|
||||||
return f.read().strip()
|
|
||||||
except:
|
# The recommended way to do this is with subprocess.run(). However,
|
||||||
return "(unknown)"
|
# some installed versions of Python are < 3.5, so we offer them
|
||||||
|
# the option of doing it the old way (for now)
|
||||||
|
if 'run' in dir(subprocess):
|
||||||
|
info = subprocess.run(command, stdout=subprocess.PIPE,
|
||||||
|
universal_newlines=True)
|
||||||
|
version = info.stdout.strip()
|
||||||
|
else:
|
||||||
|
info = subprocess.check_output(command, universal_newlines=True)
|
||||||
|
version = info.strip()
|
||||||
|
|
||||||
|
return version
|
||||||
|
|
||||||
def get_descriptions(request):
|
def get_descriptions(request):
|
||||||
"""Get the descriptions of the Solaris Porting Layer (SPL) or the
|
"""Get the descriptions of the Solaris Porting Layer (SPL) or the
|
||||||
@@ -228,29 +241,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
|
||||||
@@ -407,12 +397,8 @@ def format_raw_line(name, value):
|
|||||||
if ARGS.alt:
|
if ARGS.alt:
|
||||||
result = '{0}{1}={2}'.format(INDENT, name, value)
|
result = '{0}{1}={2}'.format(INDENT, name, value)
|
||||||
else:
|
else:
|
||||||
# Right-align the value within the line length if it fits,
|
spc = LINE_LENGTH-(len(INDENT)+len(value))
|
||||||
# otherwise just separate it from the name by a single space.
|
result = '{0}{1:<{spc}}{2}'.format(INDENT, name, value, spc=spc)
|
||||||
fit = LINE_LENGTH - len(INDENT) - len(name)
|
|
||||||
overflow = len(value) + 1
|
|
||||||
w = max(fit, overflow)
|
|
||||||
result = '{0}{1}{2:>{w}}'.format(INDENT, name, value, w=w)
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -612,20 +598,6 @@ def section_arc(kstats_dict):
|
|||||||
prt_i1('Deleted:', f_hits(arc_stats['deleted']))
|
prt_i1('Deleted:', f_hits(arc_stats['deleted']))
|
||||||
prt_i1('Mutex misses:', f_hits(arc_stats['mutex_miss']))
|
prt_i1('Mutex misses:', f_hits(arc_stats['mutex_miss']))
|
||||||
prt_i1('Eviction skips:', f_hits(arc_stats['evict_skip']))
|
prt_i1('Eviction skips:', f_hits(arc_stats['evict_skip']))
|
||||||
prt_i1('Eviction skips due to L2 writes:',
|
|
||||||
f_hits(arc_stats['evict_l2_skip']))
|
|
||||||
prt_i1('L2 cached evictions:', f_bytes(arc_stats['evict_l2_cached']))
|
|
||||||
prt_i1('L2 eligible evictions:', f_bytes(arc_stats['evict_l2_eligible']))
|
|
||||||
prt_i2('L2 eligible MFU evictions:',
|
|
||||||
f_perc(arc_stats['evict_l2_eligible_mfu'],
|
|
||||||
arc_stats['evict_l2_eligible']),
|
|
||||||
f_bytes(arc_stats['evict_l2_eligible_mfu']))
|
|
||||||
prt_i2('L2 eligible MRU evictions:',
|
|
||||||
f_perc(arc_stats['evict_l2_eligible_mru'],
|
|
||||||
arc_stats['evict_l2_eligible']),
|
|
||||||
f_bytes(arc_stats['evict_l2_eligible_mru']))
|
|
||||||
prt_i1('L2 ineligible evictions:',
|
|
||||||
f_bytes(arc_stats['evict_l2_ineligible']))
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
@@ -764,21 +736,6 @@ def section_l2arc(kstats_dict):
|
|||||||
prt_i2('Header size:',
|
prt_i2('Header size:',
|
||||||
f_perc(arc_stats['l2_hdr_size'], arc_stats['l2_size']),
|
f_perc(arc_stats['l2_hdr_size'], arc_stats['l2_size']),
|
||||||
f_bytes(arc_stats['l2_hdr_size']))
|
f_bytes(arc_stats['l2_hdr_size']))
|
||||||
prt_i2('MFU allocated size:',
|
|
||||||
f_perc(arc_stats['l2_mfu_asize'], arc_stats['l2_asize']),
|
|
||||||
f_bytes(arc_stats['l2_mfu_asize']))
|
|
||||||
prt_i2('MRU allocated size:',
|
|
||||||
f_perc(arc_stats['l2_mru_asize'], arc_stats['l2_asize']),
|
|
||||||
f_bytes(arc_stats['l2_mru_asize']))
|
|
||||||
prt_i2('Prefetch allocated size:',
|
|
||||||
f_perc(arc_stats['l2_prefetch_asize'], arc_stats['l2_asize']),
|
|
||||||
f_bytes(arc_stats['l2_prefetch_asize']))
|
|
||||||
prt_i2('Data (buffer content) allocated size:',
|
|
||||||
f_perc(arc_stats['l2_bufc_data_asize'], arc_stats['l2_asize']),
|
|
||||||
f_bytes(arc_stats['l2_bufc_data_asize']))
|
|
||||||
prt_i2('Metadata (buffer content) allocated size:',
|
|
||||||
f_perc(arc_stats['l2_bufc_metadata_asize'], arc_stats['l2_asize']),
|
|
||||||
f_bytes(arc_stats['l2_bufc_metadata_asize']))
|
|
||||||
|
|
||||||
print()
|
print()
|
||||||
prt_1('L2ARC breakdown:', f_hits(l2_access_total))
|
prt_1('L2ARC breakdown:', f_hits(l2_access_total))
|
||||||
|
|||||||
+2
-36
@@ -88,12 +88,6 @@ cols = {
|
|||||||
"mfug": [4, 1000, "MFU ghost list hits per second"],
|
"mfug": [4, 1000, "MFU ghost list hits per second"],
|
||||||
"mrug": [4, 1000, "MRU ghost list hits per second"],
|
"mrug": [4, 1000, "MRU ghost list hits per second"],
|
||||||
"eskip": [5, 1000, "evict_skip per second"],
|
"eskip": [5, 1000, "evict_skip per second"],
|
||||||
"el2skip": [7, 1000, "evict skip, due to l2 writes, per second"],
|
|
||||||
"el2cach": [7, 1024, "Size of L2 cached evictions per second"],
|
|
||||||
"el2el": [5, 1024, "Size of L2 eligible evictions per second"],
|
|
||||||
"el2mfu": [6, 1024, "Size of L2 eligible MFU evictions per second"],
|
|
||||||
"el2mru": [6, 1024, "Size of L2 eligible MRU evictions per second"],
|
|
||||||
"el2inel": [7, 1024, "Size of L2 ineligible evictions per second"],
|
|
||||||
"mtxmis": [6, 1000, "mutex_miss per second"],
|
"mtxmis": [6, 1000, "mutex_miss per second"],
|
||||||
"dread": [5, 1000, "Demand accesses per second"],
|
"dread": [5, 1000, "Demand accesses per second"],
|
||||||
"pread": [5, 1000, "Prefetch accesses per second"],
|
"pread": [5, 1000, "Prefetch accesses per second"],
|
||||||
@@ -102,16 +96,6 @@ cols = {
|
|||||||
"l2read": [6, 1000, "Total L2ARC accesses per second"],
|
"l2read": [6, 1000, "Total L2ARC accesses per second"],
|
||||||
"l2hit%": [6, 100, "L2ARC access hit percentage"],
|
"l2hit%": [6, 100, "L2ARC access hit percentage"],
|
||||||
"l2miss%": [7, 100, "L2ARC access miss percentage"],
|
"l2miss%": [7, 100, "L2ARC access miss percentage"],
|
||||||
"l2pref": [6, 1024, "L2ARC prefetch allocated size"],
|
|
||||||
"l2mfu": [5, 1024, "L2ARC MFU allocated size"],
|
|
||||||
"l2mru": [5, 1024, "L2ARC MRU allocated size"],
|
|
||||||
"l2data": [6, 1024, "L2ARC data allocated size"],
|
|
||||||
"l2meta": [6, 1024, "L2ARC metadata allocated size"],
|
|
||||||
"l2pref%": [7, 100, "L2ARC prefetch percentage"],
|
|
||||||
"l2mfu%": [6, 100, "L2ARC MFU percentage"],
|
|
||||||
"l2mru%": [6, 100, "L2ARC MRU percentage"],
|
|
||||||
"l2data%": [7, 100, "L2ARC data percentage"],
|
|
||||||
"l2meta%": [7, 100, "L2ARC metadata percentage"],
|
|
||||||
"l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"],
|
"l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"],
|
||||||
"l2size": [6, 1024, "Size of the L2ARC"],
|
"l2size": [6, 1024, "Size of the L2ARC"],
|
||||||
"l2bytes": [7, 1024, "Bytes read per second from the L2ARC"],
|
"l2bytes": [7, 1024, "Bytes read per second from the L2ARC"],
|
||||||
@@ -144,14 +128,13 @@ pretty_print = True
|
|||||||
|
|
||||||
|
|
||||||
if sys.platform.startswith('freebsd'):
|
if sys.platform.startswith('freebsd'):
|
||||||
# Requires py-sysctl on FreeBSD
|
# Requires py27-sysctl on FreeBSD
|
||||||
import sysctl
|
import sysctl
|
||||||
|
|
||||||
def kstat_update():
|
def kstat_update():
|
||||||
global kstat
|
global kstat
|
||||||
|
|
||||||
k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats')
|
k = sysctl.filter('kstat.zfs.misc.arcstats')
|
||||||
if ctl.type != sysctl.CTLTYPE_NODE]
|
|
||||||
|
|
||||||
if not k:
|
if not k:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -479,12 +462,6 @@ def calculate():
|
|||||||
v["mrug"] = d["mru_ghost_hits"] / sint
|
v["mrug"] = d["mru_ghost_hits"] / sint
|
||||||
v["mfug"] = d["mfu_ghost_hits"] / sint
|
v["mfug"] = d["mfu_ghost_hits"] / sint
|
||||||
v["eskip"] = d["evict_skip"] / sint
|
v["eskip"] = d["evict_skip"] / sint
|
||||||
v["el2skip"] = d["evict_l2_skip"] / sint
|
|
||||||
v["el2cach"] = d["evict_l2_cached"] / sint
|
|
||||||
v["el2el"] = d["evict_l2_eligible"] / sint
|
|
||||||
v["el2mfu"] = d["evict_l2_eligible_mfu"] / sint
|
|
||||||
v["el2mru"] = d["evict_l2_eligible_mru"] / sint
|
|
||||||
v["el2inel"] = d["evict_l2_ineligible"] / sint
|
|
||||||
v["mtxmis"] = d["mutex_miss"] / sint
|
v["mtxmis"] = d["mutex_miss"] / sint
|
||||||
|
|
||||||
if l2exist:
|
if l2exist:
|
||||||
@@ -498,17 +475,6 @@ def calculate():
|
|||||||
v["l2size"] = cur["l2_size"]
|
v["l2size"] = cur["l2_size"]
|
||||||
v["l2bytes"] = d["l2_read_bytes"] / sint
|
v["l2bytes"] = d["l2_read_bytes"] / sint
|
||||||
|
|
||||||
v["l2pref"] = cur["l2_prefetch_asize"]
|
|
||||||
v["l2mfu"] = cur["l2_mfu_asize"]
|
|
||||||
v["l2mru"] = cur["l2_mru_asize"]
|
|
||||||
v["l2data"] = cur["l2_bufc_data_asize"]
|
|
||||||
v["l2meta"] = cur["l2_bufc_metadata_asize"]
|
|
||||||
v["l2pref%"] = 100 * v["l2pref"] / v["l2asize"]
|
|
||||||
v["l2mfu%"] = 100 * v["l2mfu"] / v["l2asize"]
|
|
||||||
v["l2mru%"] = 100 * v["l2mru"] / v["l2asize"]
|
|
||||||
v["l2data%"] = 100 * v["l2data"] / v["l2asize"]
|
|
||||||
v["l2meta%"] = 100 * v["l2meta"] / v["l2asize"]
|
|
||||||
|
|
||||||
v["grow"] = 0 if cur["arc_no_grow"] else 1
|
v["grow"] = 0 if cur["arc_no_grow"] else 1
|
||||||
v["need"] = cur["arc_need_free"]
|
v["need"] = cur["arc_need_free"]
|
||||||
v["free"] = cur["memory_free_bytes"]
|
v["free"] = cur["memory_free_bytes"]
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ elif sys.platform.startswith("linux"):
|
|||||||
def print_incompat_helper(incompat):
|
def print_incompat_helper(incompat):
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for key in sorted(incompat):
|
for key in sorted(incompat):
|
||||||
if cnt == 0:
|
if cnt is 0:
|
||||||
sys.stderr.write("\t")
|
sys.stderr.write("\t")
|
||||||
elif cnt > 8:
|
elif cnt > 8:
|
||||||
sys.stderr.write(",\n\t")
|
sys.stderr.write(",\n\t")
|
||||||
@@ -662,7 +662,7 @@ def main():
|
|||||||
if not ifile:
|
if not ifile:
|
||||||
ifile = default_ifile()
|
ifile = default_ifile()
|
||||||
|
|
||||||
if ifile != "-":
|
if ifile is not "-":
|
||||||
try:
|
try:
|
||||||
tmp = open(ifile, "r")
|
tmp = open(ifile, "r")
|
||||||
sys.stdin = tmp
|
sys.stdin = tmp
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/fsck.zfs
|
|
||||||
@@ -1,6 +1 @@
|
|||||||
include $(top_srcdir)/config/Substfiles.am
|
|
||||||
include $(top_srcdir)/config/Shellcheck.am
|
|
||||||
|
|
||||||
dist_sbin_SCRIPTS = fsck.zfs
|
dist_sbin_SCRIPTS = fsck.zfs
|
||||||
|
|
||||||
SUBSTFILES += $(dist_sbin_SCRIPTS)
|
|
||||||
|
|||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# fsck.zfs: A fsck helper to accommodate distributions that expect
|
||||||
|
# to be able to execute a fsck on all filesystem types. Currently
|
||||||
|
# this script does nothing but it could be extended to act as a
|
||||||
|
# compatibility wrapper for 'zpool scrub'.
|
||||||
|
#
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# fsck.zfs: A fsck helper to accommodate distributions that expect
|
|
||||||
# to be able to execute a fsck on all filesystem types.
|
|
||||||
#
|
|
||||||
# This script simply bubbles up some already-known-about errors,
|
|
||||||
# see fsck.zfs(8)
|
|
||||||
#
|
|
||||||
|
|
||||||
if [ "$#" = "0" ]; then
|
|
||||||
echo "Usage: $0 [options] dataset…" >&2
|
|
||||||
exit 16
|
|
||||||
fi
|
|
||||||
|
|
||||||
ret=0
|
|
||||||
for dataset in "$@"; do
|
|
||||||
case "$dataset" in
|
|
||||||
-*)
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
pool="${dataset%%/*}"
|
|
||||||
|
|
||||||
case "$(@sbindir@/zpool list -Ho health "$pool")" in
|
|
||||||
DEGRADED)
|
|
||||||
ret=$(( ret | 4 ))
|
|
||||||
;;
|
|
||||||
FAULTED)
|
|
||||||
awk '!/^([[:space:]]*#.*)?$/ && $1 == "'"$dataset"'" && $3 == "zfs" {exit 1}' /etc/fstab || \
|
|
||||||
ret=$(( ret | 8 ))
|
|
||||||
;;
|
|
||||||
"")
|
|
||||||
# Pool not found, error printed by zpool(8)
|
|
||||||
ret=$(( ret | 8 ))
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
exit "$ret"
|
|
||||||
@@ -18,5 +18,3 @@ mount_zfs_LDADD = \
|
|||||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
||||||
|
|
||||||
mount_zfs_LDADD += $(LTLIBINTL)
|
mount_zfs_LDADD += $(LTLIBINTL)
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
+47
-40
@@ -43,45 +43,53 @@
|
|||||||
libzfs_handle_t *g_zfs;
|
libzfs_handle_t *g_zfs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opportunistically convert a target string into a pool name. If the
|
* Return the pool/dataset to mount given the name passed to mount. This
|
||||||
* string does not represent a block device with a valid zfs label
|
* is expected to be of the form pool/dataset, however may also refer to
|
||||||
* then it is passed through without modification.
|
* a block device if that device contains a valid zfs label.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
parse_dataset(const char *target, char **dataset)
|
parse_dataset(const char *target, char **dataset)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Prior to util-linux 2.36.2, if a file or directory in the
|
* We expect a pool/dataset to be provided, however if we're
|
||||||
* current working directory was named 'dataset' then mount(8)
|
* given a device which is a member of a zpool we attempt to
|
||||||
* would prepend the current working directory to the dataset.
|
* extract the pool name stored in the label. Given the pool
|
||||||
* Check for it and strip the prepended path when it is added.
|
* name we can mount the root dataset.
|
||||||
|
*/
|
||||||
|
int fd = open(target, O_RDONLY);
|
||||||
|
if (fd >= 0) {
|
||||||
|
nvlist_t *config = NULL;
|
||||||
|
if (zpool_read_label(fd, &config, NULL) != 0)
|
||||||
|
config = NULL;
|
||||||
|
if (close(fd))
|
||||||
|
perror("close");
|
||||||
|
|
||||||
|
if (config) {
|
||||||
|
char *name = NULL;
|
||||||
|
if (!nvlist_lookup_string(config,
|
||||||
|
ZPOOL_CONFIG_POOL_NAME, &name))
|
||||||
|
(void) strlcpy(*dataset, name, PATH_MAX);
|
||||||
|
nvlist_free(config);
|
||||||
|
if (name)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a file or directory in your current working directory is
|
||||||
|
* named 'dataset' then mount(8) will prepend your current working
|
||||||
|
* directory to the dataset. There is no way to prevent this
|
||||||
|
* behavior so we simply check for it and strip the prepended
|
||||||
|
* patch when it is added.
|
||||||
*/
|
*/
|
||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
if (getcwd(cwd, PATH_MAX) == NULL) {
|
if (getcwd(cwd, PATH_MAX) != NULL) {
|
||||||
perror("getcwd");
|
int len = strlen(cwd);
|
||||||
return;
|
/* Do not add one when cwd already ends in a trailing '/' */
|
||||||
|
if (strncmp(cwd, target, len) == 0)
|
||||||
|
target += len + (cwd[len-1] != '/');
|
||||||
}
|
}
|
||||||
int len = strlen(cwd);
|
|
||||||
if (strncmp(cwd, target, len) == 0)
|
|
||||||
target += len;
|
|
||||||
|
|
||||||
/* Assume pool/dataset is more likely */
|
|
||||||
strlcpy(*dataset, target, PATH_MAX);
|
strlcpy(*dataset, target, PATH_MAX);
|
||||||
|
|
||||||
int fd = open(target, O_RDONLY | O_CLOEXEC);
|
|
||||||
if (fd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nvlist_t *cfg = NULL;
|
|
||||||
if (zpool_read_label(fd, &cfg, NULL) == 0) {
|
|
||||||
char *nm = NULL;
|
|
||||||
if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm))
|
|
||||||
strlcpy(*dataset, nm, PATH_MAX);
|
|
||||||
nvlist_free(cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (close(fd))
|
|
||||||
perror("close");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -125,8 +133,8 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
|||||||
if (!fp) {
|
if (!fp) {
|
||||||
(void) fprintf(stderr, gettext(
|
(void) fprintf(stderr, gettext(
|
||||||
"filesystem '%s' was mounted, but /etc/mtab "
|
"filesystem '%s' was mounted, but /etc/mtab "
|
||||||
"could not be opened due to error: %s\n"),
|
"could not be opened due to error %d\n"),
|
||||||
dataset, strerror(errno));
|
dataset, errno);
|
||||||
return (MOUNT_FILEIO);
|
return (MOUNT_FILEIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,8 +142,8 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
|||||||
if (error) {
|
if (error) {
|
||||||
(void) fprintf(stderr, gettext(
|
(void) fprintf(stderr, gettext(
|
||||||
"filesystem '%s' was mounted, but /etc/mtab "
|
"filesystem '%s' was mounted, but /etc/mtab "
|
||||||
"could not be updated due to error: %s\n"),
|
"could not be updated due to error %d\n"),
|
||||||
dataset, strerror(errno));
|
dataset, errno);
|
||||||
return (MOUNT_FILEIO);
|
return (MOUNT_FILEIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,11 +193,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,8 +223,8 @@ main(int argc, char **argv)
|
|||||||
/* canonicalize the mount point */
|
/* canonicalize the mount point */
|
||||||
if (realpath(argv[1], mntpoint) == NULL) {
|
if (realpath(argv[1], mntpoint) == NULL) {
|
||||||
(void) fprintf(stderr, gettext("filesystem '%s' cannot be "
|
(void) fprintf(stderr, gettext("filesystem '%s' cannot be "
|
||||||
"mounted at '%s' due to canonicalization error: %s\n"),
|
"mounted at '%s' due to canonicalization error %d.\n"),
|
||||||
dataset, argv[1], strerror(errno));
|
dataset, argv[1], errno);
|
||||||
return (MOUNT_SYSERR);
|
return (MOUNT_SYSERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,5 +18,3 @@ raidz_test_LDADD = \
|
|||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la
|
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||||
|
|
||||||
raidz_test_LDADD += -lm
|
raidz_test_LDADD += -lm
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#include <sys/vdev_raidz_impl.h>
|
#include <sys/vdev_raidz_impl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "raidz_test.h"
|
#include "raidz_test.h"
|
||||||
|
|
||||||
#define GEN_BENCH_MEMORY (((uint64_t)1ULL)<<32)
|
#define GEN_BENCH_MEMORY (((uint64_t)1ULL)<<32)
|
||||||
@@ -81,17 +83,8 @@ run_gen_bench_impl(const char *impl)
|
|||||||
/* create suitable raidz_map */
|
/* create suitable raidz_map */
|
||||||
ncols = rto_opts.rto_dcols + fn + 1;
|
ncols = rto_opts.rto_dcols + fn + 1;
|
||||||
zio_bench.io_size = 1ULL << ds;
|
zio_bench.io_size = 1ULL << ds;
|
||||||
|
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
||||||
if (rto_opts.rto_expand) {
|
BENCH_ASHIFT, ncols, fn+1);
|
||||||
rm_bench = vdev_raidz_map_alloc_expanded(
|
|
||||||
zio_bench.io_abd,
|
|
||||||
zio_bench.io_size, zio_bench.io_offset,
|
|
||||||
rto_opts.rto_ashift, ncols+1, ncols,
|
|
||||||
fn+1, rto_opts.rto_expand_offset);
|
|
||||||
} else {
|
|
||||||
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
|
||||||
BENCH_ASHIFT, ncols, fn+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* estimate iteration count */
|
/* estimate iteration count */
|
||||||
iter_cnt = GEN_BENCH_MEMORY;
|
iter_cnt = GEN_BENCH_MEMORY;
|
||||||
@@ -170,16 +163,8 @@ run_rec_bench_impl(const char *impl)
|
|||||||
(1ULL << BENCH_ASHIFT))
|
(1ULL << BENCH_ASHIFT))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rto_opts.rto_expand) {
|
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
||||||
rm_bench = vdev_raidz_map_alloc_expanded(
|
BENCH_ASHIFT, ncols, PARITY_PQR);
|
||||||
zio_bench.io_abd,
|
|
||||||
zio_bench.io_size, zio_bench.io_offset,
|
|
||||||
BENCH_ASHIFT, ncols+1, ncols,
|
|
||||||
PARITY_PQR, rto_opts.rto_expand_offset);
|
|
||||||
} else {
|
|
||||||
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
|
||||||
BENCH_ASHIFT, ncols, PARITY_PQR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* estimate iteration count */
|
/* estimate iteration count */
|
||||||
iter_cnt = (REC_BENCH_MEMORY);
|
iter_cnt = (REC_BENCH_MEMORY);
|
||||||
|
|||||||
+45
-284
@@ -77,20 +77,16 @@ static void print_opts(raidz_test_opts_t *opts, boolean_t force)
|
|||||||
(void) fprintf(stdout, DBLSEP "Running with options:\n"
|
(void) fprintf(stdout, DBLSEP "Running with options:\n"
|
||||||
" (-a) zio ashift : %zu\n"
|
" (-a) zio ashift : %zu\n"
|
||||||
" (-o) zio offset : 1 << %zu\n"
|
" (-o) zio offset : 1 << %zu\n"
|
||||||
" (-e) expanded map : %s\n"
|
|
||||||
" (-r) reflow offset : %llx\n"
|
|
||||||
" (-d) number of raidz data columns : %zu\n"
|
" (-d) number of raidz data columns : %zu\n"
|
||||||
" (-s) size of DATA : 1 << %zu\n"
|
" (-s) size of DATA : 1 << %zu\n"
|
||||||
" (-S) sweep parameters : %s \n"
|
" (-S) sweep parameters : %s \n"
|
||||||
" (-v) verbose : %s \n\n",
|
" (-v) verbose : %s \n\n",
|
||||||
opts->rto_ashift, /* -a */
|
opts->rto_ashift, /* -a */
|
||||||
ilog2(opts->rto_offset), /* -o */
|
ilog2(opts->rto_offset), /* -o */
|
||||||
opts->rto_expand ? "yes" : "no", /* -e */
|
opts->rto_dcols, /* -d */
|
||||||
(u_longlong_t)opts->rto_expand_offset, /* -r */
|
ilog2(opts->rto_dsize), /* -s */
|
||||||
opts->rto_dcols, /* -d */
|
opts->rto_sweep ? "yes" : "no", /* -S */
|
||||||
ilog2(opts->rto_dsize), /* -s */
|
verbose); /* -v */
|
||||||
opts->rto_sweep ? "yes" : "no", /* -S */
|
|
||||||
verbose); /* -v */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +104,6 @@ static void usage(boolean_t requested)
|
|||||||
"\t[-S parameter sweep (default: %s)]\n"
|
"\t[-S parameter sweep (default: %s)]\n"
|
||||||
"\t[-t timeout for parameter sweep test]\n"
|
"\t[-t timeout for parameter sweep test]\n"
|
||||||
"\t[-B benchmark all raidz implementations]\n"
|
"\t[-B benchmark all raidz implementations]\n"
|
||||||
"\t[-e use expanded raidz map (default: %s)]\n"
|
|
||||||
"\t[-r expanded raidz map reflow offset (default: %llx)]\n"
|
|
||||||
"\t[-v increase verbosity (default: %zu)]\n"
|
"\t[-v increase verbosity (default: %zu)]\n"
|
||||||
"\t[-h (print help)]\n"
|
"\t[-h (print help)]\n"
|
||||||
"\t[-T test the test, see if failure would be detected]\n"
|
"\t[-T test the test, see if failure would be detected]\n"
|
||||||
@@ -120,8 +114,6 @@ static void usage(boolean_t requested)
|
|||||||
o->rto_dcols, /* -d */
|
o->rto_dcols, /* -d */
|
||||||
ilog2(o->rto_dsize), /* -s */
|
ilog2(o->rto_dsize), /* -s */
|
||||||
rto_opts.rto_sweep ? "yes" : "no", /* -S */
|
rto_opts.rto_sweep ? "yes" : "no", /* -S */
|
||||||
rto_opts.rto_expand ? "yes" : "no", /* -e */
|
|
||||||
(u_longlong_t)o->rto_expand_offset, /* -r */
|
|
||||||
o->rto_v); /* -d */
|
o->rto_v); /* -d */
|
||||||
|
|
||||||
exit(requested ? 0 : 1);
|
exit(requested ? 0 : 1);
|
||||||
@@ -136,7 +128,7 @@ static void process_options(int argc, char **argv)
|
|||||||
|
|
||||||
bcopy(&rto_opts_defaults, o, sizeof (*o));
|
bcopy(&rto_opts_defaults, o, sizeof (*o));
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "TDBSvha:er:o:d:s:t:")) != -1) {
|
while ((opt = getopt(argc, argv, "TDBSvha:o:d:s:t:")) != -1) {
|
||||||
value = 0;
|
value = 0;
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@@ -144,12 +136,6 @@ static void process_options(int argc, char **argv)
|
|||||||
value = strtoull(optarg, NULL, 0);
|
value = strtoull(optarg, NULL, 0);
|
||||||
o->rto_ashift = MIN(13, MAX(9, value));
|
o->rto_ashift = MIN(13, MAX(9, value));
|
||||||
break;
|
break;
|
||||||
case 'e':
|
|
||||||
o->rto_expand = 1;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
o->rto_expand_offset = strtoull(optarg, NULL, 0);
|
|
||||||
break;
|
|
||||||
case 'o':
|
case 'o':
|
||||||
value = strtoull(optarg, NULL, 0);
|
value = strtoull(optarg, NULL, 0);
|
||||||
o->rto_offset = ((1ULL << MIN(12, value)) >> 9) << 9;
|
o->rto_offset = ((1ULL << MIN(12, value)) >> 9) << 9;
|
||||||
@@ -193,34 +179,25 @@ static void process_options(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DATA_COL(rr, i) ((rr)->rr_col[rr->rr_firstdatacol + (i)].rc_abd)
|
#define DATA_COL(rm, i) ((rm)->rm_col[raidz_parity(rm) + (i)].rc_abd)
|
||||||
#define DATA_COL_SIZE(rr, i) ((rr)->rr_col[rr->rr_firstdatacol + (i)].rc_size)
|
#define DATA_COL_SIZE(rm, i) ((rm)->rm_col[raidz_parity(rm) + (i)].rc_size)
|
||||||
|
|
||||||
#define CODE_COL(rr, i) ((rr)->rr_col[(i)].rc_abd)
|
#define CODE_COL(rm, i) ((rm)->rm_col[(i)].rc_abd)
|
||||||
#define CODE_COL_SIZE(rr, i) ((rr)->rr_col[(i)].rc_size)
|
#define CODE_COL_SIZE(rm, i) ((rm)->rm_col[(i)].rc_size)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmp_code(raidz_test_opts_t *opts, const raidz_map_t *rm, const int parity)
|
cmp_code(raidz_test_opts_t *opts, const raidz_map_t *rm, const int parity)
|
||||||
{
|
{
|
||||||
int r, i, ret = 0;
|
int i, ret = 0;
|
||||||
|
|
||||||
VERIFY(parity >= 1 && parity <= 3);
|
VERIFY(parity >= 1 && parity <= 3);
|
||||||
|
|
||||||
for (r = 0; r < rm->rm_nrows; r++) {
|
for (i = 0; i < parity; i++) {
|
||||||
raidz_row_t * const rr = rm->rm_row[r];
|
if (abd_cmp(CODE_COL(rm, i), CODE_COL(opts->rm_golden, i))
|
||||||
raidz_row_t * const rrg = opts->rm_golden->rm_row[r];
|
!= 0) {
|
||||||
for (i = 0; i < parity; i++) {
|
ret++;
|
||||||
if (CODE_COL_SIZE(rrg, i) == 0) {
|
LOG_OPT(D_DEBUG, opts,
|
||||||
VERIFY0(CODE_COL_SIZE(rr, i));
|
"\nParity block [%d] different!\n", i);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abd_cmp(CODE_COL(rr, i),
|
|
||||||
CODE_COL(rrg, i)) != 0) {
|
|
||||||
ret++;
|
|
||||||
LOG_OPT(D_DEBUG, opts,
|
|
||||||
"\nParity block [%d] different!\n", i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -229,26 +206,16 @@ cmp_code(raidz_test_opts_t *opts, const raidz_map_t *rm, const int parity)
|
|||||||
static int
|
static int
|
||||||
cmp_data(raidz_test_opts_t *opts, raidz_map_t *rm)
|
cmp_data(raidz_test_opts_t *opts, raidz_map_t *rm)
|
||||||
{
|
{
|
||||||
int r, i, dcols, ret = 0;
|
int i, ret = 0;
|
||||||
|
int dcols = opts->rm_golden->rm_cols - raidz_parity(opts->rm_golden);
|
||||||
|
|
||||||
for (r = 0; r < rm->rm_nrows; r++) {
|
for (i = 0; i < dcols; i++) {
|
||||||
raidz_row_t *rr = rm->rm_row[r];
|
if (abd_cmp(DATA_COL(opts->rm_golden, i), DATA_COL(rm, i))
|
||||||
raidz_row_t *rrg = opts->rm_golden->rm_row[r];
|
!= 0) {
|
||||||
dcols = opts->rm_golden->rm_row[0]->rr_cols -
|
ret++;
|
||||||
raidz_parity(opts->rm_golden);
|
|
||||||
for (i = 0; i < dcols; i++) {
|
|
||||||
if (DATA_COL_SIZE(rrg, i) == 0) {
|
|
||||||
VERIFY0(DATA_COL_SIZE(rr, i));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abd_cmp(DATA_COL(rrg, i),
|
LOG_OPT(D_DEBUG, opts,
|
||||||
DATA_COL(rr, i)) != 0) {
|
"\nData block [%d] different!\n", i);
|
||||||
ret++;
|
|
||||||
|
|
||||||
LOG_OPT(D_DEBUG, opts,
|
|
||||||
"\nData block [%d] different!\n", i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -269,13 +236,12 @@ init_rand(void *data, size_t size, void *private)
|
|||||||
static void
|
static void
|
||||||
corrupt_colums(raidz_map_t *rm, const int *tgts, const int cnt)
|
corrupt_colums(raidz_map_t *rm, const int *tgts, const int cnt)
|
||||||
{
|
{
|
||||||
for (int r = 0; r < rm->rm_nrows; r++) {
|
int i;
|
||||||
raidz_row_t *rr = rm->rm_row[r];
|
raidz_col_t *col;
|
||||||
for (int i = 0; i < cnt; i++) {
|
|
||||||
raidz_col_t *col = &rr->rr_col[tgts[i]];
|
for (i = 0; i < cnt; i++) {
|
||||||
abd_iterate_func(col->rc_abd, 0, col->rc_size,
|
col = &rm->rm_col[tgts[i]];
|
||||||
init_rand, NULL);
|
abd_iterate_func(col->rc_abd, 0, col->rc_size, init_rand, NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,22 +288,10 @@ init_raidz_golden_map(raidz_test_opts_t *opts, const int parity)
|
|||||||
|
|
||||||
VERIFY0(vdev_raidz_impl_set("original"));
|
VERIFY0(vdev_raidz_impl_set("original"));
|
||||||
|
|
||||||
if (opts->rto_expand) {
|
opts->rm_golden = vdev_raidz_map_alloc(opts->zio_golden,
|
||||||
opts->rm_golden =
|
opts->rto_ashift, total_ncols, parity);
|
||||||
vdev_raidz_map_alloc_expanded(opts->zio_golden->io_abd,
|
rm_test = vdev_raidz_map_alloc(zio_test,
|
||||||
opts->zio_golden->io_size, opts->zio_golden->io_offset,
|
opts->rto_ashift, total_ncols, parity);
|
||||||
opts->rto_ashift, total_ncols+1, total_ncols,
|
|
||||||
parity, opts->rto_expand_offset);
|
|
||||||
rm_test = vdev_raidz_map_alloc_expanded(zio_test->io_abd,
|
|
||||||
zio_test->io_size, zio_test->io_offset,
|
|
||||||
opts->rto_ashift, total_ncols+1, total_ncols,
|
|
||||||
parity, opts->rto_expand_offset);
|
|
||||||
} else {
|
|
||||||
opts->rm_golden = vdev_raidz_map_alloc(opts->zio_golden,
|
|
||||||
opts->rto_ashift, total_ncols, parity);
|
|
||||||
rm_test = vdev_raidz_map_alloc(zio_test,
|
|
||||||
opts->rto_ashift, total_ncols, parity);
|
|
||||||
}
|
|
||||||
|
|
||||||
VERIFY(opts->zio_golden);
|
VERIFY(opts->zio_golden);
|
||||||
VERIFY(opts->rm_golden);
|
VERIFY(opts->rm_golden);
|
||||||
@@ -358,187 +312,6 @@ init_raidz_golden_map(raidz_test_opts_t *opts, const int parity)
|
|||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If reflow is not in progress, reflow_offset should be UINT64_MAX.
|
|
||||||
* For each row, if the row is entirely before reflow_offset, it will
|
|
||||||
* come from the new location. Otherwise this row will come from the
|
|
||||||
* old location. Therefore, rows that straddle the reflow_offset will
|
|
||||||
* come from the old location.
|
|
||||||
*
|
|
||||||
* NOTE: Until raidz expansion is implemented this function is only
|
|
||||||
* needed by raidz_test.c to the multi-row raid_map_t functionality.
|
|
||||||
*/
|
|
||||||
raidz_map_t *
|
|
||||||
vdev_raidz_map_alloc_expanded(abd_t *abd, uint64_t size, uint64_t offset,
|
|
||||||
uint64_t ashift, uint64_t physical_cols, uint64_t logical_cols,
|
|
||||||
uint64_t nparity, uint64_t reflow_offset)
|
|
||||||
{
|
|
||||||
/* The zio's size in units of the vdev's minimum sector size. */
|
|
||||||
uint64_t s = size >> ashift;
|
|
||||||
uint64_t q, r, bc, devidx, asize = 0, tot;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "Quotient": The number of data sectors for this stripe on all but
|
|
||||||
* the "big column" child vdevs that also contain "remainder" data.
|
|
||||||
* AKA "full rows"
|
|
||||||
*/
|
|
||||||
q = s / (logical_cols - nparity);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "Remainder": The number of partial stripe data sectors in this I/O.
|
|
||||||
* This will add a sector to some, but not all, child vdevs.
|
|
||||||
*/
|
|
||||||
r = s - q * (logical_cols - nparity);
|
|
||||||
|
|
||||||
/* The number of "big columns" - those which contain remainder data. */
|
|
||||||
bc = (r == 0 ? 0 : r + nparity);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The total number of data and parity sectors associated with
|
|
||||||
* this I/O.
|
|
||||||
*/
|
|
||||||
tot = s + nparity * (q + (r == 0 ? 0 : 1));
|
|
||||||
|
|
||||||
/* How many rows contain data (not skip) */
|
|
||||||
uint64_t rows = howmany(tot, logical_cols);
|
|
||||||
int cols = MIN(tot, logical_cols);
|
|
||||||
|
|
||||||
raidz_map_t *rm = kmem_zalloc(offsetof(raidz_map_t, rm_row[rows]),
|
|
||||||
KM_SLEEP);
|
|
||||||
rm->rm_nrows = rows;
|
|
||||||
|
|
||||||
for (uint64_t row = 0; row < rows; row++) {
|
|
||||||
raidz_row_t *rr = kmem_alloc(offsetof(raidz_row_t,
|
|
||||||
rr_col[cols]), KM_SLEEP);
|
|
||||||
rm->rm_row[row] = rr;
|
|
||||||
|
|
||||||
/* The starting RAIDZ (parent) vdev sector of the row. */
|
|
||||||
uint64_t b = (offset >> ashift) + row * logical_cols;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are in the middle of a reflow, and any part of this
|
|
||||||
* row has not been copied, then use the old location of
|
|
||||||
* this row.
|
|
||||||
*/
|
|
||||||
int row_phys_cols = physical_cols;
|
|
||||||
if (b + (logical_cols - nparity) > reflow_offset >> ashift)
|
|
||||||
row_phys_cols--;
|
|
||||||
|
|
||||||
/* starting child of this row */
|
|
||||||
uint64_t child_id = b % row_phys_cols;
|
|
||||||
/* The starting byte offset on each child vdev. */
|
|
||||||
uint64_t child_offset = (b / row_phys_cols) << ashift;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We set cols to the entire width of the block, even
|
|
||||||
* if this row is shorter. This is needed because parity
|
|
||||||
* generation (for Q and R) needs to know the entire width,
|
|
||||||
* because it treats the short row as though it was
|
|
||||||
* full-width (and the "phantom" sectors were zero-filled).
|
|
||||||
*
|
|
||||||
* Another approach to this would be to set cols shorter
|
|
||||||
* (to just the number of columns that we might do i/o to)
|
|
||||||
* and have another mechanism to tell the parity generation
|
|
||||||
* about the "entire width". Reconstruction (at least
|
|
||||||
* vdev_raidz_reconstruct_general()) would also need to
|
|
||||||
* know about the "entire width".
|
|
||||||
*/
|
|
||||||
rr->rr_cols = cols;
|
|
||||||
rr->rr_bigcols = bc;
|
|
||||||
rr->rr_missingdata = 0;
|
|
||||||
rr->rr_missingparity = 0;
|
|
||||||
rr->rr_firstdatacol = nparity;
|
|
||||||
rr->rr_abd_empty = NULL;
|
|
||||||
rr->rr_nempty = 0;
|
|
||||||
|
|
||||||
for (int c = 0; c < rr->rr_cols; c++, child_id++) {
|
|
||||||
if (child_id >= row_phys_cols) {
|
|
||||||
child_id -= row_phys_cols;
|
|
||||||
child_offset += 1ULL << ashift;
|
|
||||||
}
|
|
||||||
rr->rr_col[c].rc_devidx = child_id;
|
|
||||||
rr->rr_col[c].rc_offset = child_offset;
|
|
||||||
rr->rr_col[c].rc_orig_data = NULL;
|
|
||||||
rr->rr_col[c].rc_error = 0;
|
|
||||||
rr->rr_col[c].rc_tried = 0;
|
|
||||||
rr->rr_col[c].rc_skipped = 0;
|
|
||||||
rr->rr_col[c].rc_need_orig_restore = B_FALSE;
|
|
||||||
|
|
||||||
uint64_t dc = c - rr->rr_firstdatacol;
|
|
||||||
if (c < rr->rr_firstdatacol) {
|
|
||||||
rr->rr_col[c].rc_size = 1ULL << ashift;
|
|
||||||
rr->rr_col[c].rc_abd =
|
|
||||||
abd_alloc_linear(rr->rr_col[c].rc_size,
|
|
||||||
B_TRUE);
|
|
||||||
} else if (row == rows - 1 && bc != 0 && c >= bc) {
|
|
||||||
/*
|
|
||||||
* Past the end, this for parity generation.
|
|
||||||
*/
|
|
||||||
rr->rr_col[c].rc_size = 0;
|
|
||||||
rr->rr_col[c].rc_abd = NULL;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* "data column" (col excluding parity)
|
|
||||||
* Add an ASCII art diagram here
|
|
||||||
*/
|
|
||||||
uint64_t off;
|
|
||||||
|
|
||||||
if (c < bc || r == 0) {
|
|
||||||
off = dc * rows + row;
|
|
||||||
} else {
|
|
||||||
off = r * rows +
|
|
||||||
(dc - r) * (rows - 1) + row;
|
|
||||||
}
|
|
||||||
rr->rr_col[c].rc_size = 1ULL << ashift;
|
|
||||||
rr->rr_col[c].rc_abd = abd_get_offset_struct(
|
|
||||||
&rr->rr_col[c].rc_abdstruct,
|
|
||||||
abd, off << ashift, 1 << ashift);
|
|
||||||
}
|
|
||||||
|
|
||||||
asize += rr->rr_col[c].rc_size;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* If all data stored spans all columns, there's a danger that
|
|
||||||
* parity will always be on the same device and, since parity
|
|
||||||
* isn't read during normal operation, that that device's I/O
|
|
||||||
* bandwidth won't be used effectively. We therefore switch
|
|
||||||
* the parity every 1MB.
|
|
||||||
*
|
|
||||||
* ...at least that was, ostensibly, the theory. As a practical
|
|
||||||
* matter unless we juggle the parity between all devices
|
|
||||||
* evenly, we won't see any benefit. Further, occasional writes
|
|
||||||
* that aren't a multiple of the LCM of the number of children
|
|
||||||
* and the minimum stripe width are sufficient to avoid pessimal
|
|
||||||
* behavior. Unfortunately, this decision created an implicit
|
|
||||||
* on-disk format requirement that we need to support for all
|
|
||||||
* eternity, but only for single-parity RAID-Z.
|
|
||||||
*
|
|
||||||
* If we intend to skip a sector in the zeroth column for
|
|
||||||
* padding we must make sure to note this swap. We will never
|
|
||||||
* intend to skip the first column since at least one data and
|
|
||||||
* one parity column must appear in each row.
|
|
||||||
*/
|
|
||||||
if (rr->rr_firstdatacol == 1 && rr->rr_cols > 1 &&
|
|
||||||
(offset & (1ULL << 20))) {
|
|
||||||
ASSERT(rr->rr_cols >= 2);
|
|
||||||
ASSERT(rr->rr_col[0].rc_size == rr->rr_col[1].rc_size);
|
|
||||||
devidx = rr->rr_col[0].rc_devidx;
|
|
||||||
uint64_t o = rr->rr_col[0].rc_offset;
|
|
||||||
rr->rr_col[0].rc_devidx = rr->rr_col[1].rc_devidx;
|
|
||||||
rr->rr_col[0].rc_offset = rr->rr_col[1].rc_offset;
|
|
||||||
rr->rr_col[1].rc_devidx = devidx;
|
|
||||||
rr->rr_col[1].rc_offset = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
ASSERT3U(asize, ==, tot << ashift);
|
|
||||||
|
|
||||||
/* init RAIDZ parity ops */
|
|
||||||
rm->rm_ops = vdev_raidz_math_get_ops();
|
|
||||||
|
|
||||||
return (rm);
|
|
||||||
}
|
|
||||||
|
|
||||||
static raidz_map_t *
|
static raidz_map_t *
|
||||||
init_raidz_map(raidz_test_opts_t *opts, zio_t **zio, const int parity)
|
init_raidz_map(raidz_test_opts_t *opts, zio_t **zio, const int parity)
|
||||||
{
|
{
|
||||||
@@ -557,15 +330,8 @@ init_raidz_map(raidz_test_opts_t *opts, zio_t **zio, const int parity)
|
|||||||
(*zio)->io_abd = raidz_alloc(alloc_dsize);
|
(*zio)->io_abd = raidz_alloc(alloc_dsize);
|
||||||
init_zio_abd(*zio);
|
init_zio_abd(*zio);
|
||||||
|
|
||||||
if (opts->rto_expand) {
|
rm = vdev_raidz_map_alloc(*zio, opts->rto_ashift,
|
||||||
rm = vdev_raidz_map_alloc_expanded((*zio)->io_abd,
|
total_ncols, parity);
|
||||||
(*zio)->io_size, (*zio)->io_offset,
|
|
||||||
opts->rto_ashift, total_ncols+1, total_ncols,
|
|
||||||
parity, opts->rto_expand_offset);
|
|
||||||
} else {
|
|
||||||
rm = vdev_raidz_map_alloc(*zio, opts->rto_ashift,
|
|
||||||
total_ncols, parity);
|
|
||||||
}
|
|
||||||
VERIFY(rm);
|
VERIFY(rm);
|
||||||
|
|
||||||
/* Make sure code columns are destroyed */
|
/* Make sure code columns are destroyed */
|
||||||
@@ -654,7 +420,7 @@ run_rec_check_impl(raidz_test_opts_t *opts, raidz_map_t *rm, const int fn)
|
|||||||
if (fn < RAIDZ_REC_PQ) {
|
if (fn < RAIDZ_REC_PQ) {
|
||||||
/* can reconstruct 1 failed data disk */
|
/* can reconstruct 1 failed data disk */
|
||||||
for (x0 = 0; x0 < opts->rto_dcols; x0++) {
|
for (x0 = 0; x0 < opts->rto_dcols; x0++) {
|
||||||
if (x0 >= rm->rm_row[0]->rr_cols - raidz_parity(rm))
|
if (x0 >= rm->rm_cols - raidz_parity(rm))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check if should stop */
|
/* Check if should stop */
|
||||||
@@ -679,11 +445,10 @@ run_rec_check_impl(raidz_test_opts_t *opts, raidz_map_t *rm, const int fn)
|
|||||||
} else if (fn < RAIDZ_REC_PQR) {
|
} else if (fn < RAIDZ_REC_PQR) {
|
||||||
/* can reconstruct 2 failed data disk */
|
/* can reconstruct 2 failed data disk */
|
||||||
for (x0 = 0; x0 < opts->rto_dcols; x0++) {
|
for (x0 = 0; x0 < opts->rto_dcols; x0++) {
|
||||||
if (x0 >= rm->rm_row[0]->rr_cols - raidz_parity(rm))
|
if (x0 >= rm->rm_cols - raidz_parity(rm))
|
||||||
continue;
|
continue;
|
||||||
for (x1 = x0 + 1; x1 < opts->rto_dcols; x1++) {
|
for (x1 = x0 + 1; x1 < opts->rto_dcols; x1++) {
|
||||||
if (x1 >= rm->rm_row[0]->rr_cols -
|
if (x1 >= rm->rm_cols - raidz_parity(rm))
|
||||||
raidz_parity(rm))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check if should stop */
|
/* Check if should stop */
|
||||||
@@ -710,15 +475,14 @@ run_rec_check_impl(raidz_test_opts_t *opts, raidz_map_t *rm, const int fn)
|
|||||||
} else {
|
} else {
|
||||||
/* can reconstruct 3 failed data disk */
|
/* can reconstruct 3 failed data disk */
|
||||||
for (x0 = 0; x0 < opts->rto_dcols; x0++) {
|
for (x0 = 0; x0 < opts->rto_dcols; x0++) {
|
||||||
if (x0 >= rm->rm_row[0]->rr_cols - raidz_parity(rm))
|
if (x0 >= rm->rm_cols - raidz_parity(rm))
|
||||||
continue;
|
continue;
|
||||||
for (x1 = x0 + 1; x1 < opts->rto_dcols; x1++) {
|
for (x1 = x0 + 1; x1 < opts->rto_dcols; x1++) {
|
||||||
if (x1 >= rm->rm_row[0]->rr_cols -
|
if (x1 >= rm->rm_cols - raidz_parity(rm))
|
||||||
raidz_parity(rm))
|
|
||||||
continue;
|
continue;
|
||||||
for (x2 = x1 + 1; x2 < opts->rto_dcols; x2++) {
|
for (x2 = x1 + 1; x2 < opts->rto_dcols; x2++) {
|
||||||
if (x2 >= rm->rm_row[0]->rr_cols -
|
if (x2 >=
|
||||||
raidz_parity(rm))
|
rm->rm_cols - raidz_parity(rm))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check if should stop */
|
/* Check if should stop */
|
||||||
@@ -936,8 +700,6 @@ run_sweep(void)
|
|||||||
opts->rto_dcols = dcols_v[d];
|
opts->rto_dcols = dcols_v[d];
|
||||||
opts->rto_offset = (1 << ashift_v[a]) * rand();
|
opts->rto_offset = (1 << ashift_v[a]) * rand();
|
||||||
opts->rto_dsize = size_v[s];
|
opts->rto_dsize = size_v[s];
|
||||||
opts->rto_expand = rto_opts.rto_expand;
|
|
||||||
opts->rto_expand_offset = rto_opts.rto_expand_offset;
|
|
||||||
opts->rto_v = 0; /* be quiet */
|
opts->rto_v = 0; /* be quiet */
|
||||||
|
|
||||||
VERIFY3P(thread_create(NULL, 0, sweep_thread, (void *) opts,
|
VERIFY3P(thread_create(NULL, 0, sweep_thread, (void *) opts,
|
||||||
@@ -970,7 +732,6 @@ exit:
|
|||||||
return (sweep_state == SWEEP_ERROR ? SWEEP_ERROR : 0);
|
return (sweep_state == SWEEP_ERROR ? SWEEP_ERROR : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,15 +44,13 @@ static const char *raidz_impl_names[] = {
|
|||||||
|
|
||||||
typedef struct raidz_test_opts {
|
typedef struct raidz_test_opts {
|
||||||
size_t rto_ashift;
|
size_t rto_ashift;
|
||||||
uint64_t rto_offset;
|
size_t rto_offset;
|
||||||
size_t rto_dcols;
|
size_t rto_dcols;
|
||||||
size_t rto_dsize;
|
size_t rto_dsize;
|
||||||
size_t rto_v;
|
size_t rto_v;
|
||||||
size_t rto_sweep;
|
size_t rto_sweep;
|
||||||
size_t rto_sweep_timeout;
|
size_t rto_sweep_timeout;
|
||||||
size_t rto_benchmark;
|
size_t rto_benchmark;
|
||||||
size_t rto_expand;
|
|
||||||
uint64_t rto_expand_offset;
|
|
||||||
size_t rto_sanity;
|
size_t rto_sanity;
|
||||||
size_t rto_gdb;
|
size_t rto_gdb;
|
||||||
|
|
||||||
@@ -71,8 +69,6 @@ static const raidz_test_opts_t rto_opts_defaults = {
|
|||||||
.rto_v = 0,
|
.rto_v = 0,
|
||||||
.rto_sweep = 0,
|
.rto_sweep = 0,
|
||||||
.rto_benchmark = 0,
|
.rto_benchmark = 0,
|
||||||
.rto_expand = 0,
|
|
||||||
.rto_expand_offset = -1ULL,
|
|
||||||
.rto_sanity = 0,
|
.rto_sanity = 0,
|
||||||
.rto_gdb = 0,
|
.rto_gdb = 0,
|
||||||
.rto_should_stop = B_FALSE
|
.rto_should_stop = B_FALSE
|
||||||
@@ -117,7 +113,4 @@ void init_zio_abd(zio_t *zio);
|
|||||||
|
|
||||||
void run_raidz_benchmark(void);
|
void run_raidz_benchmark(void);
|
||||||
|
|
||||||
struct raidz_map *vdev_raidz_map_alloc_expanded(abd_t *, uint64_t, uint64_t,
|
|
||||||
uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
|
||||||
|
|
||||||
#endif /* RAIDZ_TEST_H */
|
#endif /* RAIDZ_TEST_H */
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
include $(top_srcdir)/config/Shellcheck.am
|
|
||||||
|
|
||||||
dist_udev_SCRIPTS = vdev_id
|
dist_udev_SCRIPTS = vdev_id
|
||||||
|
|||||||
+115
-298
@@ -79,34 +79,6 @@
|
|||||||
# channel 86:00.0 1 A
|
# channel 86:00.0 1 A
|
||||||
# channel 86:00.0 0 B
|
# channel 86:00.0 0 B
|
||||||
|
|
||||||
# #
|
|
||||||
# # Example vdev_id.conf - multipath / multijbod-daisychaining
|
|
||||||
# #
|
|
||||||
#
|
|
||||||
# multipath yes
|
|
||||||
# multijbod yes
|
|
||||||
#
|
|
||||||
# # PCI_ID HBA PORT CHANNEL NAME
|
|
||||||
# channel 85:00.0 1 A
|
|
||||||
# channel 85:00.0 0 B
|
|
||||||
# channel 86:00.0 1 A
|
|
||||||
# channel 86:00.0 0 B
|
|
||||||
|
|
||||||
# #
|
|
||||||
# # Example vdev_id.conf - multipath / mixed
|
|
||||||
# #
|
|
||||||
#
|
|
||||||
# multipath yes
|
|
||||||
# slot mix
|
|
||||||
#
|
|
||||||
# # PCI_ID HBA PORT CHANNEL NAME
|
|
||||||
# channel 85:00.0 3 A
|
|
||||||
# channel 85:00.0 2 B
|
|
||||||
# channel 86:00.0 3 A
|
|
||||||
# channel 86:00.0 2 B
|
|
||||||
# channel af:00.0 0 C
|
|
||||||
# channel af:00.0 1 C
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# # Example vdev_id.conf - alias
|
# # Example vdev_id.conf - alias
|
||||||
# #
|
# #
|
||||||
@@ -120,10 +92,9 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
|||||||
CONFIG=/etc/zfs/vdev_id.conf
|
CONFIG=/etc/zfs/vdev_id.conf
|
||||||
PHYS_PER_PORT=
|
PHYS_PER_PORT=
|
||||||
DEV=
|
DEV=
|
||||||
|
MULTIPATH=
|
||||||
TOPOLOGY=
|
TOPOLOGY=
|
||||||
BAY=
|
BAY=
|
||||||
ENCL_ID=""
|
|
||||||
UNIQ_ENCL_ID=""
|
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
@@ -136,7 +107,6 @@ Usage: vdev_id [-h]
|
|||||||
-e Create enclose device symlinks only (/dev/by-enclosure)
|
-e Create enclose device symlinks only (/dev/by-enclosure)
|
||||||
-g Storage network topology [default="$TOPOLOGY"]
|
-g Storage network topology [default="$TOPOLOGY"]
|
||||||
-m Run in multipath mode
|
-m Run in multipath mode
|
||||||
-j Run in multijbod mode
|
|
||||||
-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
|
||||||
@@ -147,13 +117,12 @@ 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
|
||||||
printf "%d" "${MAPPED_SLOT}"
|
printf "%d" ${MAPPED_SLOT}
|
||||||
}
|
}
|
||||||
|
|
||||||
map_channel() {
|
map_channel() {
|
||||||
@@ -163,120 +132,40 @@ map_channel() {
|
|||||||
|
|
||||||
case $TOPOLOGY in
|
case $TOPOLOGY in
|
||||||
"sas_switch")
|
"sas_switch")
|
||||||
MAPPED_CHAN=$(awk -v port="$PORT" \
|
MAPPED_CHAN=`awk "\\$1 == \"channel\" && \\$2 == ${PORT} \
|
||||||
'$1 == "channel" && $2 == port \
|
{ print \\$3; exit }" $CONFIG`
|
||||||
{ print $3; exit }' $CONFIG)
|
|
||||||
;;
|
;;
|
||||||
"sas_direct"|"scsi")
|
"sas_direct"|"scsi")
|
||||||
MAPPED_CHAN=$(awk -v pciID="$PCI_ID" -v port="$PORT" \
|
MAPPED_CHAN=`awk "\\$1 == \"channel\" && \
|
||||||
'$1 == "channel" && $2 == pciID && $3 == port \
|
\\$2 == \"${PCI_ID}\" && \\$3 == ${PORT} \
|
||||||
{print $4}' $CONFIG)
|
{ print \\$4; exit }" $CONFIG`
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
printf "%s" "${MAPPED_CHAN}"
|
printf "%s" ${MAPPED_CHAN}
|
||||||
}
|
|
||||||
|
|
||||||
get_encl_id() {
|
|
||||||
set -- $(echo $1)
|
|
||||||
count=$#
|
|
||||||
|
|
||||||
i=1
|
|
||||||
while [ $i -le $count ] ; do
|
|
||||||
d=$(eval echo '$'{$i})
|
|
||||||
id=$(cat "/sys/class/enclosure/${d}/id")
|
|
||||||
ENCL_ID="${ENCL_ID} $id"
|
|
||||||
i=$((i + 1))
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
get_uniq_encl_id() {
|
|
||||||
for uuid in ${ENCL_ID}; do
|
|
||||||
found=0
|
|
||||||
|
|
||||||
for count in ${UNIQ_ENCL_ID}; do
|
|
||||||
if [ $count = $uuid ]; then
|
|
||||||
found=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $found -eq 0 ]; then
|
|
||||||
UNIQ_ENCL_ID="${UNIQ_ENCL_ID} $uuid"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# map_jbod explainer: The bsg driver knows the difference between a SAS
|
|
||||||
# expander and fanout expander. Use hostX instance along with top-level
|
|
||||||
# (whole enclosure) expander instances in /sys/class/enclosure and
|
|
||||||
# matching a field in an array of expanders, using the index of the
|
|
||||||
# matched array field as the enclosure instance, thereby making jbod IDs
|
|
||||||
# dynamic. Avoids reliance on high overhead userspace commands like
|
|
||||||
# multipath and lsscsi and instead uses existing sysfs data. $HOSTCHAN
|
|
||||||
# variable derived from devpath gymnastics in sas_handler() function.
|
|
||||||
map_jbod() {
|
|
||||||
DEVEXP=$(ls -l "/sys/block/$DEV/device/" | grep enclos | awk -F/ '{print $(NF-1) }')
|
|
||||||
DEV=$1
|
|
||||||
|
|
||||||
# Use "set --" to create index values (Arrays)
|
|
||||||
set -- $(ls -l /sys/class/enclosure | grep -v "^total" | awk '{print $9}')
|
|
||||||
# Get count of total elements
|
|
||||||
JBOD_COUNT=$#
|
|
||||||
JBOD_ITEM=$*
|
|
||||||
|
|
||||||
# Build JBODs (enclosure) id from sys/class/enclosure/<dev>/id
|
|
||||||
get_encl_id "$JBOD_ITEM"
|
|
||||||
# Different expander instances for each paths.
|
|
||||||
# Filter out and keep only unique id.
|
|
||||||
get_uniq_encl_id
|
|
||||||
|
|
||||||
# Identify final 'mapped jbod'
|
|
||||||
j=0
|
|
||||||
for count in ${UNIQ_ENCL_ID}; do
|
|
||||||
i=1
|
|
||||||
j=$((j + 1))
|
|
||||||
while [ $i -le $JBOD_COUNT ] ; do
|
|
||||||
d=$(eval echo '$'{$i})
|
|
||||||
id=$(cat "/sys/class/enclosure/${d}/id")
|
|
||||||
if [ "$d" = "$DEVEXP" ] && [ $id = $count ] ; then
|
|
||||||
MAPPED_JBOD=$j
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
i=$((i + 1))
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
printf "%d" "${MAPPED_JBOD}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sas_handler() {
|
sas_handler() {
|
||||||
if [ -z "$PHYS_PER_PORT" ] ; then
|
if [ -z "$PHYS_PER_PORT" ] ; then
|
||||||
PHYS_PER_PORT=$(awk '$1 == "phys_per_port" \
|
PHYS_PER_PORT=`awk "\\$1 == \"phys_per_port\" \
|
||||||
{print $2; exit}' $CONFIG)
|
{print \\$2; exit}" $CONFIG`
|
||||||
fi
|
fi
|
||||||
PHYS_PER_PORT=${PHYS_PER_PORT:-4}
|
PHYS_PER_PORT=${PHYS_PER_PORT:-4}
|
||||||
|
if ! echo $PHYS_PER_PORT | grep -q -E '^[0-9]+$' ; then
|
||||||
if ! echo "$PHYS_PER_PORT" | grep -q -E '^[0-9]+$' ; then
|
|
||||||
echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric"
|
echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$MULTIPATH_MODE" ] ; then
|
if [ -z "$MULTIPATH_MODE" ] ; then
|
||||||
MULTIPATH_MODE=$(awk '$1 == "multipath" \
|
MULTIPATH_MODE=`awk "\\$1 == \"multipath\" \
|
||||||
{print $2; exit}' $CONFIG)
|
{print \\$2; exit}" $CONFIG`
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$MULTIJBOD_MODE" ] ; then
|
|
||||||
MULTIJBOD_MODE=$(awk '$1 == "multijbod" \
|
|
||||||
{print $2; exit}' $CONFIG)
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use first running component device if we're handling a dm-mpath device
|
# Use first running component device if we're handling a dm-mpath device
|
||||||
if [ "$MULTIPATH_MODE" = "yes" ] ; then
|
if [ "$MULTIPATH_MODE" = "yes" ] ; then
|
||||||
# If udev didn't tell us the UUID via DM_NAME, check /dev/mapper
|
# If udev didn't tell us the UUID via DM_NAME, check /dev/mapper
|
||||||
if [ -z "$DM_NAME" ] ; then
|
if [ -z "$DM_NAME" ] ; then
|
||||||
DM_NAME=$(ls -l --full-time /dev/mapper |
|
DM_NAME=`ls -l --full-time /dev/mapper |
|
||||||
grep "$DEV"$ | awk '{print $9}')
|
awk "/\/$DEV$/{print \\$9}"`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For raw disks udev exports DEVTYPE=partition when
|
# For raw disks udev exports DEVTYPE=partition when
|
||||||
@@ -286,50 +175,28 @@ sas_handler() {
|
|||||||
# we have to append the -part suffix directly in the
|
# we have to append the -part suffix directly in the
|
||||||
# helper.
|
# helper.
|
||||||
if [ "$DEVTYPE" != "partition" ] ; then
|
if [ "$DEVTYPE" != "partition" ] ; then
|
||||||
# Match p[number], remove the 'p' and prepend "-part"
|
PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'`
|
||||||
PART=$(echo "$DM_NAME" |
|
|
||||||
awk 'match($0,/p[0-9]+$/) {print "-part"substr($0,RSTART+1,RLENGTH-1)}')
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Strip off partition information.
|
# Strip off partition information.
|
||||||
DM_NAME=$(echo "$DM_NAME" | sed 's/p[0-9][0-9]*$//')
|
DM_NAME=`echo $DM_NAME | sed 's/p[0-9][0-9]*$//'`
|
||||||
if [ -z "$DM_NAME" ] ; then
|
if [ -z "$DM_NAME" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Utilize DM device name to gather subordinate block devices
|
# Get the raw scsi device name from multipath -ll. Strip off
|
||||||
# using sysfs to avoid userspace utilities
|
# leading pipe symbols to make field numbering consistent.
|
||||||
|
DEV=`multipath -ll $DM_NAME |
|
||||||
# If our DEVNAME is something like /dev/dm-177, then we may be
|
awk '/running/{gsub("^[|]"," "); print $3 ; exit}'`
|
||||||
# able to get our DMDEV from it.
|
|
||||||
DMDEV=$(echo $DEVNAME | sed 's;/dev/;;g')
|
|
||||||
if [ ! -e /sys/block/$DMDEV/slaves/* ] ; then
|
|
||||||
# It's not there, try looking in /dev/mapper
|
|
||||||
DMDEV=$(ls -l --full-time /dev/mapper | grep $DM_NAME |
|
|
||||||
awk '{gsub("../", " "); print $NF}')
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use sysfs pointers in /sys/block/dm-X/slaves because using
|
|
||||||
# userspace tools creates lots of overhead and should be avoided
|
|
||||||
# whenever possible. Use awk to isolate lowest instance of
|
|
||||||
# sd device member in dm device group regardless of string
|
|
||||||
# length.
|
|
||||||
DEV=$(ls "/sys/block/$DMDEV/slaves" | awk '
|
|
||||||
{ len=sprintf ("%20s",length($0)); gsub(/ /,0,str); a[NR]=len "_" $0; }
|
|
||||||
END {
|
|
||||||
asort(a)
|
|
||||||
print substr(a[1],22)
|
|
||||||
}')
|
|
||||||
|
|
||||||
if [ -z "$DEV" ] ; then
|
if [ -z "$DEV" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if echo "$DEV" | grep -q ^/devices/ ; then
|
if echo $DEV | grep -q ^/devices/ ; then
|
||||||
sys_path=$DEV
|
sys_path=$DEV
|
||||||
else
|
else
|
||||||
sys_path=$(udevadm info -q path -p "/sys/block/$DEV" 2>/dev/null)
|
sys_path=`udevadm info -q path -p /sys/block/$DEV 2>/dev/null`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use positional parameters as an ad-hoc array
|
# Use positional parameters as an ad-hoc array
|
||||||
@@ -339,104 +206,84 @@ sas_handler() {
|
|||||||
|
|
||||||
# Get path up to /sys/.../hostX
|
# Get path up to /sys/.../hostX
|
||||||
i=1
|
i=1
|
||||||
|
while [ $i -le $num_dirs ] ; do
|
||||||
while [ $i -le "$num_dirs" ] ; do
|
d=$(eval echo \${$i})
|
||||||
d=$(eval echo '$'{$i})
|
|
||||||
scsi_host_dir="$scsi_host_dir/$d"
|
scsi_host_dir="$scsi_host_dir/$d"
|
||||||
echo "$d" | grep -q -E '^host[0-9]+$' && break
|
echo $d | grep -q -E '^host[0-9]+$' && break
|
||||||
i=$((i + 1))
|
i=$(($i + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
# Lets grab the SAS host channel number and save it for JBOD sorting later
|
if [ $i = $num_dirs ] ; then
|
||||||
HOSTCHAN=$(echo "$d" | awk -F/ '{ gsub("host","",$NF); print $NF}')
|
|
||||||
|
|
||||||
if [ $i = "$num_dirs" ] ; then
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PCI_ID=$(eval echo '$'{$((i -1))} | awk -F: '{print $2":"$3}')
|
PCI_ID=$(eval echo \${$(($i -1))} | awk -F: '{print $2":"$3}')
|
||||||
|
|
||||||
# In sas_switch mode, the directory four levels beneath
|
# In sas_switch mode, the directory four levels beneath
|
||||||
# /sys/.../hostX contains symlinks to phy devices that reveal
|
# /sys/.../hostX contains symlinks to phy devices that reveal
|
||||||
# the switch port number. In sas_direct mode, the phy links one
|
# the switch port number. In sas_direct mode, the phy links one
|
||||||
# directory down reveal the HBA port.
|
# directory down reveal the HBA port.
|
||||||
port_dir=$scsi_host_dir
|
port_dir=$scsi_host_dir
|
||||||
|
|
||||||
case $TOPOLOGY in
|
case $TOPOLOGY in
|
||||||
"sas_switch") j=$((i + 4)) ;;
|
"sas_switch") j=$(($i + 4)) ;;
|
||||||
"sas_direct") j=$((i + 1)) ;;
|
"sas_direct") j=$(($i + 1)) ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
i=$((i + 1))
|
i=$(($i + 1))
|
||||||
|
|
||||||
while [ $i -le $j ] ; do
|
while [ $i -le $j ] ; do
|
||||||
port_dir="$port_dir/$(eval echo '$'{$i})"
|
port_dir="$port_dir/$(eval echo \${$i})"
|
||||||
i=$((i + 1))
|
i=$(($i + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
PHY=$(ls -d "$port_dir"/phy* 2>/dev/null | head -1 | awk -F: '{print $NF}')
|
PHY=`ls -d $port_dir/phy* 2>/dev/null | head -1 | awk -F: '{print $NF}'`
|
||||||
if [ -z "$PHY" ] ; then
|
if [ -z "$PHY" ] ; then
|
||||||
PHY=0
|
PHY=0
|
||||||
fi
|
fi
|
||||||
PORT=$((PHY / PHYS_PER_PORT))
|
PORT=$(( $PHY / $PHYS_PER_PORT ))
|
||||||
|
|
||||||
# Look in /sys/.../sas_device/end_device-X for the bay_identifier
|
# Look in /sys/.../sas_device/end_device-X for the bay_identifier
|
||||||
# attribute.
|
# attribute.
|
||||||
end_device_dir=$port_dir
|
end_device_dir=$port_dir
|
||||||
|
while [ $i -lt $num_dirs ] ; do
|
||||||
while [ $i -lt "$num_dirs" ] ; do
|
d=$(eval echo \${$i})
|
||||||
d=$(eval echo '$'{$i})
|
|
||||||
end_device_dir="$end_device_dir/$d"
|
end_device_dir="$end_device_dir/$d"
|
||||||
if echo "$d" | grep -q '^end_device' ; then
|
if echo $d | grep -q '^end_device' ; then
|
||||||
end_device_dir="$end_device_dir/sas_device/$d"
|
end_device_dir="$end_device_dir/sas_device/$d"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
i=$((i + 1))
|
i=$(($i + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
# Add 'mix' slot type for environments where dm-multipath devices
|
|
||||||
# include end-devices connected via SAS expanders or direct connection
|
|
||||||
# to SAS HBA. A mixed connectivity environment such as pool devices
|
|
||||||
# contained in a SAS JBOD and spare drives or log devices directly
|
|
||||||
# connected in a server backplane without expanders in the I/O path.
|
|
||||||
SLOT=
|
SLOT=
|
||||||
|
|
||||||
case $BAY in
|
case $BAY in
|
||||||
"bay")
|
"bay")
|
||||||
SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null)
|
SLOT=`cat $end_device_dir/bay_identifier 2>/dev/null`
|
||||||
;;
|
|
||||||
"mix")
|
|
||||||
if [ $(cat "$end_device_dir/bay_identifier" 2>/dev/null) ] ; then
|
|
||||||
SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null)
|
|
||||||
else
|
|
||||||
SLOT=$(cat "$end_device_dir/phy_identifier" 2>/dev/null)
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
"phy")
|
"phy")
|
||||||
SLOT=$(cat "$end_device_dir/phy_identifier" 2>/dev/null)
|
SLOT=`cat $end_device_dir/phy_identifier 2>/dev/null`
|
||||||
;;
|
;;
|
||||||
"port")
|
"port")
|
||||||
d=$(eval echo '$'{$i})
|
d=$(eval echo \${$i})
|
||||||
SLOT=$(echo "$d" | sed -e 's/^.*://')
|
SLOT=`echo $d | sed -e 's/^.*://'`
|
||||||
;;
|
;;
|
||||||
"id")
|
"id")
|
||||||
i=$((i + 1))
|
i=$(($i + 1))
|
||||||
d=$(eval echo '$'{$i})
|
d=$(eval echo \${$i})
|
||||||
SLOT=$(echo "$d" | sed -e 's/^.*://')
|
SLOT=`echo $d | sed -e 's/^.*://'`
|
||||||
;;
|
;;
|
||||||
"lun")
|
"lun")
|
||||||
i=$((i + 2))
|
i=$(($i + 2))
|
||||||
d=$(eval echo '$'{$i})
|
d=$(eval echo \${$i})
|
||||||
SLOT=$(echo "$d" | sed -e 's/^.*://')
|
SLOT=`echo $d | sed -e 's/^.*://'`
|
||||||
;;
|
;;
|
||||||
"ses")
|
"ses")
|
||||||
# look for this SAS path in all SCSI Enclosure Services
|
# look for this SAS path in all SCSI Enclosure Services
|
||||||
# (SES) enclosures
|
# (SES) enclosures
|
||||||
sas_address=$(cat "$end_device_dir/sas_address" 2>/dev/null)
|
sas_address=`cat $end_device_dir/sas_address 2>/dev/null`
|
||||||
enclosures=$(lsscsi -g | \
|
enclosures=`lsscsi -g | \
|
||||||
sed -n -e '/enclosu/s/^.* \([^ ][^ ]*\) *$/\1/p')
|
sed -n -e '/enclosu/s/^.* \([^ ][^ ]*\) *$/\1/p'`
|
||||||
for enclosure in $enclosures; do
|
for enclosure in $enclosures; do
|
||||||
set -- $(sg_ses -p aes "$enclosure" | \
|
set -- $(sg_ses -p aes $enclosure | \
|
||||||
awk "/device slot number:/{slot=\$12} \
|
awk "/device slot number:/{slot=\$12} \
|
||||||
/SAS address: $sas_address/\
|
/SAS address: $sas_address/\
|
||||||
{print slot}")
|
{print slot}")
|
||||||
@@ -451,55 +298,42 @@ sas_handler() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$MULTIJBOD_MODE" = "yes" ] ; then
|
CHAN=`map_channel $PCI_ID $PORT`
|
||||||
CHAN=$(map_channel "$PCI_ID" "$PORT")
|
SLOT=`map_slot $SLOT $CHAN`
|
||||||
SLOT=$(map_slot "$SLOT" "$CHAN")
|
if [ -z "$CHAN" ] ; then
|
||||||
JBOD=$(map_jbod "$DEV")
|
return
|
||||||
|
|
||||||
if [ -z "$CHAN" ] ; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
echo "${CHAN}"-"${JBOD}"-"${SLOT}${PART}"
|
|
||||||
else
|
|
||||||
CHAN=$(map_channel "$PCI_ID" "$PORT")
|
|
||||||
SLOT=$(map_slot "$SLOT" "$CHAN")
|
|
||||||
|
|
||||||
if [ -z "$CHAN" ] ; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
echo "${CHAN}${SLOT}${PART}"
|
|
||||||
fi
|
fi
|
||||||
|
echo ${CHAN}${SLOT}${PART}
|
||||||
}
|
}
|
||||||
|
|
||||||
scsi_handler() {
|
scsi_handler() {
|
||||||
if [ -z "$FIRST_BAY_NUMBER" ] ; then
|
if [ -z "$FIRST_BAY_NUMBER" ] ; then
|
||||||
FIRST_BAY_NUMBER=$(awk '$1 == "first_bay_number" \
|
FIRST_BAY_NUMBER=`awk "\\$1 == \"first_bay_number\" \
|
||||||
{print $2; exit}' $CONFIG)
|
{print \\$2; exit}" $CONFIG`
|
||||||
fi
|
fi
|
||||||
FIRST_BAY_NUMBER=${FIRST_BAY_NUMBER:-0}
|
FIRST_BAY_NUMBER=${FIRST_BAY_NUMBER:-0}
|
||||||
|
|
||||||
if [ -z "$PHYS_PER_PORT" ] ; then
|
if [ -z "$PHYS_PER_PORT" ] ; then
|
||||||
PHYS_PER_PORT=$(awk '$1 == "phys_per_port" \
|
PHYS_PER_PORT=`awk "\\$1 == \"phys_per_port\" \
|
||||||
{print $2; exit}' $CONFIG)
|
{print \\$2; exit}" $CONFIG`
|
||||||
fi
|
fi
|
||||||
PHYS_PER_PORT=${PHYS_PER_PORT:-4}
|
PHYS_PER_PORT=${PHYS_PER_PORT:-4}
|
||||||
|
if ! echo $PHYS_PER_PORT | grep -q -E '^[0-9]+$' ; then
|
||||||
if ! echo "$PHYS_PER_PORT" | grep -q -E '^[0-9]+$' ; then
|
|
||||||
echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric"
|
echo "Error: phys_per_port value $PHYS_PER_PORT is non-numeric"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$MULTIPATH_MODE" ] ; then
|
if [ -z "$MULTIPATH_MODE" ] ; then
|
||||||
MULTIPATH_MODE=$(awk '$1 == "multipath" \
|
MULTIPATH_MODE=`awk "\\$1 == \"multipath\" \
|
||||||
{print $2; exit}' $CONFIG)
|
{print \\$2; exit}" $CONFIG`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use first running component device if we're handling a dm-mpath device
|
# Use first running component device if we're handling a dm-mpath device
|
||||||
if [ "$MULTIPATH_MODE" = "yes" ] ; then
|
if [ "$MULTIPATH_MODE" = "yes" ] ; then
|
||||||
# If udev didn't tell us the UUID via DM_NAME, check /dev/mapper
|
# If udev didn't tell us the UUID via DM_NAME, check /dev/mapper
|
||||||
if [ -z "$DM_NAME" ] ; then
|
if [ -z "$DM_NAME" ] ; then
|
||||||
DM_NAME=$(ls -l --full-time /dev/mapper |
|
DM_NAME=`ls -l --full-time /dev/mapper |
|
||||||
grep "$DEV"$ | awk '{print $9}')
|
awk "/\/$DEV$/{print \\$9}"`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For raw disks udev exports DEVTYPE=partition when
|
# For raw disks udev exports DEVTYPE=partition when
|
||||||
@@ -509,30 +343,28 @@ scsi_handler() {
|
|||||||
# we have to append the -part suffix directly in the
|
# we have to append the -part suffix directly in the
|
||||||
# helper.
|
# helper.
|
||||||
if [ "$DEVTYPE" != "partition" ] ; then
|
if [ "$DEVTYPE" != "partition" ] ; then
|
||||||
# Match p[number], remove the 'p' and prepend "-part"
|
PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'`
|
||||||
PART=$(echo "$DM_NAME" |
|
|
||||||
awk 'match($0,/p[0-9]+$/) {print "-part"substr($0,RSTART+1,RLENGTH-1)}')
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Strip off partition information.
|
# Strip off partition information.
|
||||||
DM_NAME=$(echo "$DM_NAME" | sed 's/p[0-9][0-9]*$//')
|
DM_NAME=`echo $DM_NAME | sed 's/p[0-9][0-9]*$//'`
|
||||||
if [ -z "$DM_NAME" ] ; then
|
if [ -z "$DM_NAME" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the raw scsi device name from multipath -ll. Strip off
|
# Get the raw scsi device name from multipath -ll. Strip off
|
||||||
# leading pipe symbols to make field numbering consistent.
|
# leading pipe symbols to make field numbering consistent.
|
||||||
DEV=$(multipath -ll "$DM_NAME" |
|
DEV=`multipath -ll $DM_NAME |
|
||||||
awk '/running/{gsub("^[|]"," "); print $3 ; exit}')
|
awk '/running/{gsub("^[|]"," "); print $3 ; exit}'`
|
||||||
if [ -z "$DEV" ] ; then
|
if [ -z "$DEV" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if echo "$DEV" | grep -q ^/devices/ ; then
|
if echo $DEV | grep -q ^/devices/ ; then
|
||||||
sys_path=$DEV
|
sys_path=$DEV
|
||||||
else
|
else
|
||||||
sys_path=$(udevadm info -q path -p "/sys/block/$DEV" 2>/dev/null)
|
sys_path=`udevadm info -q path -p /sys/block/$DEV 2>/dev/null`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# expect sys_path like this, for example:
|
# expect sys_path like this, for example:
|
||||||
@@ -545,47 +377,44 @@ scsi_handler() {
|
|||||||
|
|
||||||
# Get path up to /sys/.../hostX
|
# Get path up to /sys/.../hostX
|
||||||
i=1
|
i=1
|
||||||
|
while [ $i -le $num_dirs ] ; do
|
||||||
while [ $i -le "$num_dirs" ] ; do
|
d=$(eval echo \${$i})
|
||||||
d=$(eval echo '$'{$i})
|
|
||||||
scsi_host_dir="$scsi_host_dir/$d"
|
scsi_host_dir="$scsi_host_dir/$d"
|
||||||
|
echo $d | grep -q -E '^host[0-9]+$' && break
|
||||||
echo "$d" | grep -q -E '^host[0-9]+$' && break
|
i=$(($i + 1))
|
||||||
i=$((i + 1))
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ $i = "$num_dirs" ] ; then
|
if [ $i = $num_dirs ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PCI_ID=$(eval echo '$'{$((i -1))} | awk -F: '{print $2":"$3}')
|
PCI_ID=$(eval echo \${$(($i -1))} | awk -F: '{print $2":"$3}')
|
||||||
|
|
||||||
# In scsi mode, the directory two levels beneath
|
# In scsi mode, the directory two levels beneath
|
||||||
# /sys/.../hostX reveals the port and slot.
|
# /sys/.../hostX reveals the port and slot.
|
||||||
port_dir=$scsi_host_dir
|
port_dir=$scsi_host_dir
|
||||||
j=$((i + 2))
|
j=$(($i + 2))
|
||||||
|
|
||||||
i=$((i + 1))
|
i=$(($i + 1))
|
||||||
while [ $i -le $j ] ; do
|
while [ $i -le $j ] ; do
|
||||||
port_dir="$port_dir/$(eval echo '$'{$i})"
|
port_dir="$port_dir/$(eval echo \${$i})"
|
||||||
i=$((i + 1))
|
i=$(($i + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
set -- $(echo "$port_dir" | sed -e 's/^.*:\([^:]*\):\([^:]*\)$/\1 \2/')
|
set -- $(echo $port_dir | sed -e 's/^.*:\([^:]*\):\([^:]*\)$/\1 \2/')
|
||||||
PORT=$1
|
PORT=$1
|
||||||
SLOT=$(($2 + FIRST_BAY_NUMBER))
|
SLOT=$(($2 + $FIRST_BAY_NUMBER))
|
||||||
|
|
||||||
if [ -z "$SLOT" ] ; then
|
if [ -z "$SLOT" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CHAN=$(map_channel "$PCI_ID" "$PORT")
|
CHAN=`map_channel $PCI_ID $PORT`
|
||||||
SLOT=$(map_slot "$SLOT" "$CHAN")
|
SLOT=`map_slot $SLOT $CHAN`
|
||||||
|
|
||||||
if [ -z "$CHAN" ] ; then
|
if [ -z "$CHAN" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo "${CHAN}${SLOT}${PART}"
|
echo ${CHAN}${SLOT}${PART}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Figure out the name for the enclosure symlink
|
# Figure out the name for the enclosure symlink
|
||||||
@@ -596,7 +425,7 @@ enclosure_handler () {
|
|||||||
|
|
||||||
# Get the enclosure ID ("0:0:0:0")
|
# Get the enclosure ID ("0:0:0:0")
|
||||||
ENC=$(basename $(readlink -m "/sys/$DEVPATH/../.."))
|
ENC=$(basename $(readlink -m "/sys/$DEVPATH/../.."))
|
||||||
if [ ! -d "/sys/class/enclosure/$ENC" ] ; then
|
if [ ! -d /sys/class/enclosure/$ENC ] ; then
|
||||||
# Not an enclosure, bail out
|
# Not an enclosure, bail out
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
@@ -604,14 +433,14 @@ enclosure_handler () {
|
|||||||
# Get the long sysfs device path to our enclosure. Looks like:
|
# Get the long sysfs device path to our enclosure. Looks like:
|
||||||
# /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0/ ... /enclosure/0:0:0:0
|
# /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0/ ... /enclosure/0:0:0:0
|
||||||
|
|
||||||
ENC_DEVICE=$(readlink "/sys/class/enclosure/$ENC")
|
ENC_DEVICE=$(readlink /sys/class/enclosure/$ENC)
|
||||||
|
|
||||||
# Grab the full path to the hosts port dir:
|
# Grab the full path to the hosts port dir:
|
||||||
# /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0
|
# /devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/port-0:0
|
||||||
PORT_DIR=$(echo "$ENC_DEVICE" | grep -Eo '.+host[0-9]+/port-[0-9]+:[0-9]+')
|
PORT_DIR=$(echo $ENC_DEVICE | grep -Eo '.+host[0-9]+/port-[0-9]+:[0-9]+')
|
||||||
|
|
||||||
# Get the port number
|
# Get the port number
|
||||||
PORT_ID=$(echo "$PORT_DIR" | grep -Eo "[0-9]+$")
|
PORT_ID=$(echo $PORT_DIR | grep -Eo "[0-9]+$")
|
||||||
|
|
||||||
# The PCI directory is two directories up from the port directory
|
# 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
|
||||||
@@ -621,8 +450,8 @@ enclosure_handler () {
|
|||||||
PCI_ID=$(echo "$PCI_ID_LONG" | sed -r 's/^[0-9]+://g')
|
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}int(count[$4])}; count[$4]++}' $CONFIG)
|
\$3 == \"$PORT_ID\") {print \$4int(count[\$4])}; count[\$4]++}" $CONFIG)
|
||||||
|
|
||||||
echo "${NAME}"
|
echo "${NAME}"
|
||||||
}
|
}
|
||||||
@@ -658,11 +487,9 @@ alias_handler () {
|
|||||||
# ambiguity seems unavoidable, so devices using this facility
|
# ambiguity seems unavoidable, so devices using this facility
|
||||||
# must not use such names.
|
# must not use such names.
|
||||||
DM_PART=
|
DM_PART=
|
||||||
if echo "$DM_NAME" | grep -q -E 'p[0-9][0-9]*$' ; then
|
if echo $DM_NAME | grep -q -E 'p[0-9][0-9]*$' ; then
|
||||||
if [ "$DEVTYPE" != "partition" ] ; then
|
if [ "$DEVTYPE" != "partition" ] ; then
|
||||||
# Match p[number], remove the 'p' and prepend "-part"
|
DM_PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'`
|
||||||
DM_PART=$(echo "$DM_NAME" |
|
|
||||||
awk 'match($0,/p[0-9]+$/) {print "-part"substr($0,RSTART+1,RLENGTH-1)}')
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -670,25 +497,21 @@ alias_handler () {
|
|||||||
for link in $DEVLINKS ; do
|
for link in $DEVLINKS ; do
|
||||||
# Remove partition information to match key of top-level device.
|
# Remove partition information to match key of top-level device.
|
||||||
if [ -n "$DM_PART" ] ; then
|
if [ -n "$DM_PART" ] ; then
|
||||||
link=$(echo "$link" | sed 's/p[0-9][0-9]*$//')
|
link=`echo $link | sed 's/p[0-9][0-9]*$//'`
|
||||||
fi
|
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 $(basename "$link") ; do
|
for l in $link `basename $link` ; do
|
||||||
if [ ! -z "$l" ]; then
|
alias=`awk "\\$1 == \"alias\" && \\$3 == \"${l}\" \
|
||||||
alias=$(awk -v var="$l" '($1 == "alias") && \
|
{ print \\$2; exit }" $CONFIG`
|
||||||
($3 == var) \
|
if [ -n "$alias" ] ; then
|
||||||
{ print $2; exit }' $CONFIG)
|
echo ${alias}${DM_PART}
|
||||||
if [ -n "$alias" ] ; then
|
return
|
||||||
echo "${alias}${DM_PART}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# main
|
while getopts 'c:d:eg:mp:h' OPTION; do
|
||||||
while getopts 'c:d:eg:jmp:h' OPTION; do
|
|
||||||
case ${OPTION} in
|
case ${OPTION} in
|
||||||
c)
|
c)
|
||||||
CONFIG=${OPTARG}
|
CONFIG=${OPTARG}
|
||||||
@@ -701,9 +524,7 @@ while getopts 'c:d:eg:jmp:h' OPTION; do
|
|||||||
# create the enclosure device symlinks only. We also need
|
# create the enclosure device symlinks only. We also need
|
||||||
# "enclosure_symlinks yes" set in vdev_id.config to actually create the
|
# "enclosure_symlinks yes" set in vdev_id.config to actually create the
|
||||||
# symlink.
|
# symlink.
|
||||||
ENCLOSURE_MODE=$(awk '{if ($1 == "enclosure_symlinks") \
|
ENCLOSURE_MODE=$(awk '{if ($1 == "enclosure_symlinks") print $2}' $CONFIG)
|
||||||
print $2}' "$CONFIG")
|
|
||||||
|
|
||||||
if [ "$ENCLOSURE_MODE" != "yes" ] ; then
|
if [ "$ENCLOSURE_MODE" != "yes" ] ; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
@@ -714,9 +535,6 @@ while getopts 'c:d:eg:jmp:h' OPTION; do
|
|||||||
p)
|
p)
|
||||||
PHYS_PER_PORT=${OPTARG}
|
PHYS_PER_PORT=${OPTARG}
|
||||||
;;
|
;;
|
||||||
j)
|
|
||||||
MULTIJBOD_MODE=yes
|
|
||||||
;;
|
|
||||||
m)
|
m)
|
||||||
MULTIPATH_MODE=yes
|
MULTIPATH_MODE=yes
|
||||||
;;
|
;;
|
||||||
@@ -726,8 +544,7 @@ while getopts 'c:d:eg:jmp:h' OPTION; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ! -r "$CONFIG" ] ; then
|
if [ ! -r $CONFIG ] ; then
|
||||||
echo "Error: Config file \"$CONFIG\" not found"
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -737,11 +554,11 @@ if [ -z "$DEV" ] && [ -z "$ENCLOSURE_MODE" ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$TOPOLOGY" ] ; then
|
if [ -z "$TOPOLOGY" ] ; then
|
||||||
TOPOLOGY=$(awk '($1 == "topology") {print $2; exit}' "$CONFIG")
|
TOPOLOGY=`awk "\\$1 == \"topology\" {print \\$2; exit}" $CONFIG`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$BAY" ] ; then
|
if [ -z "$BAY" ] ; then
|
||||||
BAY=$(awk '($1 == "slot") {print $2; exit}' "$CONFIG")
|
BAY=`awk "\\$1 == \"slot\" {print \\$2; exit}" $CONFIG`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TOPOLOGY=${TOPOLOGY:-sas_direct}
|
TOPOLOGY=${TOPOLOGY:-sas_direct}
|
||||||
@@ -754,7 +571,7 @@ if [ "$ENCLOSURE_MODE" = "yes" ] && [ "$TOPOLOGY" = "sas_direct" ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Just create the symlinks to the enclosure devices and then exit.
|
# Just create the symlinks to the enclosure devices and then exit.
|
||||||
ENCLOSURE_PREFIX=$(awk '/enclosure_symlinks_prefix/{print $2}' "$CONFIG")
|
ENCLOSURE_PREFIX=$(awk '/enclosure_symlinks_prefix/{print $2}' $CONFIG)
|
||||||
if [ -z "$ENCLOSURE_PREFIX" ] ; then
|
if [ -z "$ENCLOSURE_PREFIX" ] ; then
|
||||||
ENCLOSURE_PREFIX="enc"
|
ENCLOSURE_PREFIX="enc"
|
||||||
fi
|
fi
|
||||||
@@ -764,16 +581,16 @@ if [ "$ENCLOSURE_MODE" = "yes" ] && [ "$TOPOLOGY" = "sas_direct" ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# First check if an alias was defined for this device.
|
# First check if an alias was defined for this device.
|
||||||
ID_VDEV=$(alias_handler)
|
ID_VDEV=`alias_handler`
|
||||||
|
|
||||||
if [ -z "$ID_VDEV" ] ; then
|
if [ -z "$ID_VDEV" ] ; then
|
||||||
BAY=${BAY:-bay}
|
BAY=${BAY:-bay}
|
||||||
case $TOPOLOGY in
|
case $TOPOLOGY in
|
||||||
sas_direct|sas_switch)
|
sas_direct|sas_switch)
|
||||||
ID_VDEV=$(sas_handler)
|
ID_VDEV=`sas_handler`
|
||||||
;;
|
;;
|
||||||
scsi)
|
scsi)
|
||||||
ID_VDEV=$(scsi_handler)
|
ID_VDEV=`scsi_handler`
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: unknown topology $TOPOLOGY"
|
echo "Error: unknown topology $TOPOLOGY"
|
||||||
|
|||||||
@@ -14,5 +14,3 @@ zdb_LDADD = \
|
|||||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
$(abs_top_builddir)/lib/libzpool/libzpool.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
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
+67
-226
@@ -31,7 +31,6 @@
|
|||||||
*
|
*
|
||||||
* [1] Portions of this software were developed by Allan Jude
|
* [1] Portions of this software were developed by Allan Jude
|
||||||
* under sponsorship from the FreeBSD Foundation.
|
* under sponsorship from the FreeBSD Foundation.
|
||||||
* Copyright (c) 2021 Allan Jude
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -162,6 +161,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;
|
||||||
|
|
||||||
@@ -220,68 +225,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;
|
||||||
@@ -296,16 +262,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,22 +279,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);
|
||||||
|
|
||||||
@@ -637,14 +613,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
|
||||||
@@ -783,14 +755,13 @@ usage(void)
|
|||||||
"\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] "
|
"\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] "
|
||||||
"[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
|
"[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
|
||||||
"\t%s -O <dataset> <path>\n"
|
"\t%s -O <dataset> <path>\n"
|
||||||
"\t%s -r <dataset> <path> <destination>\n"
|
|
||||||
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
|
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
|
||||||
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
|
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
|
||||||
"\t%s -E [-A] word0:word1:...:word15\n"
|
"\t%s -E [-A] word0:word1:...:word15\n"
|
||||||
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
|
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
|
||||||
"<poolname>\n\n",
|
"<poolname>\n\n",
|
||||||
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
|
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
|
||||||
cmdname, cmdname, cmdname, cmdname);
|
cmdname, cmdname, cmdname);
|
||||||
|
|
||||||
(void) fprintf(stderr, " Dataset name must include at least one "
|
(void) fprintf(stderr, " Dataset name must include at least one "
|
||||||
"separator character '/' or '@'\n");
|
"separator character '/' or '@'\n");
|
||||||
@@ -829,7 +800,6 @@ usage(void)
|
|||||||
(void) fprintf(stderr, " -m metaslabs\n");
|
(void) fprintf(stderr, " -m metaslabs\n");
|
||||||
(void) fprintf(stderr, " -M metaslab groups\n");
|
(void) fprintf(stderr, " -M metaslab groups\n");
|
||||||
(void) fprintf(stderr, " -O perform object lookups by path\n");
|
(void) fprintf(stderr, " -O perform object lookups by path\n");
|
||||||
(void) fprintf(stderr, " -r copy an object by path to file\n");
|
|
||||||
(void) fprintf(stderr, " -R read and display block from a "
|
(void) fprintf(stderr, " -R read and display block from a "
|
||||||
"device\n");
|
"device\n");
|
||||||
(void) fprintf(stderr, " -s report stats on zdb's I/O\n");
|
(void) fprintf(stderr, " -s report stats on zdb's I/O\n");
|
||||||
@@ -1672,11 +1642,7 @@ dump_metaslab(metaslab_t *msp)
|
|||||||
SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
|
SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vd->vdev_ops == &vdev_draid_ops)
|
ASSERT(msp->ms_size == (1ULL << vd->vdev_ms_shift));
|
||||||
ASSERT3U(msp->ms_size, <=, 1ULL << vd->vdev_ms_shift);
|
|
||||||
else
|
|
||||||
ASSERT3U(msp->ms_size, ==, 1ULL << vd->vdev_ms_shift);
|
|
||||||
|
|
||||||
dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
|
dump_spacemap(spa->spa_meta_objset, msp->ms_sm);
|
||||||
|
|
||||||
if (spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP)) {
|
if (spa_feature_is_active(spa, SPA_FEATURE_LOG_SPACEMAP)) {
|
||||||
@@ -4236,8 +4202,6 @@ dump_l2arc_log_entries(uint64_t log_entries,
|
|||||||
(u_longlong_t)L2BLK_GET_PREFETCH((&le[j])->le_prop));
|
(u_longlong_t)L2BLK_GET_PREFETCH((&le[j])->le_prop));
|
||||||
(void) printf("|\t\t\t\taddress: %llu\n",
|
(void) printf("|\t\t\t\taddress: %llu\n",
|
||||||
(u_longlong_t)le[j].le_daddr);
|
(u_longlong_t)le[j].le_daddr);
|
||||||
(void) printf("|\t\t\t\tARC state: %llu\n",
|
|
||||||
(u_longlong_t)L2BLK_GET_STATE((&le[j])->le_prop));
|
|
||||||
(void) printf("|\n");
|
(void) printf("|\n");
|
||||||
}
|
}
|
||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
@@ -4520,7 +4484,7 @@ static char curpath[PATH_MAX];
|
|||||||
* for the last one.
|
* for the last one.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
dump_path_impl(objset_t *os, uint64_t obj, char *name, uint64_t *retobj)
|
dump_path_impl(objset_t *os, uint64_t obj, char *name)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
boolean_t header = B_TRUE;
|
boolean_t header = B_TRUE;
|
||||||
@@ -4570,15 +4534,10 @@ dump_path_impl(objset_t *os, uint64_t obj, char *name, uint64_t *retobj)
|
|||||||
switch (doi.doi_type) {
|
switch (doi.doi_type) {
|
||||||
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));
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
case DMU_OT_PLAIN_FILE_CONTENTS:
|
case DMU_OT_PLAIN_FILE_CONTENTS:
|
||||||
if (retobj != NULL) {
|
dump_object(os, child_obj, dump_opt['v'], &header, NULL, 0);
|
||||||
*retobj = child_obj;
|
|
||||||
} else {
|
|
||||||
dump_object(os, child_obj, dump_opt['v'], &header,
|
|
||||||
NULL, 0);
|
|
||||||
}
|
|
||||||
return (0);
|
return (0);
|
||||||
default:
|
default:
|
||||||
(void) fprintf(stderr, "object %llu has non-file/directory "
|
(void) fprintf(stderr, "object %llu has non-file/directory "
|
||||||
@@ -4593,7 +4552,7 @@ dump_path_impl(objset_t *os, uint64_t obj, char *name, uint64_t *retobj)
|
|||||||
* Dump the blocks for the object specified by path inside the dataset.
|
* Dump the blocks for the object specified by path inside the dataset.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
dump_path(char *ds, char *path, uint64_t *retobj)
|
dump_path(char *ds, char *path)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
objset_t *os;
|
objset_t *os;
|
||||||
@@ -4613,89 +4572,12 @@ dump_path(char *ds, char *path, uint64_t *retobj)
|
|||||||
|
|
||||||
(void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds);
|
(void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds);
|
||||||
|
|
||||||
err = dump_path_impl(os, root_obj, path, retobj);
|
err = dump_path_impl(os, root_obj, path);
|
||||||
|
|
||||||
close_objset(os, FTAG);
|
close_objset(os, FTAG);
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
uint64_t size, readsize, oursize, offset;
|
|
||||||
ssize_t writesize;
|
|
||||||
sa_handle_t *hdl;
|
|
||||||
|
|
||||||
(void) printf("Copying object %" PRIu64 " to file %s\n", srcobj,
|
|
||||||
destfile);
|
|
||||||
|
|
||||||
VERIFY3P(os, ==, sa_os);
|
|
||||||
if ((err = sa_handle_get(os, srcobj, NULL, SA_HDL_PRIVATE, &hdl))) {
|
|
||||||
(void) printf("Failed to get handle for SA znode\n");
|
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
if ((err = sa_lookup(hdl, sa_attr_table[ZPL_SIZE], &size, 8))) {
|
|
||||||
(void) sa_handle_destroy(hdl);
|
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
(void) sa_handle_destroy(hdl);
|
|
||||||
|
|
||||||
(void) printf("Object %" PRIu64 " is %" PRIu64 " bytes\n", srcobj,
|
|
||||||
size);
|
|
||||||
if (size == 0) {
|
|
||||||
return (EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
||||||
/*
|
|
||||||
* We cap the size at 1 mebibyte here to prevent
|
|
||||||
* allocation failures and nigh-infinite printing if the
|
|
||||||
* object is extremely large.
|
|
||||||
*/
|
|
||||||
oursize = MIN(size, 1 << 20);
|
|
||||||
offset = 0;
|
|
||||||
char *buf = kmem_alloc(oursize, KM_NOSLEEP);
|
|
||||||
if (buf == NULL) {
|
|
||||||
return (ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (offset < size) {
|
|
||||||
readsize = MIN(size - offset, 1 << 20);
|
|
||||||
err = dmu_read(os, srcobj, offset, readsize, buf, 0);
|
|
||||||
if (err != 0) {
|
|
||||||
(void) printf("got error %u from dmu_read\n", err);
|
|
||||||
kmem_free(buf, oursize);
|
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
if (dump_opt['v'] > 3) {
|
|
||||||
(void) printf("Read offset=%" PRIu64 " size=%" PRIu64
|
|
||||||
" error=%d\n", offset, readsize, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
writesize = write(fd, buf, readsize);
|
|
||||||
if (writesize < 0) {
|
|
||||||
err = errno;
|
|
||||||
break;
|
|
||||||
} else if (writesize != readsize) {
|
|
||||||
/* Incomplete write */
|
|
||||||
(void) fprintf(stderr, "Short write, only wrote %llu of"
|
|
||||||
" %" PRIu64 " bytes, exiting...\n",
|
|
||||||
(u_longlong_t)writesize, readsize);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += readsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) close(fd);
|
|
||||||
|
|
||||||
if (buf != NULL)
|
|
||||||
kmem_free(buf, oursize);
|
|
||||||
|
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dump_label(const char *dev)
|
dump_label(const char *dev)
|
||||||
{
|
{
|
||||||
@@ -5319,6 +5201,8 @@ zdb_blkptr_done(zio_t *zio)
|
|||||||
zdb_cb_t *zcb = zio->io_private;
|
zdb_cb_t *zcb = zio->io_private;
|
||||||
zbookmark_phys_t *zb = &zio->io_bookmark;
|
zbookmark_phys_t *zb = &zio->io_bookmark;
|
||||||
|
|
||||||
|
abd_free(zio->io_abd);
|
||||||
|
|
||||||
mutex_enter(&spa->spa_scrub_lock);
|
mutex_enter(&spa->spa_scrub_lock);
|
||||||
spa->spa_load_verify_bytes -= BP_GET_PSIZE(bp);
|
spa->spa_load_verify_bytes -= BP_GET_PSIZE(bp);
|
||||||
cv_broadcast(&spa->spa_scrub_io_cv);
|
cv_broadcast(&spa->spa_scrub_io_cv);
|
||||||
@@ -5345,8 +5229,6 @@ zdb_blkptr_done(zio_t *zio)
|
|||||||
blkbuf);
|
blkbuf);
|
||||||
}
|
}
|
||||||
mutex_exit(&spa->spa_scrub_lock);
|
mutex_exit(&spa->spa_scrub_lock);
|
||||||
|
|
||||||
abd_free(zio->io_abd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -5956,11 +5838,9 @@ zdb_leak_init_prepare_indirect_vdevs(spa_t *spa, zdb_cb_t *zcb)
|
|||||||
* metaslabs. We want to set them up for
|
* metaslabs. We want to set them up for
|
||||||
* zio_claim().
|
* zio_claim().
|
||||||
*/
|
*/
|
||||||
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++) {
|
||||||
|
|
||||||
@@ -5996,7 +5876,6 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
|
|||||||
*/
|
*/
|
||||||
spa->spa_normal_class->mc_ops = &zdb_metaslab_ops;
|
spa->spa_normal_class->mc_ops = &zdb_metaslab_ops;
|
||||||
spa->spa_log_class->mc_ops = &zdb_metaslab_ops;
|
spa->spa_log_class->mc_ops = &zdb_metaslab_ops;
|
||||||
spa->spa_embedded_log_class->mc_ops = &zdb_metaslab_ops;
|
|
||||||
|
|
||||||
zcb->zcb_vd_obsolete_counts =
|
zcb->zcb_vd_obsolete_counts =
|
||||||
umem_zalloc(rvd->vdev_children * sizeof (uint32_t *),
|
umem_zalloc(rvd->vdev_children * sizeof (uint32_t *),
|
||||||
@@ -6130,6 +6009,7 @@ zdb_leak_fini(spa_t *spa, zdb_cb_t *zcb)
|
|||||||
vdev_t *rvd = spa->spa_root_vdev;
|
vdev_t *rvd = spa->spa_root_vdev;
|
||||||
for (unsigned c = 0; c < rvd->vdev_children; c++) {
|
for (unsigned c = 0; c < rvd->vdev_children; c++) {
|
||||||
vdev_t *vd = rvd->vdev_child[c];
|
vdev_t *vd = rvd->vdev_child[c];
|
||||||
|
metaslab_group_t *mg __maybe_unused = vd->vdev_mg;
|
||||||
|
|
||||||
if (zcb->zcb_vd_obsolete_counts[c] != NULL) {
|
if (zcb->zcb_vd_obsolete_counts[c] != NULL) {
|
||||||
leaks |= zdb_check_for_obsolete_leaks(vd, zcb);
|
leaks |= zdb_check_for_obsolete_leaks(vd, zcb);
|
||||||
@@ -6137,9 +6017,7 @@ zdb_leak_fini(spa_t *spa, zdb_cb_t *zcb)
|
|||||||
|
|
||||||
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
|
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
|
||||||
metaslab_t *msp = vd->vdev_ms[m];
|
metaslab_t *msp = vd->vdev_ms[m];
|
||||||
ASSERT3P(msp->ms_group, ==, (msp->ms_group->mg_class ==
|
ASSERT3P(mg, ==, msp->ms_group);
|
||||||
spa_embedded_log_class(spa)) ?
|
|
||||||
vd->vdev_log_mg : vd->vdev_mg);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ms_allocatable has been overloaded
|
* ms_allocatable has been overloaded
|
||||||
@@ -6346,8 +6224,6 @@ dump_block_stats(spa_t *spa)
|
|||||||
zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
|
zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa));
|
||||||
zcb.zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa));
|
zcb.zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa));
|
||||||
zcb.zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
|
zcb.zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa));
|
||||||
zcb.zcb_totalasize +=
|
|
||||||
metaslab_class_get_alloc(spa_embedded_log_class(spa));
|
|
||||||
zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
|
zcb.zcb_start = zcb.zcb_lastprint = gethrtime();
|
||||||
err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
|
err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);
|
||||||
|
|
||||||
@@ -6395,7 +6271,6 @@ dump_block_stats(spa_t *spa)
|
|||||||
|
|
||||||
total_alloc = norm_alloc +
|
total_alloc = norm_alloc +
|
||||||
metaslab_class_get_alloc(spa_log_class(spa)) +
|
metaslab_class_get_alloc(spa_log_class(spa)) +
|
||||||
metaslab_class_get_alloc(spa_embedded_log_class(spa)) +
|
|
||||||
metaslab_class_get_alloc(spa_special_class(spa)) +
|
metaslab_class_get_alloc(spa_special_class(spa)) +
|
||||||
metaslab_class_get_alloc(spa_dedup_class(spa)) +
|
metaslab_class_get_alloc(spa_dedup_class(spa)) +
|
||||||
get_unflushed_alloc_space(spa);
|
get_unflushed_alloc_space(spa);
|
||||||
@@ -6441,7 +6316,7 @@ dump_block_stats(spa_t *spa)
|
|||||||
(void) printf("\t%-16s %14llu used: %5.2f%%\n", "Normal class:",
|
(void) printf("\t%-16s %14llu used: %5.2f%%\n", "Normal class:",
|
||||||
(u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space);
|
(u_longlong_t)norm_alloc, 100.0 * norm_alloc / norm_space);
|
||||||
|
|
||||||
if (spa_special_class(spa)->mc_allocator[0].mca_rotor != NULL) {
|
if (spa_special_class(spa)->mc_rotor != NULL) {
|
||||||
uint64_t alloc = metaslab_class_get_alloc(
|
uint64_t alloc = metaslab_class_get_alloc(
|
||||||
spa_special_class(spa));
|
spa_special_class(spa));
|
||||||
uint64_t space = metaslab_class_get_space(
|
uint64_t space = metaslab_class_get_space(
|
||||||
@@ -6452,7 +6327,7 @@ dump_block_stats(spa_t *spa)
|
|||||||
100.0 * alloc / space);
|
100.0 * alloc / space);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spa_dedup_class(spa)->mc_allocator[0].mca_rotor != NULL) {
|
if (spa_dedup_class(spa)->mc_rotor != NULL) {
|
||||||
uint64_t alloc = metaslab_class_get_alloc(
|
uint64_t alloc = metaslab_class_get_alloc(
|
||||||
spa_dedup_class(spa));
|
spa_dedup_class(spa));
|
||||||
uint64_t space = metaslab_class_get_space(
|
uint64_t space = metaslab_class_get_space(
|
||||||
@@ -6463,17 +6338,6 @@ dump_block_stats(spa_t *spa)
|
|||||||
100.0 * alloc / space);
|
100.0 * alloc / space);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spa_embedded_log_class(spa)->mc_allocator[0].mca_rotor != NULL) {
|
|
||||||
uint64_t alloc = metaslab_class_get_alloc(
|
|
||||||
spa_embedded_log_class(spa));
|
|
||||||
uint64_t space = metaslab_class_get_space(
|
|
||||||
spa_embedded_log_class(spa));
|
|
||||||
|
|
||||||
(void) printf("\t%-16s %14llu used: %5.2f%%\n",
|
|
||||||
"Embedded log class", (u_longlong_t)alloc,
|
|
||||||
100.0 * alloc / space);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
|
for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) {
|
||||||
if (zcb.zcb_embedded_blocks[i] == 0)
|
if (zcb.zcb_embedded_blocks[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -6892,7 +6756,6 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
|
|||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
char *poolname, *bogus_name = NULL;
|
char *poolname, *bogus_name = NULL;
|
||||||
boolean_t freecfg = B_FALSE;
|
|
||||||
|
|
||||||
/* If the target is not a pool, the extract the pool name */
|
/* If the target is not a pool, the extract the pool name */
|
||||||
char *path_start = strchr(target, '/');
|
char *path_start = strchr(target, '/');
|
||||||
@@ -6911,7 +6774,6 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
|
|||||||
"spa_get_stats() failed with error %d\n",
|
"spa_get_stats() failed with error %d\n",
|
||||||
poolname, error);
|
poolname, error);
|
||||||
}
|
}
|
||||||
freecfg = B_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asprintf(&bogus_name, "%s%s", poolname, BOGUS_SUFFIX) == -1)
|
if (asprintf(&bogus_name, "%s%s", poolname, BOGUS_SUFFIX) == -1)
|
||||||
@@ -6921,8 +6783,6 @@ import_checkpointed_state(char *target, nvlist_t *cfg, char **new_path)
|
|||||||
error = spa_import(bogus_name, cfg, NULL,
|
error = spa_import(bogus_name, cfg, NULL,
|
||||||
ZFS_IMPORT_MISSING_LOG | ZFS_IMPORT_CHECKPOINT |
|
ZFS_IMPORT_MISSING_LOG | ZFS_IMPORT_CHECKPOINT |
|
||||||
ZFS_IMPORT_SKIP_MMP);
|
ZFS_IMPORT_SKIP_MMP);
|
||||||
if (freecfg)
|
|
||||||
nvlist_free(cfg);
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
fatal("Tried to import pool \"%s\" but spa_import() failed "
|
fatal("Tried to import pool \"%s\" but spa_import() failed "
|
||||||
"with error %d\n", bogus_name, error);
|
"with error %d\n", bogus_name, error);
|
||||||
@@ -7069,7 +6929,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7151,6 +7011,7 @@ verify_checkpoint_blocks(spa_t *spa)
|
|||||||
|
|
||||||
spa_t *checkpoint_spa;
|
spa_t *checkpoint_spa;
|
||||||
char *checkpoint_pool;
|
char *checkpoint_pool;
|
||||||
|
nvlist_t *config = NULL;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -7158,7 +7019,7 @@ verify_checkpoint_blocks(spa_t *spa)
|
|||||||
* name) so we can do verification on it against the current state
|
* name) so we can do verification on it against the current state
|
||||||
* of the pool.
|
* of the pool.
|
||||||
*/
|
*/
|
||||||
checkpoint_pool = import_checkpointed_state(spa->spa_name, NULL,
|
checkpoint_pool = import_checkpointed_state(spa->spa_name, config,
|
||||||
NULL);
|
NULL);
|
||||||
ASSERT(strcmp(spa->spa_name, checkpoint_pool) != 0);
|
ASSERT(strcmp(spa->spa_name, checkpoint_pool) != 0);
|
||||||
|
|
||||||
@@ -8280,7 +8141,6 @@ main(int argc, char **argv)
|
|||||||
nvlist_t *policy = NULL;
|
nvlist_t *policy = NULL;
|
||||||
uint64_t max_txg = UINT64_MAX;
|
uint64_t max_txg = UINT64_MAX;
|
||||||
int64_t objset_id = -1;
|
int64_t objset_id = -1;
|
||||||
uint64_t object;
|
|
||||||
int flags = ZFS_IMPORT_MISSING_LOG;
|
int flags = ZFS_IMPORT_MISSING_LOG;
|
||||||
int rewind = ZPOOL_NEVER_REWIND;
|
int rewind = ZPOOL_NEVER_REWIND;
|
||||||
char *spa_config_path_env, *objset_str;
|
char *spa_config_path_env, *objset_str;
|
||||||
@@ -8309,7 +8169,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:klLmMo:Op:PqrRsSt:uU:vVx:XYyZ")) != -1) {
|
"AbcCdDeEFGhiI:klLmMo:Op:PqRsSt:uU:vVx:XYyZ")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'c':
|
case 'c':
|
||||||
@@ -8324,7 +8184,6 @@ main(int argc, char **argv)
|
|||||||
case 'm':
|
case 'm':
|
||||||
case 'M':
|
case 'M':
|
||||||
case 'O':
|
case 'O':
|
||||||
case 'r':
|
|
||||||
case 'R':
|
case 'R':
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
@@ -8414,7 +8273,7 @@ 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']) {
|
if (dump_opt['d']) {
|
||||||
/* <pool>[/<dataset | objset id> is accepted */
|
/* <pool>[/<dataset | objset id> is accepted */
|
||||||
if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL &&
|
if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL &&
|
||||||
objset_str++ != NULL) {
|
objset_str++ != NULL) {
|
||||||
@@ -8473,7 +8332,7 @@ main(int argc, char **argv)
|
|||||||
verbose = MAX(verbose, 1);
|
verbose = MAX(verbose, 1);
|
||||||
|
|
||||||
for (c = 0; c < 256; c++) {
|
for (c = 0; c < 256; c++) {
|
||||||
if (dump_all && strchr("AeEFklLOPrRSXy", c) == NULL)
|
if (dump_all && strchr("AeEFklLOPRSXy", 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;
|
||||||
@@ -8509,13 +8368,7 @@ main(int argc, char **argv)
|
|||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
usage();
|
usage();
|
||||||
dump_opt['v'] = verbose + 3;
|
dump_opt['v'] = verbose + 3;
|
||||||
return (dump_path(argv[0], argv[1], NULL));
|
return (dump_path(argv[0], argv[1]));
|
||||||
}
|
|
||||||
if (dump_opt['r']) {
|
|
||||||
if (argc != 3)
|
|
||||||
usage();
|
|
||||||
dump_opt['v'] = verbose;
|
|
||||||
error = dump_path(argv[0], argv[1], &object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump_opt['X'] || dump_opt['F'])
|
if (dump_opt['X'] || dump_opt['F'])
|
||||||
@@ -8576,11 +8429,6 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchdirs != NULL) {
|
|
||||||
umem_free(searchdirs, nsearch * sizeof (char *));
|
|
||||||
searchdirs = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* import_checkpointed_state makes the assumption that the
|
* import_checkpointed_state makes the assumption that the
|
||||||
* target pool that we pass it is already part of the spa
|
* target pool that we pass it is already part of the spa
|
||||||
@@ -8599,11 +8447,6 @@ main(int argc, char **argv)
|
|||||||
target = checkpoint_target;
|
target = checkpoint_target;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg != NULL) {
|
|
||||||
nvlist_free(cfg);
|
|
||||||
cfg = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target_pool != target)
|
if (target_pool != target)
|
||||||
free(target_pool);
|
free(target_pool);
|
||||||
|
|
||||||
@@ -8693,9 +8536,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
argv++;
|
argv++;
|
||||||
argc--;
|
argc--;
|
||||||
if (dump_opt['r']) {
|
if (!dump_opt['R']) {
|
||||||
error = zdb_copy_object(os, object, argv[1]);
|
|
||||||
} else if (!dump_opt['R']) {
|
|
||||||
flagbits['d'] = ZOR_FLAG_DIRECTORY;
|
flagbits['d'] = ZOR_FLAG_DIRECTORY;
|
||||||
flagbits['f'] = ZOR_FLAG_PLAIN_FILE;
|
flagbits['f'] = ZOR_FLAG_PLAIN_FILE;
|
||||||
flagbits['m'] = ZOR_FLAG_SPACE_MAP;
|
flagbits['m'] = ZOR_FLAG_SPACE_MAP;
|
||||||
|
|||||||
+1
-5
@@ -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,9 +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
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Intel Corporation.
|
* Copyright (c) 2016, Intel Corporation.
|
||||||
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
|
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
|
||||||
* Copyright (c) 2021 Hewlett Packard Enterprise Development LP
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libnvpair.h>
|
#include <libnvpair.h>
|
||||||
@@ -182,8 +181,6 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
* from the vdev_disk layer after a hot unplug. Fortunately we do
|
* from the vdev_disk layer after a hot unplug. Fortunately we do
|
||||||
* get an EC_DEV_REMOVE from our disk monitor and it is a suitable
|
* get an EC_DEV_REMOVE from our disk monitor and it is a suitable
|
||||||
* proxy so we remap it here for the benefit of the diagnosis engine.
|
* proxy so we remap it here for the benefit of the diagnosis engine.
|
||||||
* Starting in OpenZFS 2.0, we do get FM_RESOURCE_REMOVED from the spa
|
|
||||||
* layer. Processing multiple FM_RESOURCE_REMOVED events is not harmful.
|
|
||||||
*/
|
*/
|
||||||
if ((strcmp(class, EC_DEV_REMOVE) == 0) &&
|
if ((strcmp(class, EC_DEV_REMOVE) == 0) &&
|
||||||
(strcmp(subclass, ESC_DISK) == 0) &&
|
(strcmp(subclass, ESC_DISK) == 0) &&
|
||||||
@@ -212,18 +209,12 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
* 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 (pool_guid == 0 || vdev_guid == 0) {
|
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
||||||
if ((nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
&search.gs_devid);
|
||||||
&search.gs_devid) == 0) &&
|
(void) zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
|
||||||
(zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search)
|
pool_guid = search.gs_pool_guid;
|
||||||
== 1)) {
|
vdev_guid = search.gs_vdev_guid;
|
||||||
if (pool_guid == 0)
|
devtype = search.gs_vdev_type;
|
||||||
pool_guid = search.gs_pool_guid;
|
|
||||||
if (vdev_guid == 0)
|
|
||||||
vdev_guid = search.gs_vdev_guid;
|
|
||||||
devtype = search.gs_vdev_type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to avoid reporting "remove" events coming from
|
* We want to avoid reporting "remove" events coming from
|
||||||
@@ -392,7 +383,6 @@ zfs_agent_init(libzfs_handle_t *zfs_hdl)
|
|||||||
list_destroy(&agent_events);
|
list_destroy(&agent_events);
|
||||||
zed_log_die("Failed to initialize agents");
|
zed_log_die("Failed to initialize agents");
|
||||||
}
|
}
|
||||||
pthread_setname_np(g_agents_tid, "agents");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -435,15 +435,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE, B_FALSE);
|
||||||
* Prefer sequential resilvering when supported (mirrors and dRAID),
|
|
||||||
* otherwise fallback to a traditional healing resilver.
|
|
||||||
*/
|
|
||||||
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE, B_TRUE);
|
|
||||||
if (ret != 0) {
|
|
||||||
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot,
|
|
||||||
B_TRUE, B_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO, " zpool_vdev_replace: %s with %s (%s)",
|
zed_log_msg(LOG_INFO, " zpool_vdev_replace: %s with %s (%s)",
|
||||||
fullpath, path, (ret == 0) ? "no errors" :
|
fullpath, path, (ret == 0) ? "no errors" :
|
||||||
@@ -918,7 +910,6 @@ zfs_slm_init()
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_setname_np(g_zfs_tid, "enum-pools");
|
|
||||||
list_create(&g_device_list, sizeof (struct pendingdev),
|
list_create(&g_device_list, sizeof (struct pendingdev),
|
||||||
offsetof(struct pendingdev, pd_node));
|
offsetof(struct pendingdev, pd_node));
|
||||||
|
|
||||||
|
|||||||
@@ -219,18 +219,12 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
|||||||
* replace it.
|
* replace it.
|
||||||
*/
|
*/
|
||||||
for (s = 0; s < nspares; s++) {
|
for (s = 0; s < nspares; s++) {
|
||||||
boolean_t rebuild = B_FALSE;
|
char *spare_name;
|
||||||
char *spare_name, *type;
|
|
||||||
|
|
||||||
if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
|
if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
|
||||||
&spare_name) != 0)
|
&spare_name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* prefer sequential resilvering for distributed spares */
|
|
||||||
if ((nvlist_lookup_string(spares[s], ZPOOL_CONFIG_TYPE,
|
|
||||||
&type) == 0) && strcmp(type, VDEV_TYPE_DRAID_SPARE) == 0)
|
|
||||||
rebuild = B_TRUE;
|
|
||||||
|
|
||||||
/* if set, add the "ashift" pool property to the spare nvlist */
|
/* if set, add the "ashift" pool property to the spare nvlist */
|
||||||
if (source != ZPROP_SRC_DEFAULT)
|
if (source != ZPROP_SRC_DEFAULT)
|
||||||
(void) nvlist_add_uint64(spares[s],
|
(void) nvlist_add_uint64(spares[s],
|
||||||
@@ -243,7 +237,7 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
|||||||
dev_name, basename(spare_name));
|
dev_name, basename(spare_name));
|
||||||
|
|
||||||
if (zpool_vdev_attach(zhp, dev_name, spare_name,
|
if (zpool_vdev_attach(zhp, dev_name, spare_name,
|
||||||
replacement, B_TRUE, rebuild) == 0) {
|
replacement, B_TRUE, B_FALSE) == 0) {
|
||||||
free(dev_name);
|
free(dev_name);
|
||||||
nvlist_free(replacement);
|
nvlist_free(replacement);
|
||||||
return (B_TRUE);
|
return (B_TRUE);
|
||||||
@@ -334,7 +328,7 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
*/
|
*/
|
||||||
if (strcmp(class, "resource.fs.zfs.removed") == 0 ||
|
if (strcmp(class, "resource.fs.zfs.removed") == 0 ||
|
||||||
(strcmp(class, "resource.fs.zfs.statechange") == 0 &&
|
(strcmp(class, "resource.fs.zfs.statechange") == 0 &&
|
||||||
(state == VDEV_STATE_REMOVED || state == VDEV_STATE_FAULTED))) {
|
state == VDEV_STATE_REMOVED)) {
|
||||||
char *devtype;
|
char *devtype;
|
||||||
char *devname;
|
char *devname;
|
||||||
|
|
||||||
@@ -505,7 +499,6 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
* Attempt to substitute a hot spare.
|
* Attempt to substitute a hot spare.
|
||||||
*/
|
*/
|
||||||
(void) replace_with_spare(hdl, zhp, vdev);
|
(void) replace_with_spare(hdl, zhp, vdev);
|
||||||
|
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-25
@@ -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).
|
||||||
@@ -60,8 +60,8 @@ _setup_sig_handlers(void)
|
|||||||
zed_log_die("Failed to initialize sigset");
|
zed_log_die("Failed to initialize sigset");
|
||||||
|
|
||||||
sa.sa_flags = SA_RESTART;
|
sa.sa_flags = SA_RESTART;
|
||||||
|
|
||||||
sa.sa_handler = SIG_IGN;
|
sa.sa_handler = SIG_IGN;
|
||||||
|
|
||||||
if (sigaction(SIGPIPE, &sa, NULL) < 0)
|
if (sigaction(SIGPIPE, &sa, NULL) < 0)
|
||||||
zed_log_die("Failed to ignore SIGPIPE");
|
zed_log_die("Failed to ignore SIGPIPE");
|
||||||
|
|
||||||
@@ -75,10 +75,6 @@ _setup_sig_handlers(void)
|
|||||||
sa.sa_handler = _hup_handler;
|
sa.sa_handler = _hup_handler;
|
||||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||||
zed_log_die("Failed to register SIGHUP handler");
|
zed_log_die("Failed to register SIGHUP handler");
|
||||||
|
|
||||||
(void) sigaddset(&sa.sa_mask, SIGCHLD);
|
|
||||||
if (pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL) < 0)
|
|
||||||
zed_log_die("Failed to block SIGCHLD");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -216,20 +212,22 @@ _finish_daemonize(void)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct zed_conf zcp;
|
struct zed_conf *zcp;
|
||||||
uint64_t saved_eid;
|
uint64_t saved_eid;
|
||||||
int64_t saved_etime[2];
|
int64_t saved_etime[2];
|
||||||
|
|
||||||
zed_log_init(argv[0]);
|
zed_log_init(argv[0]);
|
||||||
zed_log_stderr_open(LOG_NOTICE);
|
zed_log_stderr_open(LOG_NOTICE);
|
||||||
zed_conf_init(&zcp);
|
zcp = zed_conf_create();
|
||||||
zed_conf_parse_opts(&zcp, argc, argv);
|
zed_conf_parse_opts(zcp, argc, argv);
|
||||||
if (zcp.do_verbose)
|
if (zcp->do_verbose)
|
||||||
zed_log_stderr_open(LOG_INFO);
|
zed_log_stderr_open(LOG_INFO);
|
||||||
|
|
||||||
if (geteuid() != 0)
|
if (geteuid() != 0)
|
||||||
zed_log_die("Must be run as root");
|
zed_log_die("Must be run as root");
|
||||||
|
|
||||||
|
zed_conf_parse_file(zcp);
|
||||||
|
|
||||||
zed_file_close_from(STDERR_FILENO + 1);
|
zed_file_close_from(STDERR_FILENO + 1);
|
||||||
|
|
||||||
(void) umask(0);
|
(void) umask(0);
|
||||||
@@ -237,32 +235,32 @@ main(int argc, char *argv[])
|
|||||||
if (chdir("/") < 0)
|
if (chdir("/") < 0)
|
||||||
zed_log_die("Failed to change to root directory");
|
zed_log_die("Failed to change to root directory");
|
||||||
|
|
||||||
if (zed_conf_scan_dir(&zcp) < 0)
|
if (zed_conf_scan_dir(zcp) < 0)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (!zcp.do_foreground) {
|
if (!zcp->do_foreground) {
|
||||||
_start_daemonize();
|
_start_daemonize();
|
||||||
zed_log_syslog_open(LOG_DAEMON);
|
zed_log_syslog_open(LOG_DAEMON);
|
||||||
}
|
}
|
||||||
_setup_sig_handlers();
|
_setup_sig_handlers();
|
||||||
|
|
||||||
if (zcp.do_memlock)
|
if (zcp->do_memlock)
|
||||||
_lock_memory();
|
_lock_memory();
|
||||||
|
|
||||||
if ((zed_conf_write_pid(&zcp) < 0) && (!zcp.do_force))
|
if ((zed_conf_write_pid(zcp) < 0) && (!zcp->do_force))
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (!zcp.do_foreground)
|
if (!zcp->do_foreground)
|
||||||
_finish_daemonize();
|
_finish_daemonize();
|
||||||
|
|
||||||
zed_log_msg(LOG_NOTICE,
|
zed_log_msg(LOG_NOTICE,
|
||||||
"ZFS Event Daemon %s-%s (PID %d)",
|
"ZFS Event Daemon %s-%s (PID %d)",
|
||||||
ZFS_META_VERSION, ZFS_META_RELEASE, (int)getpid());
|
ZFS_META_VERSION, ZFS_META_RELEASE, (int)getpid());
|
||||||
|
|
||||||
if (zed_conf_open_state(&zcp) < 0)
|
if (zed_conf_open_state(zcp) < 0)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (zed_conf_read_state(&zcp, &saved_eid, saved_etime) < 0)
|
if (zed_conf_read_state(zcp, &saved_eid, saved_etime) < 0)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
idle:
|
idle:
|
||||||
@@ -271,24 +269,24 @@ idle:
|
|||||||
* successful.
|
* successful.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
if (!zed_event_init(&zcp))
|
if (!zed_event_init(zcp))
|
||||||
break;
|
break;
|
||||||
/* Wait for some time and try again. tunable? */
|
/* Wait for some time and try again. tunable? */
|
||||||
sleep(30);
|
sleep(30);
|
||||||
} while (!_got_exit && zcp.do_idle);
|
} while (!_got_exit && zcp->do_idle);
|
||||||
|
|
||||||
if (_got_exit)
|
if (_got_exit)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
zed_event_seek(&zcp, saved_eid, saved_etime);
|
zed_event_seek(zcp, saved_eid, saved_etime);
|
||||||
|
|
||||||
while (!_got_exit) {
|
while (!_got_exit) {
|
||||||
int rv;
|
int rv;
|
||||||
if (_got_hup) {
|
if (_got_hup) {
|
||||||
_got_hup = 0;
|
_got_hup = 0;
|
||||||
(void) zed_conf_scan_dir(&zcp);
|
(void) zed_conf_scan_dir(zcp);
|
||||||
}
|
}
|
||||||
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 == ENODEV)
|
if (rv == ENODEV)
|
||||||
@@ -296,13 +294,13 @@ idle:
|
|||||||
}
|
}
|
||||||
|
|
||||||
zed_log_msg(LOG_NOTICE, "Exiting");
|
zed_log_msg(LOG_NOTICE, "Exiting");
|
||||||
zed_event_fini(&zcp);
|
zed_event_fini(zcp);
|
||||||
|
|
||||||
if (zcp.do_idle && !_got_exit)
|
if (zcp->do_idle && !_got_exit)
|
||||||
goto idle;
|
goto idle;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
zed_conf_destroy(&zcp);
|
zed_conf_destroy(zcp);
|
||||||
zed_log_fini();
|
zed_log_fini();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -52,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -12,21 +13,21 @@ FSLIST_TMP="@runstatedir@/zfs-list.cache@${ZEVENT_POOL}"
|
|||||||
[ -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"
|
||||||
|
|
||||||
[ "$ZEVENT_SUBCLASS" != "history_event" ] && exit 0
|
zed_exit_if_ignoring_this_event
|
||||||
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:
|
||||||
@@ -59,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
|
||||||
@@ -70,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
|
||||||
@@ -89,29 +85,27 @@ check_and_set_led()
|
|||||||
else
|
else
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
# process_pool ([pool])
|
||||||
#
|
#
|
||||||
# Iterate through a pool and set the vdevs' enclosure slot LEDs to
|
# Iterate through a pool (or pools) and set the VDEV's enclosure slot LEDs to
|
||||||
# those vdevs' state.
|
# the VDEV's 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
|
||||||
@@ -119,22 +113,19 @@ state_to_val()
|
|||||||
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
|
|
||||||
|
# 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
|
# Read out current LED value and path
|
||||||
# Get dev name (like 'sda')
|
tmp=$(echo "$therest" | sed 's/^.*led_token=//g')
|
||||||
dev=$(basename "$(echo "$therest" | awk '{print $(NF-1)}')")
|
vdev_enc_sysfs_path=$(echo "$tmp" | awk -F ',' '{print $2}')
|
||||||
vdev_enc_sysfs_path=$(realpath "/sys/class/block/$dev/device/enclosure_device"*)
|
current_val=$(echo "$tmp" | awk -F ',' '{print $1}')
|
||||||
current_val=$(echo "$therest" | awk '{print $NF}')
|
|
||||||
|
|
||||||
if [ "$current_val" != "0" ] ; then
|
if [ "$current_val" != "0" ] ; then
|
||||||
current_val=1
|
current_val=1
|
||||||
@@ -146,27 +137,36 @@ process_pool()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -e "$vdev_enc_sysfs_path/fault" ] ; then
|
if [ ! -e "$vdev_enc_sysfs_path/fault" ] ; then
|
||||||
rc=3
|
#shellcheck disable=SC2030
|
||||||
|
rc=1
|
||||||
zed_log_msg "vdev $vdev '$file/fault' 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 "$vdev_enc_sysfs_path/fault" "$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")
|
||||||
check_and_set_led "$ZEVENT_VDEV_ENC_SYSFS_PATH/fault" "$val"
|
check_and_set_led "$ZEVENT_VDEV_ENC_SYSFS_PATH/fault" "$val"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ fi
|
|||||||
|
|
||||||
umask 077
|
umask 077
|
||||||
note_subject="ZFS device fault for pool ${ZEVENT_POOL_GUID} 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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}>&-"
|
||||||
@@ -263,7 +267,7 @@ zed_notify_email()
|
|||||||
-e "s/@SUBJECT@/${subject}/g")"
|
-e "s/@SUBJECT@/${subject}/g")"
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS} < "${pathname}" >/dev/null 2>&1
|
eval "${ZED_EMAIL_PROG}" ${ZED_EMAIL_OPTS} < "${pathname}" >/dev/null 2>&1
|
||||||
rv=$?
|
rv=$?
|
||||||
if [ "${rv}" -ne 0 ]; then
|
if [ "${rv}" -ne 0 ]; then
|
||||||
zed_log_err "$(basename "${ZED_EMAIL_PROG}") exit=${rv}"
|
zed_log_err "$(basename "${ZED_EMAIL_PROG}") exit=${rv}"
|
||||||
@@ -363,7 +367,7 @@ zed_notify_pushbullet()
|
|||||||
#
|
#
|
||||||
# Notification via Slack Webhook <https://api.slack.com/incoming-webhooks>.
|
# Notification via Slack Webhook <https://api.slack.com/incoming-webhooks>.
|
||||||
# The Webhook URL (ZED_SLACK_WEBHOOK_URL) identifies this client to the
|
# The Webhook URL (ZED_SLACK_WEBHOOK_URL) identifies this client to the
|
||||||
# Slack channel.
|
# Slack channel.
|
||||||
#
|
#
|
||||||
# Requires awk, curl, and sed executables to be installed in the standard PATH.
|
# Requires awk, curl, and sed executables to be installed in the standard PATH.
|
||||||
#
|
#
|
||||||
@@ -507,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
|
||||||
|
|||||||
+16
-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).
|
||||||
@@ -15,6 +15,11 @@
|
|||||||
#ifndef ZED_H
|
#ifndef ZED_H
|
||||||
#define ZED_H
|
#define ZED_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Absolute path for the default zed configuration file.
|
||||||
|
*/
|
||||||
|
#define ZED_CONF_FILE SYSCONFDIR "/zfs/zed.conf"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Absolute path for the default zed pid file.
|
* Absolute path for the default zed pid file.
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +35,16 @@
|
|||||||
*/
|
*/
|
||||||
#define ZED_ZEDLET_DIR SYSCONFDIR "/zfs/zed.d"
|
#define ZED_ZEDLET_DIR SYSCONFDIR "/zfs/zed.d"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserved for future use.
|
||||||
|
*/
|
||||||
|
#define ZED_MAX_EVENTS 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserved for future use.
|
||||||
|
*/
|
||||||
|
#define ZED_MIN_EVENTS 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* String prefix for ZED variables passed via environment variables.
|
* String prefix for ZED variables passed via environment variables.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+124
-94
@@ -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).
|
||||||
@@ -32,26 +32,43 @@
|
|||||||
#include "zed_strings.h"
|
#include "zed_strings.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialise the configuration with default values.
|
* Return a new configuration with default values.
|
||||||
*/
|
*/
|
||||||
void
|
struct zed_conf *
|
||||||
zed_conf_init(struct zed_conf *zcp)
|
zed_conf_create(void)
|
||||||
{
|
{
|
||||||
memset(zcp, 0, sizeof (*zcp));
|
struct zed_conf *zcp;
|
||||||
|
|
||||||
/* zcp->zfs_hdl opened in zed_event_init() */
|
zcp = calloc(1, sizeof (*zcp));
|
||||||
/* zcp->zedlets created in zed_conf_scan_dir() */
|
if (!zcp)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
zcp->pid_fd = -1; /* opened in zed_conf_write_pid() */
|
zcp->syslog_facility = LOG_DAEMON;
|
||||||
zcp->state_fd = -1; /* opened in zed_conf_open_state() */
|
zcp->min_events = ZED_MIN_EVENTS;
|
||||||
zcp->zevent_fd = -1; /* opened in zed_event_init() */
|
zcp->max_events = ZED_MAX_EVENTS;
|
||||||
|
zcp->pid_fd = -1;
|
||||||
|
zcp->zedlets = NULL; /* created via zed_conf_scan_dir() */
|
||||||
|
zcp->state_fd = -1; /* opened via zed_conf_open_state() */
|
||||||
|
zcp->zfs_hdl = NULL; /* opened via zed_event_init() */
|
||||||
|
zcp->zevent_fd = -1; /* opened via zed_event_init() */
|
||||||
|
|
||||||
zcp->max_jobs = 16;
|
if (!(zcp->conf_file = strdup(ZED_CONF_FILE)))
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
if (!(zcp->pid_file = strdup(ZED_PID_FILE)) ||
|
if (!(zcp->pid_file = strdup(ZED_PID_FILE)))
|
||||||
!(zcp->zedlet_dir = strdup(ZED_ZEDLET_DIR)) ||
|
goto nomem;
|
||||||
!(zcp->state_file = strdup(ZED_STATE_FILE)))
|
|
||||||
zed_log_die("Failed to create conf: %s", strerror(errno));
|
if (!(zcp->zedlet_dir = strdup(ZED_ZEDLET_DIR)))
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
|
if (!(zcp->state_file = strdup(ZED_STATE_FILE)))
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
|
return (zcp);
|
||||||
|
|
||||||
|
nomem:
|
||||||
|
zed_log_die("Failed to create conf: %s", strerror(errno));
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -62,6 +79,9 @@ zed_conf_init(struct zed_conf *zcp)
|
|||||||
void
|
void
|
||||||
zed_conf_destroy(struct zed_conf *zcp)
|
zed_conf_destroy(struct zed_conf *zcp)
|
||||||
{
|
{
|
||||||
|
if (!zcp)
|
||||||
|
return;
|
||||||
|
|
||||||
if (zcp->state_fd >= 0) {
|
if (zcp->state_fd >= 0) {
|
||||||
if (close(zcp->state_fd) < 0)
|
if (close(zcp->state_fd) < 0)
|
||||||
zed_log_msg(LOG_WARNING,
|
zed_log_msg(LOG_WARNING,
|
||||||
@@ -82,6 +102,10 @@ zed_conf_destroy(struct zed_conf *zcp)
|
|||||||
zcp->pid_file, strerror(errno));
|
zcp->pid_file, strerror(errno));
|
||||||
zcp->pid_fd = -1;
|
zcp->pid_fd = -1;
|
||||||
}
|
}
|
||||||
|
if (zcp->conf_file) {
|
||||||
|
free(zcp->conf_file);
|
||||||
|
zcp->conf_file = NULL;
|
||||||
|
}
|
||||||
if (zcp->pid_file) {
|
if (zcp->pid_file) {
|
||||||
free(zcp->pid_file);
|
free(zcp->pid_file);
|
||||||
zcp->pid_file = NULL;
|
zcp->pid_file = NULL;
|
||||||
@@ -98,6 +122,7 @@ zed_conf_destroy(struct zed_conf *zcp)
|
|||||||
zed_strings_destroy(zcp->zedlets);
|
zed_strings_destroy(zcp->zedlets);
|
||||||
zcp->zedlets = NULL;
|
zcp->zedlets = NULL;
|
||||||
}
|
}
|
||||||
|
free(zcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -107,52 +132,46 @@ zed_conf_destroy(struct zed_conf *zcp)
|
|||||||
* otherwise, output to stderr and exit with a failure status.
|
* otherwise, output to stderr and exit with a failure status.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_zed_conf_display_help(const char *prog, boolean_t got_err)
|
_zed_conf_display_help(const char *prog, int got_err)
|
||||||
{
|
{
|
||||||
struct opt { const char *o, *d, *v; };
|
|
||||||
|
|
||||||
FILE *fp = got_err ? stderr : stdout;
|
FILE *fp = got_err ? stderr : stdout;
|
||||||
|
int w1 = 4; /* width of leading whitespace */
|
||||||
struct opt *oo;
|
int w2 = 8; /* width of L-justified option field */
|
||||||
struct opt iopts[] = {
|
|
||||||
{ .o = "-h", .d = "Display help" },
|
|
||||||
{ .o = "-L", .d = "Display license information" },
|
|
||||||
{ .o = "-V", .d = "Display version information" },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
struct opt nopts[] = {
|
|
||||||
{ .o = "-v", .d = "Be verbose" },
|
|
||||||
{ .o = "-f", .d = "Force daemon to run" },
|
|
||||||
{ .o = "-F", .d = "Run daemon in the foreground" },
|
|
||||||
{ .o = "-I",
|
|
||||||
.d = "Idle daemon until kernel module is (re)loaded" },
|
|
||||||
{ .o = "-M", .d = "Lock all pages in memory" },
|
|
||||||
{ .o = "-P", .d = "$PATH for ZED to use (only used by ZTS)" },
|
|
||||||
{ .o = "-Z", .d = "Zero state file" },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
struct opt vopts[] = {
|
|
||||||
{ .o = "-d DIR", .d = "Read enabled ZEDLETs from DIR.",
|
|
||||||
.v = ZED_ZEDLET_DIR },
|
|
||||||
{ .o = "-p FILE", .d = "Write daemon's PID to FILE.",
|
|
||||||
.v = ZED_PID_FILE },
|
|
||||||
{ .o = "-s FILE", .d = "Write daemon's state to FILE.",
|
|
||||||
.v = ZED_STATE_FILE },
|
|
||||||
{ .o = "-j JOBS", .d = "Start at most JOBS at once.",
|
|
||||||
.v = "16" },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
|
|
||||||
fprintf(fp, "Usage: %s [OPTION]...\n", (prog ? prog : "zed"));
|
fprintf(fp, "Usage: %s [OPTION]...\n", (prog ? prog : "zed"));
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
for (oo = iopts; oo->o; ++oo)
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-h",
|
||||||
fprintf(fp, " %*s %s\n", -8, oo->o, oo->d);
|
"Display help.");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-L",
|
||||||
|
"Display license information.");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-V",
|
||||||
|
"Display version information.");
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
for (oo = nopts; oo->o; ++oo)
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-v",
|
||||||
fprintf(fp, " %*s %s\n", -8, oo->o, oo->d);
|
"Be verbose.");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-f",
|
||||||
|
"Force daemon to run.");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-F",
|
||||||
|
"Run daemon in the foreground.");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-I",
|
||||||
|
"Idle daemon until kernel module is (re)loaded.");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-M",
|
||||||
|
"Lock all pages in memory.");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-P",
|
||||||
|
"$PATH for ZED to use (only used by ZTS).");
|
||||||
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-Z",
|
||||||
|
"Zero state file.");
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
for (oo = vopts; oo->o; ++oo)
|
#if 0
|
||||||
fprintf(fp, " %*s %s [%s]\n", -8, oo->o, oo->d, oo->v);
|
fprintf(fp, "%*c%*s %s [%s]\n", w1, 0x20, -w2, "-c FILE",
|
||||||
|
"Read configuration from FILE.", ZED_CONF_FILE);
|
||||||
|
#endif
|
||||||
|
fprintf(fp, "%*c%*s %s [%s]\n", w1, 0x20, -w2, "-d DIR",
|
||||||
|
"Read enabled ZEDLETs from DIR.", ZED_ZEDLET_DIR);
|
||||||
|
fprintf(fp, "%*c%*s %s [%s]\n", w1, 0x20, -w2, "-p FILE",
|
||||||
|
"Write daemon's PID to FILE.", ZED_PID_FILE);
|
||||||
|
fprintf(fp, "%*c%*s %s [%s]\n", w1, 0x20, -w2, "-s FILE",
|
||||||
|
"Write daemon's state to FILE.", ZED_STATE_FILE);
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
exit(got_err ? EXIT_FAILURE : EXIT_SUCCESS);
|
exit(got_err ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
@@ -164,14 +183,20 @@ _zed_conf_display_help(const char *prog, boolean_t got_err)
|
|||||||
static void
|
static void
|
||||||
_zed_conf_display_license(void)
|
_zed_conf_display_license(void)
|
||||||
{
|
{
|
||||||
printf(
|
const char **pp;
|
||||||
"The ZFS Event Daemon (ZED) is distributed under the terms of the\n"
|
const char *text[] = {
|
||||||
" Common Development and Distribution License (CDDL-1.0)\n"
|
"The ZFS Event Daemon (ZED) is distributed under the terms of the",
|
||||||
" <http://opensource.org/licenses/CDDL-1.0>.\n"
|
" Common Development and Distribution License (CDDL-1.0)",
|
||||||
"\n"
|
" <http://opensource.org/licenses/CDDL-1.0>.",
|
||||||
|
"",
|
||||||
"Developed at Lawrence Livermore National Laboratory"
|
"Developed at Lawrence Livermore National Laboratory"
|
||||||
" (LLNL-CODE-403049).\n"
|
" (LLNL-CODE-403049).",
|
||||||
"\n");
|
"",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
for (pp = text; *pp; pp++)
|
||||||
|
printf("%s\n", *pp);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -206,19 +231,16 @@ _zed_conf_parse_path(char **resultp, const char *path)
|
|||||||
|
|
||||||
if (path[0] == '/') {
|
if (path[0] == '/') {
|
||||||
*resultp = strdup(path);
|
*resultp = strdup(path);
|
||||||
|
} else if (!getcwd(buf, sizeof (buf))) {
|
||||||
|
zed_log_die("Failed to get current working dir: %s",
|
||||||
|
strerror(errno));
|
||||||
|
} else if (strlcat(buf, "/", sizeof (buf)) >= sizeof (buf)) {
|
||||||
|
zed_log_die("Failed to copy path: %s", strerror(ENAMETOOLONG));
|
||||||
|
} else if (strlcat(buf, path, sizeof (buf)) >= sizeof (buf)) {
|
||||||
|
zed_log_die("Failed to copy path: %s", strerror(ENAMETOOLONG));
|
||||||
} else {
|
} else {
|
||||||
if (!getcwd(buf, sizeof (buf)))
|
|
||||||
zed_log_die("Failed to get current working dir: %s",
|
|
||||||
strerror(errno));
|
|
||||||
|
|
||||||
if (strlcat(buf, "/", sizeof (buf)) >= sizeof (buf) ||
|
|
||||||
strlcat(buf, path, sizeof (buf)) >= sizeof (buf))
|
|
||||||
zed_log_die("Failed to copy path: %s",
|
|
||||||
strerror(ENAMETOOLONG));
|
|
||||||
|
|
||||||
*resultp = strdup(buf);
|
*resultp = strdup(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*resultp)
|
if (!*resultp)
|
||||||
zed_log_die("Failed to copy path: %s", strerror(ENOMEM));
|
zed_log_die("Failed to copy path: %s", strerror(ENOMEM));
|
||||||
}
|
}
|
||||||
@@ -229,9 +251,8 @@ _zed_conf_parse_path(char **resultp, const char *path)
|
|||||||
void
|
void
|
||||||
zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char * const opts = ":hLVd:p:P:s:vfFMZIj:";
|
const char * const opts = ":hLVc:d:p:P:s:vfFMZI";
|
||||||
int opt;
|
int opt;
|
||||||
unsigned long raw;
|
|
||||||
|
|
||||||
if (!zcp || !argv || !argv[0])
|
if (!zcp || !argv || !argv[0])
|
||||||
zed_log_die("Failed to parse options: Internal error");
|
zed_log_die("Failed to parse options: Internal error");
|
||||||
@@ -241,7 +262,7 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
|||||||
while ((opt = getopt(argc, argv, opts)) != -1) {
|
while ((opt = getopt(argc, argv, opts)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
_zed_conf_display_help(argv[0], B_FALSE);
|
_zed_conf_display_help(argv[0], EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
_zed_conf_display_license();
|
_zed_conf_display_license();
|
||||||
@@ -249,6 +270,9 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
|||||||
case 'V':
|
case 'V':
|
||||||
_zed_conf_display_version();
|
_zed_conf_display_version();
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
_zed_conf_parse_path(&zcp->conf_file, optarg);
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
_zed_conf_parse_path(&zcp->zedlet_dir, optarg);
|
_zed_conf_parse_path(&zcp->zedlet_dir, optarg);
|
||||||
break;
|
break;
|
||||||
@@ -279,30 +303,31 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
|||||||
case 'Z':
|
case 'Z':
|
||||||
zcp->do_zero = 1;
|
zcp->do_zero = 1;
|
||||||
break;
|
break;
|
||||||
case 'j':
|
|
||||||
errno = 0;
|
|
||||||
raw = strtoul(optarg, NULL, 0);
|
|
||||||
if (errno == ERANGE || raw > INT16_MAX) {
|
|
||||||
zed_log_die("%lu is too many jobs", raw);
|
|
||||||
} if (raw == 0) {
|
|
||||||
zed_log_die("0 jobs makes no sense");
|
|
||||||
} else {
|
|
||||||
zcp->max_jobs = raw;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
if (optopt == '?')
|
if (optopt == '?')
|
||||||
_zed_conf_display_help(argv[0], B_FALSE);
|
_zed_conf_display_help(argv[0], EXIT_SUCCESS);
|
||||||
|
|
||||||
fprintf(stderr, "%s: Invalid option '-%c'\n\n",
|
fprintf(stderr, "%s: %s '-%c'\n\n", argv[0],
|
||||||
argv[0], optopt);
|
"Invalid option", optopt);
|
||||||
_zed_conf_display_help(argv[0], B_TRUE);
|
_zed_conf_display_help(argv[0], EXIT_FAILURE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the configuration file into the configuration [zcp].
|
||||||
|
*
|
||||||
|
* FIXME: Not yet implemented.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
zed_conf_parse_file(struct zed_conf *zcp)
|
||||||
|
{
|
||||||
|
if (!zcp)
|
||||||
|
zed_log_die("Failed to parse config: %s", strerror(EINVAL));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the [zcp] zedlet_dir for files to exec based on the event class.
|
* Scan the [zcp] zedlet_dir for files to exec based on the event class.
|
||||||
* Files must be executable by user, but not writable by group or other.
|
* Files must be executable by user, but not writable by group or other.
|
||||||
@@ -310,6 +335,8 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
|||||||
*
|
*
|
||||||
* Return 0 on success with an updated set of zedlets,
|
* Return 0 on success with an updated set of zedlets,
|
||||||
* or -1 on error with errno set.
|
* or -1 on error with errno set.
|
||||||
|
*
|
||||||
|
* FIXME: Check if zedlet_dir and all parent dirs are secure.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
zed_conf_scan_dir(struct zed_conf *zcp)
|
zed_conf_scan_dir(struct zed_conf *zcp)
|
||||||
@@ -425,6 +452,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;
|
||||||
@@ -452,7 +481,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;
|
||||||
@@ -462,7 +491,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",
|
||||||
@@ -499,7 +528,7 @@ zed_conf_write_pid(struct zed_conf *zcp)
|
|||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
zed_log_msg(LOG_ERR, "Failed to write PID file \"%s\": %s",
|
zed_log_msg(LOG_ERR, "Failed to write PID file \"%s\": %s",
|
||||||
zcp->pid_file, strerror(errno));
|
zcp->pid_file, strerror(errno));
|
||||||
} else if (write(zcp->pid_fd, buf, n) != n) {
|
} else if (zed_file_write_n(zcp->pid_fd, buf, n) != n) {
|
||||||
zed_log_msg(LOG_ERR, "Failed to write PID file \"%s\": %s",
|
zed_log_msg(LOG_ERR, "Failed to write PID file \"%s\": %s",
|
||||||
zcp->pid_file, strerror(errno));
|
zcp->pid_file, strerror(errno));
|
||||||
} else if (fdatasync(zcp->pid_fd) < 0) {
|
} else if (fdatasync(zcp->pid_fd) < 0) {
|
||||||
@@ -527,6 +556,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;
|
||||||
@@ -548,7 +578,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));
|
||||||
@@ -566,7 +596,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));
|
||||||
|
|||||||
+22
-18
@@ -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).
|
||||||
@@ -20,39 +20,43 @@
|
|||||||
#include "zed_strings.h"
|
#include "zed_strings.h"
|
||||||
|
|
||||||
struct zed_conf {
|
struct zed_conf {
|
||||||
|
unsigned do_force:1; /* true if force enabled */
|
||||||
|
unsigned do_foreground:1; /* true if run in foreground */
|
||||||
|
unsigned do_memlock:1; /* true if locking memory */
|
||||||
|
unsigned do_verbose:1; /* true if verbosity enabled */
|
||||||
|
unsigned do_zero:1; /* true if zeroing state */
|
||||||
|
unsigned do_idle:1; /* true if idle enabled */
|
||||||
|
int syslog_facility; /* syslog facility value */
|
||||||
|
int min_events; /* RESERVED FOR FUTURE USE */
|
||||||
|
int max_events; /* RESERVED FOR FUTURE USE */
|
||||||
|
char *conf_file; /* abs path to config file */
|
||||||
char *pid_file; /* abs path to pid file */
|
char *pid_file; /* abs path to pid file */
|
||||||
char *zedlet_dir; /* abs path to zedlet dir */
|
|
||||||
char *state_file; /* abs path to state file */
|
|
||||||
|
|
||||||
libzfs_handle_t *zfs_hdl; /* handle to libzfs */
|
|
||||||
zed_strings_t *zedlets; /* names of enabled zedlets */
|
|
||||||
char *path; /* custom $PATH for zedlets to use */
|
|
||||||
|
|
||||||
int pid_fd; /* fd to pid file for lock */
|
int pid_fd; /* fd to pid file for lock */
|
||||||
|
char *zedlet_dir; /* abs path to zedlet dir */
|
||||||
|
zed_strings_t *zedlets; /* names of enabled zedlets */
|
||||||
|
char *state_file; /* abs path to state file */
|
||||||
int state_fd; /* fd to state file */
|
int state_fd; /* fd to state file */
|
||||||
|
libzfs_handle_t *zfs_hdl; /* handle to libzfs */
|
||||||
int zevent_fd; /* fd for access to zevents */
|
int zevent_fd; /* fd for access to zevents */
|
||||||
|
char *path; /* custom $PATH for zedlets to use */
|
||||||
int16_t max_jobs; /* max zedlets to run at one time */
|
|
||||||
|
|
||||||
boolean_t do_force:1; /* true if force enabled */
|
|
||||||
boolean_t do_foreground:1; /* true if run in foreground */
|
|
||||||
boolean_t do_memlock:1; /* true if locking memory */
|
|
||||||
boolean_t do_verbose:1; /* true if verbosity enabled */
|
|
||||||
boolean_t do_zero:1; /* true if zeroing state */
|
|
||||||
boolean_t do_idle:1; /* true if idle enabled */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void zed_conf_init(struct zed_conf *zcp);
|
struct zed_conf *zed_conf_create(void);
|
||||||
|
|
||||||
void zed_conf_destroy(struct zed_conf *zcp);
|
void zed_conf_destroy(struct zed_conf *zcp);
|
||||||
|
|
||||||
void zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv);
|
void zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv);
|
||||||
|
|
||||||
|
void zed_conf_parse_file(struct zed_conf *zcp);
|
||||||
|
|
||||||
int zed_conf_scan_dir(struct zed_conf *zcp);
|
int zed_conf_scan_dir(struct zed_conf *zcp);
|
||||||
|
|
||||||
int zed_conf_write_pid(struct zed_conf *zcp);
|
int zed_conf_write_pid(struct zed_conf *zcp);
|
||||||
|
|
||||||
int zed_conf_open_state(struct zed_conf *zcp);
|
int zed_conf_open_state(struct zed_conf *zcp);
|
||||||
|
|
||||||
int zed_conf_read_state(struct zed_conf *zcp, uint64_t *eidp, int64_t etime[]);
|
int zed_conf_read_state(struct zed_conf *zcp, uint64_t *eidp, int64_t etime[]);
|
||||||
|
|
||||||
int zed_conf_write_state(struct zed_conf *zcp, uint64_t eid, int64_t etime[]);
|
int zed_conf_write_state(struct zed_conf *zcp, uint64_t eid, int64_t etime[]);
|
||||||
|
|
||||||
#endif /* !ZED_CONF_H */
|
#endif /* !ZED_CONF_H */
|
||||||
|
|||||||
@@ -379,7 +379,6 @@ zed_disk_event_init()
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_setname_np(g_mon_tid, "udev monitor");
|
|
||||||
zed_log_msg(LOG_INFO, "zed_disk_event_init");
|
zed_log_msg(LOG_INFO, "zed_disk_event_init");
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
+30
-52
@@ -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).
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <libzfs_core.h>
|
#include <libzfs.h> /* FIXME: Replace with libzfs_core. */
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -54,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);
|
||||||
@@ -96,47 +96,6 @@ zed_event_fini(struct zed_conf *zcp)
|
|||||||
libzfs_fini(zcp->zfs_hdl);
|
libzfs_fini(zcp->zfs_hdl);
|
||||||
zcp->zfs_hdl = NULL;
|
zcp->zfs_hdl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
zed_exec_fini();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_bump_event_queue_length(void)
|
|
||||||
{
|
|
||||||
int zzlm = -1, wr;
|
|
||||||
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
|
|
||||||
long int qlen;
|
|
||||||
|
|
||||||
zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR);
|
|
||||||
if (zzlm < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (read(zzlm, qlen_buf, sizeof (qlen_buf)) < 0)
|
|
||||||
goto done;
|
|
||||||
qlen_buf[sizeof (qlen_buf) - 1] = '\0';
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
qlen = strtol(qlen_buf, NULL, 10);
|
|
||||||
if (errno == ERANGE)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (qlen <= 0)
|
|
||||||
qlen = 512; /* default zfs_zevent_len_max value */
|
|
||||||
else
|
|
||||||
qlen *= 2;
|
|
||||||
|
|
||||||
if (qlen > INT_MAX)
|
|
||||||
qlen = INT_MAX;
|
|
||||||
wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen);
|
|
||||||
|
|
||||||
if (pwrite(zzlm, qlen_buf, wr, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
zed_log_msg(LOG_WARNING, "Bumping queue length to %ld", qlen);
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (zzlm > -1)
|
|
||||||
(void) close(zzlm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -177,7 +136,10 @@ zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid, int64_t saved_etime[])
|
|||||||
|
|
||||||
if (n_dropped > 0) {
|
if (n_dropped > 0) {
|
||||||
zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
|
zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
|
||||||
_bump_event_queue_length();
|
/*
|
||||||
|
* FIXME: Increase max size of event nvlist in
|
||||||
|
* /sys/module/zfs/parameters/zfs_zevent_len_max ?
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
|
if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
|
||||||
zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
|
zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
|
||||||
@@ -249,7 +211,7 @@ _zed_event_value_is_hex(const char *name)
|
|||||||
*
|
*
|
||||||
* All environment variables in [zsp] should be added through this function.
|
* All environment variables in [zsp] should be added through this function.
|
||||||
*/
|
*/
|
||||||
static __attribute__((format(printf, 5, 6))) int
|
static int
|
||||||
_zed_event_add_var(uint64_t eid, zed_strings_t *zsp,
|
_zed_event_add_var(uint64_t eid, zed_strings_t *zsp,
|
||||||
const char *prefix, const char *name, const char *fmt, ...)
|
const char *prefix, const char *name, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -624,6 +586,8 @@ _zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp,
|
|||||||
* Convert the nvpair [nvp] to a string which is added to the environment
|
* Convert the nvpair [nvp] to a string which is added to the environment
|
||||||
* of the child process.
|
* of the child process.
|
||||||
* Return 0 on success, -1 on error.
|
* Return 0 on success, -1 on error.
|
||||||
|
*
|
||||||
|
* FIXME: Refactor with cmd/zpool/zpool_main.c:zpool_do_events_nvprint()?
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
|
_zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
|
||||||
@@ -722,11 +686,23 @@ _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
|
|||||||
_zed_event_add_var(eid, zsp, prefix, name,
|
_zed_event_add_var(eid, zsp, prefix, name,
|
||||||
"%llu", (u_longlong_t)i64);
|
"%llu", (u_longlong_t)i64);
|
||||||
break;
|
break;
|
||||||
|
case DATA_TYPE_NVLIST:
|
||||||
|
_zed_event_add_var(eid, zsp, prefix, name,
|
||||||
|
"%s", "_NOT_IMPLEMENTED_"); /* FIXME */
|
||||||
|
break;
|
||||||
case DATA_TYPE_STRING:
|
case DATA_TYPE_STRING:
|
||||||
(void) nvpair_value_string(nvp, &str);
|
(void) nvpair_value_string(nvp, &str);
|
||||||
_zed_event_add_var(eid, zsp, prefix, name,
|
_zed_event_add_var(eid, zsp, prefix, name,
|
||||||
"%s", (str ? str : "<NULL>"));
|
"%s", (str ? str : "<NULL>"));
|
||||||
break;
|
break;
|
||||||
|
case DATA_TYPE_BOOLEAN_ARRAY:
|
||||||
|
_zed_event_add_var(eid, zsp, prefix, name,
|
||||||
|
"%s", "_NOT_IMPLEMENTED_"); /* FIXME */
|
||||||
|
break;
|
||||||
|
case DATA_TYPE_BYTE_ARRAY:
|
||||||
|
_zed_event_add_var(eid, zsp, prefix, name,
|
||||||
|
"%s", "_NOT_IMPLEMENTED_"); /* FIXME */
|
||||||
|
break;
|
||||||
case DATA_TYPE_INT8_ARRAY:
|
case DATA_TYPE_INT8_ARRAY:
|
||||||
_zed_event_add_int8_array(eid, zsp, prefix, nvp);
|
_zed_event_add_int8_array(eid, zsp, prefix, nvp);
|
||||||
break;
|
break;
|
||||||
@@ -754,11 +730,9 @@ _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
|
|||||||
case DATA_TYPE_STRING_ARRAY:
|
case DATA_TYPE_STRING_ARRAY:
|
||||||
_zed_event_add_string_array(eid, zsp, prefix, nvp);
|
_zed_event_add_string_array(eid, zsp, prefix, nvp);
|
||||||
break;
|
break;
|
||||||
case DATA_TYPE_NVLIST:
|
|
||||||
case DATA_TYPE_BOOLEAN_ARRAY:
|
|
||||||
case DATA_TYPE_BYTE_ARRAY:
|
|
||||||
case DATA_TYPE_NVLIST_ARRAY:
|
case DATA_TYPE_NVLIST_ARRAY:
|
||||||
_zed_event_add_var(eid, zsp, prefix, name, "_NOT_IMPLEMENTED_");
|
_zed_event_add_var(eid, zsp, prefix, name,
|
||||||
|
"%s", "_NOT_IMPLEMENTED_"); /* FIXME */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@@ -938,7 +912,10 @@ zed_event_service(struct zed_conf *zcp)
|
|||||||
|
|
||||||
if (n_dropped > 0) {
|
if (n_dropped > 0) {
|
||||||
zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
|
zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
|
||||||
_bump_event_queue_length();
|
/*
|
||||||
|
* FIXME: Increase max size of event nvlist in
|
||||||
|
* /sys/module/zfs/parameters/zfs_zevent_len_max ?
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
|
if (nvlist_lookup_uint64(nvl, "eid", &eid) != 0) {
|
||||||
zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
|
zed_log_msg(LOG_WARNING, "Failed to lookup zevent eid");
|
||||||
@@ -976,7 +953,8 @@ zed_event_service(struct zed_conf *zcp)
|
|||||||
|
|
||||||
_zed_event_add_time_strings(eid, zsp, etime);
|
_zed_event_add_time_strings(eid, zsp, etime);
|
||||||
|
|
||||||
zed_exec_process(eid, class, subclass, zcp, zsp);
|
zed_exec_process(eid, class, subclass,
|
||||||
|
zcp->zedlet_dir, zcp->zedlets, zsp, zcp->zevent_fd);
|
||||||
|
|
||||||
zed_conf_write_state(zcp, eid, etime);
|
zed_conf_write_state(zcp, eid, etime);
|
||||||
|
|
||||||
|
|||||||
+1
-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).
|
||||||
|
|||||||
+59
-195
@@ -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).
|
||||||
@@ -18,53 +18,17 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <sys/avl.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pthread.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"
|
||||||
|
|
||||||
#define ZEVENT_FILENO 3
|
#define ZEVENT_FILENO 3
|
||||||
|
|
||||||
struct launched_process_node {
|
|
||||||
avl_node_t node;
|
|
||||||
pid_t pid;
|
|
||||||
uint64_t eid;
|
|
||||||
char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
_launched_process_node_compare(const void *x1, const void *x2)
|
|
||||||
{
|
|
||||||
pid_t p1;
|
|
||||||
pid_t p2;
|
|
||||||
|
|
||||||
assert(x1 != NULL);
|
|
||||||
assert(x2 != NULL);
|
|
||||||
|
|
||||||
p1 = ((const struct launched_process_node *) x1)->pid;
|
|
||||||
p2 = ((const struct launched_process_node *) x2)->pid;
|
|
||||||
|
|
||||||
if (p1 < p2)
|
|
||||||
return (-1);
|
|
||||||
else if (p1 == p2)
|
|
||||||
return (0);
|
|
||||||
else
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pthread_t _reap_children_tid = (pthread_t)-1;
|
|
||||||
static volatile boolean_t _reap_children_stop;
|
|
||||||
static avl_tree_t _launched_processes;
|
|
||||||
static pthread_mutex_t _launched_processes_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
static int16_t _launched_processes_limit;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create an environment string array for passing to execve() using the
|
* Create an environment string array for passing to execve() using the
|
||||||
* NAME=VALUE strings in container [zsp].
|
* NAME=VALUE strings in container [zsp].
|
||||||
@@ -115,26 +79,20 @@ _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;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int fd;
|
int fd;
|
||||||
struct launched_process_node *node;
|
pid_t wpid;
|
||||||
sigset_t mask;
|
int status;
|
||||||
struct timespec launch_timeout =
|
|
||||||
{ .tv_sec = 0, .tv_nsec = 200 * 1000 * 1000, };
|
|
||||||
|
|
||||||
assert(dir != NULL);
|
assert(dir != NULL);
|
||||||
assert(prog != NULL);
|
assert(prog != NULL);
|
||||||
assert(env != NULL);
|
assert(env != NULL);
|
||||||
assert(zfd >= 0);
|
assert(zfd >= 0);
|
||||||
|
|
||||||
while (__atomic_load_n(&_launched_processes_limit,
|
|
||||||
__ATOMIC_SEQ_CST) <= 0)
|
|
||||||
(void) nanosleep(&launch_timeout, NULL);
|
|
||||||
|
|
||||||
n = snprintf(path, sizeof (path), "%s/%s", dir, prog);
|
n = snprintf(path, sizeof (path), "%s/%s", dir, prog);
|
||||||
if ((n < 0) || (n >= sizeof (path))) {
|
if ((n < 0) || (n >= sizeof (path))) {
|
||||||
zed_log_msg(LOG_WARNING,
|
zed_log_msg(LOG_WARNING,
|
||||||
@@ -142,179 +100,100 @@ _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));
|
||||||
return;
|
return;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
(void) sigemptyset(&mask);
|
|
||||||
(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 */
|
||||||
|
|
||||||
node = calloc(1, sizeof (*node));
|
|
||||||
if (node) {
|
|
||||||
node->pid = pid;
|
|
||||||
node->eid = eid;
|
|
||||||
node->name = strdup(prog);
|
|
||||||
|
|
||||||
avl_add(&_launched_processes, node);
|
|
||||||
}
|
|
||||||
(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",
|
zed_log_msg(LOG_INFO, "Invoking \"%s\" eid=%llu pid=%d",
|
||||||
prog, eid, pid);
|
prog, eid, pid);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
/* FIXME: Timeout rogue child processes with sigalarm? */
|
||||||
_nop(int sig)
|
|
||||||
{}
|
|
||||||
|
|
||||||
static void *
|
/*
|
||||||
_reap_children(void *arg)
|
* Wait for child process using WNOHANG to limit
|
||||||
{
|
* the time spent waiting to 10 seconds (10,000ms).
|
||||||
struct launched_process_node node, *pnode;
|
*/
|
||||||
pid_t pid;
|
for (n = 0; n < 1000; n++) {
|
||||||
int status;
|
wpid = waitpid(pid, &status, WNOHANG);
|
||||||
struct rusage usage;
|
if (wpid == (pid_t)-1) {
|
||||||
struct sigaction sa = {};
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
zed_log_msg(LOG_WARNING,
|
||||||
|
"Failed to wait for \"%s\" eid=%llu pid=%d",
|
||||||
|
prog, eid, pid);
|
||||||
|
break;
|
||||||
|
} else if (wpid == 0) {
|
||||||
|
struct timespec t;
|
||||||
|
|
||||||
(void) sigfillset(&sa.sa_mask);
|
/* child still running */
|
||||||
(void) sigdelset(&sa.sa_mask, SIGCHLD);
|
t.tv_sec = 0;
|
||||||
(void) pthread_sigmask(SIG_SETMASK, &sa.sa_mask, NULL);
|
t.tv_nsec = 10000000; /* 10ms */
|
||||||
|
(void) nanosleep(&t, NULL);
|
||||||
(void) sigemptyset(&sa.sa_mask);
|
continue;
|
||||||
sa.sa_handler = _nop;
|
|
||||||
sa.sa_flags = SA_NOCLDSTOP;
|
|
||||||
(void) sigaction(SIGCHLD, &sa, NULL);
|
|
||||||
|
|
||||||
for (_reap_children_stop = B_FALSE; !_reap_children_stop; ) {
|
|
||||||
(void) pthread_mutex_lock(&_launched_processes_lock);
|
|
||||||
pid = wait4(0, &status, WNOHANG, &usage);
|
|
||||||
|
|
||||||
if (pid == 0 || pid == (pid_t)-1) {
|
|
||||||
(void) pthread_mutex_unlock(&_launched_processes_lock);
|
|
||||||
if (pid == 0 || errno == ECHILD)
|
|
||||||
pause();
|
|
||||||
else if (errno != EINTR)
|
|
||||||
zed_log_msg(LOG_WARNING,
|
|
||||||
"Failed to wait for children: %s",
|
|
||||||
strerror(errno));
|
|
||||||
} else {
|
|
||||||
memset(&node, 0, sizeof (node));
|
|
||||||
node.pid = pid;
|
|
||||||
pnode = avl_find(&_launched_processes, &node, NULL);
|
|
||||||
if (pnode) {
|
|
||||||
memcpy(&node, pnode, sizeof (node));
|
|
||||||
|
|
||||||
avl_remove(&_launched_processes, pnode);
|
|
||||||
free(pnode);
|
|
||||||
}
|
|
||||||
(void) pthread_mutex_unlock(&_launched_processes_lock);
|
|
||||||
__atomic_add_fetch(&_launched_processes_limit, 1,
|
|
||||||
__ATOMIC_SEQ_CST);
|
|
||||||
|
|
||||||
usage.ru_utime.tv_sec += usage.ru_stime.tv_sec;
|
|
||||||
usage.ru_utime.tv_usec += usage.ru_stime.tv_usec;
|
|
||||||
usage.ru_utime.tv_sec +=
|
|
||||||
usage.ru_utime.tv_usec / (1000 * 1000);
|
|
||||||
usage.ru_utime.tv_usec %= 1000 * 1000;
|
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
"Finished \"%s\" eid=%llu pid=%d "
|
|
||||||
"time=%llu.%06us exit=%d",
|
|
||||||
node.name, node.eid, pid,
|
|
||||||
(unsigned long long) usage.ru_utime.tv_sec,
|
|
||||||
(unsigned int) usage.ru_utime.tv_usec,
|
|
||||||
WEXITSTATUS(status));
|
|
||||||
} else if (WIFSIGNALED(status)) {
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
"Finished \"%s\" eid=%llu pid=%d "
|
|
||||||
"time=%llu.%06us sig=%d/%s",
|
|
||||||
node.name, node.eid, pid,
|
|
||||||
(unsigned long long) usage.ru_utime.tv_sec,
|
|
||||||
(unsigned int) usage.ru_utime.tv_usec,
|
|
||||||
WTERMSIG(status),
|
|
||||||
strsignal(WTERMSIG(status)));
|
|
||||||
} else {
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
"Finished \"%s\" eid=%llu pid=%d "
|
|
||||||
"time=%llu.%06us status=0x%X",
|
|
||||||
node.name, node.eid,
|
|
||||||
(unsigned long long) usage.ru_utime.tv_sec,
|
|
||||||
(unsigned int) usage.ru_utime.tv_usec,
|
|
||||||
(unsigned int) status);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(node.name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
zed_log_msg(LOG_INFO,
|
||||||
|
"Finished \"%s\" eid=%llu pid=%d exit=%d",
|
||||||
|
prog, eid, pid, WEXITSTATUS(status));
|
||||||
|
} else if (WIFSIGNALED(status)) {
|
||||||
|
zed_log_msg(LOG_INFO,
|
||||||
|
"Finished \"%s\" eid=%llu pid=%d sig=%d/%s",
|
||||||
|
prog, eid, pid, WTERMSIG(status),
|
||||||
|
strsignal(WTERMSIG(status)));
|
||||||
|
} else {
|
||||||
|
zed_log_msg(LOG_INFO,
|
||||||
|
"Finished \"%s\" eid=%llu pid=%d status=0x%X",
|
||||||
|
prog, eid, (unsigned int) status);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (NULL);
|
/*
|
||||||
}
|
* kill child process after 10 seconds
|
||||||
|
*/
|
||||||
void
|
if (wpid == 0) {
|
||||||
zed_exec_fini(void)
|
zed_log_msg(LOG_WARNING, "Killing hung \"%s\" pid=%d",
|
||||||
{
|
prog, pid);
|
||||||
struct launched_process_node *node;
|
(void) kill(pid, SIGKILL);
|
||||||
void *ck = NULL;
|
|
||||||
|
|
||||||
if (_reap_children_tid == (pthread_t)-1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_reap_children_stop = B_TRUE;
|
|
||||||
(void) pthread_kill(_reap_children_tid, SIGCHLD);
|
|
||||||
(void) pthread_join(_reap_children_tid, NULL);
|
|
||||||
|
|
||||||
while ((node = avl_destroy_nodes(&_launched_processes, &ck)) != NULL) {
|
|
||||||
free(node->name);
|
|
||||||
free(node);
|
|
||||||
}
|
}
|
||||||
avl_destroy(&_launched_processes);
|
|
||||||
|
|
||||||
(void) pthread_mutex_destroy(&_launched_processes_lock);
|
|
||||||
(void) pthread_mutex_init(&_launched_processes_lock, NULL);
|
|
||||||
|
|
||||||
_reap_children_tid = (pthread_t)-1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process the event [eid] by synchronously invoking all zedlets with a
|
* Process the event [eid] by synchronously invoking all zedlets with a
|
||||||
* matching class prefix.
|
* matching class prefix.
|
||||||
*
|
*
|
||||||
* Each executable in [zcp->zedlets] from the directory [zcp->zedlet_dir]
|
* Each executable in [zedlets] from the directory [dir] is matched against
|
||||||
* is matched against the event's [class], [subclass], and the "all" class
|
* the event's [class], [subclass], and the "all" class (which matches
|
||||||
* (which matches all events).
|
* all events). Every zedlet with a matching class prefix is invoked.
|
||||||
* Every zedlet with a matching class prefix is invoked.
|
|
||||||
* The NAME=VALUE strings in [envs] will be passed to the zedlet as
|
* The NAME=VALUE strings in [envs] will be passed to the zedlet as
|
||||||
* environment variables.
|
* environment variables.
|
||||||
*
|
*
|
||||||
* The file descriptor [zcp->zevent_fd] is the zevent_fd used to track the
|
* The file descriptor [zfd] is the zevent_fd used to track the
|
||||||
* current cursor location within the zevent nvlist.
|
* current cursor location within the zevent nvlist.
|
||||||
*
|
*
|
||||||
* Return 0 on success, -1 on error.
|
* Return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
||||||
struct zed_conf *zcp, zed_strings_t *envs)
|
const char *dir, zed_strings_t *zedlets, zed_strings_t *envs, int zfd)
|
||||||
{
|
{
|
||||||
const char *class_strings[4];
|
const char *class_strings[4];
|
||||||
const char *allclass = "all";
|
const char *allclass = "all";
|
||||||
@@ -323,22 +202,9 @@ zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
|||||||
char **e;
|
char **e;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (!zcp->zedlet_dir || !zcp->zedlets || !envs || zcp->zevent_fd < 0)
|
if (!dir || !zedlets || !envs || zfd < 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (_reap_children_tid == (pthread_t)-1) {
|
|
||||||
_launched_processes_limit = zcp->max_jobs;
|
|
||||||
|
|
||||||
if (pthread_create(&_reap_children_tid, NULL,
|
|
||||||
_reap_children, NULL) != 0)
|
|
||||||
return (-1);
|
|
||||||
pthread_setname_np(_reap_children_tid, "reap ZEDLETs");
|
|
||||||
|
|
||||||
avl_create(&_launched_processes, _launched_process_node_compare,
|
|
||||||
sizeof (struct launched_process_node),
|
|
||||||
offsetof(struct launched_process_node, node));
|
|
||||||
}
|
|
||||||
|
|
||||||
csp = class_strings;
|
csp = class_strings;
|
||||||
|
|
||||||
if (class)
|
if (class)
|
||||||
@@ -354,13 +220,11 @@ zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
|||||||
|
|
||||||
e = _zed_exec_create_env(envs);
|
e = _zed_exec_create_env(envs);
|
||||||
|
|
||||||
for (z = zed_strings_first(zcp->zedlets); z;
|
for (z = zed_strings_first(zedlets); z; z = zed_strings_next(zedlets)) {
|
||||||
z = zed_strings_next(zcp->zedlets)) {
|
|
||||||
for (csp = class_strings; *csp; csp++) {
|
for (csp = class_strings; *csp; csp++) {
|
||||||
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, dir, z, e, zfd);
|
||||||
z, e, zcp->zevent_fd, zcp->do_foreground);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(e);
|
free(e);
|
||||||
|
|||||||
+3
-5
@@ -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).
|
||||||
@@ -17,11 +17,9 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "zed_strings.h"
|
#include "zed_strings.h"
|
||||||
#include "zed_conf.h"
|
|
||||||
|
|
||||||
void zed_exec_fini(void);
|
|
||||||
|
|
||||||
int zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
int zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
||||||
struct zed_conf *zcp, zed_strings_t *envs);
|
const char *dir, zed_strings_t *zedlets, zed_strings_t *envs,
|
||||||
|
int zevent_fd);
|
||||||
|
|
||||||
#endif /* !ZED_EXEC_H */
|
#endif /* !ZED_EXEC_H */
|
||||||
|
|||||||
+97
-21
@@ -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).
|
||||||
@@ -12,17 +12,73 @@
|
|||||||
* You may not use this file except in compliance with the license.
|
* You may not use this file except in compliance with the license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "zed_file.h"
|
#include "zed_file.h"
|
||||||
#include "zed_log.h"
|
#include "zed_log.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read up to [n] bytes from [fd] into [buf].
|
||||||
|
* Return the number of bytes read, 0 on EOF, or -1 on error.
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
zed_file_read_n(int fd, void *buf, size_t n)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
size_t n_left;
|
||||||
|
ssize_t n_read;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
n_left = n;
|
||||||
|
while (n_left > 0) {
|
||||||
|
if ((n_read = read(fd, p, n_left)) < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
} else if (n_read == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n_left -= n_read;
|
||||||
|
p += n_read;
|
||||||
|
}
|
||||||
|
return (n - n_left);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write [n] bytes from [buf] out to [fd].
|
||||||
|
* Return the number of bytes written, or -1 on error.
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
zed_file_write_n(int fd, void *buf, size_t n)
|
||||||
|
{
|
||||||
|
const unsigned char *p;
|
||||||
|
size_t n_left;
|
||||||
|
ssize_t n_written;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
n_left = n;
|
||||||
|
while (n_left > 0) {
|
||||||
|
if ((n_written = write(fd, p, n_left)) < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
}
|
||||||
|
n_left -= n_written;
|
||||||
|
p += n_written;
|
||||||
|
}
|
||||||
|
return (n);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set an exclusive advisory lock on the open file descriptor [fd].
|
* Set an exclusive advisory lock on the open file descriptor [fd].
|
||||||
* Return 0 on success, 1 if a conflicting lock is held by another process,
|
* Return 0 on success, 1 if a conflicting lock is held by another process,
|
||||||
@@ -104,13 +160,6 @@ zed_file_is_locked(int fd)
|
|||||||
return (lock.l_pid);
|
return (lock.l_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if __APPLE__
|
|
||||||
#define PROC_SELF_FD "/dev/fd"
|
|
||||||
#else /* Linux-compatible layout */
|
|
||||||
#define PROC_SELF_FD "/proc/self/fd"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close all open file descriptors greater than or equal to [lowfd].
|
* Close all open file descriptors greater than or equal to [lowfd].
|
||||||
* Any errors encountered while closing file descriptors are ignored.
|
* Any errors encountered while closing file descriptors are ignored.
|
||||||
@@ -118,24 +167,51 @@ zed_file_is_locked(int fd)
|
|||||||
void
|
void
|
||||||
zed_file_close_from(int lowfd)
|
zed_file_close_from(int lowfd)
|
||||||
{
|
{
|
||||||
int errno_bak = errno;
|
const int maxfd_def = 256;
|
||||||
int maxfd = 0;
|
int errno_bak;
|
||||||
|
struct rlimit rl;
|
||||||
|
int maxfd;
|
||||||
int fd;
|
int fd;
|
||||||
DIR *fddir;
|
|
||||||
struct dirent *fdent;
|
|
||||||
|
|
||||||
if ((fddir = opendir(PROC_SELF_FD)) != NULL) {
|
errno_bak = errno;
|
||||||
while ((fdent = readdir(fddir)) != NULL) {
|
|
||||||
fd = atoi(fdent->d_name);
|
if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
|
||||||
if (fd > maxfd && fd != dirfd(fddir))
|
maxfd = maxfd_def;
|
||||||
maxfd = fd;
|
} else if (rl.rlim_max == RLIM_INFINITY) {
|
||||||
}
|
maxfd = maxfd_def;
|
||||||
(void) closedir(fddir);
|
|
||||||
} else {
|
} else {
|
||||||
maxfd = sysconf(_SC_OPEN_MAX);
|
maxfd = rl.rlim_max;
|
||||||
}
|
}
|
||||||
for (fd = lowfd; fd < maxfd; fd++)
|
for (fd = lowfd; fd < maxfd; fd++)
|
||||||
(void) close(fd);
|
(void) close(fd);
|
||||||
|
|
||||||
errno = errno_bak;
|
errno = errno_bak;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the CLOEXEC flag on file descriptor [fd] so it will be automatically
|
||||||
|
* closed upon successful execution of one of the exec functions.
|
||||||
|
* Return 0 on success, or -1 on error.
|
||||||
|
*
|
||||||
|
* FIXME: No longer needed?
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zed_file_close_on_exec(int fd)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
errno = EBADF;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
flags = fcntl(fd, F_GETFD);
|
||||||
|
if (flags == -1)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
flags |= FD_CLOEXEC;
|
||||||
|
|
||||||
|
if (fcntl(fd, F_SETFD, flags) == -1)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|||||||
+7
-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).
|
||||||
@@ -18,6 +18,10 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
ssize_t zed_file_read_n(int fd, void *buf, size_t n);
|
||||||
|
|
||||||
|
ssize_t zed_file_write_n(int fd, void *buf, size_t n);
|
||||||
|
|
||||||
int zed_file_lock(int fd);
|
int zed_file_lock(int fd);
|
||||||
|
|
||||||
int zed_file_unlock(int fd);
|
int zed_file_unlock(int fd);
|
||||||
@@ -26,4 +30,6 @@ pid_t zed_file_is_locked(int fd);
|
|||||||
|
|
||||||
void zed_file_close_from(int fd);
|
void zed_file_close_from(int fd);
|
||||||
|
|
||||||
|
int zed_file_close_on_exec(int fd);
|
||||||
|
|
||||||
#endif /* !ZED_FILE_H */
|
#endif /* !ZED_FILE_H */
|
||||||
|
|||||||
+1
-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).
|
||||||
|
|||||||
+1
-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).
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -21,5 +21,3 @@ zfs_LDADD += $(LTLIBINTL)
|
|||||||
if BUILD_FREEBSD
|
if BUILD_FREEBSD
|
||||||
zfs_LDADD += -lgeom -ljail
|
zfs_LDADD += -lgeom -ljail
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
+23
-185
@@ -53,6 +53,7 @@
|
|||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/debug.h>
|
||||||
#include <sys/list.h>
|
#include <sys/list.h>
|
||||||
#include <sys/mkdev.h>
|
#include <sys/mkdev.h>
|
||||||
#include <sys/mntent.h>
|
#include <sys/mntent.h>
|
||||||
@@ -70,6 +71,7 @@
|
|||||||
#include <zfs_prop.h>
|
#include <zfs_prop.h>
|
||||||
#include <zfs_deleg.h>
|
#include <zfs_deleg.h>
|
||||||
#include <libzutil.h>
|
#include <libzutil.h>
|
||||||
|
#include <libuutil.h>
|
||||||
#ifdef HAVE_IDMAP
|
#ifdef HAVE_IDMAP
|
||||||
#include <aclutils.h>
|
#include <aclutils.h>
|
||||||
#include <directory.h>
|
#include <directory.h>
|
||||||
@@ -268,7 +270,7 @@ get_usage(zfs_help_t idx)
|
|||||||
return (gettext("\tclone [-p] [-o property=value] ... "
|
return (gettext("\tclone [-p] [-o property=value] ... "
|
||||||
"<snapshot> <filesystem|volume>\n"));
|
"<snapshot> <filesystem|volume>\n"));
|
||||||
case HELP_CREATE:
|
case HELP_CREATE:
|
||||||
return (gettext("\tcreate [-Pnpuv] [-o property=value] ... "
|
return (gettext("\tcreate [-Pnpv] [-o property=value] ... "
|
||||||
"<filesystem>\n"
|
"<filesystem>\n"
|
||||||
"\tcreate [-Pnpsv] [-b blocksize] [-o property=value] ... "
|
"\tcreate [-Pnpsv] [-b blocksize] [-o property=value] ... "
|
||||||
"-V <size> <volume>\n"));
|
"-V <size> <volume>\n"));
|
||||||
@@ -728,32 +730,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)
|
||||||
{
|
{
|
||||||
@@ -916,107 +892,6 @@ usage:
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a default volblocksize for the pool which always uses more than
|
|
||||||
* half of the data sectors. This primarily applies to dRAID which always
|
|
||||||
* writes full stripe widths.
|
|
||||||
*/
|
|
||||||
static uint64_t
|
|
||||||
default_volblocksize(zpool_handle_t *zhp, nvlist_t *props)
|
|
||||||
{
|
|
||||||
uint64_t volblocksize, asize = SPA_MINBLOCKSIZE;
|
|
||||||
nvlist_t *tree, **vdevs;
|
|
||||||
uint_t nvdevs;
|
|
||||||
|
|
||||||
nvlist_t *config = zpool_get_config(zhp, NULL);
|
|
||||||
|
|
||||||
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree) != 0 ||
|
|
||||||
nvlist_lookup_nvlist_array(tree, ZPOOL_CONFIG_CHILDREN,
|
|
||||||
&vdevs, &nvdevs) != 0) {
|
|
||||||
return (ZVOL_DEFAULT_BLOCKSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nvdevs; i++) {
|
|
||||||
nvlist_t *nv = vdevs[i];
|
|
||||||
uint64_t ashift, ndata, nparity;
|
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT, &ashift) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_DRAID_NDATA,
|
|
||||||
&ndata) == 0) {
|
|
||||||
/* dRAID minimum allocation width */
|
|
||||||
asize = MAX(asize, ndata * (1ULL << ashift));
|
|
||||||
} else if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
|
|
||||||
&nparity) == 0) {
|
|
||||||
/* raidz minimum allocation width */
|
|
||||||
if (nparity == 1)
|
|
||||||
asize = MAX(asize, 2 * (1ULL << ashift));
|
|
||||||
else
|
|
||||||
asize = MAX(asize, 4 * (1ULL << ashift));
|
|
||||||
} else {
|
|
||||||
/* mirror or (non-redundant) leaf vdev */
|
|
||||||
asize = MAX(asize, 1ULL << ashift);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the target volblocksize such that more than half
|
|
||||||
* of the asize is used. The following table is for 4k sectors.
|
|
||||||
*
|
|
||||||
* n asize blksz used | n asize blksz used
|
|
||||||
* -------------------------+---------------------------------
|
|
||||||
* 1 4,096 8,192 100% | 9 36,864 32,768 88%
|
|
||||||
* 2 8,192 8,192 100% | 10 40,960 32,768 80%
|
|
||||||
* 3 12,288 8,192 66% | 11 45,056 32,768 72%
|
|
||||||
* 4 16,384 16,384 100% | 12 49,152 32,768 66%
|
|
||||||
* 5 20,480 16,384 80% | 13 53,248 32,768 61%
|
|
||||||
* 6 24,576 16,384 66% | 14 57,344 32,768 57%
|
|
||||||
* 7 28,672 16,384 57% | 15 61,440 32,768 53%
|
|
||||||
* 8 32,768 32,768 100% | 16 65,536 65,636 100%
|
|
||||||
*
|
|
||||||
* This is primarily a concern for dRAID which always allocates
|
|
||||||
* a full stripe width. For dRAID the default stripe width is
|
|
||||||
* n=8 in which case the volblocksize is set to 32k. Ignoring
|
|
||||||
* compression there are no unused sectors. This same reasoning
|
|
||||||
* applies to raidz[2,3] so target 4 sectors to minimize waste.
|
|
||||||
*/
|
|
||||||
uint64_t tgt_volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
|
|
||||||
while (tgt_volblocksize * 2 <= asize)
|
|
||||||
tgt_volblocksize *= 2;
|
|
||||||
|
|
||||||
const char *prop = zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE);
|
|
||||||
if (nvlist_lookup_uint64(props, prop, &volblocksize) == 0) {
|
|
||||||
|
|
||||||
/* Issue a warning when a non-optimal size is requested. */
|
|
||||||
if (volblocksize < ZVOL_DEFAULT_BLOCKSIZE) {
|
|
||||||
(void) fprintf(stderr, gettext("Warning: "
|
|
||||||
"volblocksize (%llu) is less than the default "
|
|
||||||
"minimum block size (%llu).\nTo reduce wasted "
|
|
||||||
"space a volblocksize of %llu is recommended.\n"),
|
|
||||||
(u_longlong_t)volblocksize,
|
|
||||||
(u_longlong_t)ZVOL_DEFAULT_BLOCKSIZE,
|
|
||||||
(u_longlong_t)tgt_volblocksize);
|
|
||||||
} else if (volblocksize < tgt_volblocksize) {
|
|
||||||
(void) fprintf(stderr, gettext("Warning: "
|
|
||||||
"volblocksize (%llu) is much less than the "
|
|
||||||
"minimum allocation\nunit (%llu), which wastes "
|
|
||||||
"at least %llu%% of space. To reduce wasted "
|
|
||||||
"space,\nuse a larger volblocksize (%llu is "
|
|
||||||
"recommended), fewer dRAID data disks\n"
|
|
||||||
"per group, or smaller sector size (ashift).\n"),
|
|
||||||
(u_longlong_t)volblocksize, (u_longlong_t)asize,
|
|
||||||
(u_longlong_t)((100 * (asize - volblocksize)) /
|
|
||||||
asize), (u_longlong_t)tgt_volblocksize);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
volblocksize = tgt_volblocksize;
|
|
||||||
fnvlist_add_uint64(props, prop, volblocksize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (volblocksize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* zfs create [-Pnpv] [-o prop=value] ... fs
|
* zfs create [-Pnpv] [-o prop=value] ... fs
|
||||||
* zfs create [-Pnpsv] [-b blocksize] [-o prop=value] ... -V vol size
|
* zfs create [-Pnpsv] [-b blocksize] [-o prop=value] ... -V vol size
|
||||||
@@ -1036,8 +911,6 @@ default_volblocksize(zpool_handle_t *zhp, nvlist_t *props)
|
|||||||
* check of arguments and properties, but does not check for permissions,
|
* check of arguments and properties, but does not check for permissions,
|
||||||
* available space, etc.
|
* available space, etc.
|
||||||
*
|
*
|
||||||
* The '-u' flag prevents the newly created file system from being mounted.
|
|
||||||
*
|
|
||||||
* The '-v' flag is for verbose output.
|
* The '-v' flag is for verbose output.
|
||||||
*
|
*
|
||||||
* The '-P' flag is used for parseable output. It implies '-v'.
|
* The '-P' flag is used for parseable output. It implies '-v'.
|
||||||
@@ -1054,19 +927,17 @@ zfs_do_create(int argc, char **argv)
|
|||||||
boolean_t bflag = B_FALSE;
|
boolean_t bflag = B_FALSE;
|
||||||
boolean_t parents = B_FALSE;
|
boolean_t parents = B_FALSE;
|
||||||
boolean_t dryrun = B_FALSE;
|
boolean_t dryrun = B_FALSE;
|
||||||
boolean_t nomount = B_FALSE;
|
|
||||||
boolean_t verbose = B_FALSE;
|
boolean_t verbose = B_FALSE;
|
||||||
boolean_t parseable = B_FALSE;
|
boolean_t parseable = B_FALSE;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
nvlist_t *props;
|
nvlist_t *props;
|
||||||
uint64_t intval;
|
uint64_t intval;
|
||||||
char *strval;
|
|
||||||
|
|
||||||
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
|
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
|
||||||
nomem();
|
nomem();
|
||||||
|
|
||||||
/* check options */
|
/* check options */
|
||||||
while ((c = getopt(argc, argv, ":PV:b:nso:puv")) != -1) {
|
while ((c = getopt(argc, argv, ":PV:b:nso:pv")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'V':
|
case 'V':
|
||||||
type = ZFS_TYPE_VOLUME;
|
type = ZFS_TYPE_VOLUME;
|
||||||
@@ -1113,9 +984,6 @@ zfs_do_create(int argc, char **argv)
|
|||||||
case 's':
|
case 's':
|
||||||
noreserve = B_TRUE;
|
noreserve = B_TRUE;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
|
||||||
nomount = B_TRUE;
|
|
||||||
break;
|
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose = B_TRUE;
|
verbose = B_TRUE;
|
||||||
break;
|
break;
|
||||||
@@ -1135,11 +1003,6 @@ zfs_do_create(int argc, char **argv)
|
|||||||
"used when creating a volume\n"));
|
"used when creating a volume\n"));
|
||||||
goto badusage;
|
goto badusage;
|
||||||
}
|
}
|
||||||
if (nomount && type != ZFS_TYPE_FILESYSTEM) {
|
|
||||||
(void) fprintf(stderr, gettext("'-u' can only be "
|
|
||||||
"used when creating a filesystem\n"));
|
|
||||||
goto badusage;
|
|
||||||
}
|
|
||||||
|
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
@@ -1155,7 +1018,7 @@ zfs_do_create(int argc, char **argv)
|
|||||||
goto badusage;
|
goto badusage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dryrun || type == ZFS_TYPE_VOLUME) {
|
if (dryrun || (type == ZFS_TYPE_VOLUME && !noreserve)) {
|
||||||
char msg[ZFS_MAX_DATASET_NAME_LEN * 2];
|
char msg[ZFS_MAX_DATASET_NAME_LEN * 2];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
@@ -1177,24 +1040,18 @@ zfs_do_create(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if volsize is not a multiple of volblocksize, round it up to the
|
||||||
|
* nearest multiple of the volblocksize
|
||||||
|
*/
|
||||||
if (type == ZFS_TYPE_VOLUME) {
|
if (type == ZFS_TYPE_VOLUME) {
|
||||||
const char *prop = zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE);
|
uint64_t volblocksize;
|
||||||
uint64_t volblocksize = default_volblocksize(zpool_handle,
|
|
||||||
real_props);
|
|
||||||
|
|
||||||
if (volblocksize != ZVOL_DEFAULT_BLOCKSIZE &&
|
if (nvlist_lookup_uint64(props,
|
||||||
nvlist_lookup_string(props, prop, &strval) != 0) {
|
zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
|
||||||
if (asprintf(&strval, "%llu",
|
&volblocksize) != 0)
|
||||||
(u_longlong_t)volblocksize) == -1)
|
volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
|
||||||
nomem();
|
|
||||||
nvlist_add_string(props, prop, strval);
|
|
||||||
free(strval);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If volsize is not a multiple of volblocksize, round it
|
|
||||||
* up to the nearest multiple of the volblocksize.
|
|
||||||
*/
|
|
||||||
if (volsize % volblocksize) {
|
if (volsize % volblocksize) {
|
||||||
volsize = P2ROUNDUP_TYPED(volsize, volblocksize,
|
volsize = P2ROUNDUP_TYPED(volsize, volblocksize,
|
||||||
uint64_t);
|
uint64_t);
|
||||||
@@ -1207,9 +1064,11 @@ zfs_do_create(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (type == ZFS_TYPE_VOLUME && !noreserve) {
|
if (type == ZFS_TYPE_VOLUME && !noreserve) {
|
||||||
uint64_t spa_version;
|
uint64_t spa_version;
|
||||||
zfs_prop_t resv_prop;
|
zfs_prop_t resv_prop;
|
||||||
|
char *strval;
|
||||||
|
|
||||||
spa_version = zpool_get_prop_int(zpool_handle,
|
spa_version = zpool_get_prop_int(zpool_handle,
|
||||||
ZPOOL_PROP_VERSION, NULL);
|
ZPOOL_PROP_VERSION, NULL);
|
||||||
@@ -1300,11 +1159,6 @@ zfs_do_create(int argc, char **argv)
|
|||||||
log_history = B_FALSE;
|
log_history = B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nomount) {
|
|
||||||
ret = 0;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
|
ret = zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
|
||||||
error:
|
error:
|
||||||
nvlist_free(props);
|
nvlist_free(props);
|
||||||
@@ -4402,7 +4256,6 @@ zfs_do_send(int argc, char **argv)
|
|||||||
|
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
{"replicate", no_argument, NULL, 'R'},
|
{"replicate", no_argument, NULL, 'R'},
|
||||||
{"skip-missing", no_argument, NULL, 's'},
|
|
||||||
{"redact", required_argument, NULL, 'd'},
|
{"redact", required_argument, NULL, 'd'},
|
||||||
{"props", no_argument, NULL, 'p'},
|
{"props", no_argument, NULL, 'p'},
|
||||||
{"parsable", no_argument, NULL, 'P'},
|
{"parsable", no_argument, NULL, 'P'},
|
||||||
@@ -4421,7 +4274,7 @@ zfs_do_send(int argc, char **argv)
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* check options */
|
/* check options */
|
||||||
while ((c = getopt_long(argc, argv, ":i:I:RsDpvnPLeht:cwbd:S",
|
while ((c = getopt_long(argc, argv, ":i:I:RDpvnPLeht:cwbd:S",
|
||||||
long_options, NULL)) != -1) {
|
long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'i':
|
case 'i':
|
||||||
@@ -4438,9 +4291,6 @@ zfs_do_send(int argc, char **argv)
|
|||||||
case 'R':
|
case 'R':
|
||||||
flags.replicate = B_TRUE;
|
flags.replicate = B_TRUE;
|
||||||
break;
|
break;
|
||||||
case 's':
|
|
||||||
flags.skipmissing = B_TRUE;
|
|
||||||
break;
|
|
||||||
case 'd':
|
case 'd':
|
||||||
redactbook = optarg;
|
redactbook = optarg;
|
||||||
break;
|
break;
|
||||||
@@ -4598,23 +4448,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) {
|
|
||||||
(void) fprintf(stderr,
|
|
||||||
gettext("skip-missing flag can only be used in "
|
|
||||||
"conjunction with replicate\n"));
|
|
||||||
usage(B_FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4658,8 +4496,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4736,7 +4572,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);
|
||||||
}
|
}
|
||||||
@@ -6955,6 +6790,9 @@ report_mount_progress(int current, int total)
|
|||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
char info[32];
|
char info[32];
|
||||||
|
|
||||||
|
/* report 1..n instead of 0..n-1 */
|
||||||
|
++current;
|
||||||
|
|
||||||
/* display header if we're here for the first time */
|
/* display header if we're here for the first time */
|
||||||
if (current == 1) {
|
if (current == 1) {
|
||||||
set_progress_header(gettext("Mounting ZFS filesystems"));
|
set_progress_header(gettext("Mounting ZFS filesystems"));
|
||||||
@@ -8532,7 +8370,7 @@ zfs_do_wait(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
boolean_t enabled[ZFS_WAIT_NUM_ACTIVITIES];
|
boolean_t enabled[ZFS_WAIT_NUM_ACTIVITIES];
|
||||||
int error, i;
|
int error, i;
|
||||||
int c;
|
char c;
|
||||||
|
|
||||||
/* By default, wait for all types of activity. */
|
/* By default, wait for all types of activity. */
|
||||||
for (i = 0; i < ZFS_WAIT_NUM_ACTIVITIES; i++)
|
for (i = 0; i < ZFS_WAIT_NUM_ACTIVITIES; i++)
|
||||||
|
|||||||
@@ -7,5 +7,3 @@ zfs_ids_to_path_SOURCES = \
|
|||||||
|
|
||||||
zfs_ids_to_path_LDADD = \
|
zfs_ids_to_path_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzfs/libzfs.la
|
$(abs_top_builddir)/lib/libzfs/libzfs.la
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ libzfs_handle_t *g_zfs;
|
|||||||
static void
|
static void
|
||||||
usage(int err)
|
usage(int err)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: zfs_ids_to_path [-v] <pool> <objset id> "
|
fprintf(stderr, "Usage: [-v] zfs_ids_to_path <pool> <objset id> "
|
||||||
"<object id>\n");
|
"<object id>\n");
|
||||||
exit(err);
|
exit(err);
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ int
|
|||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
boolean_t verbose = B_FALSE;
|
boolean_t verbose = B_FALSE;
|
||||||
int c;
|
char c;
|
||||||
while ((c = getopt(argc, argv, "v")) != -1) {
|
while ((c = getopt(argc, argv, "v")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'v':
|
case 'v':
|
||||||
@@ -63,11 +63,11 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
uint64_t objset, object;
|
uint64_t objset, object;
|
||||||
if (sscanf(argv[1], "%llu", (u_longlong_t *)&objset) != 1) {
|
if (sscanf(argv[1], "%llu", (u_longlong_t *)&objset) != 1) {
|
||||||
(void) fprintf(stderr, "Invalid objset id: %s\n", argv[1]);
|
(void) fprintf(stderr, "Invalid objset id: %s\n", argv[2]);
|
||||||
usage(2);
|
usage(2);
|
||||||
}
|
}
|
||||||
if (sscanf(argv[2], "%llu", (u_longlong_t *)&object) != 1) {
|
if (sscanf(argv[2], "%llu", (u_longlong_t *)&object) != 1) {
|
||||||
(void) fprintf(stderr, "Invalid object id: %s\n", argv[2]);
|
(void) fprintf(stderr, "Invalid object id: %s\n", argv[3]);
|
||||||
usage(3);
|
usage(3);
|
||||||
}
|
}
|
||||||
if ((g_zfs = libzfs_init()) == NULL) {
|
if ((g_zfs = libzfs_init()) == NULL) {
|
||||||
@@ -76,7 +76,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
zpool_handle_t *pool = zpool_open(g_zfs, argv[0]);
|
zpool_handle_t *pool = zpool_open(g_zfs, argv[0]);
|
||||||
if (pool == NULL) {
|
if (pool == NULL) {
|
||||||
fprintf(stderr, "Could not open pool %s\n", argv[0]);
|
fprintf(stderr, "Could not open pool %s\n", argv[1]);
|
||||||
libzfs_fini(g_zfs);
|
libzfs_fini(g_zfs);
|
||||||
return (5);
|
return (5);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
sbin_PROGRAMS = zgenhostid
|
bin_PROGRAMS = zgenhostid
|
||||||
|
|
||||||
zgenhostid_SOURCES = zgenhostid.c
|
zgenhostid_SOURCES = zgenhostid.c
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -127,7 +137,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we need just 4 bytes in native endianness
|
* we need just 4 bytes in native endianess
|
||||||
* not using sethostid() because it may be missing or just a stub
|
* not using sethostid() because it may be missing or just a stub
|
||||||
*/
|
*/
|
||||||
uint32_t hostid = input_i;
|
uint32_t hostid = input_i;
|
||||||
|
|||||||
@@ -12,5 +12,3 @@ zhack_LDADD = \
|
|||||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
$(abs_top_builddir)/lib/libzpool/libzpool.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
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
@@ -150,7 +150,6 @@ zhack_import(char *target, boolean_t readonly)
|
|||||||
zfeature_checks_disable = B_TRUE;
|
zfeature_checks_disable = B_TRUE;
|
||||||
error = spa_import(target, config, props,
|
error = spa_import(target, config, props,
|
||||||
(readonly ? ZFS_IMPORT_SKIP_MMP : ZFS_IMPORT_NORMAL));
|
(readonly ? ZFS_IMPORT_SKIP_MMP : ZFS_IMPORT_NORMAL));
|
||||||
fnvlist_free(config);
|
|
||||||
zfeature_checks_disable = B_FALSE;
|
zfeature_checks_disable = B_FALSE;
|
||||||
if (error == EEXIST)
|
if (error == EEXIST)
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|||||||
@@ -11,5 +11,3 @@ zinject_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
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|||||||
+1
-53
@@ -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)
|
||||||
|
|
||||||
@@ -35,12 +34,10 @@ zpool_LDADD += -lgeom
|
|||||||
endif
|
endif
|
||||||
zpool_LDADD += -lm $(LIBBLKID_LIBS) $(LIBUUID_LIBS)
|
zpool_LDADD += -lm $(LIBBLKID_LIBS) $(LIBUUID_LIBS)
|
||||||
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
|
|
||||||
zpoolconfdir = $(sysconfdir)/zfs/zpool.d
|
zpoolconfdir = $(sysconfdir)/zfs/zpool.d
|
||||||
zpoolexecdir = $(zfsexecdir)/zpool.d
|
zpoolexecdir = $(zfsexecdir)/zpool.d
|
||||||
|
|
||||||
EXTRA_DIST = zpool.d/README compatibility.d
|
EXTRA_DIST = zpool.d/README
|
||||||
|
|
||||||
dist_zpoolexec_SCRIPTS = \
|
dist_zpoolexec_SCRIPTS = \
|
||||||
zpool.d/dm-deps \
|
zpool.d/dm-deps \
|
||||||
@@ -130,52 +127,6 @@ zpoolconfdefaults = \
|
|||||||
test_progress \
|
test_progress \
|
||||||
test_ended
|
test_ended
|
||||||
|
|
||||||
zpoolcompatdir = $(pkgdatadir)/compatibility.d
|
|
||||||
|
|
||||||
dist_zpoolcompat_DATA = \
|
|
||||||
compatibility.d/compat-2018 \
|
|
||||||
compatibility.d/compat-2019 \
|
|
||||||
compatibility.d/compat-2020 \
|
|
||||||
compatibility.d/compat-2021 \
|
|
||||||
compatibility.d/freebsd-11.0 \
|
|
||||||
compatibility.d/freebsd-11.2 \
|
|
||||||
compatibility.d/freebsd-11.3 \
|
|
||||||
compatibility.d/freenas-9.10.2 \
|
|
||||||
compatibility.d/grub2 \
|
|
||||||
compatibility.d/openzfsonosx-1.7.0 \
|
|
||||||
compatibility.d/openzfsonosx-1.8.1 \
|
|
||||||
compatibility.d/openzfsonosx-1.9.3 \
|
|
||||||
compatibility.d/openzfs-2.0-freebsd \
|
|
||||||
compatibility.d/openzfs-2.0-linux \
|
|
||||||
compatibility.d/openzfs-2.1-freebsd \
|
|
||||||
compatibility.d/openzfs-2.1-linux \
|
|
||||||
compatibility.d/zol-0.6.1 \
|
|
||||||
compatibility.d/zol-0.6.4 \
|
|
||||||
compatibility.d/zol-0.6.5 \
|
|
||||||
compatibility.d/zol-0.7 \
|
|
||||||
compatibility.d/zol-0.8
|
|
||||||
|
|
||||||
# canonical <- alias symbolic link pairs
|
|
||||||
# eg: "2018" is a link to "compat-2018"
|
|
||||||
zpoolcompatlinks = \
|
|
||||||
"compat-2018 2018" \
|
|
||||||
"compat-2019 2019" \
|
|
||||||
"compat-2020 2020" \
|
|
||||||
"compat-2021 2021" \
|
|
||||||
"freebsd-11.0 freebsd-11.1" \
|
|
||||||
"freebsd-11.0 freenas-11.0" \
|
|
||||||
"freebsd-11.2 freenas-11.2" \
|
|
||||||
"freebsd-11.3 freebsd-11.4" \
|
|
||||||
"freebsd-11.3 freebsd-12.0" \
|
|
||||||
"freebsd-11.3 freebsd-12.1" \
|
|
||||||
"freebsd-11.3 freebsd-12.2" \
|
|
||||||
"freebsd-11.3 freenas-11.3" \
|
|
||||||
"freenas-11.0 freenas-11.1" \
|
|
||||||
"openzfsonosx-1.9.3 openzfsonosx-1.9.4" \
|
|
||||||
"openzfs-2.0-freebsd truenas-12.0" \
|
|
||||||
"zol-0.7 ubuntu-18.04" \
|
|
||||||
"zol-0.8 ubuntu-20.04"
|
|
||||||
|
|
||||||
install-data-hook:
|
install-data-hook:
|
||||||
$(MKDIR_P) "$(DESTDIR)$(zpoolconfdir)"
|
$(MKDIR_P) "$(DESTDIR)$(zpoolconfdir)"
|
||||||
for f in $(zpoolconfdefaults); do \
|
for f in $(zpoolconfdefaults); do \
|
||||||
@@ -183,6 +134,3 @@ install-data-hook:
|
|||||||
-L "$(DESTDIR)$(zpoolconfdir)/$${f}" || \
|
-L "$(DESTDIR)$(zpoolconfdir)/$${f}" || \
|
||||||
ln -s "$(zpoolexecdir)/$${f}" "$(DESTDIR)$(zpoolconfdir)"; \
|
ln -s "$(zpoolexecdir)/$${f}" "$(DESTDIR)$(zpoolconfdir)"; \
|
||||||
done
|
done
|
||||||
for l in $(zpoolcompatlinks); do \
|
|
||||||
(cd "$(DESTDIR)$(zpoolcompatdir)"; ln -sf $${l} ); \
|
|
||||||
done
|
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# Features supported by all Tier 1 platforms as of 2018
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Features supported by all Tier 1 platforms as of 2019
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Features supported by all Tier 1 platforms as of 2020
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Features supported by all Tier 1 platforms as of 2021
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
device_removal
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
zpool_checkpoint
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Features supported by FreeBSD 11.0
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Features supported by FreeBSD 11.2
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
device_removal
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
zpool_checkpoint
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Features supported by FreeBSD 11.3
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
device_removal
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
zpool_checkpoint
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Features supported by FreeNAS 9.10.2
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Features which are supported by GRUB2
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Features supported by OpenZFS 2.0 on FreeBSD
|
|
||||||
allocation_classes
|
|
||||||
async_destroy
|
|
||||||
bookmark_v2
|
|
||||||
bookmark_written
|
|
||||||
bookmarks
|
|
||||||
device_rebuild
|
|
||||||
device_removal
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
encryption
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
large_dnode
|
|
||||||
livelist
|
|
||||||
log_spacemap
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
project_quota
|
|
||||||
redacted_datasets
|
|
||||||
redaction_bookmarks
|
|
||||||
resilver_defer
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
userobj_accounting
|
|
||||||
zpool_checkpoint
|
|
||||||
zstd_compress
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Features supported by OpenZFS 2.0 on Linux
|
|
||||||
allocation_classes
|
|
||||||
async_destroy
|
|
||||||
bookmark_v2
|
|
||||||
bookmark_written
|
|
||||||
bookmarks
|
|
||||||
device_rebuild
|
|
||||||
device_removal
|
|
||||||
edonr
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
encryption
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
large_dnode
|
|
||||||
livelist
|
|
||||||
log_spacemap
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
project_quota
|
|
||||||
redacted_datasets
|
|
||||||
redaction_bookmarks
|
|
||||||
resilver_defer
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
userobj_accounting
|
|
||||||
zpool_checkpoint
|
|
||||||
zstd_compress
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Features supported by OpenZFS 2.1 on FreeBSD
|
|
||||||
allocation_classes
|
|
||||||
async_destroy
|
|
||||||
bookmark_v2
|
|
||||||
bookmark_written
|
|
||||||
bookmarks
|
|
||||||
device_rebuild
|
|
||||||
device_removal
|
|
||||||
draid
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
encryption
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
large_dnode
|
|
||||||
livelist
|
|
||||||
log_spacemap
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
project_quota
|
|
||||||
redacted_datasets
|
|
||||||
redaction_bookmarks
|
|
||||||
resilver_defer
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
userobj_accounting
|
|
||||||
zpool_checkpoint
|
|
||||||
zstd_compress
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Features supported by OpenZFS 2.1 on Linux
|
|
||||||
allocation_classes
|
|
||||||
async_destroy
|
|
||||||
bookmark_v2
|
|
||||||
bookmark_written
|
|
||||||
bookmarks
|
|
||||||
device_rebuild
|
|
||||||
device_removal
|
|
||||||
draid
|
|
||||||
edonr
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
encryption
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
large_dnode
|
|
||||||
livelist
|
|
||||||
log_spacemap
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
project_quota
|
|
||||||
redacted_datasets
|
|
||||||
redaction_bookmarks
|
|
||||||
resilver_defer
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
userobj_accounting
|
|
||||||
zpool_checkpoint
|
|
||||||
zstd_compress
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Features supported by OpenZFSonOSX 1.7.0
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
edonr
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# Features supported by OpenZFSonOSX 1.8.1
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
device_removal
|
|
||||||
edonr
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
encryption
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
zpool_checkpoint
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Features supported by OpenZFSonOSX 1.9.3
|
|
||||||
allocation_classes
|
|
||||||
async_destroy
|
|
||||||
bookmark_v2
|
|
||||||
bookmarks
|
|
||||||
device_removal
|
|
||||||
edonr
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
encryption
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
large_dnode
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
project_quota
|
|
||||||
resilver_defer
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
userobj_accounting
|
|
||||||
zpool_checkpoint
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Features supported by ZFSonLinux v0.6.1
|
|
||||||
async_destroy
|
|
||||||
empty_bpobj
|
|
||||||
lz4_compress
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Features supported by ZFSonLinux v0.6.4
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
hole_birth
|
|
||||||
lz4_compress
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Features supported by ZFSonLinux v0.6.5
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
lz4_compress
|
|
||||||
spacemap_histogram
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Features supported by ZFSonLinux v0.7
|
|
||||||
async_destroy
|
|
||||||
bookmarks
|
|
||||||
edonr
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
large_dnode
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
userobj_accounting
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Features supported by ZFSonLinux v0.8
|
|
||||||
allocation_classes
|
|
||||||
async_destroy
|
|
||||||
bookmark_v2
|
|
||||||
bookmarks
|
|
||||||
device_removal
|
|
||||||
edonr
|
|
||||||
embedded_data
|
|
||||||
empty_bpobj
|
|
||||||
enabled_txg
|
|
||||||
encryption
|
|
||||||
extensible_dataset
|
|
||||||
filesystem_limits
|
|
||||||
hole_birth
|
|
||||||
large_blocks
|
|
||||||
large_dnode
|
|
||||||
lz4_compress
|
|
||||||
multi_vdev_crash_dump
|
|
||||||
obsolete_counts
|
|
||||||
project_quota
|
|
||||||
resilver_defer
|
|
||||||
sha512
|
|
||||||
skein
|
|
||||||
spacemap_histogram
|
|
||||||
spacemap_v2
|
|
||||||
userobj_accounting
|
|
||||||
zpool_checkpoint
|
|
||||||
@@ -101,18 +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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -79,6 +79,9 @@
|
|||||||
|
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <scsi/sg.h>
|
#include <scsi/sg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/efi_partition.h>
|
#include <sys/efi_partition.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/vtoc.h>
|
#include <sys/vtoc.h>
|
||||||
@@ -405,8 +408,3 @@ check_device(const char *path, boolean_t force,
|
|||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
after_zpool_upgrade(zpool_handle_t *zhp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+5
-10
@@ -494,25 +494,19 @@ vdev_run_cmd(vdev_cmd_data_t *data, char *cmd)
|
|||||||
/* Setup our custom environment variables */
|
/* Setup our custom environment variables */
|
||||||
rc = asprintf(&env[1], "VDEV_PATH=%s",
|
rc = asprintf(&env[1], "VDEV_PATH=%s",
|
||||||
data->path ? data->path : "");
|
data->path ? data->path : "");
|
||||||
if (rc == -1) {
|
if (rc == -1)
|
||||||
env[1] = NULL;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
rc = asprintf(&env[2], "VDEV_UPATH=%s",
|
rc = asprintf(&env[2], "VDEV_UPATH=%s",
|
||||||
data->upath ? data->upath : "");
|
data->upath ? data->upath : "");
|
||||||
if (rc == -1) {
|
if (rc == -1)
|
||||||
env[2] = NULL;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
rc = asprintf(&env[3], "VDEV_ENC_SYSFS_PATH=%s",
|
rc = asprintf(&env[3], "VDEV_ENC_SYSFS_PATH=%s",
|
||||||
data->vdev_enc_sysfs_path ?
|
data->vdev_enc_sysfs_path ?
|
||||||
data->vdev_enc_sysfs_path : "");
|
data->vdev_enc_sysfs_path : "");
|
||||||
if (rc == -1) {
|
if (rc == -1)
|
||||||
env[3] = NULL;
|
|
||||||
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,
|
||||||
@@ -531,7 +525,8 @@ out:
|
|||||||
|
|
||||||
/* Start with i = 1 since env[0] was statically allocated */
|
/* Start with i = 1 since env[0] was statically allocated */
|
||||||
for (i = 1; i < ARRAY_SIZE(env); i++)
|
for (i = 1; i < ARRAY_SIZE(env); i++)
|
||||||
free(env[i]);
|
if (env[i] != NULL)
|
||||||
|
free(env[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+178
-570
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user