mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 19:28:53 +03:00
Compare commits
523 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 52bad4f23d | |||
| 2b8b89c6b3 | |||
| 90abfdf8ee | |||
| 847d03060f | |||
| 9e3619c535 | |||
| 421750672b | |||
| 275c756730 | |||
| 0bebcbcf5e | |||
| 7b215d93bc | |||
| ef83e07db5 | |||
| 145af480d3 | |||
| b3b6491ce9 | |||
| b3427b18b1 | |||
| 0e2bb1a3ee | |||
| 037434e4fc | |||
| 190516f0c5 | |||
| e2fddf07bd | |||
| 4cb88d7fdc | |||
| ddcdccbcc4 | |||
| f2eaa97840 | |||
| 7bd292e59b | |||
| 5c80a25653 | |||
| 1d70698174 | |||
| b55ed8df92 | |||
| bcddb18bae | |||
| 6c6153e5b8 | |||
| 336c6d5f54 | |||
| 4b3fbf3c16 | |||
| 02309af096 | |||
| 94a4b7ec3d | |||
| ccbe9efd6b | |||
| 882bc4ad61 | |||
| f4c2b21823 | |||
| d24bdf4ee4 | |||
| 11bd8cd002 | |||
| a38e7bc922 | |||
| d4e8dcf07e | |||
| f03cf651ec | |||
| bc99c809d5 | |||
| 5c19af07d4 | |||
| 2681f8a5b8 | |||
| c7fcf00917 | |||
| 52aae04c6a | |||
| 77ae804f9e | |||
| 3b52ccd7d7 | |||
| bb271d67e8 | |||
| a61915e086 | |||
| 765be36006 | |||
| 0cb2d8a60b | |||
| 745a7f78da | |||
| d6b7903032 | |||
| cd0e238049 | |||
| 3e27b589cf | |||
| 9221ff1888 | |||
| 72a82f312f | |||
| 5753e7a7c5 | |||
| 7f4f461bcf | |||
| f601ee1e43 | |||
| 5987838a3f | |||
| 8285e1b09d | |||
| c454e46336 | |||
| 306cccca27 | |||
| 4730c3f249 | |||
| 4fea6a6737 | |||
| fc3230a781 | |||
| ed064ed596 | |||
| 74bba85423 | |||
| f22ebf8fa6 | |||
| 1fb5566a25 | |||
| be01ee8629 | |||
| efbed102f0 | |||
| 19a4bf445f | |||
| f9baf968b8 | |||
| 9cbc2ed20f | |||
| 9b185de6fa | |||
| 4d4f0d1a05 | |||
| 687de107b7 | |||
| 2e3b3e3a2e | |||
| a35125e3d5 | |||
| fe8b0a33d4 | |||
| d4794c8204 | |||
| 29e05d5345 | |||
| f471a0a0a7 | |||
| d76917b2ec | |||
| 487bb77623 | |||
| f31b45176c | |||
| 4613504809 | |||
| 44bb2fcf38 | |||
| e56dffe4b5 | |||
| e257bd481b | |||
| 1009e60992 | |||
| 4f6599416a | |||
| f42c126029 | |||
| 2ce06d93a8 | |||
| 8ef01afbfc | |||
| 70b7b1975d | |||
| c31c1146b6 | |||
| b3e0853951 | |||
| 0da15f9194 | |||
| 5303fc4c95 | |||
| 4aceda0497 | |||
| ddb5a7a182 | |||
| af1630c883 | |||
| 1828b68a0b | |||
| f4def7ec6c | |||
| c9c9d634aa | |||
| 36a91d6cef | |||
| 1259dc6e6a | |||
| 6575defc52 | |||
| 5d8c081193 | |||
| 14bf91a043 | |||
| 1833de8103 | |||
| a1a52a356b | |||
| 9ec630ff2c | |||
| 4b2bac5fe9 | |||
| 786abf5321 | |||
| 913ae45218 | |||
| af88d47f1e | |||
| 24221589dd | |||
| def73c0735 | |||
| effe984148 | |||
| 19337332cc | |||
| b96737b83e | |||
| 4b7bfcf8a0 | |||
| 07165ce540 | |||
| 6ed7d77b44 | |||
| 64e88992b6 | |||
| ad15fb430a | |||
| 57f6a050e6 | |||
| b3b293c9fc | |||
| bef7c02c81 | |||
| ea61e07413 | |||
| 9519fe1ff8 | |||
| 0c40ff56f2 | |||
| 806c3777e7 | |||
| ac9b1aa1bf | |||
| e20186f5d5 | |||
| 16da688f25 | |||
| e9ee57f682 | |||
| d346361515 | |||
| 12d27e7134 | |||
| a1a29bf8fc | |||
| ea0dda5999 | |||
| d7e640cf95 | |||
| 664d487a5d | |||
| 5bf81fea2f | |||
| 1fca958615 | |||
| 22b0891dbb | |||
| 0e537a0195 | |||
| db9e1c907a | |||
| d11b03ed81 | |||
| 586b5d366e | |||
| 27d9c6ae2b | |||
| b7ecb4ff0d | |||
| af9aa4a216 | |||
| 55ab3773d7 | |||
| 143476ce8d | |||
| d8a97a7be2 | |||
| 8cd9f20a34 | |||
| 71c6098526 | |||
| a3da79d582 | |||
| bb80b4649a | |||
| 7816a6b85b | |||
| 9183321501 | |||
| 32512acbc0 | |||
| cea0752f8d | |||
| 7d70f1e099 | |||
| fd92825445 | |||
| 7bf68e9806 | |||
| ad8dc99ed2 | |||
| 6ca1f30708 | |||
| e16e05c9cf | |||
| 5331e2d216 | |||
| d6dae00982 | |||
| 993d4b28af | |||
| 004e7d3f9a | |||
| aef8a72afe | |||
| 81611683c8 | |||
| 72a989cf60 | |||
| 6bb6410570 | |||
| 6c3c7dc846 | |||
| 2904ec57f0 | |||
| bc371b2806 | |||
| e78d06f89b | |||
| 2016d7fb9c | |||
| 584b7a214e | |||
| 1655ce5619 | |||
| 5de6e4ec94 | |||
| a4862125b8 | |||
| 61773f41b8 | |||
| 40e02f49e9 | |||
| c600f0687f | |||
| 5afc35b698 | |||
| c6c0d30016 | |||
| 24e51e3749 | |||
| 744f3009fc | |||
| cacc48702b | |||
| cc55271681 | |||
| 477edd642c | |||
| 23184b172a | |||
| 32a971e749 | |||
| c07ed69577 | |||
| ddb732e2c8 | |||
| 451d6da988 | |||
| e298ac5d04 | |||
| 9429910781 | |||
| 8a969f3e2d | |||
| 898b1e173c | |||
| 406534f807 | |||
| ac573e3105 | |||
| 99df200ffc | |||
| bd910fdeb0 | |||
| 9cc9821014 | |||
| fceda40c1e | |||
| 4434baab11 | |||
| 6385f4e70e | |||
| 2f073cc9c6 | |||
| 729eb48666 | |||
| 93e11e257b | |||
| eaa10257ca | |||
| 32c0b6468c | |||
| 7c61e1ef9d | |||
| 6a49948c73 | |||
| 4dfb698aac | |||
| 4affa09f3e | |||
| 0ca9558561 | |||
| c2c4d05700 | |||
| f8c2e91db5 | |||
| 056c273939 | |||
| ba76bb30a6 | |||
| 968dc13572 | |||
| 960a5a557b | |||
| 45305a067f | |||
| a5e68f0478 | |||
| 8415c3c170 | |||
| 04ebe29188 | |||
| a0b4da2297 | |||
| c84670950a | |||
| 49bb454120 | |||
| 41b33dce44 | |||
| dab147d65a | |||
| 7138fe7205 | |||
| fd2e4d143d | |||
| 0cb122941e | |||
| c20ba9bd7a | |||
| 15177c1aac | |||
| 035219ee10 | |||
| 2334bc4efa | |||
| d6c2b89032 | |||
| f3969ea78b | |||
| 6fe6192796 | |||
| 1826068523 | |||
| 4f92fe0f5c | |||
| 508fff0e4b | |||
| d3942963ee | |||
| 0584ad8f94 | |||
| ea47857090 | |||
| 4ebda5d4d3 | |||
| 57ce66d293 | |||
| da6c288dfc | |||
| aee26af277 | |||
| 620389d32f | |||
| 5d7f47d828 | |||
| 977540168c | |||
| 1143d3d29d | |||
| 088712793e | |||
| e0886c96a8 | |||
| 5e89181544 | |||
| dfbda2465f | |||
| 6b239d1757 | |||
| 9a865b7fb7 | |||
| 3de7aeb68a | |||
| ff64096e75 | |||
| 7e2212990b | |||
| bd83c1e0c6 | |||
| a416b29e16 | |||
| af4b6f7dab | |||
| c3b60ededa | |||
| 57196f8ae9 | |||
| 8dc540ae16 | |||
| efdfb14fc8 | |||
| 2e158b0e0b | |||
| 4cf3e48a3b | |||
| 4e0fff2e02 | |||
| 14973b917c | |||
| a444efb6d7 | |||
| 0bef46e6d5 | |||
| 1180d61152 | |||
| 6ce97bb4a2 | |||
| 27d3cc6cd3 | |||
| d6a0cecab1 | |||
| 2c3d7283b4 | |||
| d7e6f293da | |||
| 2f23f0f940 | |||
| a377bde727 | |||
| e76373de7b | |||
| b05ae1a82a | |||
| b12a6d961c | |||
| 11b165cc9b | |||
| 2dde9202d9 | |||
| 998035d534 | |||
| 64e38df237 | |||
| d3dddbaa20 | |||
| e298695809 | |||
| c650ceb64d | |||
| 13c9a41140 | |||
| af80160f48 | |||
| db9048741b | |||
| b1b1faf0f1 | |||
| 2fe8060cee | |||
| 6e01b47a28 | |||
| cc9dae2404 | |||
| 1fb18c4bde | |||
| a0c055cfd3 | |||
| 91bb2e91bd | |||
| 132240507d | |||
| d6f8f41c21 | |||
| 2f5c39137a | |||
| 90d0023005 | |||
| dbfbc1e524 | |||
| a61c502907 | |||
| f2e890ddfa | |||
| 71f6e6480e | |||
| a1b1007e95 | |||
| 01918aa3f4 | |||
| e1ae0c4b99 | |||
| 475ee3bc2b | |||
| f6ce806298 | |||
| ea034765b4 | |||
| 9d7c10388a | |||
| f67a920a6d | |||
| 5c7c2b1301 | |||
| 5d08b105a2 | |||
| 55b6d4a3d8 | |||
| a0372059b1 | |||
| 68a310dc45 | |||
| 8ed04625db | |||
| c3c65e3cfb | |||
| eb9d335009 | |||
| 85c43508f3 | |||
| 09c0a8fd1a | |||
| ec3b25825e | |||
| 0382362ce0 | |||
| 0458070928 | |||
| 1fc5f8cbfd | |||
| 263b3d64ab | |||
| c1a64be6d4 | |||
| e40ffed021 | |||
| 59d91b4d10 | |||
| d53a6969c1 | |||
| 019739b6e9 | |||
| 7d9f3ef0ef | |||
| 0a01f36b69 | |||
| 9e06df8ab0 | |||
| 57e3b9c3cc | |||
| 605b901ca6 | |||
| c5f268fa14 | |||
| bc7792cad2 | |||
| f3222062c0 | |||
| 6316086b72 | |||
| 7cdd4dd33b | |||
| a7bb2dab4e | |||
| ecebf770c1 | |||
| aa4a84e616 | |||
| cc1c7b0171 | |||
| fa7ee48e10 | |||
| d6bedbbc44 | |||
| ab6717cba6 | |||
| 33a06f27e6 | |||
| 7ad8fc5407 | |||
| 272b178d52 | |||
| 8f3584292f | |||
| 289b1393a4 | |||
| ec75f80a50 | |||
| c2c02e490f | |||
| 793dffb04e | |||
| faa5673982 | |||
| ade8e4b7d6 | |||
| 1a7bad542b | |||
| 17351a79e2 | |||
| 1cb517aebd | |||
| cb2e336038 | |||
| 381a0ca1e8 | |||
| f7a69b93c6 | |||
| 8f6e2b5485 | |||
| 14b56624c8 | |||
| 214ae461f1 | |||
| 12ed5275d1 | |||
| 133fd00930 | |||
| 74256266ff | |||
| 2085a5f992 | |||
| b1dd6351bb | |||
| cb18cf6b0a | |||
| 6c25218c7e | |||
| 0bb2a48ee6 | |||
| f15ec889a9 | |||
| 0db64e9036 | |||
| 85071b2ff5 | |||
| 1a0ce3d5ef | |||
| 08d2e39719 | |||
| f87f41009f | |||
| 918e5c6fca | |||
| 9c5256a2fe | |||
| 39bcdd8d74 | |||
| 075dcad351 | |||
| 5701e393b7 | |||
| 910b43310f | |||
| 4ac37f8b2e | |||
| 6f2012c1dc | |||
| 96f04062e4 | |||
| a7a579e6e1 | |||
| 463d7e1a61 | |||
| 6c1a7be11e | |||
| 1b7d883eaa | |||
| e5c01296ff | |||
| 64b83a0bf1 | |||
| 8fd65351a7 | |||
| 79d9f663b0 | |||
| 478b8ec8f2 | |||
| 219acd907b | |||
| cc33149e5a | |||
| 40abc63c40 | |||
| cdc27fd061 | |||
| 121a34e36b | |||
| dfa2beddea | |||
| 14a1980b35 | |||
| 9747310cc1 | |||
| 0b10994cea | |||
| 692387343f | |||
| 8d869cd840 | |||
| ae8dd6676b | |||
| d938c6ee27 | |||
| dc4d55268c | |||
| bdcf0cca10 | |||
| 7be4669a65 | |||
| e5c4f86e7a | |||
| 4c925936e3 | |||
| 15d3470c2e | |||
| 55cf5a255a | |||
| d682e20ba4 | |||
| 9c470dc6c0 | |||
| 7616fc7971 | |||
| 7bf3959601 | |||
| 25cd7b520d | |||
| 4a30a0b947 | |||
| ecd6ad66b0 | |||
| 2aa0d643fd | |||
| a6b82cc0bb | |||
| 4568b5cfba | |||
| ffc2e74f79 | |||
| 8b03fce289 | |||
| 1f3de97374 | |||
| 7de1797cee | |||
| 44ccb1d20f | |||
| dfd3015048 | |||
| 4a9b29375e | |||
| 2453d0263d | |||
| ab88e9e264 | |||
| 54aaed5c45 | |||
| aa52015d45 | |||
| 5faeaa1365 | |||
| 17792783d0 | |||
| 07d64c07e0 | |||
| f8631d0fe0 | |||
| afe2a5ca12 | |||
| 2a667acfcb | |||
| 5f3f4def83 | |||
| 8bc955f546 | |||
| b3bb604a4c | |||
| 2ae2892235 | |||
| 9d47853c74 | |||
| 30f5b2fbe2 | |||
| ad34215364 | |||
| 1eee2c7b27 | |||
| f17d146ca6 | |||
| a35cadcf14 | |||
| 72a9750ac8 | |||
| 7822c01eb6 | |||
| 96e15d29fa | |||
| bb8db9d927 | |||
| 32cc3f0837 | |||
| f96dbd7a29 | |||
| c30fef2523 | |||
| 487cd2df11 | |||
| 5a674a1b42 | |||
| 52f65648e0 | |||
| 55780d8ec0 | |||
| b3a7e6e7f3 | |||
| ea30225fdb | |||
| 018560b153 | |||
| 48b60cffda | |||
| cb97db792e | |||
| 718ee43362 | |||
| 01219379cf | |||
| 0a51083e39 | |||
| b73e40a5ad | |||
| fa991f2a47 | |||
| dbf8baf8dd | |||
| 9160c441a4 | |||
| 84c1652a0a | |||
| 7474d775c7 | |||
| 506ffdf648 | |||
| 0bf91beab9 | |||
| 04344d5bc3 | |||
| 46aec6d439 | |||
| 1bb4b5a5ae | |||
| 71a3487a89 | |||
| 2aed1ab13d | |||
| d09e1c1343 | |||
| e2f5074c0f | |||
| ca7af7f675 | |||
| 35cce6ea63 | |||
| d539b77934 | |||
| 202e7545dc | |||
| 003f2d04b6 | |||
| ec311430e2 | |||
| 895d39aa83 | |||
| 7f789e150f | |||
| 917f4b334c | |||
| 6613ea3b33 | |||
| e783fa0925 | |||
| dc52c0d725 | |||
| bfdd001679 |
-21
@@ -1,21 +0,0 @@
|
|||||||
env:
|
|
||||||
CIRRUS_CLONE_DEPTH: 1
|
|
||||||
ARCH: amd64
|
|
||||||
|
|
||||||
build_task:
|
|
||||||
matrix:
|
|
||||||
freebsd_instance:
|
|
||||||
image_family: freebsd-12-4
|
|
||||||
freebsd_instance:
|
|
||||||
image_family: freebsd-13-2
|
|
||||||
freebsd_instance:
|
|
||||||
image_family: freebsd-14-0-snap
|
|
||||||
prepare_script:
|
|
||||||
- pkg install -y autoconf automake libtool gettext-runtime gmake ksh93 py39-packaging py39-cffi py39-sysctl
|
|
||||||
configure_script:
|
|
||||||
- env MAKE=gmake ./autogen.sh
|
|
||||||
- env MAKE=gmake ./configure --with-config="user" --with-python=3.9
|
|
||||||
build_script:
|
|
||||||
- gmake -j `sysctl -n kern.smp.cpus`
|
|
||||||
install_script:
|
|
||||||
- gmake install
|
|
||||||
+11
-7
@@ -145,18 +145,22 @@ Once everything is in good shape and the details have been worked out you can re
|
|||||||
Any required reviews can then be finalized and the pull request merged.
|
Any required reviews can then be finalized and the pull request merged.
|
||||||
|
|
||||||
#### Tests and Benchmarks
|
#### Tests and Benchmarks
|
||||||
* Every pull request is tested using a GitHub Actions workflow on multiple platforms by running the [zfs-tests.sh and zloop.sh](
|
* Every pull request will by tested by the buildbot on multiple platforms by running the [zfs-tests.sh and zloop.sh](
|
||||||
https://openzfs.github.io/openzfs-docs/Developer%20Resources/Building%20ZFS.html#running-zloop-sh-and-zfs-tests-sh) test suites.
|
https://openzfs.github.io/openzfs-docs/Developer%20Resources/Building%20ZFS.html#running-zloop-sh-and-zfs-tests-sh) test suites.
|
||||||
`.github/workflows/scripts/generate-ci-type.py` is used to determine whether the pull request is nonbehavior, i.e., not introducing behavior changes of any code, configuration or tests. If so, the CI will run on fewer platforms and only essential sanity tests will run. You can always override this by adding `ZFS-CI-Type` line to your commit message:
|
|
||||||
* If your last commit (or `HEAD` in git terms) contains a line `ZFS-CI-Type: quick`, quick mode is forced regardless of what files are changed.
|
|
||||||
* Otherwise, if any commit in a PR contains a line `ZFS-CI-Type: full`, full mode is forced.
|
|
||||||
* To verify your changes conform to the [style guidelines](
|
* To verify your changes conform to the [style guidelines](
|
||||||
https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md#style-guides
|
https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md#style-guides
|
||||||
), please run `make checkstyle` and resolve any warnings.
|
), please run `make checkstyle` and resolve any warnings.
|
||||||
* Code analysis is performed by [CodeQL](https://codeql.github.com/) for each pull request.
|
* Static code analysis of each pull request is performed by the buildbot; run `make lint` to check your changes.
|
||||||
* Test cases should be provided when appropriate. This includes making sure new features have adequate code coverage.
|
* Test cases should be provided when appropriate.
|
||||||
|
This includes making sure new features have adequate code coverage.
|
||||||
* If your pull request improves performance, please include some benchmarks.
|
* If your pull request improves performance, please include some benchmarks.
|
||||||
* The pull request must pass all CI checks before being accepted.
|
* The pull request must pass all required [ZFS
|
||||||
|
Buildbot](http://build.zfsonlinux.org/) builders before
|
||||||
|
being accepted. If you are experiencing intermittent TEST
|
||||||
|
builder failures, you may be experiencing a [test suite
|
||||||
|
issue](https://github.com/openzfs/zfs/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Test+Suite%22).
|
||||||
|
There are also various [buildbot options](https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.html)
|
||||||
|
to control how changes are tested.
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
All help is appreciated! If you're in a position to run the latest code
|
All help is appreciated! If you're in a position to run the latest code
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
name: "Custom CodeQL Analysis"
|
|
||||||
|
|
||||||
queries:
|
|
||||||
- uses: ./.github/codeql/custom-queries/cpp/deprecatedFunctionUsage.ql
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
name: "Custom CodeQL Analysis"
|
|
||||||
|
|
||||||
paths-ignore:
|
|
||||||
- tests
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/**
|
|
||||||
* @name Deprecated function usage detection
|
|
||||||
* @description Detects functions whose usage is banned from the OpenZFS
|
|
||||||
* codebase due to QA concerns.
|
|
||||||
* @kind problem
|
|
||||||
* @severity error
|
|
||||||
* @id cpp/deprecated-function-usage
|
|
||||||
*/
|
|
||||||
|
|
||||||
import cpp
|
|
||||||
|
|
||||||
predicate isDeprecatedFunction(Function f) {
|
|
||||||
f.getName() = "strtok" or
|
|
||||||
f.getName() = "__xpg_basename" or
|
|
||||||
f.getName() = "basename" or
|
|
||||||
f.getName() = "dirname" or
|
|
||||||
f.getName() = "bcopy" or
|
|
||||||
f.getName() = "bcmp" or
|
|
||||||
f.getName() = "bzero" or
|
|
||||||
f.getName() = "asctime" or
|
|
||||||
f.getName() = "asctime_r" or
|
|
||||||
f.getName() = "gmtime" or
|
|
||||||
f.getName() = "localtime" or
|
|
||||||
f.getName() = "strncpy"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
string getReplacementMessage(Function f) {
|
|
||||||
if f.getName() = "strtok" then
|
|
||||||
result = "Use strtok_r(3) instead!"
|
|
||||||
else if f.getName() = "__xpg_basename" then
|
|
||||||
result = "basename(3) is underspecified. Use zfs_basename() instead!"
|
|
||||||
else if f.getName() = "basename" then
|
|
||||||
result = "basename(3) is underspecified. Use zfs_basename() instead!"
|
|
||||||
else if f.getName() = "dirname" then
|
|
||||||
result = "dirname(3) is underspecified. Use zfs_dirnamelen() instead!"
|
|
||||||
else if f.getName() = "bcopy" then
|
|
||||||
result = "bcopy(3) is deprecated. Use memcpy(3)/memmove(3) instead!"
|
|
||||||
else if f.getName() = "bcmp" then
|
|
||||||
result = "bcmp(3) is deprecated. Use memcmp(3) instead!"
|
|
||||||
else if f.getName() = "bzero" then
|
|
||||||
result = "bzero(3) is deprecated. Use memset(3) instead!"
|
|
||||||
else if f.getName() = "asctime" then
|
|
||||||
result = "Use strftime(3) instead!"
|
|
||||||
else if f.getName() = "asctime_r" then
|
|
||||||
result = "Use strftime(3) instead!"
|
|
||||||
else if f.getName() = "gmtime" then
|
|
||||||
result = "gmtime(3) isn't thread-safe. Use gmtime_r(3) instead!"
|
|
||||||
else if f.getName() = "localtime" then
|
|
||||||
result = "localtime(3) isn't thread-safe. Use localtime_r(3) instead!"
|
|
||||||
else
|
|
||||||
result = "strncpy(3) is deprecated. Use strlcpy(3) instead!"
|
|
||||||
}
|
|
||||||
|
|
||||||
from FunctionCall fc, Function f
|
|
||||||
where
|
|
||||||
fc.getTarget() = f and
|
|
||||||
isDeprecatedFunction(f)
|
|
||||||
select fc, getReplacementMessage(f)
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
name: openzfs-cpp-queries
|
|
||||||
version: 0.0.0
|
|
||||||
libraryPathDependencies: codeql-cpp
|
|
||||||
suites: openzfs-cpp-suite
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
|
|
||||||
## The testings are done this way
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
flowchart TB
|
|
||||||
subgraph CleanUp and Summary
|
|
||||||
CleanUp+Summary
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph Functional Testings
|
|
||||||
sanity-checks-20.04
|
|
||||||
zloop-checks-20.04
|
|
||||||
functional-testing-20.04-->Part1-20.04
|
|
||||||
functional-testing-20.04-->Part2-20.04
|
|
||||||
functional-testing-20.04-->Part3-20.04
|
|
||||||
functional-testing-20.04-->Part4-20.04
|
|
||||||
functional-testing-22.04-->Part1-22.04
|
|
||||||
functional-testing-22.04-->Part2-22.04
|
|
||||||
functional-testing-22.04-->Part3-22.04
|
|
||||||
functional-testing-22.04-->Part4-22.04
|
|
||||||
sanity-checks-22.04
|
|
||||||
zloop-checks-22.04
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph Code Checking + Building
|
|
||||||
Build-Ubuntu-20.04
|
|
||||||
codeql.yml
|
|
||||||
checkstyle.yml
|
|
||||||
Build-Ubuntu-22.04
|
|
||||||
end
|
|
||||||
|
|
||||||
Build-Ubuntu-20.04-->sanity-checks-20.04
|
|
||||||
Build-Ubuntu-20.04-->zloop-checks-20.04
|
|
||||||
Build-Ubuntu-20.04-->functional-testing-20.04
|
|
||||||
Build-Ubuntu-22.04-->sanity-checks-22.04
|
|
||||||
Build-Ubuntu-22.04-->zloop-checks-22.04
|
|
||||||
Build-Ubuntu-22.04-->functional-testing-22.04
|
|
||||||
|
|
||||||
sanity-checks-20.04-->CleanUp+Summary
|
|
||||||
Part1-20.04-->CleanUp+Summary
|
|
||||||
Part2-20.04-->CleanUp+Summary
|
|
||||||
Part3-20.04-->CleanUp+Summary
|
|
||||||
Part4-20.04-->CleanUp+Summary
|
|
||||||
Part1-22.04-->CleanUp+Summary
|
|
||||||
Part2-22.04-->CleanUp+Summary
|
|
||||||
Part3-22.04-->CleanUp+Summary
|
|
||||||
Part4-22.04-->CleanUp+Summary
|
|
||||||
sanity-checks-22.04-->CleanUp+Summary
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
1) build zfs modules for Ubuntu 20.04 and 22.04 (~15m)
|
|
||||||
2) 2x zloop test (~10m) + 2x sanity test (~25m)
|
|
||||||
3) 4x functional testings in parts 1..4 (each ~1h)
|
|
||||||
4) cleanup and create summary
|
|
||||||
- content of summary depends on the results of the steps
|
|
||||||
|
|
||||||
When everything runs fine, the full run should be done in
|
|
||||||
about 2 hours.
|
|
||||||
|
|
||||||
The codeql.yml and checkstyle.yml are not part in this circle.
|
|
||||||
@@ -4,60 +4,46 @@ on:
|
|||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
checkstyle:
|
checkstyle:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
# for x in lxd core20 snapd; do sudo snap remove $x; done
|
sudo apt-get update
|
||||||
sudo apt-get purge -y snapd google-chrome-stable firefox
|
sudo apt-get install --yes -qq build-essential autoconf libtool gawk alien fakeroot linux-headers-$(uname -r)
|
||||||
ONLY_DEPS=1 .github/workflows/scripts/qemu-3-deps.sh ubuntu22
|
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 -y cppcheck devscripts mandoc pax-utils shellcheck
|
# packages for tests
|
||||||
sudo python -m pipx install --quiet flake8
|
sudo apt-get install --yes -qq parted lsscsi ksh attr acl nfs-kernel-server fio
|
||||||
# confirm that the tools are installed
|
sudo apt-get install --yes -qq mandoc cppcheck pax-utils devscripts
|
||||||
# the build system doesn't fail when they are not
|
sudo -E pip --quiet install flake8
|
||||||
checkbashisms --version
|
|
||||||
cppcheck --version
|
|
||||||
flake8 --version
|
|
||||||
scanelf --version
|
|
||||||
shellcheck --version
|
|
||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
sed -i '/DEBUG_CFLAGS="-Werror"/s/^/#/' config/zfs-build.m4
|
sh ./autogen.sh
|
||||||
./autogen.sh
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./configure
|
./configure
|
||||||
- name: Make
|
make -j$(nproc)
|
||||||
run: |
|
|
||||||
make -j$(nproc) --no-print-directory --silent
|
|
||||||
- name: Checkstyle
|
- name: Checkstyle
|
||||||
run: |
|
run: |
|
||||||
make -j$(nproc) --no-print-directory --silent checkstyle
|
make checkstyle
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: |
|
run: |
|
||||||
make -j$(nproc) --no-print-directory --silent lint
|
make lint
|
||||||
- name: CheckABI
|
- name: CheckABI
|
||||||
id: CheckABI
|
id: CheckABI
|
||||||
run: |
|
run: |
|
||||||
docker run -v $PWD:/source ghcr.io/openzfs/libabigail make -j$(nproc) --no-print-directory --silent checkabi
|
sudo docker run -v $(pwd):/source ghcr.io/openzfs/libabigail make checkabi
|
||||||
- name: StoreABI
|
- name: StoreABI
|
||||||
if: failure() && steps.CheckABI.outcome == 'failure'
|
if: failure() && steps.CheckABI.outcome == 'failure'
|
||||||
run: |
|
run: |
|
||||||
docker run -v $PWD:/source ghcr.io/openzfs/libabigail make -j$(nproc) --no-print-directory --silent storeabi
|
sudo docker run -v $(pwd):/source ghcr.io/openzfs/libabigail make storeabi
|
||||||
- name: Prepare artifacts
|
- name: Prepare artifacts
|
||||||
if: failure() && steps.CheckABI.outcome == 'failure'
|
if: failure() && steps.CheckABI.outcome == 'failure'
|
||||||
run: |
|
run: |
|
||||||
find -name *.abi | tar -cf abi_files.tar -T -
|
find -name *.abi | tar -cf abi_files.tar -T -
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v2
|
||||||
if: failure() && steps.CheckABI.outcome == 'failure'
|
if: failure() && steps.CheckABI.outcome == 'failure'
|
||||||
with:
|
with:
|
||||||
name: New ABI files (use only if you're sure about interface changes)
|
name: New ABI files (use only if you're sure about interface changes)
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'cpp', 'python' ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Set make jobs
|
|
||||||
run: |
|
|
||||||
echo "MAKEFLAGS=-j$(nproc)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
config-file: .github/codeql-${{ matrix.language }}.yml
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v3
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
Workflow for each operating system:
|
|
||||||
- install qemu on the github runner
|
|
||||||
- download current cloud image of operating system
|
|
||||||
- start and init that image via cloud-init
|
|
||||||
- install dependencies and poweroff system
|
|
||||||
- start system and build openzfs and then poweroff again
|
|
||||||
- clone build system and start 2 instances of it
|
|
||||||
- run functional testings and complete in around 3h
|
|
||||||
- when tests are done, do some logfile preparing
|
|
||||||
- show detailed results for each system
|
|
||||||
- in the end, generate the job summary
|
|
||||||
|
|
||||||
/TR 14.09.2024
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
"""
|
|
||||||
Determine the CI type based on the change list and commit message.
|
|
||||||
|
|
||||||
Prints "quick" if (explicity required by user):
|
|
||||||
- the *last* commit message contains 'ZFS-CI-Type: quick'
|
|
||||||
or if (heuristics):
|
|
||||||
- the files changed are not in the list of specified directories, and
|
|
||||||
- all commit messages do not contain 'ZFS-CI-Type: full'
|
|
||||||
|
|
||||||
Otherwise prints "full".
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
|
|
||||||
"""
|
|
||||||
Patterns of files that are not considered to trigger full CI.
|
|
||||||
Note: not using pathlib.Path.match() because it does not support '**'
|
|
||||||
"""
|
|
||||||
FULL_RUN_IGNORE_REGEX = list(map(re.compile, [
|
|
||||||
r'.*\.md',
|
|
||||||
r'.*\.gitignore'
|
|
||||||
]))
|
|
||||||
|
|
||||||
"""
|
|
||||||
Patterns of files that are considered to trigger full CI.
|
|
||||||
"""
|
|
||||||
FULL_RUN_REGEX = list(map(re.compile, [
|
|
||||||
r'cmd.*',
|
|
||||||
r'configs/.*',
|
|
||||||
r'META',
|
|
||||||
r'.*\.am',
|
|
||||||
r'.*\.m4',
|
|
||||||
r'autogen\.sh',
|
|
||||||
r'configure\.ac',
|
|
||||||
r'copy-builtin',
|
|
||||||
r'contrib',
|
|
||||||
r'etc',
|
|
||||||
r'include',
|
|
||||||
r'lib/.*',
|
|
||||||
r'module/.*',
|
|
||||||
r'scripts/.*',
|
|
||||||
r'tests/.*',
|
|
||||||
r'udev/.*'
|
|
||||||
]))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
prog = sys.argv[0]
|
|
||||||
|
|
||||||
if len(sys.argv) != 3:
|
|
||||||
print(f'Usage: {prog} <head_ref> <base_ref>')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
head, base = sys.argv[1:3]
|
|
||||||
|
|
||||||
def output_type(type, reason):
|
|
||||||
print(f'{prog}: will run {type} CI: {reason}', file=sys.stderr)
|
|
||||||
print(type)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# check last (HEAD) commit message
|
|
||||||
last_commit_message_raw = subprocess.run([
|
|
||||||
'git', 'show', '-s', '--format=%B', 'HEAD'
|
|
||||||
], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
|
|
||||||
for line in last_commit_message_raw.stdout.decode().splitlines():
|
|
||||||
if line.strip().lower() == 'zfs-ci-type: quick':
|
|
||||||
output_type('quick', f'explicitly requested by HEAD commit {head}')
|
|
||||||
|
|
||||||
# check all commit messages
|
|
||||||
all_commit_message_raw = subprocess.run([
|
|
||||||
'git', 'show', '-s',
|
|
||||||
'--format=ZFS-CI-Commit: %H%n%B', f'{head}...{base}'
|
|
||||||
], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
all_commit_message = all_commit_message_raw.stdout.decode().splitlines()
|
|
||||||
|
|
||||||
commit_ref = head
|
|
||||||
for line in all_commit_message:
|
|
||||||
if line.startswith('ZFS-CI-Commit:'):
|
|
||||||
commit_ref = line.lstrip('ZFS-CI-Commit:').rstrip()
|
|
||||||
if line.strip().lower() == 'zfs-ci-type: full':
|
|
||||||
output_type('full', f'explicitly requested by commit {commit_ref}')
|
|
||||||
|
|
||||||
# check changed files
|
|
||||||
changed_files_raw = subprocess.run([
|
|
||||||
'git', 'diff', '--name-only', head, base
|
|
||||||
], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
changed_files = changed_files_raw.stdout.decode().splitlines()
|
|
||||||
|
|
||||||
for f in changed_files:
|
|
||||||
for r in FULL_RUN_IGNORE_REGEX:
|
|
||||||
if r.match(f):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
for r in FULL_RUN_REGEX:
|
|
||||||
if r.match(f):
|
|
||||||
output_type(
|
|
||||||
'full',
|
|
||||||
f'changed file "{f}" matches pattern "{r.pattern}"'
|
|
||||||
)
|
|
||||||
|
|
||||||
# catch-all
|
|
||||||
output_type('quick', 'no changed file matches full CI patterns')
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
#!/bin/awk -f
|
|
||||||
#
|
|
||||||
# Merge multiple ZTS tests results summaries into a single summary. This is
|
|
||||||
# needed when you're running different parts of ZTS on different tests
|
|
||||||
# runners or VMs.
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
#
|
|
||||||
# ./merge_summary.awk summary1.txt [summary2.txt] [summary3.txt] ...
|
|
||||||
#
|
|
||||||
# or:
|
|
||||||
#
|
|
||||||
# cat summary*.txt | ./merge_summary.awk
|
|
||||||
#
|
|
||||||
BEGIN {
|
|
||||||
i=-1
|
|
||||||
pass=0
|
|
||||||
fail=0
|
|
||||||
skip=0
|
|
||||||
state=""
|
|
||||||
cl=0
|
|
||||||
el=0
|
|
||||||
upl=0
|
|
||||||
ul=0
|
|
||||||
|
|
||||||
# Total seconds of tests runtime
|
|
||||||
total=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Skip empty lines
|
|
||||||
/^\s*$/{next}
|
|
||||||
|
|
||||||
# Skip Configuration and Test lines
|
|
||||||
/^Test:/{state=""; next}
|
|
||||||
/Configuration/{state="";next}
|
|
||||||
|
|
||||||
# When we see "test-runner.py" stop saving config lines, and
|
|
||||||
# save test runner lines
|
|
||||||
/test-runner.py/{state="testrunner"; runner=runner$0"\n"; next}
|
|
||||||
|
|
||||||
# We need to differentiate the PASS counts from test result lines that start
|
|
||||||
# with PASS, like:
|
|
||||||
#
|
|
||||||
# PASS mv_files/setup
|
|
||||||
#
|
|
||||||
# Use state="pass_count" to differentiate
|
|
||||||
#
|
|
||||||
/Results Summary/{state="pass_count"; next}
|
|
||||||
/PASS/{ if (state=="pass_count") {pass += $2}}
|
|
||||||
/FAIL/{ if (state=="pass_count") {fail += $2}}
|
|
||||||
/SKIP/{ if (state=="pass_count") {skip += $2}}
|
|
||||||
/Running Time/{
|
|
||||||
state="";
|
|
||||||
running[i]=$3;
|
|
||||||
split($3, arr, ":")
|
|
||||||
total += arr[1] * 60 * 60;
|
|
||||||
total += arr[2] * 60;
|
|
||||||
total += arr[3]
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/Tests with results other than PASS that are expected/{state="expected_lines"; next}
|
|
||||||
/Tests with result of PASS that are unexpected/{state="unexpected_pass_lines"; next}
|
|
||||||
/Tests with results other than PASS that are unexpected/{state="unexpected_lines"; next}
|
|
||||||
{
|
|
||||||
if (state == "expected_lines") {
|
|
||||||
expected_lines[el] = $0
|
|
||||||
el++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == "unexpected_pass_lines") {
|
|
||||||
unexpected_pass_lines[upl] = $0
|
|
||||||
upl++
|
|
||||||
}
|
|
||||||
if (state == "unexpected_lines") {
|
|
||||||
unexpected_lines[ul] = $0
|
|
||||||
ul++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Reproduce summary
|
|
||||||
END {
|
|
||||||
print runner;
|
|
||||||
print "\nResults Summary"
|
|
||||||
print "PASS\t"pass
|
|
||||||
print "FAIL\t"fail
|
|
||||||
print "SKIP\t"skip
|
|
||||||
print ""
|
|
||||||
print "Running Time:\t"strftime("%T", total, 1)
|
|
||||||
if (pass+fail+skip > 0) {
|
|
||||||
percent_passed=(pass/(pass+fail+skip) * 100)
|
|
||||||
}
|
|
||||||
printf "Percent passed:\t%3.2f%", percent_passed
|
|
||||||
|
|
||||||
print "\n\nTests with results other than PASS that are expected:"
|
|
||||||
asort(expected_lines, sorted)
|
|
||||||
for (j in sorted)
|
|
||||||
print sorted[j]
|
|
||||||
|
|
||||||
print "\n\nTests with result of PASS that are unexpected:"
|
|
||||||
asort(unexpected_pass_lines, sorted)
|
|
||||||
for (j in sorted)
|
|
||||||
print sorted[j]
|
|
||||||
|
|
||||||
print "\n\nTests with results other than PASS that are unexpected:"
|
|
||||||
asort(unexpected_lines, sorted)
|
|
||||||
for (j in sorted)
|
|
||||||
print sorted[j]
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 1) setup qemu instance on action runner
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# install needed packages
|
|
||||||
export DEBIAN_FRONTEND="noninteractive"
|
|
||||||
sudo apt-get -y update
|
|
||||||
sudo apt-get install -y axel cloud-image-utils daemonize guestfs-tools \
|
|
||||||
ksmtuned virt-manager linux-modules-extra-$(uname -r) zfsutils-linux
|
|
||||||
|
|
||||||
# generate ssh keys
|
|
||||||
rm -f ~/.ssh/id_ed25519
|
|
||||||
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -q -N ""
|
|
||||||
|
|
||||||
# we expect RAM shortage
|
|
||||||
cat << EOF | sudo tee /etc/ksmtuned.conf > /dev/null
|
|
||||||
# /etc/ksmtuned.conf - Configuration file for ksmtuned
|
|
||||||
# https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/virtualization_tuning_and_optimization_guide/chap-ksm
|
|
||||||
KSM_MONITOR_INTERVAL=60
|
|
||||||
|
|
||||||
# Millisecond sleep between ksm scans for 16Gb server.
|
|
||||||
# Smaller servers sleep more, bigger sleep less.
|
|
||||||
KSM_SLEEP_MSEC=30
|
|
||||||
|
|
||||||
KSM_NPAGES_BOOST=0
|
|
||||||
KSM_NPAGES_DECAY=0
|
|
||||||
KSM_NPAGES_MIN=1000
|
|
||||||
KSM_NPAGES_MAX=25000
|
|
||||||
|
|
||||||
KSM_THRES_COEF=80
|
|
||||||
KSM_THRES_CONST=8192
|
|
||||||
|
|
||||||
LOGFILE=/var/log/ksmtuned.log
|
|
||||||
DEBUG=1
|
|
||||||
EOF
|
|
||||||
sudo systemctl restart ksm
|
|
||||||
sudo systemctl restart ksmtuned
|
|
||||||
|
|
||||||
# not needed
|
|
||||||
sudo systemctl stop docker.socket
|
|
||||||
sudo systemctl stop multipathd.socket
|
|
||||||
|
|
||||||
# remove default swapfile and /mnt
|
|
||||||
sudo swapoff -a
|
|
||||||
sudo umount -l /mnt
|
|
||||||
DISK="/dev/disk/cloud/azure_resource-part1"
|
|
||||||
sudo sed -e "s|^$DISK.*||g" -i /etc/fstab
|
|
||||||
sudo wipefs -aq $DISK
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
|
|
||||||
sudo modprobe loop
|
|
||||||
sudo modprobe zfs
|
|
||||||
|
|
||||||
# partition the disk as needed
|
|
||||||
DISK="/dev/disk/cloud/azure_resource"
|
|
||||||
sudo sgdisk --zap-all $DISK
|
|
||||||
sudo sgdisk -p \
|
|
||||||
-n 1:0:+16G -c 1:"swap" \
|
|
||||||
-n 2:0:0 -c 2:"tests" \
|
|
||||||
$DISK
|
|
||||||
sync
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# swap with same size as RAM
|
|
||||||
sudo mkswap $DISK-part1
|
|
||||||
sudo swapon $DISK-part1
|
|
||||||
|
|
||||||
# 60GB data disk
|
|
||||||
SSD1="$DISK-part2"
|
|
||||||
|
|
||||||
# 10GB data disk on ext4
|
|
||||||
sudo fallocate -l 10G /test.ssd1
|
|
||||||
SSD2=$(sudo losetup -b 4096 -f /test.ssd1 --show)
|
|
||||||
|
|
||||||
# adjust zfs module parameter and create pool
|
|
||||||
exec 1>/dev/null
|
|
||||||
ARC_MIN=$((1024*1024*256))
|
|
||||||
ARC_MAX=$((1024*1024*512))
|
|
||||||
echo $ARC_MIN | sudo tee /sys/module/zfs/parameters/zfs_arc_min
|
|
||||||
echo $ARC_MAX | sudo tee /sys/module/zfs/parameters/zfs_arc_max
|
|
||||||
echo 1 | sudo tee /sys/module/zfs/parameters/zvol_use_blk_mq
|
|
||||||
sudo zpool create -f -o ashift=12 zpool $SSD1 $SSD2 \
|
|
||||||
-O relatime=off -O atime=off -O xattr=sa -O compression=lz4 \
|
|
||||||
-O mountpoint=/mnt/tests
|
|
||||||
|
|
||||||
# no need for some scheduler
|
|
||||||
for i in /sys/block/s*/queue/scheduler; do
|
|
||||||
echo "none" | sudo tee $i > /dev/null
|
|
||||||
done
|
|
||||||
@@ -1,232 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 2) start qemu with some operating system, init via cloud-init
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# short name used in zfs-qemu.yml
|
|
||||||
OS="$1"
|
|
||||||
|
|
||||||
# OS variant (virt-install --os-variant list)
|
|
||||||
OSv=$OS
|
|
||||||
|
|
||||||
# compressed with .zst extension
|
|
||||||
REPO="https://github.com/mcmilk/openzfs-freebsd-images"
|
|
||||||
FREEBSD="$REPO/releases/download/v2024-12-14"
|
|
||||||
URLzs=""
|
|
||||||
|
|
||||||
# Ubuntu mirrors
|
|
||||||
#UBMIRROR="https://cloud-images.ubuntu.com"
|
|
||||||
#UBMIRROR="https://mirrors.cloud.tencent.com/ubuntu-cloud-images"
|
|
||||||
UBMIRROR="https://mirror.citrahost.com/ubuntu-cloud-images"
|
|
||||||
|
|
||||||
# default nic model for vm's
|
|
||||||
NIC="virtio"
|
|
||||||
|
|
||||||
case "$OS" in
|
|
||||||
almalinux8)
|
|
||||||
OSNAME="AlmaLinux 8"
|
|
||||||
URL="https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-latest.x86_64.qcow2"
|
|
||||||
;;
|
|
||||||
almalinux9)
|
|
||||||
OSNAME="AlmaLinux 9"
|
|
||||||
URL="https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2"
|
|
||||||
;;
|
|
||||||
archlinux)
|
|
||||||
OSNAME="Archlinux"
|
|
||||||
URL="https://geo.mirror.pkgbuild.com/images/latest/Arch-Linux-x86_64-cloudimg.qcow2"
|
|
||||||
# dns sometimes fails with that url :/
|
|
||||||
echo "89.187.191.12 geo.mirror.pkgbuild.com" | sudo tee /etc/hosts > /dev/null
|
|
||||||
;;
|
|
||||||
centos-stream10)
|
|
||||||
OSNAME="CentOS Stream 10"
|
|
||||||
# TODO: #16903 Overwrite OSv to stream9 for virt-install until it's added to osinfo
|
|
||||||
OSv="centos-stream9"
|
|
||||||
URL="https://cloud.centos.org/centos/10-stream/x86_64/images/CentOS-Stream-GenericCloud-10-latest.x86_64.qcow2"
|
|
||||||
;;
|
|
||||||
centos-stream9)
|
|
||||||
OSNAME="CentOS Stream 9"
|
|
||||||
URL="https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-latest.x86_64.qcow2"
|
|
||||||
;;
|
|
||||||
debian11)
|
|
||||||
OSNAME="Debian 11"
|
|
||||||
URL="https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.qcow2"
|
|
||||||
;;
|
|
||||||
debian12)
|
|
||||||
OSNAME="Debian 12"
|
|
||||||
URL="https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
|
|
||||||
;;
|
|
||||||
fedora40)
|
|
||||||
OSNAME="Fedora 40"
|
|
||||||
OSv="fedora-unknown"
|
|
||||||
URL="https://download.fedoraproject.org/pub/fedora/linux/releases/40/Cloud/x86_64/images/Fedora-Cloud-Base-Generic.x86_64-40-1.14.qcow2"
|
|
||||||
;;
|
|
||||||
fedora41)
|
|
||||||
OSNAME="Fedora 41"
|
|
||||||
OSv="fedora-unknown"
|
|
||||||
URL="https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-41-1.4.x86_64.qcow2"
|
|
||||||
;;
|
|
||||||
freebsd13-3r)
|
|
||||||
OSNAME="FreeBSD 13.3-RELEASE"
|
|
||||||
OSv="freebsd13.0"
|
|
||||||
URLzs="$FREEBSD/amd64-freebsd-13.3-RELEASE.qcow2.zst"
|
|
||||||
BASH="/usr/local/bin/bash"
|
|
||||||
NIC="rtl8139"
|
|
||||||
;;
|
|
||||||
freebsd13-4r)
|
|
||||||
OSNAME="FreeBSD 13.4-RELEASE"
|
|
||||||
OSv="freebsd13.0"
|
|
||||||
URLzs="$FREEBSD/amd64-freebsd-13.4-RELEASE.qcow2.zst"
|
|
||||||
BASH="/usr/local/bin/bash"
|
|
||||||
NIC="rtl8139"
|
|
||||||
;;
|
|
||||||
freebsd14-1r)
|
|
||||||
OSNAME="FreeBSD 14.1-RELEASE"
|
|
||||||
OSv="freebsd14.0"
|
|
||||||
URLzs="$FREEBSD/amd64-freebsd-14.1-RELEASE.qcow2.zst"
|
|
||||||
BASH="/usr/local/bin/bash"
|
|
||||||
;;
|
|
||||||
freebsd14-2r)
|
|
||||||
OSNAME="FreeBSD 14.2-RELEASE"
|
|
||||||
OSv="freebsd14.0"
|
|
||||||
URLzs="$FREEBSD/amd64-freebsd-14.2-RELEASE.qcow2.zst"
|
|
||||||
BASH="/usr/local/bin/bash"
|
|
||||||
;;
|
|
||||||
freebsd13-4s)
|
|
||||||
OSNAME="FreeBSD 13.4-STABLE"
|
|
||||||
OSv="freebsd13.0"
|
|
||||||
URLzs="$FREEBSD/amd64-freebsd-13.4-STABLE.qcow2.zst"
|
|
||||||
BASH="/usr/local/bin/bash"
|
|
||||||
NIC="rtl8139"
|
|
||||||
;;
|
|
||||||
freebsd14-2s)
|
|
||||||
OSNAME="FreeBSD 14.2-STABLE"
|
|
||||||
OSv="freebsd14.0"
|
|
||||||
URLzs="$FREEBSD/amd64-freebsd-14.2-STABLE.qcow2.zst"
|
|
||||||
BASH="/usr/local/bin/bash"
|
|
||||||
;;
|
|
||||||
freebsd15-0c)
|
|
||||||
OSNAME="FreeBSD 15.0-CURRENT"
|
|
||||||
OSv="freebsd14.0"
|
|
||||||
URLzs="$FREEBSD/amd64-freebsd-15.0-CURRENT.qcow2.zst"
|
|
||||||
BASH="/usr/local/bin/bash"
|
|
||||||
;;
|
|
||||||
tumbleweed)
|
|
||||||
OSNAME="openSUSE Tumbleweed"
|
|
||||||
OSv="opensusetumbleweed"
|
|
||||||
MIRROR="http://opensuse-mirror-gce-us.susecloud.net"
|
|
||||||
URL="$MIRROR/tumbleweed/appliances/openSUSE-MicroOS.x86_64-OpenStack-Cloud.qcow2"
|
|
||||||
;;
|
|
||||||
ubuntu20)
|
|
||||||
OSNAME="Ubuntu 20.04"
|
|
||||||
OSv="ubuntu20.04"
|
|
||||||
URL="$UBMIRROR/focal/current/focal-server-cloudimg-amd64.img"
|
|
||||||
;;
|
|
||||||
ubuntu22)
|
|
||||||
OSNAME="Ubuntu 22.04"
|
|
||||||
OSv="ubuntu22.04"
|
|
||||||
URL="$UBMIRROR/jammy/current/jammy-server-cloudimg-amd64.img"
|
|
||||||
;;
|
|
||||||
ubuntu24)
|
|
||||||
OSNAME="Ubuntu 24.04"
|
|
||||||
OSv="ubuntu24.04"
|
|
||||||
URL="$UBMIRROR/noble/current/noble-server-cloudimg-amd64.img"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Wrong value for OS variable!"
|
|
||||||
exit 111
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# environment file
|
|
||||||
ENV="/var/tmp/env.txt"
|
|
||||||
echo "ENV=$ENV" >> $ENV
|
|
||||||
|
|
||||||
# result path
|
|
||||||
echo 'RESPATH="/var/tmp/test_results"' >> $ENV
|
|
||||||
|
|
||||||
# FreeBSD 13 has problems with: e1000+virtio
|
|
||||||
echo "NIC=$NIC" >> $ENV
|
|
||||||
|
|
||||||
# freebsd15 -> used in zfs-qemu.yml
|
|
||||||
echo "OS=$OS" >> $ENV
|
|
||||||
|
|
||||||
# freebsd14.0 -> used for virt-install
|
|
||||||
echo "OSv=\"$OSv\"" >> $ENV
|
|
||||||
|
|
||||||
# FreeBSD 15 (Current) -> used for summary
|
|
||||||
echo "OSNAME=\"$OSNAME\"" >> $ENV
|
|
||||||
|
|
||||||
sudo mkdir -p "/mnt/tests"
|
|
||||||
sudo chown -R $(whoami) /mnt/tests
|
|
||||||
|
|
||||||
# we are downloading via axel, curl and wget are mostly slower and
|
|
||||||
# require more return value checking
|
|
||||||
IMG="/mnt/tests/cloudimg.qcow2"
|
|
||||||
if [ ! -z "$URLzs" ]; then
|
|
||||||
echo "Loading image $URLzs ..."
|
|
||||||
time axel -q -o "$IMG.zst" "$URLzs"
|
|
||||||
zstd -q -d --rm "$IMG.zst"
|
|
||||||
else
|
|
||||||
echo "Loading image $URL ..."
|
|
||||||
time axel -q -o "$IMG" "$URL"
|
|
||||||
fi
|
|
||||||
|
|
||||||
DISK="/dev/zvol/zpool/openzfs"
|
|
||||||
FORMAT="raw"
|
|
||||||
sudo zfs create -ps -b 64k -V 80g zpool/openzfs
|
|
||||||
while true; do test -b $DISK && break; sleep 1; done
|
|
||||||
echo "Importing VM image to zvol..."
|
|
||||||
sudo qemu-img dd -f qcow2 -O raw if=$IMG of=$DISK bs=4M
|
|
||||||
rm -f $IMG
|
|
||||||
|
|
||||||
PUBKEY=$(cat ~/.ssh/id_ed25519.pub)
|
|
||||||
cat <<EOF > /tmp/user-data
|
|
||||||
#cloud-config
|
|
||||||
|
|
||||||
fqdn: $OS
|
|
||||||
|
|
||||||
users:
|
|
||||||
- name: root
|
|
||||||
shell: $BASH
|
|
||||||
- name: zfs
|
|
||||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
|
||||||
shell: $BASH
|
|
||||||
ssh_authorized_keys:
|
|
||||||
- $PUBKEY
|
|
||||||
|
|
||||||
growpart:
|
|
||||||
mode: auto
|
|
||||||
devices: ['/']
|
|
||||||
ignore_growroot_disabled: false
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo virsh net-update default add ip-dhcp-host \
|
|
||||||
"<host mac='52:54:00:83:79:00' ip='192.168.122.10'/>" --live --config
|
|
||||||
|
|
||||||
sudo virt-install \
|
|
||||||
--os-variant $OSv \
|
|
||||||
--name "openzfs" \
|
|
||||||
--cpu host-passthrough \
|
|
||||||
--virt-type=kvm --hvm \
|
|
||||||
--vcpus=4,sockets=1 \
|
|
||||||
--memory $((1024*12)) \
|
|
||||||
--memballoon model=virtio \
|
|
||||||
--graphics none \
|
|
||||||
--network bridge=virbr0,model=$NIC,mac='52:54:00:83:79:00' \
|
|
||||||
--cloud-init user-data=/tmp/user-data \
|
|
||||||
--disk $DISK,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \
|
|
||||||
--import --noautoconsole >/dev/null
|
|
||||||
|
|
||||||
# in case the directory isn't there already
|
|
||||||
mkdir -p $HOME/.ssh
|
|
||||||
|
|
||||||
cat <<EOF >> $HOME/.ssh/config
|
|
||||||
# no questions please
|
|
||||||
StrictHostKeyChecking no
|
|
||||||
|
|
||||||
# small timeout, used in while loops later
|
|
||||||
ConnectTimeout 1
|
|
||||||
EOF
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 3) install dependencies for compiling and loading
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
function archlinux() {
|
|
||||||
echo "##[group]Running pacman -Syu"
|
|
||||||
sudo btrfs filesystem resize max /
|
|
||||||
sudo pacman -Syu --noconfirm
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Install Development Tools"
|
|
||||||
sudo pacman -Sy --noconfirm base-devel bc cpio cryptsetup dhclient dkms \
|
|
||||||
fakeroot fio gdb inetutils jq less linux linux-headers lsscsi nfs-utils \
|
|
||||||
parted pax perf python-packaging python-setuptools qemu-guest-agent ksh \
|
|
||||||
samba sysstat rng-tools rsync wget xxhash
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
function debian() {
|
|
||||||
export DEBIAN_FRONTEND="noninteractive"
|
|
||||||
|
|
||||||
echo "##[group]Running apt-get update+upgrade"
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get upgrade -y
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Install Development Tools"
|
|
||||||
sudo apt-get install -y \
|
|
||||||
acl alien attr autoconf bc cpio cryptsetup curl dbench dh-python dkms \
|
|
||||||
fakeroot fio gdb gdebi git ksh lcov isc-dhcp-client jq libacl1-dev \
|
|
||||||
libaio-dev libattr1-dev libblkid-dev libcurl4-openssl-dev libdevmapper-dev \
|
|
||||||
libelf-dev libffi-dev libmount-dev libpam0g-dev libselinux-dev libssl-dev \
|
|
||||||
libtool libtool-bin libudev-dev libunwind-dev linux-headers-$(uname -r) \
|
|
||||||
lsscsi nfs-kernel-server pamtester parted python3 python3-all-dev \
|
|
||||||
python3-cffi python3-dev python3-distlib python3-packaging \
|
|
||||||
python3-setuptools python3-sphinx qemu-guest-agent rng-tools rpm2cpio \
|
|
||||||
rsync samba sysstat uuid-dev watchdog wget xfslibs-dev xxhash zlib1g-dev
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
function freebsd() {
|
|
||||||
export ASSUME_ALWAYS_YES="YES"
|
|
||||||
|
|
||||||
echo "##[group]Install Development Tools"
|
|
||||||
sudo pkg install -y autoconf automake autotools base64 checkbashisms fio \
|
|
||||||
gdb gettext gettext-runtime git gmake gsed jq ksh93 lcov libtool lscpu \
|
|
||||||
pkgconf python python3 pamtester pamtester qemu-guest-agent rsync xxhash
|
|
||||||
sudo pkg install -xy \
|
|
||||||
'^samba4[[:digit:]]+$' \
|
|
||||||
'^py3[[:digit:]]+-cffi$' \
|
|
||||||
'^py3[[:digit:]]+-sysctl$' \
|
|
||||||
'^py3[[:digit:]]+-packaging$'
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
# common packages for: almalinux, centos, redhat
|
|
||||||
function rhel() {
|
|
||||||
echo "##[group]Running dnf update"
|
|
||||||
echo "max_parallel_downloads=10" | sudo -E tee -a /etc/dnf/dnf.conf
|
|
||||||
sudo dnf clean all
|
|
||||||
sudo dnf update -y --setopt=fastestmirror=1 --refresh
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Install Development Tools"
|
|
||||||
|
|
||||||
# Alma wants "Development Tools", Fedora 41 wants "development-tools"
|
|
||||||
if ! sudo dnf group install -y "Development Tools" ; then
|
|
||||||
echo "Trying 'development-tools' instead of 'Development Tools'"
|
|
||||||
sudo dnf group install -y development-tools
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo dnf install -y \
|
|
||||||
acl attr bc bzip2 cryptsetup curl dbench dkms elfutils-libelf-devel fio \
|
|
||||||
gdb git jq kernel-rpm-macros ksh libacl-devel libaio-devel \
|
|
||||||
libargon2-devel libattr-devel libblkid-devel libcurl-devel libffi-devel \
|
|
||||||
ncompress libselinux-devel libtirpc-devel libtool libudev-devel \
|
|
||||||
libuuid-devel lsscsi mdadm nfs-utils openssl-devel pam-devel pamtester \
|
|
||||||
parted perf python3 python3-cffi python3-devel python3-packaging \
|
|
||||||
kernel-devel python3-setuptools qemu-guest-agent rng-tools rpcgen \
|
|
||||||
rpm-build rsync samba sysstat systemd watchdog wget xfsprogs-devel xxhash \
|
|
||||||
zlib-devel
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
function tumbleweed() {
|
|
||||||
echo "##[group]Running zypper is TODO!"
|
|
||||||
sleep 23456
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
case "$1" in
|
|
||||||
almalinux8)
|
|
||||||
echo "##[group]Enable epel and powertools repositories"
|
|
||||||
sudo dnf config-manager -y --set-enabled powertools
|
|
||||||
sudo dnf install -y epel-release
|
|
||||||
echo "##[endgroup]"
|
|
||||||
rhel
|
|
||||||
echo "##[group]Install kernel-abi-whitelists"
|
|
||||||
sudo dnf install -y kernel-abi-whitelists
|
|
||||||
echo "##[endgroup]"
|
|
||||||
;;
|
|
||||||
almalinux9|centos-stream9|centos-stream10)
|
|
||||||
echo "##[group]Enable epel and crb repositories"
|
|
||||||
sudo dnf config-manager -y --set-enabled crb
|
|
||||||
sudo dnf install -y epel-release
|
|
||||||
echo "##[endgroup]"
|
|
||||||
rhel
|
|
||||||
echo "##[group]Install kernel-abi-stablelists"
|
|
||||||
sudo dnf install -y kernel-abi-stablelists
|
|
||||||
echo "##[endgroup]"
|
|
||||||
;;
|
|
||||||
archlinux)
|
|
||||||
archlinux
|
|
||||||
;;
|
|
||||||
debian*)
|
|
||||||
echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selections
|
|
||||||
debian
|
|
||||||
echo "##[group]Install Debian specific"
|
|
||||||
sudo apt-get install -yq linux-perf dh-sequence-dkms
|
|
||||||
echo "##[endgroup]"
|
|
||||||
;;
|
|
||||||
fedora*)
|
|
||||||
rhel
|
|
||||||
;;
|
|
||||||
freebsd*)
|
|
||||||
freebsd
|
|
||||||
;;
|
|
||||||
tumbleweed)
|
|
||||||
tumbleweed
|
|
||||||
;;
|
|
||||||
ubuntu*)
|
|
||||||
debian
|
|
||||||
echo "##[group]Install Ubuntu specific"
|
|
||||||
sudo apt-get install -yq linux-tools-common libtirpc-dev \
|
|
||||||
linux-modules-extra-$(uname -r)
|
|
||||||
if [ "$1" != "ubuntu20" ]; then
|
|
||||||
sudo apt-get install -yq dh-sequence-dkms
|
|
||||||
fi
|
|
||||||
echo "##[endgroup]"
|
|
||||||
echo "##[group]Delete Ubuntu OpenZFS modules"
|
|
||||||
for i in $(find /lib/modules -name zfs -type d); do sudo rm -rvf $i; done
|
|
||||||
echo "##[endgroup]"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# This script is used for checkstyle + zloop deps also.
|
|
||||||
# Install only the needed packages and exit - when used this way.
|
|
||||||
test -z "${ONLY_DEPS:-}" || exit 0
|
|
||||||
|
|
||||||
# Start services
|
|
||||||
echo "##[group]Enable services"
|
|
||||||
case "$1" in
|
|
||||||
freebsd*)
|
|
||||||
# add virtio things
|
|
||||||
echo 'virtio_load="YES"' | sudo -E tee -a /boot/loader.conf
|
|
||||||
for i in balloon blk console random scsi; do
|
|
||||||
echo "virtio_${i}_load=\"YES\"" | sudo -E tee -a /boot/loader.conf
|
|
||||||
done
|
|
||||||
echo "fdescfs /dev/fd fdescfs rw 0 0" | sudo -E tee -a /etc/fstab
|
|
||||||
sudo -E mount /dev/fd
|
|
||||||
sudo -E touch /etc/zfs/exports
|
|
||||||
sudo -E sysrc mountd_flags="/etc/zfs/exports"
|
|
||||||
echo '[global]' | sudo -E tee /usr/local/etc/smb4.conf >/dev/null
|
|
||||||
sudo -E service nfsd enable
|
|
||||||
sudo -E service qemu-guest-agent enable
|
|
||||||
sudo -E service samba_server enable
|
|
||||||
;;
|
|
||||||
debian*|ubuntu*)
|
|
||||||
sudo -E systemctl enable nfs-kernel-server
|
|
||||||
sudo -E systemctl enable qemu-guest-agent
|
|
||||||
sudo -E systemctl enable smbd
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
# All other linux distros
|
|
||||||
sudo -E systemctl enable nfs-server
|
|
||||||
sudo -E systemctl enable qemu-guest-agent
|
|
||||||
sudo -E systemctl enable smb
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
# Setup Kernel cmdline
|
|
||||||
CMDLINE="console=tty0 console=ttyS0,115200n8"
|
|
||||||
CMDLINE="$CMDLINE selinux=0"
|
|
||||||
CMDLINE="$CMDLINE random.trust_cpu=on"
|
|
||||||
CMDLINE="$CMDLINE no_timer_check"
|
|
||||||
case "$1" in
|
|
||||||
almalinux*|centos*|fedora*)
|
|
||||||
GRUB_CFG="/boot/grub2/grub.cfg"
|
|
||||||
GRUB_MKCONFIG="grub2-mkconfig"
|
|
||||||
CMDLINE="$CMDLINE biosdevname=0 net.ifnames=0"
|
|
||||||
echo 'GRUB_SERIAL_COMMAND="serial --speed=115200"' \
|
|
||||||
| sudo tee -a /etc/default/grub >/dev/null
|
|
||||||
;;
|
|
||||||
ubuntu24)
|
|
||||||
GRUB_CFG="/boot/grub/grub.cfg"
|
|
||||||
GRUB_MKCONFIG="grub-mkconfig"
|
|
||||||
echo 'GRUB_DISABLE_OS_PROBER="false"' \
|
|
||||||
| sudo tee -a /etc/default/grub >/dev/null
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
GRUB_CFG="/boot/grub/grub.cfg"
|
|
||||||
GRUB_MKCONFIG="grub-mkconfig"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
archlinux|freebsd*)
|
|
||||||
true
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "##[group]Edit kernel cmdline"
|
|
||||||
sudo sed -i -e '/^GRUB_CMDLINE_LINUX/d' /etc/default/grub || true
|
|
||||||
echo "GRUB_CMDLINE_LINUX=\"$CMDLINE\"" \
|
|
||||||
| sudo tee -a /etc/default/grub >/dev/null
|
|
||||||
sudo $GRUB_MKCONFIG -o $GRUB_CFG
|
|
||||||
echo "##[endgroup]"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# reset cloud-init configuration and poweroff
|
|
||||||
sudo cloud-init clean --logs
|
|
||||||
sleep 2 && sudo poweroff &
|
|
||||||
exit 0
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 4) configure and build openzfs modules
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
function run() {
|
|
||||||
LOG="/var/tmp/build-stderr.txt"
|
|
||||||
echo "****************************************************"
|
|
||||||
echo "$(date) ($*)"
|
|
||||||
echo "****************************************************"
|
|
||||||
($@ || echo $? > /tmp/rv) 3>&1 1>&2 2>&3 | stdbuf -eL -oL tee -a $LOG
|
|
||||||
if [ -f /tmp/rv ]; then
|
|
||||||
RV=$(cat /tmp/rv)
|
|
||||||
echo "****************************************************"
|
|
||||||
echo "exit with value=$RV ($*)"
|
|
||||||
echo "****************************************************"
|
|
||||||
echo 1 > /var/tmp/build-exitcode.txt
|
|
||||||
exit $RV
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function freebsd() {
|
|
||||||
export MAKE="gmake"
|
|
||||||
echo "##[group]Autogen.sh"
|
|
||||||
run ./autogen.sh
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Configure"
|
|
||||||
run ./configure \
|
|
||||||
--prefix=/usr/local \
|
|
||||||
--with-libintl-prefix=/usr/local \
|
|
||||||
--enable-pyzfs \
|
|
||||||
--enable-debug \
|
|
||||||
--enable-debuginfo
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Build"
|
|
||||||
run gmake -j$(sysctl -n hw.ncpu)
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Install"
|
|
||||||
run sudo gmake install
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
function linux() {
|
|
||||||
echo "##[group]Autogen.sh"
|
|
||||||
run ./autogen.sh
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Configure"
|
|
||||||
run ./configure \
|
|
||||||
--prefix=/usr \
|
|
||||||
--enable-pyzfs \
|
|
||||||
--enable-debug \
|
|
||||||
--enable-debuginfo
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Build"
|
|
||||||
run make -j$(nproc)
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Install"
|
|
||||||
run sudo make install
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
function rpm_build_and_install() {
|
|
||||||
EXTRA_CONFIG="${1:-}"
|
|
||||||
echo "##[group]Autogen.sh"
|
|
||||||
run ./autogen.sh
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Configure"
|
|
||||||
run ./configure --enable-debug --enable-debuginfo $EXTRA_CONFIG
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Build"
|
|
||||||
run make pkg-kmod pkg-utils
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Install"
|
|
||||||
run sudo dnf -y --nobest install $(ls *.rpm | grep -v src.rpm)
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function deb_build_and_install() {
|
|
||||||
echo "##[group]Autogen.sh"
|
|
||||||
run ./autogen.sh
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Configure"
|
|
||||||
run ./configure \
|
|
||||||
--prefix=/usr \
|
|
||||||
--enable-pyzfs \
|
|
||||||
--enable-debug \
|
|
||||||
--enable-debuginfo
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Build"
|
|
||||||
run make native-deb-kmod native-deb-utils
|
|
||||||
echo "##[endgroup]"
|
|
||||||
|
|
||||||
echo "##[group]Install"
|
|
||||||
# Do kmod install. Note that when you build the native debs, the
|
|
||||||
# packages themselves are placed in parent directory '../' rather than
|
|
||||||
# in the source directory like the rpms are.
|
|
||||||
run sudo apt-get -y install $(find ../ | grep -E '\.deb$' \
|
|
||||||
| grep -Ev 'dkms|dracut')
|
|
||||||
echo "##[endgroup]"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Debug: show kernel cmdline
|
|
||||||
if [ -f /proc/cmdline ] ; then
|
|
||||||
cat /proc/cmdline || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# save some sysinfo
|
|
||||||
uname -a > /var/tmp/uname.txt
|
|
||||||
|
|
||||||
cd $HOME/zfs
|
|
||||||
export PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin"
|
|
||||||
|
|
||||||
# build
|
|
||||||
case "$1" in
|
|
||||||
freebsd*)
|
|
||||||
freebsd
|
|
||||||
;;
|
|
||||||
alma*|centos*)
|
|
||||||
rpm_build_and_install "--with-spec=redhat"
|
|
||||||
;;
|
|
||||||
fedora*)
|
|
||||||
rpm_build_and_install
|
|
||||||
;;
|
|
||||||
debian*|ubuntu*)
|
|
||||||
deb_build_and_install
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
linux
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# building the zfs module was ok
|
|
||||||
echo 0 > /var/tmp/build-exitcode.txt
|
|
||||||
|
|
||||||
# reset cloud-init configuration and poweroff
|
|
||||||
sudo cloud-init clean --logs
|
|
||||||
sync && sleep 2 && sudo poweroff &
|
|
||||||
exit 0
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 5) start test machines and load openzfs module
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# read our defined variables
|
|
||||||
source /var/tmp/env.txt
|
|
||||||
|
|
||||||
# wait for poweroff to succeed
|
|
||||||
PID=$(pidof /usr/bin/qemu-system-x86_64)
|
|
||||||
tail --pid=$PID -f /dev/null
|
|
||||||
sudo virsh undefine openzfs
|
|
||||||
|
|
||||||
# default values per test vm:
|
|
||||||
VMs=2
|
|
||||||
CPU=2
|
|
||||||
|
|
||||||
# cpu pinning
|
|
||||||
CPUSET=("0,1" "2,3")
|
|
||||||
|
|
||||||
case "$OS" in
|
|
||||||
freebsd*)
|
|
||||||
# FreeBSD can't be optimized via ksmtuned
|
|
||||||
RAM=6
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
# Linux can be optimized via ksmtuned
|
|
||||||
RAM=8
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# this can be different for each distro
|
|
||||||
echo "VMs=$VMs" >> $ENV
|
|
||||||
|
|
||||||
# create snapshot we can clone later
|
|
||||||
sudo zfs snapshot zpool/openzfs@now
|
|
||||||
|
|
||||||
# setup the testing vm's
|
|
||||||
PUBKEY=$(cat ~/.ssh/id_ed25519.pub)
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
|
|
||||||
echo "Creating disk for vm$i..."
|
|
||||||
DISK="/dev/zvol/zpool/vm$i"
|
|
||||||
FORMAT="raw"
|
|
||||||
sudo zfs clone zpool/openzfs@now zpool/vm$i
|
|
||||||
sudo zfs create -ps -b 64k -V 80g zpool/vm$i-2
|
|
||||||
|
|
||||||
cat <<EOF > /tmp/user-data
|
|
||||||
#cloud-config
|
|
||||||
|
|
||||||
fqdn: vm$i
|
|
||||||
|
|
||||||
users:
|
|
||||||
- name: root
|
|
||||||
shell: $BASH
|
|
||||||
- name: zfs
|
|
||||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
|
||||||
shell: $BASH
|
|
||||||
ssh_authorized_keys:
|
|
||||||
- $PUBKEY
|
|
||||||
|
|
||||||
growpart:
|
|
||||||
mode: auto
|
|
||||||
devices: ['/']
|
|
||||||
ignore_growroot_disabled: false
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo virsh net-update default add ip-dhcp-host \
|
|
||||||
"<host mac='52:54:00:83:79:0$i' ip='192.168.122.1$i'/>" --live --config
|
|
||||||
|
|
||||||
sudo virt-install \
|
|
||||||
--os-variant $OSv \
|
|
||||||
--name "vm$i" \
|
|
||||||
--cpu host-passthrough \
|
|
||||||
--virt-type=kvm --hvm \
|
|
||||||
--vcpus=$CPU,sockets=1 \
|
|
||||||
--cpuset=${CPUSET[$((i-1))]} \
|
|
||||||
--memory $((1024*RAM)) \
|
|
||||||
--memballoon model=virtio \
|
|
||||||
--graphics none \
|
|
||||||
--cloud-init user-data=/tmp/user-data \
|
|
||||||
--network bridge=virbr0,model=$NIC,mac="52:54:00:83:79:0$i" \
|
|
||||||
--disk $DISK,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \
|
|
||||||
--disk $DISK-2,bus=virtio,cache=none,format=$FORMAT,driver.discard=unmap \
|
|
||||||
--import --noautoconsole >/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
# check the memory state from time to time
|
|
||||||
cat <<EOF > cronjob.sh
|
|
||||||
# $OS
|
|
||||||
exec 1>>/var/tmp/stats.txt
|
|
||||||
exec 2>&1
|
|
||||||
echo "*******************************************************"
|
|
||||||
date
|
|
||||||
uptime
|
|
||||||
free -m
|
|
||||||
df -h /mnt/tests
|
|
||||||
zfs list
|
|
||||||
EOF
|
|
||||||
sudo chmod +x cronjob.sh
|
|
||||||
sudo mv -f cronjob.sh /root/cronjob.sh
|
|
||||||
echo '*/5 * * * * /root/cronjob.sh' > crontab.txt
|
|
||||||
sudo crontab crontab.txt
|
|
||||||
rm crontab.txt
|
|
||||||
|
|
||||||
# check if the machines are okay
|
|
||||||
echo "Waiting for vm's to come up... (${VMs}x CPU=$CPU RAM=$RAM)"
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
while true; do
|
|
||||||
ssh 2>/dev/null zfs@192.168.122.1$i "uname -a" && break
|
|
||||||
done
|
|
||||||
done
|
|
||||||
echo "All $VMs VMs are up now."
|
|
||||||
|
|
||||||
# Save the VM's serial output (ttyS0) to /var/tmp/console.txt
|
|
||||||
# - ttyS0 on the VM corresponds to a local /dev/pty/N entry
|
|
||||||
# - use 'virsh ttyconsole' to lookup the /dev/pty/N entry
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
mkdir -p $RESPATH/vm$i
|
|
||||||
read "pty" <<< $(sudo virsh ttyconsole vm$i)
|
|
||||||
sudo nohup bash -c "cat $pty > $RESPATH/vm$i/console.txt" &
|
|
||||||
done
|
|
||||||
echo "Console logging for ${VMs}x $OS started."
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 6) load openzfs module and run the tests
|
|
||||||
#
|
|
||||||
# called on runner: qemu-6-tests.sh
|
|
||||||
# called on qemu-vm: qemu-6-tests.sh $OS $2/$3
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
function prefix() {
|
|
||||||
ID="$1"
|
|
||||||
LINE="$2"
|
|
||||||
CURRENT=$(date +%s)
|
|
||||||
TSSTART=$(cat /tmp/tsstart)
|
|
||||||
DIFF=$((CURRENT-TSSTART))
|
|
||||||
H=$((DIFF/3600))
|
|
||||||
DIFF=$((DIFF-(H*3600)))
|
|
||||||
M=$((DIFF/60))
|
|
||||||
S=$((DIFF-(M*60)))
|
|
||||||
|
|
||||||
CTR=$(cat /tmp/ctr)
|
|
||||||
echo $LINE| grep -q "^Test[: ]" && CTR=$((CTR+1)) && echo $CTR > /tmp/ctr
|
|
||||||
|
|
||||||
BASE="$HOME/work/zfs/zfs"
|
|
||||||
COLOR="$BASE/scripts/zfs-tests-color.sh"
|
|
||||||
CLINE=$(echo $LINE| grep "^Test[ :]" | sed -e 's|/usr/local|/usr|g' \
|
|
||||||
| sed -e 's| /usr/share/zfs/zfs-tests/tests/| |g' | $COLOR)
|
|
||||||
if [ -z "$CLINE" ]; then
|
|
||||||
printf "vm${ID}: %s\n" "$LINE"
|
|
||||||
else
|
|
||||||
# [vm2: 00:15:54 256] Test: functional/checksum/setup (run as root) [00:00] [PASS]
|
|
||||||
printf "[vm${ID}: %02d:%02d:%02d %4d] %s\n" \
|
|
||||||
"$H" "$M" "$S" "$CTR" "$CLINE"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# called directly on the runner
|
|
||||||
if [ -z ${1:-} ]; then
|
|
||||||
cd "/var/tmp"
|
|
||||||
source env.txt
|
|
||||||
SSH=$(which ssh)
|
|
||||||
TESTS='$HOME/zfs/.github/workflows/scripts/qemu-6-tests.sh'
|
|
||||||
echo 0 > /tmp/ctr
|
|
||||||
date "+%s" > /tmp/tsstart
|
|
||||||
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
IP="192.168.122.1$i"
|
|
||||||
daemonize -c /var/tmp -p vm${i}.pid -o vm${i}log.txt -- \
|
|
||||||
$SSH zfs@$IP $TESTS $OS $i $VMs $CI_TYPE
|
|
||||||
# handly line by line and add info prefix
|
|
||||||
stdbuf -oL tail -fq vm${i}log.txt \
|
|
||||||
| while read -r line; do prefix "$i" "$line"; done &
|
|
||||||
echo $! > vm${i}log.pid
|
|
||||||
# don't mix up the initial --- Configuration --- part
|
|
||||||
sleep 0.13
|
|
||||||
done
|
|
||||||
|
|
||||||
# wait for all vm's to finish
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
tail --pid=$(cat vm${i}.pid) -f /dev/null
|
|
||||||
pid=$(cat vm${i}log.pid)
|
|
||||||
rm -f vm${i}log.pid
|
|
||||||
kill $pid
|
|
||||||
done
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# this part runs inside qemu vm
|
|
||||||
export PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/usr/local/bin"
|
|
||||||
case "$1" in
|
|
||||||
freebsd*)
|
|
||||||
sudo kldstat -n zfs 2>/dev/null && sudo kldunload zfs
|
|
||||||
sudo -E ./zfs/scripts/zfs.sh
|
|
||||||
TDIR="/usr/local/share/zfs"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
# use xfs @ /var/tmp for all distros
|
|
||||||
sudo mv -f /var/tmp/*.txt /tmp
|
|
||||||
sudo mkfs.xfs -fq /dev/vdb
|
|
||||||
sudo mount -o noatime /dev/vdb /var/tmp
|
|
||||||
sudo chmod 1777 /var/tmp
|
|
||||||
sudo mv -f /tmp/*.txt /var/tmp
|
|
||||||
sudo -E modprobe zfs
|
|
||||||
TDIR="/usr/share/zfs"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# run functional testings and save exitcode
|
|
||||||
cd /var/tmp
|
|
||||||
TAGS=$2/$3
|
|
||||||
if [ "$4" == "quick" ]; then
|
|
||||||
export RUNFILES="sanity.run"
|
|
||||||
fi
|
|
||||||
sudo dmesg -c > dmesg-prerun.txt
|
|
||||||
mount > mount.txt
|
|
||||||
df -h > df-prerun.txt
|
|
||||||
$TDIR/zfs-tests.sh -vK -s 3GB -T $TAGS
|
|
||||||
RV=$?
|
|
||||||
df -h > df-postrun.txt
|
|
||||||
echo $RV > tests-exitcode.txt
|
|
||||||
sync
|
|
||||||
exit 0
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 7) prepare output of the results
|
|
||||||
# - this script pre-creates all needed logfiles for later summary
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# read our defined variables
|
|
||||||
cd /var/tmp
|
|
||||||
source env.txt
|
|
||||||
|
|
||||||
mkdir -p $RESPATH
|
|
||||||
|
|
||||||
# check if building the module has failed
|
|
||||||
if [ -z ${VMs:-} ]; then
|
|
||||||
cd $RESPATH
|
|
||||||
echo ":exclamation: ZFS module didn't build successfully :exclamation:" \
|
|
||||||
| tee summary.txt | tee /tmp/summary.txt
|
|
||||||
cp /var/tmp/*.txt .
|
|
||||||
tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# build was okay
|
|
||||||
BASE="$HOME/work/zfs/zfs"
|
|
||||||
MERGE="$BASE/.github/workflows/scripts/merge_summary.awk"
|
|
||||||
|
|
||||||
# catch result files of testings (vm's should be there)
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
rsync -arL zfs@192.168.122.1$i:$RESPATH/current $RESPATH/vm$i || true
|
|
||||||
scp zfs@192.168.122.1$i:"/var/tmp/*.txt" $RESPATH/vm$i || true
|
|
||||||
done
|
|
||||||
cp -f /var/tmp/*.txt $RESPATH || true
|
|
||||||
cd $RESPATH
|
|
||||||
|
|
||||||
# prepare result files for summary
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
file="vm$i/build-stderr.txt"
|
|
||||||
test -s $file && mv -f $file build-stderr.txt
|
|
||||||
|
|
||||||
file="vm$i/build-exitcode.txt"
|
|
||||||
test -s $file && mv -f $file build-exitcode.txt
|
|
||||||
|
|
||||||
file="vm$i/uname.txt"
|
|
||||||
test -s $file && mv -f $file uname.txt
|
|
||||||
|
|
||||||
file="vm$i/tests-exitcode.txt"
|
|
||||||
if [ ! -s $file ]; then
|
|
||||||
# XXX - add some tests for kernel panic's here
|
|
||||||
# tail -n 80 vm$i/console.txt | grep XYZ
|
|
||||||
echo 1 > $file
|
|
||||||
fi
|
|
||||||
rv=$(cat vm$i/tests-exitcode.txt)
|
|
||||||
test $rv != 0 && touch /tmp/have_failed_tests
|
|
||||||
|
|
||||||
file="vm$i/current/log"
|
|
||||||
if [ -s $file ]; then
|
|
||||||
cat $file >> log
|
|
||||||
awk '/\[FAIL\]|\[KILLED\]/{ show=1; print; next; }; \
|
|
||||||
/\[SKIP\]|\[PASS\]/{ show=0; } show' \
|
|
||||||
$file > /tmp/vm${i}dbg.txt
|
|
||||||
fi
|
|
||||||
|
|
||||||
file="vm${i}log.txt"
|
|
||||||
fileC="/tmp/vm${i}log.txt"
|
|
||||||
if [ -s $file ]; then
|
|
||||||
cat $file >> summary
|
|
||||||
cat $file | $BASE/scripts/zfs-tests-color.sh > $fileC
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# create summary of tests
|
|
||||||
if [ -s summary ]; then
|
|
||||||
$MERGE summary | grep -v '^/' > summary.txt
|
|
||||||
$MERGE summary | $BASE/scripts/zfs-tests-color.sh > /tmp/summary.txt
|
|
||||||
rm -f summary
|
|
||||||
else
|
|
||||||
touch summary.txt /tmp/summary.txt
|
|
||||||
fi
|
|
||||||
|
|
||||||
# create file for debugging
|
|
||||||
if [ -s log ]; then
|
|
||||||
awk '/\[FAIL\]|\[KILLED\]/{ show=1; print; next; }; \
|
|
||||||
/\[SKIP\]|\[PASS\]/{ show=0; } show' \
|
|
||||||
log > summary-failure-logs.txt
|
|
||||||
rm -f log
|
|
||||||
else
|
|
||||||
touch summary-failure-logs.txt
|
|
||||||
fi
|
|
||||||
|
|
||||||
# create debug overview for failed tests
|
|
||||||
cat summary.txt \
|
|
||||||
| awk '/\(expected PASS\)/{ if ($1!="SKIP") print $2; next; } show' \
|
|
||||||
| while read t; do
|
|
||||||
cat summary-failure-logs.txt \
|
|
||||||
| awk '$0~/Test[: ]/{ show=0; } $0~v{ show=1; } show' v="$t" \
|
|
||||||
> /tmp/fail.txt
|
|
||||||
SIZE=$(stat --printf="%s" /tmp/fail.txt)
|
|
||||||
SIZE=$((SIZE/1024))
|
|
||||||
# Test Summary:
|
|
||||||
echo "##[group]$t ($SIZE KiB)" >> /tmp/failed.txt
|
|
||||||
cat /tmp/fail.txt | $BASE/scripts/zfs-tests-color.sh >> /tmp/failed.txt
|
|
||||||
echo "##[endgroup]" >> /tmp/failed.txt
|
|
||||||
# Job Summary:
|
|
||||||
echo -e "\n<details>\n<summary>$t ($SIZE KiB)</summary><pre>" >> failed.txt
|
|
||||||
cat /tmp/fail.txt >> failed.txt
|
|
||||||
echo "</pre></details>" >> failed.txt
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -e /tmp/have_failed_tests ]; then
|
|
||||||
echo ":warning: Some tests failed!" >> failed.txt
|
|
||||||
else
|
|
||||||
echo ":thumbsup: All tests passed." >> failed.txt
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -s uname.txt ]; then
|
|
||||||
echo ":interrobang: Panic - where is my uname.txt?" > uname.txt
|
|
||||||
fi
|
|
||||||
|
|
||||||
# artifact ready now
|
|
||||||
tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 8) show colored output of results
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# read our defined variables
|
|
||||||
source /var/tmp/env.txt
|
|
||||||
cd $RESPATH
|
|
||||||
|
|
||||||
# helper function for showing some content with headline
|
|
||||||
function showfile() {
|
|
||||||
content=$(dd if=$1 bs=1024 count=400k 2>/dev/null)
|
|
||||||
if [ -z "$2" ]; then
|
|
||||||
group1=""
|
|
||||||
group2=""
|
|
||||||
else
|
|
||||||
SIZE=$(stat --printf="%s" "$file")
|
|
||||||
SIZE=$((SIZE/1024))
|
|
||||||
group1="##[group]$2 ($SIZE KiB)"
|
|
||||||
group2="##[endgroup]"
|
|
||||||
fi
|
|
||||||
cat <<EOF > tmp$$
|
|
||||||
$group1
|
|
||||||
$content
|
|
||||||
$group2
|
|
||||||
EOF
|
|
||||||
cat tmp$$
|
|
||||||
rm -f tmp$$
|
|
||||||
}
|
|
||||||
|
|
||||||
# overview
|
|
||||||
cat /tmp/summary.txt
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ -f /tmp/have_failed_tests -a -s /tmp/failed.txt ]; then
|
|
||||||
echo "Debuginfo of failed tests:"
|
|
||||||
cat /tmp/failed.txt
|
|
||||||
echo ""
|
|
||||||
cat /tmp/summary.txt | grep -v '^/'
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "\nFull logs for download:\n $1\n"
|
|
||||||
|
|
||||||
for i in $(seq 1 $VMs); do
|
|
||||||
rv=$(cat vm$i/tests-exitcode.txt)
|
|
||||||
|
|
||||||
if [ $rv = 0 ]; then
|
|
||||||
vm="[92mvm$i[0m"
|
|
||||||
else
|
|
||||||
vm="[1;91mvm$i[0m"
|
|
||||||
fi
|
|
||||||
|
|
||||||
file="vm$i/dmesg-prerun.txt"
|
|
||||||
test -s "$file" && showfile "$file" "$vm: dmesg kernel"
|
|
||||||
|
|
||||||
file="/tmp/vm${i}log.txt"
|
|
||||||
test -s "$file" && showfile "$file" "$vm: test results"
|
|
||||||
|
|
||||||
file="vm$i/console.txt"
|
|
||||||
test -s "$file" && showfile "$file" "$vm: serial console"
|
|
||||||
|
|
||||||
file="/tmp/vm${i}dbg.txt"
|
|
||||||
test -s "$file" && showfile "$file" "$vm: failure logfile"
|
|
||||||
done
|
|
||||||
|
|
||||||
test -f /tmp/have_failed_tests && exit 1
|
|
||||||
exit 0
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# 9) generate github summary page of all the testings
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
function output() {
|
|
||||||
echo -e $* >> "out-$logfile.md"
|
|
||||||
}
|
|
||||||
|
|
||||||
function outfile() {
|
|
||||||
cat "$1" >> "out-$logfile.md"
|
|
||||||
}
|
|
||||||
|
|
||||||
function outfile_plain() {
|
|
||||||
output "<pre>"
|
|
||||||
cat "$1" >> "out-$logfile.md"
|
|
||||||
output "</pre>"
|
|
||||||
}
|
|
||||||
|
|
||||||
function send2github() {
|
|
||||||
test -f "$1" || exit 0
|
|
||||||
dd if="$1" bs=1023k count=1 >> $GITHUB_STEP_SUMMARY
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://docs.github.com/en/enterprise-server@3.6/actions/using-workflows/workflow-commands-for-github-actions#step-isolation-and-limits
|
|
||||||
# Job summaries are isolated between steps and each step is restricted to a maximum size of 1MiB.
|
|
||||||
# [ ] can not show all error findings here
|
|
||||||
# [x] split files into smaller ones and create additional steps
|
|
||||||
|
|
||||||
# first call, generate all summaries
|
|
||||||
if [ ! -f out-1.md ]; then
|
|
||||||
logfile="1"
|
|
||||||
for tarfile in Logs-functional-*/qemu-*.tar; do
|
|
||||||
rm -rf vm* *.txt
|
|
||||||
if [ ! -s "$tarfile" ]; then
|
|
||||||
output "\n## Functional Tests: unknown\n"
|
|
||||||
output ":exclamation: Tarfile $tarfile is empty :exclamation:"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
tar xf "$tarfile"
|
|
||||||
test -s env.txt || continue
|
|
||||||
source env.txt
|
|
||||||
# when uname.txt is there, the other files are also ok
|
|
||||||
test -s uname.txt || continue
|
|
||||||
output "\n## Functional Tests: $OSNAME\n"
|
|
||||||
outfile_plain uname.txt
|
|
||||||
outfile_plain summary.txt
|
|
||||||
outfile failed.txt
|
|
||||||
logfile=$((logfile+1))
|
|
||||||
done
|
|
||||||
send2github out-1.md
|
|
||||||
else
|
|
||||||
send2github out-$1.md
|
|
||||||
fi
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
name: zfs-qemu
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
include_stream9:
|
|
||||||
type: boolean
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
description: 'Test on CentOS 9 stream'
|
|
||||||
include_stream10:
|
|
||||||
type: boolean
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
description: 'Test on CentOS 10 stream'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test-config:
|
|
||||||
name: Setup
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
outputs:
|
|
||||||
test_os: ${{ steps.os.outputs.os }}
|
|
||||||
ci_type: ${{ steps.os.outputs.ci_type }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Generate OS config and CI type
|
|
||||||
id: os
|
|
||||||
run: |
|
|
||||||
FULL_OS='["almalinux8", "almalinux9", "debian11", "debian12", "fedora40", "fedora41", "freebsd13-3r", "freebsd13-4s", "freebsd14-1r", "freebsd14-2s", "freebsd15-0c", "ubuntu20", "ubuntu22", "ubuntu24"]'
|
|
||||||
QUICK_OS='["almalinux8", "almalinux9", "debian12", "fedora41", "freebsd13-3r", "freebsd14-2r", "ubuntu24"]'
|
|
||||||
# determine CI type when running on PR
|
|
||||||
ci_type="full"
|
|
||||||
if ${{ github.event_name == 'pull_request' }}; then
|
|
||||||
head=${{ github.event.pull_request.head.sha }}
|
|
||||||
base=${{ github.event.pull_request.base.sha }}
|
|
||||||
ci_type=$(python3 .github/workflows/scripts/generate-ci-type.py $head $base)
|
|
||||||
fi
|
|
||||||
if [ "$ci_type" == "quick" ]; then
|
|
||||||
os_selection="$QUICK_OS"
|
|
||||||
else
|
|
||||||
os_selection="$FULL_OS"
|
|
||||||
fi
|
|
||||||
os_json=$(echo ${os_selection} | jq -c)
|
|
||||||
|
|
||||||
# Add optional runners
|
|
||||||
if [ "${{ github.event.inputs.include_stream9 }}" == 'true' ]; then
|
|
||||||
os_json=$(echo $os_json | jq -c '. += ["centos-stream9"]')
|
|
||||||
fi
|
|
||||||
if [ "${{ github.event.inputs.include_stream10 }}" == 'true' ]; then
|
|
||||||
os_json=$(echo $os_json | jq -c '. += ["centos-stream10"]')
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo $os_json
|
|
||||||
echo "os=$os_json" >> $GITHUB_OUTPUT
|
|
||||||
echo "ci_type=$ci_type" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
qemu-vm:
|
|
||||||
name: qemu-x86
|
|
||||||
needs: [ test-config ]
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# rhl: almalinux8, almalinux9, centos-stream9, fedora40, fedora41
|
|
||||||
# debian: debian11, debian12, ubuntu20, ubuntu22, ubuntu24
|
|
||||||
# misc: archlinux, tumbleweed
|
|
||||||
# FreeBSD variants of 2024-12:
|
|
||||||
# FreeBSD Release: freebsd13-3r, freebsd13-4r, freebsd14-1r, freebsd14-2r
|
|
||||||
# FreeBSD Stable: freebsd13-4s, freebsd14-2s
|
|
||||||
# FreeBSD Current: freebsd15-0c
|
|
||||||
os: ${{ fromJson(needs.test-config.outputs.test_os) }}
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
|
|
||||||
- name: Setup QEMU
|
|
||||||
timeout-minutes: 10
|
|
||||||
run: .github/workflows/scripts/qemu-1-setup.sh
|
|
||||||
|
|
||||||
- name: Start build machine
|
|
||||||
timeout-minutes: 10
|
|
||||||
run: .github/workflows/scripts/qemu-2-start.sh ${{ matrix.os }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
timeout-minutes: 20
|
|
||||||
run: |
|
|
||||||
echo "Install dependencies in QEMU machine"
|
|
||||||
IP=192.168.122.10
|
|
||||||
while pidof /usr/bin/qemu-system-x86_64 >/dev/null; do
|
|
||||||
ssh 2>/dev/null zfs@$IP "uname -a" && break
|
|
||||||
done
|
|
||||||
scp .github/workflows/scripts/qemu-3-deps.sh zfs@$IP:qemu-3-deps.sh
|
|
||||||
PID=`pidof /usr/bin/qemu-system-x86_64`
|
|
||||||
ssh zfs@$IP '$HOME/qemu-3-deps.sh' ${{ matrix.os }}
|
|
||||||
# wait for poweroff to succeed
|
|
||||||
tail --pid=$PID -f /dev/null
|
|
||||||
sleep 5 # avoid this: "error: Domain is already active"
|
|
||||||
rm -f $HOME/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Build modules
|
|
||||||
timeout-minutes: 30
|
|
||||||
run: |
|
|
||||||
echo "Build modules in QEMU machine"
|
|
||||||
sudo virsh start openzfs
|
|
||||||
IP=192.168.122.10
|
|
||||||
while pidof /usr/bin/qemu-system-x86_64 >/dev/null; do
|
|
||||||
ssh 2>/dev/null zfs@$IP "uname -a" && break
|
|
||||||
done
|
|
||||||
rsync -ar $HOME/work/zfs/zfs zfs@$IP:./
|
|
||||||
ssh zfs@$IP '$HOME/zfs/.github/workflows/scripts/qemu-4-build.sh' ${{ matrix.os }}
|
|
||||||
|
|
||||||
- name: Setup testing machines
|
|
||||||
timeout-minutes: 5
|
|
||||||
run: .github/workflows/scripts/qemu-5-setup.sh
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
timeout-minutes: 270
|
|
||||||
run: .github/workflows/scripts/qemu-6-tests.sh
|
|
||||||
env:
|
|
||||||
CI_TYPE: ${{ needs.test-config.outputs.ci_type }}
|
|
||||||
|
|
||||||
- name: Prepare artifacts
|
|
||||||
if: always()
|
|
||||||
timeout-minutes: 10
|
|
||||||
run: .github/workflows/scripts/qemu-7-prepare.sh
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
id: artifact-upload
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: Logs-functional-${{ matrix.os }}
|
|
||||||
path: /tmp/qemu-${{ matrix.os }}.tar
|
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|
||||||
- name: Test Summary
|
|
||||||
if: always()
|
|
||||||
run: .github/workflows/scripts/qemu-8-summary.sh '${{ steps.artifact-upload.outputs.artifact-url }}'
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if: always()
|
|
||||||
name: Cleanup
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [ qemu-vm ]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- uses: actions/download-artifact@v4
|
|
||||||
- name: Generating summary
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 2
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 3
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 4
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 5
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 6
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 7
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 8
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 9
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 10
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 11
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 12
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 13
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 14
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 15
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 16
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 17
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 18
|
|
||||||
- name: Generating summary...
|
|
||||||
run: .github/workflows/scripts/qemu-9-summary-page.sh 19
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: Summary Files
|
|
||||||
path: out-*
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
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 python3-packaging \
|
||||||
|
libcurl4-openssl-dev
|
||||||
|
- 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 for cloud-init bug
|
||||||
|
# see https://github.com/openzfs/zfs/issues/12644
|
||||||
|
FILE=/lib/udev/rules.d/10-cloud-init-hook-hotplug.rules
|
||||||
|
if [ -r "${FILE}" ]; then
|
||||||
|
HASH=$(md5sum "${FILE}" | awk '{ print $1 }')
|
||||||
|
if [ "${HASH}" = "121ff0ef1936cd2ef65aec0458a35772" ]; then
|
||||||
|
# Just shove a zd* exclusion right above the hotplug hook...
|
||||||
|
sudo sed -i -e s/'LABEL="cloudinit_hook"'/'KERNEL=="zd*", GOTO="cloudinit_end"\n&'/ "${FILE}"
|
||||||
|
sudo udevadm control --reload-rules
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# 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 -vR -s 3G
|
||||||
|
timeout-minutes: 330
|
||||||
|
- 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 /var/tmp/test_results -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
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
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 python3-packaging \
|
||||||
|
libcurl4-openssl-dev
|
||||||
|
- 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 for cloud-init bug
|
||||||
|
# see https://github.com/openzfs/zfs/issues/12644
|
||||||
|
FILE=/lib/udev/rules.d/10-cloud-init-hook-hotplug.rules
|
||||||
|
if [ -r "${FILE}" ]; then
|
||||||
|
HASH=$(md5sum "${FILE}" | awk '{ print $1 }')
|
||||||
|
if [ "${HASH}" = "121ff0ef1936cd2ef65aec0458a35772" ]; then
|
||||||
|
# Just shove a zd* exclusion right above the hotplug hook...
|
||||||
|
sudo sed -i -e s/'LABEL="cloudinit_hook"'/'KERNEL=="zd*", GOTO="cloudinit_end"\n&'/ "${FILE}"
|
||||||
|
sudo udevadm control --reload-rules
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# 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 -vR -s 3G -r sanity
|
||||||
|
timeout-minutes: 330
|
||||||
|
- 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 /var/tmp/test_results -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
|
||||||
+23
-33
@@ -4,63 +4,53 @@ on:
|
|||||||
push:
|
push:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
zloop:
|
tests:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
TEST_DIR: /var/tmp/zloop
|
TEST_DIR: /var/tmp/zloop
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get purge -y snapd google-chrome-stable firefox
|
sudo apt-get update
|
||||||
ONLY_DEPS=1 .github/workflows/scripts/qemu-3-deps.sh ubuntu24
|
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 python-packaging \
|
||||||
|
python3 python3-dev python3-setuptools python3-cffi python3-packaging
|
||||||
- name: Autogen.sh
|
- name: Autogen.sh
|
||||||
run: |
|
run: |
|
||||||
sed -i '/DEBUG_CFLAGS="-Werror"/s/^/#/' config/zfs-build.m4
|
sh autogen.sh
|
||||||
./autogen.sh
|
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
./configure --prefix=/usr --enable-debug --enable-debuginfo \
|
./configure --enable-debug --enable-debuginfo
|
||||||
--enable-asan --enable-ubsan \
|
|
||||||
--enable-debug-kmem --enable-debug-kmem-tracking
|
|
||||||
- name: Make
|
- name: Make
|
||||||
run: |
|
run: |
|
||||||
make -j$(nproc)
|
make --no-print-directory -s pkg-utils pkg-kmod
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
sudo make install
|
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 depmod
|
||||||
sudo modprobe zfs
|
sudo modprobe zfs
|
||||||
- name: Tests
|
- name: Tests
|
||||||
run: |
|
run: |
|
||||||
sudo mkdir -p $TEST_DIR
|
sudo mkdir -p $TEST_DIR
|
||||||
# run for 10 minutes or at most 6 iterations for a maximum runner
|
# run for 20 minutes to have a total runner time of 30 minutes
|
||||||
# time of 60 minutes.
|
sudo /usr/share/zfs/zloop.sh -t 1200 -l -m1 -- -T 120 -P 60
|
||||||
sudo /usr/share/zfs/zloop.sh -t 600 -I 6 -l -m 1 -- -T 120 -P 60
|
|
||||||
- name: Prepare artifacts
|
- name: Prepare artifacts
|
||||||
if: failure()
|
if: failure()
|
||||||
run: |
|
run: |
|
||||||
sudo chmod +r -R $TEST_DIR/
|
sudo chmod +r -R $TEST_DIR/
|
||||||
- name: Ztest log
|
- uses: actions/upload-artifact@v2
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
grep -B10 -A1000 'ASSERT' $TEST_DIR/*/ztest.out || tail -n 1000 $TEST_DIR/*/ztest.out
|
|
||||||
- name: Gdb log
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
sed -n '/Backtraces (full)/q;p' $TEST_DIR/*/ztest.gdb
|
|
||||||
- name: Zdb log
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
cat $TEST_DIR/*/ztest.zdb
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: Logs
|
name: Logs
|
||||||
@@ -68,7 +58,7 @@ jobs:
|
|||||||
/var/tmp/zloop/*/
|
/var/tmp/zloop/*/
|
||||||
!/var/tmp/zloop/*/vdev/
|
!/var/tmp/zloop/*/vdev/
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v2
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: Pool files
|
name: Pool files
|
||||||
|
|||||||
+36
-56
@@ -1,7 +1,6 @@
|
|||||||
#
|
#
|
||||||
# This is the top-level .gitignore file:
|
# N.B.
|
||||||
# ignore everything except a list of allowed files.
|
# This is the toplevel .gitignore file.
|
||||||
#
|
|
||||||
# This is not the place for entries that are specific to
|
# This is not the place for entries that are specific to
|
||||||
# a subdirectory. Instead add those files to the
|
# a subdirectory. Instead add those files to the
|
||||||
# .gitignore file in that subdirectory.
|
# .gitignore file in that subdirectory.
|
||||||
@@ -11,57 +10,6 @@
|
|||||||
# command after changing this file, to see if there are
|
# command after changing this file, to see if there are
|
||||||
# any tracked files which get ignored after the change.
|
# any tracked files which get ignored after the change.
|
||||||
|
|
||||||
*
|
|
||||||
|
|
||||||
!.github
|
|
||||||
!cmd
|
|
||||||
!config
|
|
||||||
!contrib
|
|
||||||
!etc
|
|
||||||
!include
|
|
||||||
!lib
|
|
||||||
!man
|
|
||||||
!module
|
|
||||||
!rpm
|
|
||||||
!scripts
|
|
||||||
!tests
|
|
||||||
!udev
|
|
||||||
|
|
||||||
!.github/**
|
|
||||||
!cmd/**
|
|
||||||
!config/**
|
|
||||||
!contrib/**
|
|
||||||
!etc/**
|
|
||||||
!include/**
|
|
||||||
!lib/**
|
|
||||||
!man/**
|
|
||||||
!module/**
|
|
||||||
!rpm/**
|
|
||||||
!scripts/**
|
|
||||||
!tests/**
|
|
||||||
!udev/**
|
|
||||||
|
|
||||||
!.editorconfig
|
|
||||||
!.cirrus.yml
|
|
||||||
!.gitignore
|
|
||||||
!.gitmodules
|
|
||||||
!.mailmap
|
|
||||||
!AUTHORS
|
|
||||||
!autogen.sh
|
|
||||||
!CODE_OF_CONDUCT.md
|
|
||||||
!configure.ac
|
|
||||||
!copy-builtin
|
|
||||||
!COPYRIGHT
|
|
||||||
!LICENSE
|
|
||||||
!Makefile.am
|
|
||||||
!META
|
|
||||||
!NEWS
|
|
||||||
!NOTICE
|
|
||||||
!README.md
|
|
||||||
!RELEASES.md
|
|
||||||
!TEST
|
|
||||||
!zfs.release.in
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Normal rules
|
# Normal rules
|
||||||
#
|
#
|
||||||
@@ -83,8 +31,40 @@
|
|||||||
modules.order
|
modules.order
|
||||||
Makefile
|
Makefile
|
||||||
Makefile.in
|
Makefile.in
|
||||||
changelog
|
|
||||||
|
#
|
||||||
|
# Top level generated files specific to this top level dir
|
||||||
|
#
|
||||||
|
/bin
|
||||||
|
/build
|
||||||
|
/configure
|
||||||
|
/config.log
|
||||||
|
/config.status
|
||||||
|
/libtool
|
||||||
|
/zfs_config.h
|
||||||
|
/zfs_config.h.in
|
||||||
|
/zfs.release
|
||||||
|
/stamp-h1
|
||||||
|
/aclocal.m4
|
||||||
|
/autom4te.cache
|
||||||
|
|
||||||
|
#
|
||||||
|
# Top level generic files
|
||||||
|
#
|
||||||
|
!.gitignore
|
||||||
|
tags
|
||||||
|
TAGS
|
||||||
|
current
|
||||||
|
cscope.*
|
||||||
|
*.rpm
|
||||||
|
*.deb
|
||||||
|
*.tar.gz
|
||||||
*.patch
|
*.patch
|
||||||
*.orig
|
*.orig
|
||||||
*.tmp
|
|
||||||
*.log
|
*.log
|
||||||
|
*.tmp
|
||||||
|
venv
|
||||||
|
|
||||||
|
*.so
|
||||||
|
*.so.debug
|
||||||
|
*.so.full
|
||||||
|
|||||||
@@ -1,216 +0,0 @@
|
|||||||
# This file maps the name+email seen in a commit back to a canonical
|
|
||||||
# name+email. Git will replace the commit name/email with the canonical version
|
|
||||||
# wherever it sees it.
|
|
||||||
#
|
|
||||||
# If there is a commit in the history with a "wrong" name or email, list it
|
|
||||||
# here. If you regularly commit with an alternate name or email address and
|
|
||||||
# would like to ensure that you are always listed consistently in the repo, add
|
|
||||||
# mapping here.
|
|
||||||
#
|
|
||||||
# On the other hand, if you use multiple names or email addresses legitimately
|
|
||||||
# (eg you use a company email address for your paid OpenZFS work, and a
|
|
||||||
# personal address for your evening side projects), then don't map one to the
|
|
||||||
# other here.
|
|
||||||
#
|
|
||||||
# The most common formats are:
|
|
||||||
#
|
|
||||||
# Canonical Name <canonical-email>
|
|
||||||
# Canonical Name <canonical-email> <commit-email>
|
|
||||||
# Canonical Name <canonical-email> Commit Name <commit-email>
|
|
||||||
#
|
|
||||||
# See https://git-scm.com/docs/gitmailmap for more info.
|
|
||||||
|
|
||||||
# These maps are making names consistent where they have varied but the email
|
|
||||||
# address has never changed. In most cases, the full name is in the
|
|
||||||
# Signed-off-by of a commit with a matching author.
|
|
||||||
Ahelenia Ziemiańska <nabijaczleweli@gmail.com>
|
|
||||||
Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
|
|
||||||
Alex John <alex@stty.io>
|
|
||||||
Andreas Dilger <adilger@dilger.ca>
|
|
||||||
Andrew Walker <awalker@ixsystems.com>
|
|
||||||
Benedikt Neuffer <github@itfriend.de>
|
|
||||||
Chengfei Zhu <chengfeix.zhu@intel.com>
|
|
||||||
ChenHao Lu <18302010006@fudan.edu.cn>
|
|
||||||
Chris Lindee <chris.lindee+github@gmail.com>
|
|
||||||
Colm Buckley <colm@tuatha.org>
|
|
||||||
Crag Wang <crag0715@gmail.com>
|
|
||||||
Damian Szuberski <szuberskidamian@gmail.com>
|
|
||||||
Daniel Kolesa <daniel@octaforge.org>
|
|
||||||
Debabrata Banerjee <dbavatar@gmail.com>
|
|
||||||
Finix Yan <yanchongwen@hotmail.com>
|
|
||||||
Gaurav Kumar <gauravk.18@gmail.com>
|
|
||||||
Gionatan Danti <g.danti@assyoma.it>
|
|
||||||
Glenn Washburn <development@efficientek.com>
|
|
||||||
Gordan Bobic <gordan.bobic@gmail.com>
|
|
||||||
Gregory Bartholomew <gregory.lee.bartholomew@gmail.com>
|
|
||||||
hedong zhang <h_d_zhang@163.com>
|
|
||||||
Ilkka Sovanto <github@ilkka.kapsi.fi>
|
|
||||||
InsanePrawn <Insane.Prawny@gmail.com>
|
|
||||||
Jason Cohen <jwittlincohen@gmail.com>
|
|
||||||
Jason Harmening <jason.harmening@gmail.com>
|
|
||||||
Jeremy Faulkner <gldisater@gmail.com>
|
|
||||||
Jinshan Xiong <jinshan.xiong@gmail.com>
|
|
||||||
John Poduska <jpoduska@datto.com>
|
|
||||||
Justin Scholz <git@justinscholz.de>
|
|
||||||
Ka Ho Ng <khng300@gmail.com>
|
|
||||||
Kash Pande <github@tripleback.net>
|
|
||||||
Kay Pedersen <christianpe96@gmail.com>
|
|
||||||
KernelOfTruth <kerneloftruth@gmail.com>
|
|
||||||
Liu Hua <liu.hua130@zte.com.cn>
|
|
||||||
Liu Qing <winglq@gmail.com>
|
|
||||||
loli10K <ezomori.nozomu@gmail.com>
|
|
||||||
Mart Frauenlob <allkind@fastest.cc>
|
|
||||||
Matthias Blankertz <matthias@blankertz.org>
|
|
||||||
Michael Gmelin <grembo@FreeBSD.org>
|
|
||||||
Olivier Mazouffre <olivier.mazouffre@ims-bordeaux.fr>
|
|
||||||
Piotr Kubaj <pkubaj@anongoth.pl>
|
|
||||||
Quentin Zdanis <zdanisq@gmail.com>
|
|
||||||
Roberto Ricci <ricci@disroot.org>
|
|
||||||
Rob Norris <robn@despairlabs.com>
|
|
||||||
Rob Norris <rob.norris@klarasystems.com>
|
|
||||||
Sam Lunt <samuel.j.lunt@gmail.com>
|
|
||||||
Sanjeev Bagewadi <sanjeev.bagewadi@gmail.com>
|
|
||||||
Sebastian Wuerl <s.wuerl@mailbox.org>
|
|
||||||
Stoiko Ivanov <github@nomore.at>
|
|
||||||
Tamas TEVESZ <ice@extreme.hu>
|
|
||||||
WHR <msl0000023508@gmail.com>
|
|
||||||
Yanping Gao <yanping.gao@xtaotech.com>
|
|
||||||
Youzhong Yang <youzhong@gmail.com>
|
|
||||||
|
|
||||||
# Signed-off-by: overriding Author:
|
|
||||||
Ryan <errornointernet@envs.net> <error.nointernet@gmail.com>
|
|
||||||
Sietse <sietse@wizdom.nu> <uglymotha@wizdom.nu>
|
|
||||||
Qiuhao Chen <chenqiuhao1997@gmail.com> <haohao0924@126.com>
|
|
||||||
Yuxin Wang <yuxinwang9999@gmail.com> <Bi11gates9999@gmail.com>
|
|
||||||
Zhenlei Huang <zlei@FreeBSD.org> <zlei.huang@gmail.com>
|
|
||||||
|
|
||||||
# Commits from strange places, long ago
|
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov> <behlendo@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
|
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov> <behlendo@fedora-17-amd64.(none)>
|
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov> <behlendo@myhost.(none)>
|
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov> <ubuntu@ip-172-31-16-145.us-west-1.compute.internal>
|
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov> <ubuntu@ip-172-31-20-6.us-west-1.compute.internal>
|
|
||||||
Herb Wartens <wartens2@llnl.gov> <wartens2@7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c>
|
|
||||||
Ned Bass <bass6@llnl.gov> <bass6@zeno1.(none)>
|
|
||||||
Tulsi Jain <tulsi.jain@delphix.com> <tulsi.jain@Tulsi-Jains-MacBook-Pro.local>
|
|
||||||
|
|
||||||
# Mappings from Github no-reply addresses
|
|
||||||
ajs124 <git@ajs124.de> <ajs124@users.noreply.github.com>
|
|
||||||
Alek Pinchuk <apinchuk@axcient.com> <alek-p@users.noreply.github.com>
|
|
||||||
Alexander Lobakin <alobakin@pm.me> <solbjorn@users.noreply.github.com>
|
|
||||||
Alexey Smirnoff <fling@member.fsf.org> <fling-@users.noreply.github.com>
|
|
||||||
Allen Holl <allen.m.holl@gmail.com> <65494904+allen-4@users.noreply.github.com>
|
|
||||||
Alphan Yılmaz <alphanyilmaz@gmail.com> <a1ea321@users.noreply.github.com>
|
|
||||||
Ameer Hamza <ahamza@ixsystems.com> <106930537+ixhamza@users.noreply.github.com>
|
|
||||||
Andrew J. Hesford <ajh@sideband.org> <48421688+ahesford@users.noreply.github.com>>
|
|
||||||
Andrew Sun <me@andrewsun.com> <as-com@users.noreply.github.com>
|
|
||||||
Aron Xu <happyaron.xu@gmail.com> <happyaron@users.noreply.github.com>
|
|
||||||
Arun KV <arun.kv@datacore.com> <65647132+arun-kv@users.noreply.github.com>
|
|
||||||
Ben Wolsieffer <benwolsieffer@gmail.com> <lopsided98@users.noreply.github.com>
|
|
||||||
bernie1995 <bernie.pikes@gmail.com> <42413912+bernie1995@users.noreply.github.com>
|
|
||||||
Bojan Novković <bnovkov@FreeBSD.org> <72801811+bnovkov@users.noreply.github.com>
|
|
||||||
Boris Protopopov <boris.protopopov@actifio.com> <bprotopopov@users.noreply.github.com>
|
|
||||||
Brad Forschinger <github@bnjf.id.au> <bnjf@users.noreply.github.com>
|
|
||||||
Brandon Thetford <brandon@dodecatec.com> <dodexahedron@users.noreply.github.com>
|
|
||||||
buzzingwires <buzzingwires@outlook.com> <131118055+buzzingwires@users.noreply.github.com>
|
|
||||||
Cedric Maunoury <cedric.maunoury@gmail.com> <38213715+cedricmaunoury@users.noreply.github.com>
|
|
||||||
Charles Suh <charles.suh@gmail.com> <charlessuh@users.noreply.github.com>
|
|
||||||
Chris Peredun <chris.peredun@ixsystems.com> <126915832+chrisperedun@users.noreply.github.com>
|
|
||||||
Dacian Reece-Stremtan <dacianstremtan@gmail.com> <35844628+dacianstremtan@users.noreply.github.com>
|
|
||||||
Damian Szuberski <szuberskidamian@gmail.com> <30863496+szubersk@users.noreply.github.com>
|
|
||||||
Daniel Hiepler <d-git@coderdu.de> <32984777+heeplr@users.noreply.github.com>
|
|
||||||
Daniel Kobras <d.kobras@science-computing.de> <sckobras@users.noreply.github.com>
|
|
||||||
Daniel Reichelt <hacking@nachtgeist.net> <nachtgeist@users.noreply.github.com>
|
|
||||||
David Quigley <david.quigley@intel.com> <dpquigl@users.noreply.github.com>
|
|
||||||
Dennis R. Friedrichsen <dennis.r.friedrichsen@gmail.com> <31087738+dennisfriedrichsen@users.noreply.github.com>
|
|
||||||
Dex Wood <slash2314@gmail.com> <slash2314@users.noreply.github.com>
|
|
||||||
DHE <git@dehacked.net> <DeHackEd@users.noreply.github.com>
|
|
||||||
Dmitri John Ledkov <dimitri.ledkov@canonical.com> <19779+xnox@users.noreply.github.com>
|
|
||||||
Dries Michiels <driesm.michiels@gmail.com> <32487486+driesmp@users.noreply.github.com>
|
|
||||||
Edmund Nadolski <edmund.nadolski@ixsystems.com> <137826107+ednadolski-ix@users.noreply.github.com>
|
|
||||||
Érico Nogueira <erico.erc@gmail.com> <34201958+ericonr@users.noreply.github.com>
|
|
||||||
Fedor Uporov <fuporov.vstack@gmail.com> <60701163+fuporovvStack@users.noreply.github.com>
|
|
||||||
Felix Dörre <felix@dogcraft.de> <felixdoerre@users.noreply.github.com>
|
|
||||||
Felix Neumärker <xdch47@posteo.de> <34678034+xdch47@users.noreply.github.com>
|
|
||||||
Finix Yan <yancw@info2soft.com> <Finix1979@users.noreply.github.com>
|
|
||||||
Gaurav Kumar <gauravk.18@gmail.com> <gaurkuma@users.noreply.github.com>
|
|
||||||
George Gaydarov <git@gg7.io> <gg7@users.noreply.github.com>
|
|
||||||
Georgy Yakovlev <gyakovlev@gentoo.org> <168902+gyakovlev@users.noreply.github.com>
|
|
||||||
Gerardwx <gerardw@alum.mit.edu> <Gerardwx@users.noreply.github.com>
|
|
||||||
Gian-Carlo DeFazio <defazio1@llnl.gov> <defaziogiancarlo@users.noreply.github.com>
|
|
||||||
Giuseppe Di Natale <dinatale2@llnl.gov> <dinatale2@users.noreply.github.com>
|
|
||||||
Hajo Möller <dasjoe@gmail.com> <dasjoe@users.noreply.github.com>
|
|
||||||
Harry Mallon <hjmallon@gmail.com> <1816667+hjmallon@users.noreply.github.com>
|
|
||||||
Hiếu Lê <leorize+oss@disroot.org> <alaviss@users.noreply.github.com>
|
|
||||||
Jake Howard <git@theorangeone.net> <RealOrangeOne@users.noreply.github.com>
|
|
||||||
James Cowgill <james.cowgill@mips.com> <jcowgill@users.noreply.github.com>
|
|
||||||
Jaron Kent-Dobias <jaron@kent-dobias.com> <kentdobias@users.noreply.github.com>
|
|
||||||
Jason King <jason.king@joyent.com> <jasonbking@users.noreply.github.com>
|
|
||||||
Jeff Dike <jdike@akamai.com> <52420226+jdike@users.noreply.github.com>
|
|
||||||
Jitendra Patidar <jitendra.patidar@nutanix.com> <53164267+jsai20@users.noreply.github.com>
|
|
||||||
João Carlos Mendes Luís <jonny@jonny.eng.br> <dioni21@users.noreply.github.com>
|
|
||||||
John Eismeier <john.eismeier@gmail.com> <32205350+jeis2497052@users.noreply.github.com>
|
|
||||||
John L. Hammond <john.hammond@intel.com> <35266395+jhammond-intel@users.noreply.github.com>
|
|
||||||
John-Mark Gurney <jmg@funkthat.com> <jmgurney@users.noreply.github.com>
|
|
||||||
John Ramsden <johnramsden@riseup.net> <johnramsden@users.noreply.github.com>
|
|
||||||
Jonathon Fernyhough <jonathon@m2x.dev> <559369+jonathonf@users.noreply.github.com>
|
|
||||||
Jose Luis Duran <jlduran@gmail.com> <jlduran@users.noreply.github.com>
|
|
||||||
Justin Hibbits <chmeeedalf@gmail.com> <chmeeedalf@users.noreply.github.com>
|
|
||||||
Kevin Greene <kevin.greene@delphix.com> <104801862+kxgreene@users.noreply.github.com>
|
|
||||||
Kevin Jin <lostking2008@hotmail.com> <33590050+jxdking@users.noreply.github.com>
|
|
||||||
Kevin P. Fleming <kevin@km6g.us> <kpfleming@users.noreply.github.com>
|
|
||||||
Krzysztof Piecuch <piecuch@kpiecuch.pl> <3964215+pikrzysztof@users.noreply.github.com>
|
|
||||||
Kyle Evans <kevans@FreeBSD.org> <kevans91@users.noreply.github.com>
|
|
||||||
Laurențiu Nicola <lnicola@dend.ro> <lnicola@users.noreply.github.com>
|
|
||||||
loli10K <ezomori.nozomu@gmail.com> <loli10K@users.noreply.github.com>
|
|
||||||
Lorenz Hüdepohl <dev@stellardeath.org> <lhuedepohl@users.noreply.github.com>
|
|
||||||
Luís Henriques <henrix@camandro.org> <73643340+lumigch@users.noreply.github.com>
|
|
||||||
Marcin Skarbek <git@skarbek.name> <mskarbek@users.noreply.github.com>
|
|
||||||
Matt Fiddaman <github@m.fiddaman.uk> <81489167+matt-fidd@users.noreply.github.com>
|
|
||||||
Maxim Filimonov <che@bein.link> <part1zano@users.noreply.github.com>
|
|
||||||
Max Zettlmeißl <max@zettlmeissl.de> <6818198+maxz@users.noreply.github.com>
|
|
||||||
Michael Niewöhner <foss@mniewoehner.de> <c0d3z3r0@users.noreply.github.com>
|
|
||||||
Michael Zhivich <mzhivich@akamai.com> <33133421+mzhivich@users.noreply.github.com>
|
|
||||||
MigeljanImeri <ImeriMigel@gmail.com> <78048439+MigeljanImeri@users.noreply.github.com>
|
|
||||||
Mo Zhou <cdluminate@gmail.com> <5723047+cdluminate@users.noreply.github.com>
|
|
||||||
Nick Mattis <nickm970@gmail.com> <nmattis@users.noreply.github.com>
|
|
||||||
omni <omni+vagant@hack.org> <79493359+omnivagant@users.noreply.github.com>
|
|
||||||
Pablo Correa Gómez <ablocorrea@hotmail.com> <32678034+pablofsf@users.noreply.github.com>
|
|
||||||
Paul Zuchowski <pzuchowski@datto.com> <31706010+PaulZ-98@users.noreply.github.com>
|
|
||||||
Peter Ashford <ashford@accs.com> <pashford@users.noreply.github.com>
|
|
||||||
Peter Dave Hello <hsu@peterdavehello.org> <PeterDaveHello@users.noreply.github.com>
|
|
||||||
Peter Wirdemo <peter.wirdemo@gmail.com> <4224155+pewo@users.noreply.github.com>
|
|
||||||
Petros Koutoupis <petros@petroskoutoupis.com> <pkoutoupis@users.noreply.github.com>
|
|
||||||
Ping Huang <huangping@smartx.com> <101400146+hpingfs@users.noreply.github.com>
|
|
||||||
Piotr P. Stefaniak <pstef@freebsd.org> <pstef@users.noreply.github.com>
|
|
||||||
Richard Allen <belperite@gmail.com> <33836503+belperite@users.noreply.github.com>
|
|
||||||
Rich Ercolani <rincebrain@gmail.com> <214141+rincebrain@users.noreply.github.com>
|
|
||||||
Rick Macklem <rmacklem@uoguelph.ca> <64620010+rmacklem@users.noreply.github.com>
|
|
||||||
Rob Wing <rob.wing@klarasystems.com> <98866084+rob-wing@users.noreply.github.com>
|
|
||||||
Roman Strashkin <roman.strashkin@nexenta.com> <Ramzec@users.noreply.github.com>
|
|
||||||
Ryan Hirasaki <ryanhirasaki@gmail.com> <4690732+RyanHir@users.noreply.github.com>
|
|
||||||
Samuel Wycliffe J <samwyc@hpe.com> <115969550+samwyc@users.noreply.github.com>
|
|
||||||
Samuel Wycliffe <samuelwycliffe@gmail.com> <50765275+npc203@users.noreply.github.com>
|
|
||||||
Savyasachee Jha <hi@savyasacheejha.com> <savyajha@users.noreply.github.com>
|
|
||||||
Scott Colby <scott@scolby.com> <scolby33@users.noreply.github.com>
|
|
||||||
Sean Eric Fagan <kithrup@mac.com> <kithrup@users.noreply.github.com>
|
|
||||||
Spencer Kinny <spencerkinny1995@gmail.com> <30333052+Spencer-Kinny@users.noreply.github.com>
|
|
||||||
Srikanth N S <srikanth.nagasubbaraoseetharaman@hpe.com> <75025422+nssrikanth@users.noreply.github.com>
|
|
||||||
Stefan Lendl <s.lendl@proxmox.com> <1321542+stfl@users.noreply.github.com>
|
|
||||||
Thomas Bertschinger <bertschinger@lanl.gov> <101425190+bertschinger@users.noreply.github.com>
|
|
||||||
Thomas Geppert <geppi@digitx.de> <geppi@users.noreply.github.com>
|
|
||||||
Tim Crawford <tcrawford@datto.com> <crawfxrd@users.noreply.github.com>
|
|
||||||
Todd Seidelmann <18294602+seidelma@users.noreply.github.com>
|
|
||||||
Tom Matthews <tom@axiom-partners.com> <tomtastic@users.noreply.github.com>
|
|
||||||
Tony Perkins <tperkins@datto.com> <62951051+tony-zfs@users.noreply.github.com>
|
|
||||||
Torsten Wörtwein <twoertwein@gmail.com> <twoertwein@users.noreply.github.com>
|
|
||||||
Tulsi Jain <tulsi.jain@delphix.com> <TulsiJain@users.noreply.github.com>
|
|
||||||
Václav Skála <skala@vshosting.cz> <33496485+vaclavskala@users.noreply.github.com>
|
|
||||||
Vaibhav Bhanawat <vaibhav.bhanawat@delphix.com> <88050553+vaibhav-delphix@users.noreply.github.com>
|
|
||||||
Violet Purcell <vimproved@inventati.org> <66446404+vimproved@users.noreply.github.com>
|
|
||||||
Vipin Kumar Verma <vipin.verma@hpe.com> <75025470+vermavipinkumar@users.noreply.github.com>
|
|
||||||
Wolfgang Bumiller <w.bumiller@proxmox.com> <Blub@users.noreply.github.com>
|
|
||||||
XDTG <click1799@163.com> <35128600+XDTG@users.noreply.github.com>
|
|
||||||
xtouqh <xtouqh@hotmail.com> <72357159+xtouqh@users.noreply.github.com>
|
|
||||||
Yuri Pankov <yuripv@FreeBSD.org> <113725409+yuripv@users.noreply.github.com>
|
|
||||||
Yuri Pankov <yuripv@FreeBSD.org> <82001006+yuripv@users.noreply.github.com>
|
|
||||||
@@ -10,671 +10,299 @@ PAST MAINTAINERS:
|
|||||||
CONTRIBUTORS:
|
CONTRIBUTORS:
|
||||||
|
|
||||||
Aaron Fineman <abyxcos@gmail.com>
|
Aaron Fineman <abyxcos@gmail.com>
|
||||||
Adam D. Moss <c@yotes.com>
|
|
||||||
Adam Leventhal <ahl@delphix.com>
|
Adam Leventhal <ahl@delphix.com>
|
||||||
Adam Stevko <adam.stevko@gmail.com>
|
Adam Stevko <adam.stevko@gmail.com>
|
||||||
adisbladis <adis@blad.is>
|
|
||||||
Adrian Chadd <adrian@freebsd.org>
|
|
||||||
Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
|
|
||||||
Ahmed G <ahmedg@delphix.com>
|
Ahmed G <ahmedg@delphix.com>
|
||||||
Aidan Harris <me@aidanharr.is>
|
|
||||||
AJ Jordan <alex@strugee.net>
|
|
||||||
ajs124 <git@ajs124.de>
|
|
||||||
Akash Ayare <aayare@delphix.com>
|
Akash Ayare <aayare@delphix.com>
|
||||||
Akash B <akash-b@hpe.com>
|
|
||||||
Alan Somers <asomers@gmail.com>
|
Alan Somers <asomers@gmail.com>
|
||||||
Alar Aun <spamtoaun@gmail.com>
|
Alar Aun <spamtoaun@gmail.com>
|
||||||
Albert Lee <trisk@nexenta.com>
|
Albert Lee <trisk@nexenta.com>
|
||||||
Alec Salazar <alec.j.salazar@gmail.com>
|
Alec Salazar <alec.j.salazar@gmail.com>
|
||||||
Alejandro Colomar <Colomar.6.4.3@GMail.com>
|
|
||||||
Alejandro R. Sedeño <asedeno@mit.edu>
|
Alejandro R. Sedeño <asedeno@mit.edu>
|
||||||
Alek Pinchuk <alek@nexenta.com>
|
Alek Pinchuk <alek@nexenta.com>
|
||||||
Aleksa Sarai <cyphar@cyphar.com>
|
|
||||||
Alexander Eremin <a.eremin@nexenta.com>
|
|
||||||
Alexander Lobakin <alobakin@pm.me>
|
|
||||||
Alexander Motin <mav@freebsd.org>
|
|
||||||
Alexander Pyhalov <apyhalov@gmail.com>
|
|
||||||
Alexander Richardson <Alexander.Richardson@cl.cam.ac.uk>
|
|
||||||
Alexander Stetsenko <ams@nexenta.com>
|
|
||||||
Alex Braunegg <alex.braunegg@gmail.com>
|
Alex Braunegg <alex.braunegg@gmail.com>
|
||||||
Alexey Shvetsov <alexxy@gentoo.org>
|
|
||||||
Alexey Smirnoff <fling@member.fsf.org>
|
|
||||||
Alex John <alex@stty.io>
|
|
||||||
Alex McWhirter <alexmcwhirter@triadic.us>
|
Alex McWhirter <alexmcwhirter@triadic.us>
|
||||||
Alex Reece <alex@delphix.com>
|
Alex Reece <alex@delphix.com>
|
||||||
Alex Wilson <alex.wilson@joyent.com>
|
Alex Wilson <alex.wilson@joyent.com>
|
||||||
Alex Zhuravlev <alexey.zhuravlev@intel.com>
|
Alex Zhuravlev <alexey.zhuravlev@intel.com>
|
||||||
|
Alexander Eremin <a.eremin@nexenta.com>
|
||||||
|
Alexander Motin <mav@freebsd.org>
|
||||||
|
Alexander Pyhalov <apyhalov@gmail.com>
|
||||||
|
Alexander Stetsenko <ams@nexenta.com>
|
||||||
|
Alexey Shvetsov <alexxy@gentoo.org>
|
||||||
|
Alexey Smirnoff <fling@member.fsf.org>
|
||||||
Allan Jude <allanjude@freebsd.org>
|
Allan Jude <allanjude@freebsd.org>
|
||||||
Allen Holl <allen.m.holl@gmail.com>
|
|
||||||
Alphan Yılmaz <alphanyilmaz@gmail.com>
|
|
||||||
alteriks <alteriks@gmail.com>
|
|
||||||
Alyssa Ross <hi@alyssa.is>
|
|
||||||
Ameer Hamza <ahamza@ixsystems.com>
|
|
||||||
Anatoly Borodin <anatoly.borodin@gmail.com>
|
|
||||||
AndCycle <andcycle@andcycle.idv.tw>
|
AndCycle <andcycle@andcycle.idv.tw>
|
||||||
Andrea Gelmini <andrea.gelmini@gelma.net>
|
|
||||||
Andrea Righi <andrea.righi@canonical.com>
|
|
||||||
Andreas Buschmann <andreas.buschmann@tech.net.de>
|
Andreas Buschmann <andreas.buschmann@tech.net.de>
|
||||||
Andreas Dilger <adilger@intel.com>
|
Andreas Dilger <adilger@intel.com>
|
||||||
Andreas Vögele <andreas@andreasvoegele.com>
|
|
||||||
Andrew Barnes <barnes333@gmail.com>
|
Andrew Barnes <barnes333@gmail.com>
|
||||||
Andrew Hamilton <ahamilto@tjhsst.edu>
|
Andrew Hamilton <ahamilto@tjhsst.edu>
|
||||||
Andrew Innes <andrew.c12@gmail.com>
|
|
||||||
Andrew J. Hesford <ajh@sideband.org>
|
|
||||||
Andrew Reid <ColdCanuck@nailedtotheperch.com>
|
Andrew Reid <ColdCanuck@nailedtotheperch.com>
|
||||||
Andrew Stormont <andrew.stormont@nexenta.com>
|
Andrew Stormont <andrew.stormont@nexenta.com>
|
||||||
Andrew Sun <me@andrewsun.com>
|
|
||||||
Andrew Tselischev <andrewtselischev@gmail.com>
|
Andrew Tselischev <andrewtselischev@gmail.com>
|
||||||
Andrew Turner <andrew@fubar.geek.nz>
|
|
||||||
Andrew Walker <awalker@ixsystems.com>
|
|
||||||
Andrey Prokopenko <job@terem.fr>
|
|
||||||
Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
|
Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
|
||||||
Andriy Gapon <avg@freebsd.org>
|
Andriy Gapon <avg@freebsd.org>
|
||||||
Andy Bakun <github@thwartedefforts.org>
|
Andy Bakun <github@thwartedefforts.org>
|
||||||
Andy Fiddaman <omnios@citrus-it.co.uk>
|
|
||||||
Aniruddha Shankar <k@191a.net>
|
Aniruddha Shankar <k@191a.net>
|
||||||
Anton Gubarkov <anton.gubarkov@gmail.com>
|
|
||||||
Antonio Russo <antonio.e.russo@gmail.com>
|
Antonio Russo <antonio.e.russo@gmail.com>
|
||||||
Arkadiusz Bubała <arkadiusz.bubala@open-e.com>
|
Arkadiusz Bubała <arkadiusz.bubala@open-e.com>
|
||||||
Armin Wehrfritz <dkxls23@gmail.com>
|
|
||||||
Arne Jansen <arne@die-jansens.de>
|
Arne Jansen <arne@die-jansens.de>
|
||||||
Aron Xu <happyaron.xu@gmail.com>
|
Aron Xu <happyaron.xu@gmail.com>
|
||||||
Arshad Hussain <arshad.hussain@aeoncomputing.com>
|
|
||||||
Arun KV <arun.kv@datacore.com>
|
|
||||||
Arvind Sankar <nivedita@alum.mit.edu>
|
|
||||||
Attila Fülöp <attila@fueloep.org>
|
|
||||||
Avatat <kontakt@avatat.pl>
|
|
||||||
Bart Coddens <bart.coddens@gmail.com>
|
Bart Coddens <bart.coddens@gmail.com>
|
||||||
Basil Crow <basil.crow@delphix.com>
|
Basil Crow <basil.crow@delphix.com>
|
||||||
Bassu <bassu@phi9.com>
|
Huang Liu <liu.huang@zte.com.cn>
|
||||||
Ben Allen <bsallen@alcf.anl.gov>
|
Ben Allen <bsallen@alcf.anl.gov>
|
||||||
Ben Cordero <bencord0@condi.me>
|
|
||||||
Benda Xu <orv@debian.org>
|
|
||||||
Benedikt Neuffer <github@itfriend.de>
|
|
||||||
Benjamin Albrecht <git@albrecht.io>
|
|
||||||
Benjamin Gentil <benjgentil.pro@gmail.com>
|
|
||||||
Benjamin Sherman <benjamin@holyarmy.org>
|
|
||||||
Ben McGough <bmcgough@fredhutch.org>
|
|
||||||
Ben Rubson <ben.rubson@gmail.com>
|
Ben Rubson <ben.rubson@gmail.com>
|
||||||
Ben Wolsieffer <benwolsieffer@gmail.com>
|
Benjamin Albrecht <git@albrecht.io>
|
||||||
bernie1995 <bernie.pikes@gmail.com>
|
|
||||||
Bill McGonigle <bill-github.com-public1@bfccomputing.com>
|
Bill McGonigle <bill-github.com-public1@bfccomputing.com>
|
||||||
Bill Pijewski <wdp@joyent.com>
|
Bill Pijewski <wdp@joyent.com>
|
||||||
Bojan Novković <bnovkov@FreeBSD.org>
|
|
||||||
Boris Protopopov <boris.protopopov@nexenta.com>
|
Boris Protopopov <boris.protopopov@nexenta.com>
|
||||||
Brad Forschinger <github@bnjf.id.au>
|
|
||||||
Brad Lewis <brad.lewis@delphix.com>
|
Brad Lewis <brad.lewis@delphix.com>
|
||||||
Brandon Thetford <brandon@dodecatec.com>
|
|
||||||
Brian Atkinson <bwa@g.clemson.edu>
|
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov>
|
Brian Behlendorf <behlendorf1@llnl.gov>
|
||||||
Brian J. Murrell <brian@sun.com>
|
Brian J. Murrell <brian@sun.com>
|
||||||
Brooks Davis <brooks@one-eyed-alien.net>
|
|
||||||
BtbN <btbn@btbn.de>
|
|
||||||
bunder2015 <omfgbunder@gmail.com>
|
|
||||||
buzzingwires <buzzingwires@outlook.com>
|
|
||||||
bzzz77 <bzzz.tomas@gmail.com>
|
|
||||||
cable2999 <cable2999@users.noreply.github.com>
|
|
||||||
Caleb James DeLisle <calebdelisle@lavabit.com>
|
Caleb James DeLisle <calebdelisle@lavabit.com>
|
||||||
Cameron Harr <harr1@llnl.gov>
|
|
||||||
Cao Xuewen <cao.xuewen@zte.com.cn>
|
Cao Xuewen <cao.xuewen@zte.com.cn>
|
||||||
Carlo Landmeter <clandmeter@gmail.com>
|
Carlo Landmeter <clandmeter@gmail.com>
|
||||||
Carlos Alberto Lopez Perez <clopez@igalia.com>
|
Carlos Alberto Lopez Perez <clopez@igalia.com>
|
||||||
Cedric Maunoury <cedric.maunoury@gmail.com>
|
|
||||||
Chaoyu Zhang <zhang.chaoyu@zte.com.cn>
|
Chaoyu Zhang <zhang.chaoyu@zte.com.cn>
|
||||||
Charles Suh <charles.suh@gmail.com>
|
|
||||||
Chen Can <chen.can2@zte.com.cn>
|
Chen Can <chen.can2@zte.com.cn>
|
||||||
Chengfei Zhu <chengfeix.zhu@intel.com>
|
|
||||||
Chen Haiquan <oc@yunify.com>
|
Chen Haiquan <oc@yunify.com>
|
||||||
ChenHao Lu <18302010006@fudan.edu.cn>
|
|
||||||
Chip Parker <aparker@enthought.com>
|
Chip Parker <aparker@enthought.com>
|
||||||
Chris Burroughs <chris.burroughs@gmail.com>
|
Chris Burroughs <chris.burroughs@gmail.com>
|
||||||
Chris Davidson <christopher.davidson@gmail.com>
|
|
||||||
Chris Dunlap <cdunlap@llnl.gov>
|
Chris Dunlap <cdunlap@llnl.gov>
|
||||||
Chris Dunlop <chris@onthe.net.au>
|
Chris Dunlop <chris@onthe.net.au>
|
||||||
Chris Lindee <chris.lindee+github@gmail.com>
|
|
||||||
Chris McDonough <chrism@plope.com>
|
|
||||||
Chris Peredun <chris.peredun@ixsystems.com>
|
|
||||||
Chris Siden <chris.siden@delphix.com>
|
Chris Siden <chris.siden@delphix.com>
|
||||||
Chris Siebenmann <cks.github@cs.toronto.edu>
|
Chris Wedgwood <cw@f00f.org>
|
||||||
|
Chris Williamson <chris.williamson@delphix.com>
|
||||||
|
Chris Zubrzycki <github@mid-earth.net>
|
||||||
|
Christ Schlacta <aarcane@aarcane.info>
|
||||||
Christer Ekholm <che@chrekh.se>
|
Christer Ekholm <che@chrekh.se>
|
||||||
Christian Kohlschütter <christian@kohlschutter.com>
|
Christian Kohlschütter <christian@kohlschutter.com>
|
||||||
Christian Neukirchen <chneukirchen@gmail.com>
|
Christian Neukirchen <chneukirchen@gmail.com>
|
||||||
Christian Schwarz <me@cschwarz.com>
|
Christian Schwarz <me@cschwarz.com>
|
||||||
Christopher Voltz <cjunk@voltz.ws>
|
Christopher Voltz <cjunk@voltz.ws>
|
||||||
Christ Schlacta <aarcane@aarcane.info>
|
|
||||||
Chris Wedgwood <cw@f00f.org>
|
|
||||||
Chris Williamson <chris.williamson@delphix.com>
|
|
||||||
Chris Zubrzycki <github@mid-earth.net>
|
|
||||||
Chuck Tuffli <ctuffli@gmail.com>
|
|
||||||
Chunwei Chen <david.chen@nutanix.com>
|
Chunwei Chen <david.chen@nutanix.com>
|
||||||
Clemens Fruhwirth <clemens@endorphin.org>
|
Clemens Fruhwirth <clemens@endorphin.org>
|
||||||
Clemens Lang <cl@clang.name>
|
|
||||||
Clint Armstrong <clint@clintarmstrong.net>
|
|
||||||
Coleman Kane <ckane@colemankane.org>
|
Coleman Kane <ckane@colemankane.org>
|
||||||
Colin Ian King <colin.king@canonical.com>
|
Colin Ian King <colin.king@canonical.com>
|
||||||
Colin Percival <cperciva@tarsnap.com>
|
|
||||||
Colm Buckley <colm@tuatha.org>
|
|
||||||
Crag Wang <crag0715@gmail.com>
|
|
||||||
Craig Loomis <cloomis@astro.princeton.edu>
|
Craig Loomis <cloomis@astro.princeton.edu>
|
||||||
Craig Sanders <github@taz.net.au>
|
Craig Sanders <github@taz.net.au>
|
||||||
Cyril Plisko <cyril.plisko@infinidat.com>
|
Cyril Plisko <cyril.plisko@infinidat.com>
|
||||||
Cy Schubert <cy@FreeBSD.org>
|
DHE <git@dehacked.net>
|
||||||
Cédric Berger <cedric@precidata.com>
|
|
||||||
Dacian Reece-Stremtan <dacianstremtan@gmail.com>
|
|
||||||
Dag-Erling Smørgrav <des@FreeBSD.org>
|
|
||||||
Damiano Albani <damiano.albani@gmail.com>
|
|
||||||
Damian Szuberski <szuberskidamian@gmail.com>
|
|
||||||
Damian Wojsław <damian@wojslaw.pl>
|
Damian Wojsław <damian@wojslaw.pl>
|
||||||
Daniel Berlin <dberlin@dberlin.org>
|
|
||||||
Daniel Hiepler <d-git@coderdu.de>
|
|
||||||
Daniel Hoffman <dj.hoffman@delphix.com>
|
|
||||||
Daniel Kobras <d.kobras@science-computing.de>
|
|
||||||
Daniel Kolesa <daniel@octaforge.org>
|
|
||||||
Daniel Perry <dtperry@amazon.com>
|
|
||||||
Daniel Reichelt <hacking@nachtgeist.net>
|
|
||||||
Daniel Stevenson <bot@dstev.net>
|
|
||||||
Daniel Verite <daniel@verite.pro>
|
|
||||||
Daniil Lunev <d.lunev.mail@gmail.com>
|
|
||||||
Dan Kimmel <dan.kimmel@delphix.com>
|
Dan Kimmel <dan.kimmel@delphix.com>
|
||||||
Dan McDonald <danmcd@nexenta.com>
|
Dan McDonald <danmcd@nexenta.com>
|
||||||
Dan Swartzendruber <dswartz@druber.com>
|
Dan Swartzendruber <dswartz@druber.com>
|
||||||
Dan Vatca <dan.vatca@gmail.com>
|
Dan Vatca <dan.vatca@gmail.com>
|
||||||
|
Daniel Hoffman <dj.hoffman@delphix.com>
|
||||||
|
Daniel Verite <daniel@verite.pro>
|
||||||
|
Daniil Lunev <d.lunev.mail@gmail.com>
|
||||||
Darik Horn <dajhorn@vanadac.com>
|
Darik Horn <dajhorn@vanadac.com>
|
||||||
Dave Eddy <dave@daveeddy.com>
|
Dave Eddy <dave@daveeddy.com>
|
||||||
David Hedberg <david@qzx.se>
|
|
||||||
David Lamparter <equinox@diac24.net>
|
David Lamparter <equinox@diac24.net>
|
||||||
David Qian <david.qian@intel.com>
|
David Qian <david.qian@intel.com>
|
||||||
David Quigley <david.quigley@intel.com>
|
David Quigley <david.quigley@intel.com>
|
||||||
Debabrata Banerjee <dbanerje@akamai.com>
|
Debabrata Banerjee <dbanerje@akamai.com>
|
||||||
D. Ebdrup <debdrup@freebsd.org>
|
|
||||||
Dennis R. Friedrichsen <dennis.r.friedrichsen@gmail.com>
|
|
||||||
Denys Rtveliashvili <denys@rtveliashvili.name>
|
Denys Rtveliashvili <denys@rtveliashvili.name>
|
||||||
Derek Dai <daiderek@gmail.com>
|
Derek Dai <daiderek@gmail.com>
|
||||||
Derek Schrock <dereks@lifeofadishwasher.com>
|
|
||||||
Dex Wood <slash2314@gmail.com>
|
|
||||||
DHE <git@dehacked.net>
|
|
||||||
Didier Roche <didrocks@ubuntu.com>
|
|
||||||
Dimitri John Ledkov <xnox@ubuntu.com>
|
Dimitri John Ledkov <xnox@ubuntu.com>
|
||||||
Dimitry Andric <dimitry@andric.com>
|
|
||||||
Dirkjan Bussink <d.bussink@gmail.com>
|
|
||||||
Dmitry Khasanov <pik4ez@gmail.com>
|
Dmitry Khasanov <pik4ez@gmail.com>
|
||||||
Dominic Pearson <dsp@technoanimal.net>
|
|
||||||
Dominik Hassler <hadfl@omniosce.org>
|
Dominik Hassler <hadfl@omniosce.org>
|
||||||
Dominik Honnef <dominikh@fork-bomb.org>
|
Dominik Honnef <dominikh@fork-bomb.org>
|
||||||
Don Brady <don.brady@delphix.com>
|
Don Brady <don.brady@delphix.com>
|
||||||
Doug Rabson <dfr@rabson.org>
|
|
||||||
Dr. András Korn <korn-github.com@elan.rulez.org>
|
Dr. András Korn <korn-github.com@elan.rulez.org>
|
||||||
Dries Michiels <driesm.michiels@gmail.com>
|
|
||||||
Edmund Nadolski <edmund.nadolski@ixsystems.com>
|
|
||||||
Eitan Adler <lists@eitanadler.com>
|
|
||||||
Eli Rosenthal <eli.rosenthal@delphix.com>
|
Eli Rosenthal <eli.rosenthal@delphix.com>
|
||||||
Eli Schwartz <eschwartz93@gmail.com>
|
|
||||||
Eric Desrochers <eric.desrochers@canonical.com>
|
Eric Desrochers <eric.desrochers@canonical.com>
|
||||||
Eric Dillmann <eric@jave.fr>
|
Eric Dillmann <eric@jave.fr>
|
||||||
Eric Schrock <Eric.Schrock@delphix.com>
|
Eric Schrock <Eric.Schrock@delphix.com>
|
||||||
Ethan Coe-Renner <coerenner1@llnl.gov>
|
|
||||||
Etienne Dechamps <etienne@edechamps.fr>
|
Etienne Dechamps <etienne@edechamps.fr>
|
||||||
Evan Allrich <eallrich@gmail.com>
|
|
||||||
Evan Harris <eharris@puremagic.com>
|
|
||||||
Evan Susarret <evansus@gmail.com>
|
Evan Susarret <evansus@gmail.com>
|
||||||
Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
||||||
Fabio Buso <dev.siroibaf@gmail.com>
|
|
||||||
Fabio Scaccabarozzi <fsvm88@gmail.com>
|
|
||||||
Fajar A. Nugraha <github@fajar.net>
|
Fajar A. Nugraha <github@fajar.net>
|
||||||
Fan Yong <fan.yong@intel.com>
|
Fan Yong <fan.yong@intel.com>
|
||||||
fbynite <fbynite@users.noreply.github.com>
|
|
||||||
Fedor Uporov <fuporov.vstack@gmail.com>
|
|
||||||
Felix Dörre <felix@dogcraft.de>
|
|
||||||
Felix Neumärker <xdch47@posteo.de>
|
|
||||||
Feng Sun <loyou85@gmail.com>
|
Feng Sun <loyou85@gmail.com>
|
||||||
Finix Yan <yancw@info2soft.com>
|
|
||||||
Francesco Mazzoli <f@mazzo.li>
|
|
||||||
Frederik Wessels <wessels147@gmail.com>
|
Frederik Wessels <wessels147@gmail.com>
|
||||||
Frédéric Vanniere <f.vanniere@planet-work.com>
|
Frédéric Vanniere <f.vanniere@planet-work.com>
|
||||||
Gabriel A. Devenyi <gdevenyi@gmail.com>
|
|
||||||
Garrett D'Amore <garrett@nexenta.com>
|
Garrett D'Amore <garrett@nexenta.com>
|
||||||
Garrett Fields <ghfields@gmail.com>
|
|
||||||
Garrison Jensen <garrison.jensen@gmail.com>
|
Garrison Jensen <garrison.jensen@gmail.com>
|
||||||
Gary Mills <gary_mills@fastmail.fm>
|
Gary Mills <gary_mills@fastmail.fm>
|
||||||
Gaurav Kumar <gauravk.18@gmail.com>
|
Gaurav Kumar <gauravk.18@gmail.com>
|
||||||
GeLiXin <ge.lixin@zte.com.cn>
|
GeLiXin <ge.lixin@zte.com.cn>
|
||||||
George Amanakis <g_amanakis@yahoo.com>
|
George Amanakis <g_amanakis@yahoo.com>
|
||||||
George Diamantopoulos <georgediam@gmail.com>
|
|
||||||
George Gaydarov <git@gg7.io>
|
|
||||||
George Melikov <mail@gmelikov.ru>
|
George Melikov <mail@gmelikov.ru>
|
||||||
George Wilson <gwilson@delphix.com>
|
George Wilson <gwilson@delphix.com>
|
||||||
Georgy Yakovlev <ya@sysdump.net>
|
Georgy Yakovlev <ya@sysdump.net>
|
||||||
Gerardwx <gerardw@alum.mit.edu>
|
|
||||||
Gian-Carlo DeFazio <defazio1@llnl.gov>
|
|
||||||
Gionatan Danti <g.danti@assyoma.it>
|
|
||||||
Giuseppe Di Natale <guss80@gmail.com>
|
Giuseppe Di Natale <guss80@gmail.com>
|
||||||
Gleb Smirnoff <glebius@FreeBSD.org>
|
|
||||||
Glenn Washburn <development@efficientek.com>
|
|
||||||
glibg10b <glibg10b@users.noreply.github.com>
|
|
||||||
gofaster <felix.gofaster@gmail.com>
|
|
||||||
Gordan Bobic <gordan@redsleeve.org>
|
Gordan Bobic <gordan@redsleeve.org>
|
||||||
Gordon Bergling <gbergling@googlemail.com>
|
|
||||||
Gordon Ross <gwr@nexenta.com>
|
Gordon Ross <gwr@nexenta.com>
|
||||||
Gordon Tetlow <gordon@freebsd.org>
|
|
||||||
Graham Christensen <graham@grahamc.com>
|
|
||||||
Graham Perrin <grahamperrin@gmail.com>
|
|
||||||
Gregor Kopka <gregor@kopka.net>
|
Gregor Kopka <gregor@kopka.net>
|
||||||
Gregory Bartholomew <gregory.lee.bartholomew@gmail.com>
|
|
||||||
grembo <freebsd@grem.de>
|
|
||||||
Grischa Zengel <github.zfsonlinux@zengel.info>
|
Grischa Zengel <github.zfsonlinux@zengel.info>
|
||||||
grodik <pat@litke.dev>
|
|
||||||
Gunnar Beutner <gunnar@beutner.name>
|
Gunnar Beutner <gunnar@beutner.name>
|
||||||
Gvozden Neskovic <neskovic@gmail.com>
|
Gvozden Neskovic <neskovic@gmail.com>
|
||||||
Hajo Möller <dasjoe@gmail.com>
|
Hajo Möller <dasjoe@gmail.com>
|
||||||
Han Gao <rabenda.cn@gmail.com>
|
|
||||||
Hans Rosenfeld <hans.rosenfeld@nexenta.com>
|
Hans Rosenfeld <hans.rosenfeld@nexenta.com>
|
||||||
Harald van Dijk <harald@gigawatt.nl>
|
|
||||||
Harry Mallon <hjmallon@gmail.com>
|
|
||||||
Harry Sintonen <github-piru@kyber.fi>
|
|
||||||
HC <mmttdebbcc@yahoo.com>
|
|
||||||
hedong zhang <h_d_zhang@163.com>
|
|
||||||
Heitor Alves de Siqueira <halves@canonical.com>
|
|
||||||
Henrik Riomar <henrik.riomar@gmail.com>
|
|
||||||
Herb Wartens <wartens2@llnl.gov>
|
|
||||||
Hiếu Lê <leorize+oss@disroot.org>
|
|
||||||
Huang Liu <liu.huang@zte.com.cn>
|
|
||||||
Håkan Johansson <f96hajo@chalmers.se>
|
Håkan Johansson <f96hajo@chalmers.se>
|
||||||
Igor K <igor@dilos.org>
|
|
||||||
Igor Kozhukhov <ikozhukhov@gmail.com>
|
Igor Kozhukhov <ikozhukhov@gmail.com>
|
||||||
Igor Lvovsky <ilvovsky@gmail.com>
|
Igor Lvovsky <ilvovsky@gmail.com>
|
||||||
ilbsmart <wgqimut@gmail.com>
|
|
||||||
Ilkka Sovanto <github@ilkka.kapsi.fi>
|
|
||||||
illiliti <illiliti@protonmail.com>
|
|
||||||
ilovezfs <ilovezfs@icloud.com>
|
|
||||||
InsanePrawn <Insane.Prawny@gmail.com>
|
|
||||||
Isaac Huang <he.huang@intel.com>
|
Isaac Huang <he.huang@intel.com>
|
||||||
|
JK Dingwall <james@dingwall.me.uk>
|
||||||
Jacek Fefliński <feflik@gmail.com>
|
Jacek Fefliński <feflik@gmail.com>
|
||||||
Jacob Adams <tookmund@gmail.com>
|
|
||||||
Jake Howard <git@theorangeone.net>
|
|
||||||
James Cowgill <james.cowgill@mips.com>
|
James Cowgill <james.cowgill@mips.com>
|
||||||
James H <james@kagisoft.co.uk>
|
|
||||||
James Lee <jlee@thestaticvoid.com>
|
James Lee <jlee@thestaticvoid.com>
|
||||||
James Pan <jiaming.pan@yahoo.com>
|
James Pan <jiaming.pan@yahoo.com>
|
||||||
James Wah <james@laird-wah.net>
|
|
||||||
Jan Engelhardt <jengelh@inai.de>
|
Jan Engelhardt <jengelh@inai.de>
|
||||||
Jan Kryl <jan.kryl@nexenta.com>
|
Jan Kryl <jan.kryl@nexenta.com>
|
||||||
Jan Sanislo <oystr@cs.washington.edu>
|
Jan Sanislo <oystr@cs.washington.edu>
|
||||||
Jaron Kent-Dobias <jaron@kent-dobias.com>
|
|
||||||
Jason Cohen <jwittlincohen@gmail.com>
|
|
||||||
Jason Harmening <jason.harmening@gmail.com>
|
|
||||||
Jason King <jason.brian.king@gmail.com>
|
Jason King <jason.brian.king@gmail.com>
|
||||||
Jason Lee <jasonlee@lanl.gov>
|
|
||||||
Jason Zaman <jasonzaman@gmail.com>
|
Jason Zaman <jasonzaman@gmail.com>
|
||||||
Javen Wu <wu.javen@gmail.com>
|
Javen Wu <wu.javen@gmail.com>
|
||||||
Jean-Baptiste Lallement <jean-baptiste@ubuntu.com>
|
|
||||||
Jeff Dike <jdike@akamai.com>
|
|
||||||
Jeremy Faulkner <gldisater@gmail.com>
|
|
||||||
Jeremy Gill <jgill@parallax-innovations.com>
|
Jeremy Gill <jgill@parallax-innovations.com>
|
||||||
Jeremy Jones <jeremy@delphix.com>
|
Jeremy Jones <jeremy@delphix.com>
|
||||||
Jeremy Visser <jeremy.visser@gmail.com>
|
|
||||||
Jerry Jelinek <jerry.jelinek@joyent.com>
|
Jerry Jelinek <jerry.jelinek@joyent.com>
|
||||||
Jessica Clarke <jrtc27@jrtc27.com>
|
|
||||||
Jinshan Xiong <jinshan.xiong@intel.com>
|
Jinshan Xiong <jinshan.xiong@intel.com>
|
||||||
Jitendra Patidar <jitendra.patidar@nutanix.com>
|
|
||||||
JK Dingwall <james@dingwall.me.uk>
|
|
||||||
Joe Stein <joe.stein@delphix.com>
|
Joe Stein <joe.stein@delphix.com>
|
||||||
John-Mark Gurney <jmg@funkthat.com>
|
|
||||||
John Albietz <inthecloud247@gmail.com>
|
John Albietz <inthecloud247@gmail.com>
|
||||||
John Eismeier <john.eismeier@gmail.com>
|
John Eismeier <john.eismeier@gmail.com>
|
||||||
John Gallagher <john.gallagher@delphix.com>
|
|
||||||
John Layman <jlayman@sagecloud.com>
|
|
||||||
John L. Hammond <john.hammond@intel.com>
|
John L. Hammond <john.hammond@intel.com>
|
||||||
John M. Layman <jml@frijid.net>
|
John Layman <jlayman@sagecloud.com>
|
||||||
Johnny Stenback <github@jstenback.com>
|
|
||||||
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
|
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
|
||||||
John Poduska <jpoduska@datto.com>
|
|
||||||
John Ramsden <johnramsden@riseup.net>
|
|
||||||
John Wren Kennedy <john.kennedy@delphix.com>
|
John Wren Kennedy <john.kennedy@delphix.com>
|
||||||
jokersus <lolivampireslave@gmail.com>
|
Johnny Stenback <github@jstenback.com>
|
||||||
Jonathon Fernyhough <jonathon@m2x.dev>
|
|
||||||
Jorgen Lundman <lundman@lundman.net>
|
Jorgen Lundman <lundman@lundman.net>
|
||||||
Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
|
Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
|
||||||
Jose Luis Duran <jlduran@gmail.com>
|
|
||||||
Josh Soref <jsoref@users.noreply.github.com>
|
|
||||||
Joshua M. Clulow <josh@sysmgr.org>
|
Joshua M. Clulow <josh@sysmgr.org>
|
||||||
José Luis Salvador Rufo <salvador.joseluis@gmail.com>
|
|
||||||
João Carlos Mendes Luís <jonny@jonny.eng.br>
|
|
||||||
Julian Brunner <julian.brunner@gmail.com>
|
|
||||||
Julian Heuking <JulianH@beckhoff.com>
|
|
||||||
jumbi77 <jumbi77@users.noreply.github.com>
|
|
||||||
Justin Bedő <cu@cua0.org>
|
Justin Bedő <cu@cua0.org>
|
||||||
Justin Gottula <justin@jgottula.com>
|
|
||||||
Justin Hibbits <chmeeedalf@gmail.com>
|
|
||||||
Justin Keogh <github.com@v6y.net>
|
|
||||||
Justin Lecher <jlec@gentoo.org>
|
Justin Lecher <jlec@gentoo.org>
|
||||||
Justin Scholz <git@justinscholz.de>
|
|
||||||
Justin T. Gibbs <gibbs@FreeBSD.org>
|
Justin T. Gibbs <gibbs@FreeBSD.org>
|
||||||
jyxent <jordanp@gmail.com>
|
|
||||||
Jörg Thalheim <joerg@higgsboson.tk>
|
Jörg Thalheim <joerg@higgsboson.tk>
|
||||||
ka7 <ka7@la-evento.com>
|
KORN Andras <korn@elan.rulez.org>
|
||||||
Ka Ho Ng <khng@FreeBSD.org>
|
|
||||||
Kamil Domański <kamil@domanski.co>
|
Kamil Domański <kamil@domanski.co>
|
||||||
Karsten Kretschmer <kkretschmer@gmail.com>
|
Karsten Kretschmer <kkretschmer@gmail.com>
|
||||||
Kash Pande <kash@tripleback.net>
|
Kash Pande <kash@tripleback.net>
|
||||||
Kay Pedersen <christianpe96@gmail.com>
|
|
||||||
Keith M Wesolowski <wesolows@foobazco.org>
|
Keith M Wesolowski <wesolows@foobazco.org>
|
||||||
Kent Ross <k@mad.cash>
|
|
||||||
KernelOfTruth <kerneloftruth@gmail.com>
|
|
||||||
Kevin Bowling <kevin.bowling@kev009.com>
|
|
||||||
Kevin Greene <kevin.greene@delphix.com>
|
|
||||||
Kevin Jin <lostking2008@hotmail.com>
|
|
||||||
Kevin P. Fleming <kevin@km6g.us>
|
|
||||||
Kevin Tanguy <kevin.tanguy@ovh.net>
|
Kevin Tanguy <kevin.tanguy@ovh.net>
|
||||||
KireinaHoro <i@jsteward.moe>
|
KireinaHoro <i@jsteward.moe>
|
||||||
Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>
|
Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>
|
||||||
Kleber Tarcísio <klebertarcisio@yahoo.com.br>
|
|
||||||
Kody A Kantor <kody.kantor@gmail.com>
|
|
||||||
Kohsuke Kawaguchi <kk@kohsuke.org>
|
Kohsuke Kawaguchi <kk@kohsuke.org>
|
||||||
Konstantin Khorenko <khorenko@virtuozzo.com>
|
|
||||||
KORN Andras <korn@elan.rulez.org>
|
|
||||||
Kristof Provost <github@sigsegv.be>
|
|
||||||
Krzysztof Piecuch <piecuch@kpiecuch.pl>
|
|
||||||
Kyle Blatter <kyleblatter@llnl.gov>
|
Kyle Blatter <kyleblatter@llnl.gov>
|
||||||
Kyle Evans <kevans@FreeBSD.org>
|
|
||||||
Kyle Fuller <inbox@kylefuller.co.uk>
|
Kyle Fuller <inbox@kylefuller.co.uk>
|
||||||
Laevos <Laevos@users.noreply.github.com>
|
|
||||||
Lalufu <Lalufu@users.noreply.github.com>
|
|
||||||
Lars Johannsen <laj@it.dk>
|
|
||||||
Laura Hild <lsh@jlab.org>
|
|
||||||
Laurențiu Nicola <lnicola@dend.ro>
|
|
||||||
Lauri Tirkkonen <lauri@hacktheplanet.fi>
|
|
||||||
liaoyuxiangqin <guo.yong33@zte.com.cn>
|
|
||||||
Li Dongyang <dongyang.li@anu.edu.au>
|
|
||||||
Liu Hua <liu.hua130@zte.com.cn>
|
|
||||||
Liu Qing <winglq@gmail.com>
|
|
||||||
Li Wei <W.Li@Sun.COM>
|
|
||||||
Loli <ezomori.nozomu@gmail.com>
|
Loli <ezomori.nozomu@gmail.com>
|
||||||
lorddoskias <lorddoskias@gmail.com>
|
Lars Johannsen <laj@it.dk>
|
||||||
Lorenz Brun <lorenz@dolansoft.org>
|
Li Dongyang <dongyang.li@anu.edu.au>
|
||||||
Lorenz Hüdepohl <dev@stellardeath.org>
|
Li Wei <W.Li@Sun.COM>
|
||||||
louwrentius <louwrentius@gmail.com>
|
|
||||||
Lukas Wunner <lukas@wunner.de>
|
Lukas Wunner <lukas@wunner.de>
|
||||||
luozhengzheng <luo.zhengzheng@zte.com.cn>
|
|
||||||
Luís Henriques <henrix@camandro.org>
|
|
||||||
Madhav Suresh <madhav.suresh@delphix.com>
|
Madhav Suresh <madhav.suresh@delphix.com>
|
||||||
manfromafar <jonsonb10@gmail.com>
|
|
||||||
Manoj Joseph <manoj.joseph@delphix.com>
|
Manoj Joseph <manoj.joseph@delphix.com>
|
||||||
Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
|
Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
|
||||||
Marcel Huber <marcelhuberfoo@gmail.com>
|
Marcel Huber <marcelhuberfoo@gmail.com>
|
||||||
Marcel Menzel <mail@mcl.gg>
|
|
||||||
Marcel Schilling <marcel.schilling@uni-luebeck.de>
|
|
||||||
Marcel Telka <marcel.telka@nexenta.com>
|
Marcel Telka <marcel.telka@nexenta.com>
|
||||||
Marcel Wysocki <maci.stgn@gmail.com>
|
Marcel Wysocki <maci.stgn@gmail.com>
|
||||||
Marcin Skarbek <git@skarbek.name>
|
|
||||||
Mariusz Zaborski <mariusz.zaborski@klarasystems.com>
|
|
||||||
Mark Johnston <markj@FreeBSD.org>
|
|
||||||
Mark Maybee <mark.maybee@delphix.com>
|
|
||||||
Mark Roper <markroper@gmail.com>
|
|
||||||
Mark Shellenbaum <Mark.Shellenbaum@Oracle.COM>
|
Mark Shellenbaum <Mark.Shellenbaum@Oracle.COM>
|
||||||
marku89 <mar42@kola.li>
|
|
||||||
Mark Wright <markwright@internode.on.net>
|
Mark Wright <markwright@internode.on.net>
|
||||||
Mart Frauenlob <allkind@fastest.cc>
|
|
||||||
Martin Matuska <mm@FreeBSD.org>
|
Martin Matuska <mm@FreeBSD.org>
|
||||||
Martin Rüegg <martin.rueegg@metaworx.ch>
|
|
||||||
Martin Wagner <martin.wagner.dev@gmail.com>
|
|
||||||
Massimo Maggi <me@massimo-maggi.eu>
|
Massimo Maggi <me@massimo-maggi.eu>
|
||||||
Mateusz Guzik <mjguzik@gmail.com>
|
|
||||||
Mateusz Piotrowski <0mp@FreeBSD.org>
|
|
||||||
Mathieu Velten <matmaul@gmail.com>
|
|
||||||
Matt Fiddaman <github@m.fiddaman.uk>
|
|
||||||
Matthew Ahrens <matt@delphix.com>
|
|
||||||
Matthew Heller <matthew.f.heller@gmail.com>
|
|
||||||
Matthew Thode <mthode@mthode.org>
|
|
||||||
Matthias Blankertz <matthias@blankertz.org>
|
|
||||||
Matt Johnston <matt@fugro-fsi.com.au>
|
Matt Johnston <matt@fugro-fsi.com.au>
|
||||||
Matt Kemp <matt@mattikus.com>
|
Matt Kemp <matt@mattikus.com>
|
||||||
Matt Macy <mmacy@freebsd.org>
|
Matthew Ahrens <matt@delphix.com>
|
||||||
|
Matthew Thode <mthode@mthode.org>
|
||||||
Matus Kral <matuskral@me.com>
|
Matus Kral <matuskral@me.com>
|
||||||
Mauricio Faria de Oliveira <mfo@canonical.com>
|
|
||||||
Max Grossman <max.grossman@delphix.com>
|
Max Grossman <max.grossman@delphix.com>
|
||||||
Maxim Filimonov <che@bein.link>
|
|
||||||
Maximilian Mehnert <maximilian.mehnert@gmx.de>
|
Maximilian Mehnert <maximilian.mehnert@gmx.de>
|
||||||
Max Zettlmeißl <max@zettlmeissl.de>
|
|
||||||
Md Islam <mdnahian@outlook.com>
|
|
||||||
megari <megari@iki.fi>
|
|
||||||
Michael D Labriola <michael.d.labriola@gmail.com>
|
|
||||||
Michael Franzl <michael@franzl.name>
|
|
||||||
Michael Gebetsroither <michael@mgeb.org>
|
Michael Gebetsroither <michael@mgeb.org>
|
||||||
Michael Kjorling <michael@kjorling.se>
|
Michael Kjorling <michael@kjorling.se>
|
||||||
Michael Martin <mgmartin.mgm@gmail.com>
|
Michael Martin <mgmartin.mgm@gmail.com>
|
||||||
Michael Niewöhner <foss@mniewoehner.de>
|
Michael Niewöhner <foss@mniewoehner.de>
|
||||||
Michael Zhivich <mzhivich@akamai.com>
|
|
||||||
Michal Vasilek <michal@vasilek.cz>
|
|
||||||
MigeljanImeri <ImeriMigel@gmail.com>
|
|
||||||
Mike Gerdts <mike.gerdts@joyent.com>
|
Mike Gerdts <mike.gerdts@joyent.com>
|
||||||
Mike Harsch <mike@harschsystems.com>
|
Mike Harsch <mike@harschsystems.com>
|
||||||
Mike Leddy <mike.leddy@gmail.com>
|
Mike Leddy <mike.leddy@gmail.com>
|
||||||
Mike Swanson <mikeonthecomputer@gmail.com>
|
Mike Swanson <mikeonthecomputer@gmail.com>
|
||||||
Milan Jurik <milan.jurik@xylab.cz>
|
Milan Jurik <milan.jurik@xylab.cz>
|
||||||
Minsoo Choo <minsoochoo0122@proton.me>
|
|
||||||
Mohamed Tawfik <m_tawfik@aucegypt.edu>
|
|
||||||
Morgan Jones <mjones@rice.edu>
|
Morgan Jones <mjones@rice.edu>
|
||||||
Moritz Maxeiner <moritz@ucworks.org>
|
Moritz Maxeiner <moritz@ucworks.org>
|
||||||
Mo Zhou <cdluminate@gmail.com>
|
|
||||||
naivekun <naivekun@outlook.com>
|
|
||||||
nathancheek <myself@nathancheek.com>
|
|
||||||
Nathaniel Clark <Nathaniel.Clark@misrule.us>
|
Nathaniel Clark <Nathaniel.Clark@misrule.us>
|
||||||
Nathaniel Wesley Filardo <nwf@cs.jhu.edu>
|
Nathaniel Wesley Filardo <nwf@cs.jhu.edu>
|
||||||
Nathan Lewis <linux.robotdude@gmail.com>
|
|
||||||
Nav Ravindranath <nav@delphix.com>
|
Nav Ravindranath <nav@delphix.com>
|
||||||
Neal Gompa (ニール・ゴンパ) <ngompa13@gmail.com>
|
Neal Gompa (ニール・ゴンパ) <ngompa13@gmail.com>
|
||||||
Ned Bass <bass6@llnl.gov>
|
Ned Bass <bass6@llnl.gov>
|
||||||
Neependra Khare <neependra@kqinfotech.com>
|
Neependra Khare <neependra@kqinfotech.com>
|
||||||
Neil Stockbridge <neil@dist.ro>
|
Neil Stockbridge <neil@dist.ro>
|
||||||
Nick Black <dank@qemfd.net>
|
|
||||||
Nick Garvey <garvey.nick@gmail.com>
|
Nick Garvey <garvey.nick@gmail.com>
|
||||||
Nick Mattis <nickm970@gmail.com>
|
|
||||||
Nick Terrell <terrelln@fb.com>
|
|
||||||
Niklas Haas <github-c6e1c8@haasn.xyz>
|
|
||||||
Nikolay Borisov <n.borisov.lkml@gmail.com>
|
Nikolay Borisov <n.borisov.lkml@gmail.com>
|
||||||
nordaux <nordaux@gmail.com>
|
|
||||||
ofthesun9 <olivier@ofthesun.net>
|
|
||||||
Olaf Faaland <faaland1@llnl.gov>
|
Olaf Faaland <faaland1@llnl.gov>
|
||||||
Oleg Drokin <green@linuxhacker.ru>
|
Oleg Drokin <green@linuxhacker.ru>
|
||||||
Oleg Stepura <oleg@stepura.com>
|
Oleg Stepura <oleg@stepura.com>
|
||||||
Olivier Certner <olce.freebsd@certner.fr>
|
|
||||||
Olivier Mazouffre <olivier.mazouffre@ims-bordeaux.fr>
|
|
||||||
omni <omni+vagant@hack.org>
|
|
||||||
Orivej Desh <orivej@gmx.fr>
|
|
||||||
Pablo Correa Gómez <ablocorrea@hotmail.com>
|
|
||||||
Palash Gandhi <pbg4930@rit.edu>
|
|
||||||
Patrick Mooney <pmooney@pfmooney.com>
|
|
||||||
Patrik Greco <sikevux@sikevux.se>
|
Patrik Greco <sikevux@sikevux.se>
|
||||||
Paul B. Henson <henson@acm.org>
|
Paul B. Henson <henson@acm.org>
|
||||||
Paul Dagnelie <pcd@delphix.com>
|
Paul Dagnelie <pcd@delphix.com>
|
||||||
Paul Zuchowski <pzuchowski@datto.com>
|
Paul Zuchowski <pzuchowski@datto.com>
|
||||||
Pavel Boldin <boldin.pavel@gmail.com>
|
Pavel Boldin <boldin.pavel@gmail.com>
|
||||||
Pavel Snajdr <snajpa@snajpa.net>
|
|
||||||
Pavel Zakharov <pavel.zakharov@delphix.com>
|
Pavel Zakharov <pavel.zakharov@delphix.com>
|
||||||
Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||||
Pedro Giffuni <pfg@freebsd.org>
|
Pedro Giffuni <pfg@freebsd.org>
|
||||||
Peng <peng.hse@xtaotech.com>
|
Peng <peng.hse@xtaotech.com>
|
||||||
Peter Ashford <ashford@accs.com>
|
Peter Ashford <ashford@accs.com>
|
||||||
Peter Dave Hello <hsu@peterdavehello.org>
|
|
||||||
Peter Doherty <peterd@acranox.org>
|
|
||||||
Peter Levine <plevine457@gmail.com>
|
|
||||||
Peter Wirdemo <peter.wirdemo@gmail.com>
|
|
||||||
Petros Koutoupis <petros@petroskoutoupis.com>
|
|
||||||
Philip Pokorny <ppokorny@penguincomputing.com>
|
|
||||||
Philipp Riederer <pt@philipptoelke.de>
|
|
||||||
Phil Kauffman <philip@kauffman.me>
|
|
||||||
Ping Huang <huangping@smartx.com>
|
|
||||||
Piotr Kubaj <pkubaj@anongoth.pl>
|
|
||||||
Piotr P. Stefaniak <pstef@freebsd.org>
|
|
||||||
Prakash Surya <prakash.surya@delphix.com>
|
Prakash Surya <prakash.surya@delphix.com>
|
||||||
Prasad Joshi <prasadjoshi124@gmail.com>
|
Prasad Joshi <prasadjoshi124@gmail.com>
|
||||||
privb0x23 <privb0x23@users.noreply.github.com>
|
|
||||||
P.SCH <p88@yahoo.com>
|
|
||||||
Qiuhao Chen <chenqiuhao1997@gmail.com>
|
|
||||||
Quartz <yyhran@163.com>
|
|
||||||
Quentin Zdanis <zdanisq@gmail.com>
|
|
||||||
Rafael Kitover <rkitover@gmail.com>
|
|
||||||
RageLtMan <sempervictus@users.noreply.github.com>
|
|
||||||
Ralf Ertzinger <ralf@skytale.net>
|
Ralf Ertzinger <ralf@skytale.net>
|
||||||
Randall Mason <ClashTheBunny@gmail.com>
|
Randall Mason <ClashTheBunny@gmail.com>
|
||||||
Remy Blank <remy.blank@pobox.com>
|
Remy Blank <remy.blank@pobox.com>
|
||||||
renelson <bnelson@nelsonbe.com>
|
|
||||||
Reno Reckling <e-github@wthack.de>
|
|
||||||
Ricardo M. Correia <ricardo.correia@oracle.com>
|
Ricardo M. Correia <ricardo.correia@oracle.com>
|
||||||
Riccardo Schirone <rschirone91@gmail.com>
|
Rich Ercolani <rincebrain@gmail.com>
|
||||||
Richard Allen <belperite@gmail.com>
|
|
||||||
Richard Elling <Richard.Elling@RichardElling.com>
|
Richard Elling <Richard.Elling@RichardElling.com>
|
||||||
Richard Kojedzinszky <richard@kojedz.in>
|
|
||||||
Richard Laager <rlaager@wiktel.com>
|
Richard Laager <rlaager@wiktel.com>
|
||||||
Richard Lowe <richlowe@richlowe.net>
|
Richard Lowe <richlowe@richlowe.net>
|
||||||
Richard Sharpe <rsharpe@samba.org>
|
Richard Sharpe <rsharpe@samba.org>
|
||||||
Richard Yao <ryao@gentoo.org>
|
Richard Yao <ryao@gentoo.org>
|
||||||
Rich Ercolani <rincebrain@gmail.com>
|
|
||||||
Rick Macklem <rmacklem@uoguelph.ca>
|
|
||||||
rilysh <nightquick@proton.me>
|
|
||||||
Robert Evans <evansr@google.com>
|
|
||||||
Robert Novak <sailnfool@gmail.com>
|
|
||||||
Roberto Ricci <ricci@disroot.org>
|
|
||||||
Rob Norris <robn@despairlabs.com>
|
|
||||||
Rob Wing <rew@FreeBSD.org>
|
|
||||||
Rohan Puri <rohan.puri15@gmail.com>
|
Rohan Puri <rohan.puri15@gmail.com>
|
||||||
Romain Dolbeau <romain.dolbeau@atos.net>
|
Romain Dolbeau <romain.dolbeau@atos.net>
|
||||||
Roman Strashkin <roman.strashkin@nexenta.com>
|
Roman Strashkin <roman.strashkin@nexenta.com>
|
||||||
Ross Williams <ross@ross-williams.net>
|
|
||||||
Ruben Kerkhof <ruben@rubenkerkhof.com>
|
Ruben Kerkhof <ruben@rubenkerkhof.com>
|
||||||
Ryan <errornointernet@envs.net>
|
|
||||||
Ryan Hirasaki <ryanhirasaki@gmail.com>
|
|
||||||
Ryan Lahfa <masterancpp@gmail.com>
|
|
||||||
Ryan Libby <rlibby@FreeBSD.org>
|
|
||||||
Ryan Moeller <freqlabs@FreeBSD.org>
|
|
||||||
Sam Atkinson <samatk@amazon.com>
|
|
||||||
Sam Hathaway <github.com@munkynet.org>
|
|
||||||
Sam James <sam@gentoo.org>
|
|
||||||
Sam Lunt <samuel.j.lunt@gmail.com>
|
|
||||||
Samuel VERSCHELDE <stormi-github@ylix.fr>
|
|
||||||
Samuel Wycliffe <samuelwycliffe@gmail.com>
|
|
||||||
Samuel Wycliffe J <samwyc@hpe.com>
|
|
||||||
Sanjeev Bagewadi <sanjeev.bagewadi@gmail.com>
|
|
||||||
Sara Hartse <sara.hartse@delphix.com>
|
|
||||||
Saso Kiselkov <saso.kiselkov@nexenta.com>
|
Saso Kiselkov <saso.kiselkov@nexenta.com>
|
||||||
Satadru Pramanik <satadru@gmail.com>
|
|
||||||
Savyasachee Jha <genghizkhan91@hawkradius.com>
|
|
||||||
Scott Colby <scott@scolby.com>
|
|
||||||
Scot W. Stevenson <scot.stevenson@gmail.com>
|
Scot W. Stevenson <scot.stevenson@gmail.com>
|
||||||
Sean Eric Fagan <sef@ixsystems.com>
|
Sean Eric Fagan <sef@ixsystems.com>
|
||||||
Sebastian Gottschall <s.gottschall@dd-wrt.com>
|
Sebastian Gottschall <s.gottschall@dd-wrt.com>
|
||||||
Sebastian Wuerl <s.wuerl@mailbox.org>
|
|
||||||
Sebastien Roy <seb@delphix.com>
|
|
||||||
Sen Haerens <sen@senhaerens.be>
|
Sen Haerens <sen@senhaerens.be>
|
||||||
Serapheim Dimitropoulos <serapheim@delphix.com>
|
Serapheim Dimitropoulos <serapheim@delphix.com>
|
||||||
Seth Forshee <seth.forshee@canonical.com>
|
Seth Forshee <seth.forshee@canonical.com>
|
||||||
Seth Hoffert <Seth.Hoffert@gmail.com>
|
|
||||||
Seth Troisi <sethtroisi@google.com>
|
|
||||||
Shaan Nobee <sniper111@gmail.com>
|
|
||||||
Shampavman <sham.pavman@nexenta.com>
|
Shampavman <sham.pavman@nexenta.com>
|
||||||
Shaun Tancheff <shaun@aeonazure.com>
|
|
||||||
Shawn Bayern <sbayern@law.fsu.edu>
|
|
||||||
Shengqi Chen <harry-chen@outlook.com>
|
|
||||||
Shen Yan <shenyanxxxy@qq.com>
|
Shen Yan <shenyanxxxy@qq.com>
|
||||||
Sietse <sietse@wizdom.nu>
|
|
||||||
Simon Guest <simon.guest@tesujimath.org>
|
Simon Guest <simon.guest@tesujimath.org>
|
||||||
Simon Klinkert <simon.klinkert@gmail.com>
|
Simon Klinkert <simon.klinkert@gmail.com>
|
||||||
Sowrabha Gopal <sowrabha.gopal@delphix.com>
|
Sowrabha Gopal <sowrabha.gopal@delphix.com>
|
||||||
Spencer Kinny <spencerkinny1995@gmail.com>
|
|
||||||
Srikanth N S <srikanth.nagasubbaraoseetharaman@hpe.com>
|
|
||||||
Stanislav Seletskiy <s.seletskiy@gmail.com>
|
Stanislav Seletskiy <s.seletskiy@gmail.com>
|
||||||
Stefan Lendl <s.lendl@proxmox.com>
|
|
||||||
Steffen Müthing <steffen.muething@iwr.uni-heidelberg.de>
|
Steffen Müthing <steffen.muething@iwr.uni-heidelberg.de>
|
||||||
Stephen Blinick <stephen.blinick@delphix.com>
|
Stephen Blinick <stephen.blinick@delphix.com>
|
||||||
sterlingjensen <sterlingjensen@users.noreply.github.com>
|
|
||||||
Steve Dougherty <sdougherty@barracuda.com>
|
Steve Dougherty <sdougherty@barracuda.com>
|
||||||
Steve Mokris <smokris@softpixel.com>
|
|
||||||
Steven Burgess <sburgess@dattobackup.com>
|
Steven Burgess <sburgess@dattobackup.com>
|
||||||
Steven Hartland <smh@freebsd.org>
|
Steven Hartland <smh@freebsd.org>
|
||||||
Steven Johnson <sjohnson@sakuraindustries.com>
|
Steven Johnson <sjohnson@sakuraindustries.com>
|
||||||
Steven Noonan <steven@uplinklabs.net>
|
|
||||||
stf <s@ctrlc.hu>
|
|
||||||
Stian Ellingsen <stian@plaimi.net>
|
Stian Ellingsen <stian@plaimi.net>
|
||||||
Stoiko Ivanov <github@nomore.at>
|
|
||||||
Stéphane Lesimple <speed47_github@speed47.net>
|
|
||||||
Suman Chakravartula <schakrava@gmail.com>
|
Suman Chakravartula <schakrava@gmail.com>
|
||||||
Sydney Vanda <sydney.m.vanda@intel.com>
|
Sydney Vanda <sydney.m.vanda@intel.com>
|
||||||
Sören Tempel <soeren+git@soeren-tempel.net>
|
Sören Tempel <soeren+git@soeren-tempel.net>
|
||||||
Tamas TEVESZ <ice@extreme.hu>
|
|
||||||
Teodor Spæren <teodor_spaeren@riseup.net>
|
|
||||||
TerraTech <TerraTech@users.noreply.github.com>
|
|
||||||
Theera K. <tkittich@hotmail.com>
|
|
||||||
Thijs Cramer <thijs.cramer@gmail.com>
|
Thijs Cramer <thijs.cramer@gmail.com>
|
||||||
Thomas Bertschinger <bertschinger@lanl.gov>
|
|
||||||
Thomas Geppert <geppi@digitx.de>
|
|
||||||
Thomas Lamprecht <guggentom@hotmail.de>
|
|
||||||
Till Maas <opensource@till.name>
|
|
||||||
Tim Chase <tim@chase2k.com>
|
Tim Chase <tim@chase2k.com>
|
||||||
Tim Connors <tconnors@rather.puzzling.org>
|
Tim Connors <tconnors@rather.puzzling.org>
|
||||||
Tim Crawford <tcrawford@datto.com>
|
Tim Crawford <tcrawford@datto.com>
|
||||||
Tim Haley <Tim.Haley@Sun.COM>
|
Tim Haley <Tim.Haley@Sun.COM>
|
||||||
timor <timor.dd@googlemail.com>
|
|
||||||
Timothy Day <tday141@gmail.com>
|
|
||||||
Tim Schumacher <timschumi@gmx.de>
|
|
||||||
Tino Reichardt <milky-zfs@mcmilk.de>
|
|
||||||
Tobin Harding <me@tobin.cc>
|
Tobin Harding <me@tobin.cc>
|
||||||
Todd Seidelmann <seidelma@users.noreply.github.com>
|
|
||||||
Tom Caputi <tcaputi@datto.com>
|
Tom Caputi <tcaputi@datto.com>
|
||||||
Tom Matthews <tom@axiom-partners.com>
|
Tom Matthews <tom@axiom-partners.com>
|
||||||
Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
|
|
||||||
Tom Prince <tom.prince@ualberta.net>
|
Tom Prince <tom.prince@ualberta.net>
|
||||||
|
Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
|
||||||
Tony Hutter <hutter2@llnl.gov>
|
Tony Hutter <hutter2@llnl.gov>
|
||||||
Tony Nguyen <tony.nguyen@delphix.com>
|
|
||||||
Tony Perkins <tperkins@datto.com>
|
|
||||||
Toomas Soome <tsoome@me.com>
|
Toomas Soome <tsoome@me.com>
|
||||||
Torsten Wörtwein <twoertwein@gmail.com>
|
|
||||||
Toyam Cox <aviator45003@gmail.com>
|
|
||||||
Trevor Bautista <trevrb@trevrb.net>
|
|
||||||
Trey Dockendorf <treydock@gmail.com>
|
Trey Dockendorf <treydock@gmail.com>
|
||||||
Troels Nørgaard <tnn@tradeshift.com>
|
|
||||||
tstabrawa <tstabrawa@users.noreply.github.com>
|
|
||||||
Tulsi Jain <tulsi.jain@delphix.com>
|
|
||||||
Turbo Fredriksson <turbo@bayour.com>
|
Turbo Fredriksson <turbo@bayour.com>
|
||||||
Tyler J. Stachecki <stachecki.tyler@gmail.com>
|
Tyler J. Stachecki <stachecki.tyler@gmail.com>
|
||||||
Umer Saleem <usaleem@ixsystems.com>
|
|
||||||
Vaibhav Bhanawat <vaibhav.bhanawat@delphix.com>
|
|
||||||
Valmiky Arquissandas <kayvlim@gmail.com>
|
|
||||||
Val Packett <val@packett.cool>
|
|
||||||
Vince van Oosten <techhazard@codeforyouand.me>
|
|
||||||
Violet Purcell <vimproved@inventati.org>
|
|
||||||
Vipin Kumar Verma <vipin.verma@hpe.com>
|
|
||||||
Vitaut Bajaryn <vitaut.bayaryn@gmail.com>
|
Vitaut Bajaryn <vitaut.bayaryn@gmail.com>
|
||||||
Volker Mauel <volkermauel@gmail.com>
|
|
||||||
Václav Skála <skala@vshosting.cz>
|
|
||||||
Walter Huf <hufman@gmail.com>
|
|
||||||
Warner Losh <imp@bsdimp.com>
|
|
||||||
Weigang Li <weigang.li@intel.com>
|
Weigang Li <weigang.li@intel.com>
|
||||||
WHR <msl0000023508@gmail.com>
|
|
||||||
Will Andrews <will@freebsd.org>
|
Will Andrews <will@freebsd.org>
|
||||||
Will Rouesnel <w.rouesnel@gmail.com>
|
Will Rouesnel <w.rouesnel@gmail.com>
|
||||||
Windel Bouwman <windel@windel.nl>
|
|
||||||
Wojciech Małota-Wójcik <outofforest@users.noreply.github.com>
|
|
||||||
Wolfgang Bumiller <w.bumiller@proxmox.com>
|
Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||||
XDTG <click1799@163.com>
|
|
||||||
Xin Li <delphij@FreeBSD.org>
|
Xin Li <delphij@FreeBSD.org>
|
||||||
Xinliang Liu <xinliang.liu@linaro.org>
|
|
||||||
xtouqh <xtouqh@hotmail.com>
|
|
||||||
Yann Collet <cyan@fb.com>
|
|
||||||
Yanping Gao <yanping.gao@xtaotech.com>
|
|
||||||
Ying Zhu <casualfisher@gmail.com>
|
Ying Zhu <casualfisher@gmail.com>
|
||||||
Youzhong Yang <youzhong@gmail.com>
|
|
||||||
yparitcher <y@paritcher.com>
|
|
||||||
yuina822 <ayuichi@club.kyutech.ac.jp>
|
|
||||||
YunQiang Su <syq@debian.org>
|
YunQiang Su <syq@debian.org>
|
||||||
Yuri Pankov <yuri.pankov@gmail.com>
|
Yuri Pankov <yuri.pankov@gmail.com>
|
||||||
Yuxin Wang <yuxinwang9999@gmail.com>
|
|
||||||
Yuxuan Shui <yshuiv7@gmail.com>
|
Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
Zachary Bedell <zac@thebedells.org>
|
Zachary Bedell <zac@thebedells.org>
|
||||||
Zach Dykstra <dykstra.zachary@gmail.com>
|
|
||||||
zgock <zgock@nuc.base.zgock-lab.net>
|
|
||||||
Zhao Yongming <zym@apache.org>
|
|
||||||
Zhenlei Huang <zlei@FreeBSD.org>
|
|
||||||
Zhu Chuang <chuang@melty.land>
|
|
||||||
Érico Nogueira <erico.erc@gmail.com>
|
|
||||||
Đoàn Trần Công Danh <congdanhqx@gmail.com>
|
|
||||||
韩朴宇 <w12101111@gmail.com>
|
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
The [OpenZFS Code of Conduct](https://openzfs.org/wiki/Code_of_Conduct)
|
The [OpenZFS Code of Conduct](http://www.open-zfs.org/wiki/Code_of_Conduct)
|
||||||
applies to spaces associated with the OpenZFS project, including GitHub.
|
applies to spaces associated with the OpenZFS project, including GitHub.
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
Meta: 1
|
Meta: 1
|
||||||
Name: zfs
|
Name: zfs
|
||||||
Branch: 1.0
|
Branch: 1.0
|
||||||
Version: 2.3.0
|
Version: 2.1.4
|
||||||
Release: 1
|
Release: 1
|
||||||
Release-Tags: relext
|
Release-Tags: relext
|
||||||
License: CDDL
|
License: CDDL
|
||||||
Author: OpenZFS
|
Author: OpenZFS
|
||||||
Linux-Maximum: 6.12
|
Linux-Maximum: 5.17
|
||||||
Linux-Minimum: 4.18
|
Linux-Minimum: 3.10
|
||||||
|
|||||||
+125
-96
@@ -1,82 +1,68 @@
|
|||||||
CLEANFILES =
|
|
||||||
dist_noinst_DATA =
|
|
||||||
INSTALL_DATA_HOOKS =
|
|
||||||
ALL_LOCAL =
|
|
||||||
CLEAN_LOCAL =
|
|
||||||
CHECKS = shellcheck checkbashisms
|
|
||||||
|
|
||||||
include $(top_srcdir)/config/Rules.am
|
|
||||||
include $(top_srcdir)/config/CppCheck.am
|
|
||||||
include $(top_srcdir)/config/Shellcheck.am
|
include $(top_srcdir)/config/Shellcheck.am
|
||||||
include $(top_srcdir)/config/Substfiles.am
|
|
||||||
include $(top_srcdir)/scripts/Makefile.am
|
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I config
|
ACLOCAL_AMFLAGS = -I config
|
||||||
|
|
||||||
SUBDIRS = include
|
SUBDIRS = include
|
||||||
if BUILD_LINUX
|
if BUILD_LINUX
|
||||||
include $(srcdir)/%D%/rpm/Makefile.am
|
SUBDIRS += rpm
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if CONFIG_USER
|
if CONFIG_USER
|
||||||
include $(srcdir)/%D%/cmd/Makefile.am
|
SUBDIRS += man scripts lib tests cmd etc contrib
|
||||||
include $(srcdir)/%D%/contrib/Makefile.am
|
|
||||||
include $(srcdir)/%D%/etc/Makefile.am
|
|
||||||
include $(srcdir)/%D%/lib/Makefile.am
|
|
||||||
include $(srcdir)/%D%/man/Makefile.am
|
|
||||||
include $(srcdir)/%D%/tests/Makefile.am
|
|
||||||
if BUILD_LINUX
|
if BUILD_LINUX
|
||||||
include $(srcdir)/%D%/udev/Makefile.am
|
SUBDIRS += udev
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
CPPCHECKDIRS += module
|
|
||||||
if CONFIG_KERNEL
|
if CONFIG_KERNEL
|
||||||
SUBDIRS += module
|
SUBDIRS += module
|
||||||
|
|
||||||
extradir = $(prefix)/src/zfs-$(VERSION)
|
extradir = $(prefix)/src/zfs-$(VERSION)
|
||||||
extra_HEADERS = zfs.release.in zfs_config.h.in
|
extra_HEADERS = zfs.release.in zfs_config.h.in
|
||||||
|
|
||||||
|
if BUILD_LINUX
|
||||||
|
kerneldir = $(prefix)/src/zfs-$(VERSION)/$(LINUX_VERSION)
|
||||||
|
nodist_kernel_HEADERS = zfs.release zfs_config.h module/$(LINUX_SYMBOLS)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dist_noinst_DATA += autogen.sh copy-builtin
|
AUTOMAKE_OPTIONS = foreign
|
||||||
dist_noinst_DATA += AUTHORS CODE_OF_CONDUCT.md COPYRIGHT LICENSE META NEWS NOTICE
|
EXTRA_DIST = autogen.sh copy-builtin
|
||||||
dist_noinst_DATA += README.md RELEASES.md
|
EXTRA_DIST += config/config.awk config/rpm.am config/deb.am config/tgz.am
|
||||||
dist_noinst_DATA += module/lua/README.zfs module/os/linux/spl/README.md
|
EXTRA_DIST += AUTHORS CODE_OF_CONDUCT.md COPYRIGHT LICENSE META NEWS NOTICE
|
||||||
|
EXTRA_DIST += README.md RELEASES.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
|
||||||
dist_noinst_DATA += module/icp/algs/skein/THIRDPARTYLICENSE
|
EXTRA_DIST += module/icp/algs/skein/THIRDPARTYLICENSE
|
||||||
dist_noinst_DATA += module/icp/algs/skein/THIRDPARTYLICENSE.descrip
|
EXTRA_DIST += module/icp/algs/skein/THIRDPARTYLICENSE.descrip
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman
|
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman.descrip
|
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman.descrip
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
|
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl.descrip
|
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl.descrip
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams
|
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams.descrip
|
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams.descrip
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl
|
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl
|
||||||
dist_noinst_DATA += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl.descrip
|
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl.descrip
|
||||||
dist_noinst_DATA += module/os/linux/spl/THIRDPARTYLICENSE.gplv2
|
EXTRA_DIST += module/os/linux/spl/THIRDPARTYLICENSE.gplv2
|
||||||
dist_noinst_DATA += module/os/linux/spl/THIRDPARTYLICENSE.gplv2.descrip
|
EXTRA_DIST += module/os/linux/spl/THIRDPARTYLICENSE.gplv2.descrip
|
||||||
dist_noinst_DATA += module/zfs/THIRDPARTYLICENSE.cityhash
|
EXTRA_DIST += module/zfs/THIRDPARTYLICENSE.cityhash
|
||||||
dist_noinst_DATA += module/zfs/THIRDPARTYLICENSE.cityhash.descrip
|
EXTRA_DIST += module/zfs/THIRDPARTYLICENSE.cityhash.descrip
|
||||||
|
|
||||||
@CODE_COVERAGE_RULES@
|
@CODE_COVERAGE_RULES@
|
||||||
|
|
||||||
GITREV = include/zfs_gitrev.h
|
GITREV = include/zfs_gitrev.h
|
||||||
CLEANFILES += $(GITREV)
|
|
||||||
PHONY += gitrev
|
PHONY = gitrev
|
||||||
gitrev:
|
gitrev:
|
||||||
$(AM_V_GEN)$(top_srcdir)/scripts/make_gitrev.sh $(GITREV)
|
$(AM_V_GEN)$(top_srcdir)/scripts/make_gitrev.sh $(GITREV)
|
||||||
|
|
||||||
all: gitrev
|
all: gitrev
|
||||||
|
|
||||||
PHONY += install-data-hook $(INSTALL_DATA_HOOKS)
|
# Double-colon rules are allowed; there are multiple independent definitions.
|
||||||
install-data-hook: $(INSTALL_DATA_HOOKS)
|
maintainer-clean-local::
|
||||||
|
|
||||||
PHONY += maintainer-clean-local
|
|
||||||
maintainer-clean-local:
|
|
||||||
-$(RM) $(GITREV)
|
-$(RM) $(GITREV)
|
||||||
|
|
||||||
PHONY += distclean-local
|
distclean-local::
|
||||||
distclean-local:
|
|
||||||
-$(RM) -R autom4te*.cache build
|
-$(RM) -R autom4te*.cache build
|
||||||
-find . \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
|
-find . \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
|
||||||
-o -name .pc -o -name .hg -o -name .git \) -prune -o \
|
-o -name .pc -o -name .hg -o -name .git \) -prune -o \
|
||||||
@@ -86,105 +72,148 @@ distclean-local:
|
|||||||
-o -name 'core' -o -name 'Makefile' -o -name 'Module.symvers' \
|
-o -name 'core' -o -name 'Makefile' -o -name 'Module.symvers' \
|
||||||
-o -name '*.order' -o -name '*.markers' -o -name '*.gcda' \
|
-o -name '*.order' -o -name '*.markers' -o -name '*.gcda' \
|
||||||
-o -name '*.gcno' \) \
|
-o -name '*.gcno' \) \
|
||||||
-type f -delete
|
-type f -print | xargs $(RM)
|
||||||
|
|
||||||
PHONY += $(CLEAN_LOCAL)
|
all-local:
|
||||||
clean-local: $(CLEAN_LOCAL)
|
-[ -x ${top_builddir}/scripts/zfs-tests.sh ] && \
|
||||||
|
${top_builddir}/scripts/zfs-tests.sh -c
|
||||||
PHONY += $(ALL_LOCAL)
|
|
||||||
all-local: $(ALL_LOCAL)
|
|
||||||
|
|
||||||
dist-hook:
|
dist-hook:
|
||||||
$(top_srcdir)/scripts/make_gitrev.sh -D $(distdir) $(GITREV)
|
$(AM_V_GEN)$(top_srcdir)/scripts/make_gitrev.sh -D $(distdir) $(GITREV)
|
||||||
$(SED) $(ac_inplace) 's/\(Release:[[:space:]]*\).*/\1$(RELEASE)/' $(distdir)/META
|
$(SED) ${ac_inplace} -e 's/Release:[[:print:]]*/Release: $(RELEASE)/' \
|
||||||
|
$(distdir)/META
|
||||||
|
|
||||||
PHONY += codecheck $(CHECKS)
|
if BUILD_LINUX
|
||||||
codecheck: $(CHECKS)
|
# For compatibility, create a matching spl-x.y.z directly which contains
|
||||||
|
# symlinks to the updated header and object file locations. These
|
||||||
|
# compatibility links will be removed in the next major release.
|
||||||
|
if CONFIG_KERNEL
|
||||||
|
install-data-hook:
|
||||||
|
rm -rf $(DESTDIR)$(prefix)/src/spl-$(VERSION) && \
|
||||||
|
mkdir $(DESTDIR)$(prefix)/src/spl-$(VERSION) && \
|
||||||
|
cd $(DESTDIR)$(prefix)/src/spl-$(VERSION) && \
|
||||||
|
ln -s ../zfs-$(VERSION)/include/spl include && \
|
||||||
|
ln -s ../zfs-$(VERSION)/$(LINUX_VERSION) $(LINUX_VERSION) && \
|
||||||
|
ln -s ../zfs-$(VERSION)/zfs_config.h.in spl_config.h.in && \
|
||||||
|
ln -s ../zfs-$(VERSION)/zfs.release.in spl.release.in && \
|
||||||
|
cd $(DESTDIR)$(prefix)/src/zfs-$(VERSION)/$(LINUX_VERSION) && \
|
||||||
|
ln -fs zfs_config.h spl_config.h && \
|
||||||
|
ln -fs zfs.release spl.release
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
SHELLCHECKSCRIPTS += autogen.sh
|
PHONY += codecheck
|
||||||
|
codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck
|
||||||
|
|
||||||
PHONY += checkstyle
|
PHONY += checkstyle
|
||||||
checkstyle: codecheck commitcheck
|
checkstyle: codecheck commitcheck
|
||||||
|
|
||||||
PHONY += commitcheck
|
PHONY += commitcheck
|
||||||
commitcheck:
|
commitcheck:
|
||||||
$(AM_V_at)if git rev-parse --git-dir > /dev/null 2>&1; then \
|
@if git rev-parse --git-dir > /dev/null 2>&1; then \
|
||||||
${top_srcdir}/scripts/commitcheck.sh; \
|
${top_srcdir}/scripts/commitcheck.sh; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if HAVE_PARALLEL
|
PHONY += cstyle
|
||||||
cstyle_line = -print0 | parallel -X0 ${top_srcdir}/scripts/cstyle.pl -cpP {}
|
|
||||||
else
|
|
||||||
cstyle_line = -exec ${top_srcdir}/scripts/cstyle.pl -cpP {} +
|
|
||||||
endif
|
|
||||||
CHECKS += cstyle
|
|
||||||
cstyle:
|
cstyle:
|
||||||
$(AM_V_at)find $(top_srcdir) -name build -prune \
|
@find ${top_srcdir} -name build -prune \
|
||||||
-o -type f -name '*.[hc]' \
|
-o -type f -name '*.[hc]' \
|
||||||
! -name 'zfs_config.*' ! -name '*.mod.c' \
|
! -name 'zfs_config.*' ! -name '*.mod.c' \
|
||||||
! -name 'opt_global.h' ! -name '*_if*.h' \
|
! -name 'opt_global.h' ! -name '*_if*.h' \
|
||||||
! -name 'zstd_compat_wrapper.h' \
|
|
||||||
! -path './module/zstd/lib/*' \
|
! -path './module/zstd/lib/*' \
|
||||||
! -path './include/sys/lua/*' \
|
-exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
|
||||||
! -path './module/lua/l*.[ch]' \
|
|
||||||
! -path './module/zfs/lz4.c' \
|
|
||||||
$(cstyle_line)
|
|
||||||
|
|
||||||
filter_executable = -exec test -x '{}' \; -print
|
filter_executable = -exec test -x '{}' \; -print
|
||||||
CHECKS += testscheck
|
|
||||||
testscheck:
|
|
||||||
$(AM_V_at)[ $$(find $(top_srcdir)/tests/zfs-tests -type f \
|
|
||||||
\( -name '*.ksh' -not $(filter_executable) \) -o \
|
|
||||||
\( -name '*.kshlib' $(filter_executable) \) -o \
|
|
||||||
\( -name '*.shlib' $(filter_executable) \) -o \
|
|
||||||
\( -name '*.cfg' $(filter_executable) \) | \
|
|
||||||
tee /dev/stderr | wc -l) -eq 0 ]
|
|
||||||
|
|
||||||
CHECKS += vcscheck
|
SHELLCHECKDIRS = cmd contrib etc scripts tests
|
||||||
|
SHELLCHECKSCRIPTS = autogen.sh
|
||||||
|
|
||||||
|
PHONY += checkabi storeabi
|
||||||
|
|
||||||
|
checklibabiversion:
|
||||||
|
libabiversion=`abidw -v | $(SED) 's/[^0-9]//g'`; \
|
||||||
|
if test $$libabiversion -lt "200"; then \
|
||||||
|
/bin/echo -e "\n" \
|
||||||
|
"*** Please use libabigail 2.0.0 version or newer;\n" \
|
||||||
|
"*** otherwise results are not consistent!\n" \
|
||||||
|
"(or see https://github.com/openzfs/libabigail-docker )\n"; \
|
||||||
|
exit 1; \
|
||||||
|
fi;
|
||||||
|
|
||||||
|
checkabi: checklibabiversion lib
|
||||||
|
$(MAKE) -C lib checkabi
|
||||||
|
|
||||||
|
storeabi: checklibabiversion lib
|
||||||
|
$(MAKE) -C lib storeabi
|
||||||
|
|
||||||
|
PHONY += mancheck
|
||||||
|
mancheck:
|
||||||
|
${top_srcdir}/scripts/mancheck.sh ${top_srcdir}/man ${top_srcdir}/tests/test-runner/man
|
||||||
|
|
||||||
|
if BUILD_LINUX
|
||||||
|
stat_fmt = -c '%A %n'
|
||||||
|
else
|
||||||
|
stat_fmt = -f '%Sp %N'
|
||||||
|
endif
|
||||||
|
|
||||||
|
PHONY += testscheck
|
||||||
|
testscheck:
|
||||||
|
@find ${top_srcdir}/tests/zfs-tests -type f \
|
||||||
|
\( -name '*.ksh' -not ${filter_executable} \) -o \
|
||||||
|
\( -name '*.kshlib' ${filter_executable} \) -o \
|
||||||
|
\( -name '*.shlib' ${filter_executable} \) -o \
|
||||||
|
\( -name '*.cfg' ${filter_executable} \) | \
|
||||||
|
xargs -r stat ${stat_fmt} | \
|
||||||
|
awk '{c++; print} END {if(c>0) exit 1}'
|
||||||
|
|
||||||
|
PHONY += vcscheck
|
||||||
vcscheck:
|
vcscheck:
|
||||||
$(AM_V_at)if git rev-parse --git-dir > /dev/null 2>&1; then \
|
@if git rev-parse --git-dir > /dev/null 2>&1; then \
|
||||||
git ls-files . --exclude-standard --others | \
|
git ls-files . --exclude-standard --others | \
|
||||||
awk '{c++; print} END {if(c>0) exit 1}' ; \
|
awk '{c++; print} END {if(c>0) exit 1}' ; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CHECKS += zstdcheck
|
|
||||||
zstdcheck:
|
|
||||||
@$(MAKE) -C module check-zstd-symbols
|
|
||||||
|
|
||||||
PHONY += lint
|
PHONY += lint
|
||||||
lint: cppcheck paxcheck
|
lint: cppcheck paxcheck
|
||||||
|
|
||||||
|
CPPCHECKDIRS = cmd lib module
|
||||||
|
PHONY += cppcheck
|
||||||
|
cppcheck: $(CPPCHECKDIRS)
|
||||||
|
@if test -n "$(CPPCHECK)"; then \
|
||||||
|
set -e ; for dir in $(CPPCHECKDIRS) ; do \
|
||||||
|
$(MAKE) -C $$dir cppcheck ; \
|
||||||
|
done \
|
||||||
|
else \
|
||||||
|
echo "skipping cppcheck because cppcheck is not installed"; \
|
||||||
|
fi
|
||||||
|
|
||||||
PHONY += paxcheck
|
PHONY += paxcheck
|
||||||
paxcheck:
|
paxcheck:
|
||||||
$(AM_V_at)if type scanelf > /dev/null 2>&1; then \
|
@if type scanelf > /dev/null 2>&1; then \
|
||||||
$(top_srcdir)/scripts/paxcheck.sh $(top_builddir); \
|
${top_srcdir}/scripts/paxcheck.sh ${top_builddir}; \
|
||||||
else \
|
else \
|
||||||
echo "skipping paxcheck because scanelf is not installed"; \
|
echo "skipping paxcheck because scanelf is not installed"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CHECKS += flake8
|
PHONY += flake8
|
||||||
flake8:
|
flake8:
|
||||||
$(AM_V_at)if type flake8 > /dev/null 2>&1; then \
|
@if type flake8 > /dev/null 2>&1; then \
|
||||||
flake8 $(top_srcdir); \
|
flake8 ${top_srcdir}; \
|
||||||
else \
|
else \
|
||||||
echo "skipping flake8 because flake8 is not installed"; \
|
echo "skipping flake8 because flake8 is not installed"; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PHONY += regen-tests
|
|
||||||
regen-tests:
|
|
||||||
@$(MAKE) -C tests/zfs-tests/tests regen
|
|
||||||
|
|
||||||
PHONY += ctags
|
PHONY += ctags
|
||||||
ctags:
|
ctags:
|
||||||
$(RM) tags
|
$(RM) tags
|
||||||
find $(top_srcdir) -name '.?*' -prune \
|
find $(top_srcdir) -name '.?*' -prune \
|
||||||
-o -type f -name '*.[hcS]' -exec ctags -a {} +
|
-o -type f -name '*.[hcS]' -print | xargs ctags -a
|
||||||
|
|
||||||
PHONY += etags
|
PHONY += etags
|
||||||
etags:
|
etags:
|
||||||
$(RM) TAGS
|
$(RM) TAGS
|
||||||
find $(top_srcdir) -name '.?*' -prune \
|
find $(top_srcdir) -name '.?*' -prune \
|
||||||
-o -type f -name '*.[hcS]' -exec etags -a {} +
|
-o -type f -name '*.[hcS]' -print | xargs etags -a
|
||||||
|
|
||||||
PHONY += cscopelist
|
PHONY += cscopelist
|
||||||
cscopelist:
|
cscopelist:
|
||||||
|
|||||||
@@ -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 13.0-RELEASE.
|
* Supported FreeBSD versions are any supported branches and releases starting from 12.2-RELEASE.
|
||||||
|
|||||||
+2
-60
@@ -1,62 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
[ "${0%/*}" = "$0" ] || cd "${0%/*}" || exit
|
|
||||||
|
|
||||||
# %reldir%/%canon_reldir% (%D%/%C%) only appeared in automake 1.14, but RHEL/CentOS 7 has 1.13.4
|
autoreconf -fiv || exit 1
|
||||||
# This is an (overly) simplistic preprocessor that papers around this for the duration of the generation step,
|
rm -Rf autom4te.cache
|
||||||
# and can be removed once support for CentOS 7 is dropped
|
|
||||||
automake --version | awk '{print $NF; exit}' | (
|
|
||||||
IFS=. read -r AM_MAJ AM_MIN _
|
|
||||||
[ "$AM_MAJ" -gt 1 ] || [ "$AM_MIN" -ge 14 ]
|
|
||||||
) || {
|
|
||||||
process_root() {
|
|
||||||
root="$1"; shift
|
|
||||||
|
|
||||||
grep -q '%[CD]%' "$root/Makefile.am" || return
|
|
||||||
find "$root" -name Makefile.am "$@" | while read -r dir; do
|
|
||||||
dir="${dir%/Makefile.am}"
|
|
||||||
grep -q '%[CD]%' "$dir/Makefile.am" || continue
|
|
||||||
|
|
||||||
reldir="${dir#"$root"}"
|
|
||||||
reldir="${reldir#/}"
|
|
||||||
|
|
||||||
canon_reldir="$(printf '%s' "$reldir" | tr -C 'a-zA-Z0-9@_' '_')"
|
|
||||||
|
|
||||||
reldir_slash="$reldir/"
|
|
||||||
canon_reldir_slash="${canon_reldir}_"
|
|
||||||
[ -z "$reldir" ] && reldir_slash=
|
|
||||||
[ -z "$reldir" ] && canon_reldir_slash=
|
|
||||||
|
|
||||||
echo "$dir/Makefile.am" >&3
|
|
||||||
sed -i~ -e "s:%D%/:$reldir_slash:g" -e "s:%D%:$reldir:g" \
|
|
||||||
-e "s:%C%_:$canon_reldir_slash:g" -e "s:%C%:$canon_reldir:g" "$dir/Makefile.am"
|
|
||||||
done 3>>"$substituted_files"
|
|
||||||
}
|
|
||||||
|
|
||||||
rollback() {
|
|
||||||
while read -r f; do
|
|
||||||
mv "$f~" "$f"
|
|
||||||
done < "$substituted_files"
|
|
||||||
rm -f "$substituted_files"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
echo "Automake <1.14; papering over missing %reldir%/%canon_reldir% support" >&2
|
|
||||||
|
|
||||||
substituted_files="$(mktemp)"
|
|
||||||
trap rollback EXIT
|
|
||||||
|
|
||||||
roots="$(sed '/Makefile$/!d;/module/d;s:^\s*:./:;s:/Makefile::;/^\.$/d' configure.ac)"
|
|
||||||
|
|
||||||
IFS="
|
|
||||||
"
|
|
||||||
for root in $roots; do
|
|
||||||
root="${root#./}"
|
|
||||||
process_root "$root"
|
|
||||||
done
|
|
||||||
|
|
||||||
set -f
|
|
||||||
# shellcheck disable=SC2086,SC2046
|
|
||||||
process_root . $(printf '!\n-path\n%s/*\n' $roots)
|
|
||||||
}
|
|
||||||
|
|
||||||
autoreconf -fiv && rm -rf autom4te.cache
|
|
||||||
|
|||||||
+19
-106
@@ -1,114 +1,27 @@
|
|||||||
bin_SCRIPTS =
|
include $(top_srcdir)/config/Shellcheck.am
|
||||||
bin_PROGRAMS =
|
|
||||||
sbin_SCRIPTS =
|
|
||||||
sbin_PROGRAMS =
|
|
||||||
dist_bin_SCRIPTS =
|
|
||||||
zfsexec_PROGRAMS =
|
|
||||||
mounthelper_PROGRAMS =
|
|
||||||
|
|
||||||
|
SUBDIRS = zfs zpool zdb zhack zinject zstream ztest
|
||||||
|
SUBDIRS += fsck_zfs vdev_id raidz_test zfs_ids_to_path
|
||||||
|
SUBDIRS += zpool_influxdb
|
||||||
|
|
||||||
sbin_SCRIPTS += fsck.zfs
|
CPPCHECKDIRS = zfs zpool zdb zhack zinject zstream ztest
|
||||||
SHELLCHECKSCRIPTS += fsck.zfs
|
CPPCHECKDIRS += raidz_test zfs_ids_to_path zpool_influxdb
|
||||||
CLEANFILES += fsck.zfs
|
|
||||||
dist_noinst_DATA += %D%/fsck.zfs.in
|
|
||||||
$(call SUBST,fsck.zfs,%D%/)
|
|
||||||
|
|
||||||
|
|
||||||
sbin_PROGRAMS += zfs_ids_to_path
|
|
||||||
CPPCHECKTARGETS += zfs_ids_to_path
|
|
||||||
|
|
||||||
zfs_ids_to_path_SOURCES = \
|
|
||||||
%D%/zfs_ids_to_path.c
|
|
||||||
|
|
||||||
zfs_ids_to_path_LDADD = \
|
|
||||||
libzfs.la
|
|
||||||
|
|
||||||
|
|
||||||
zhack_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
|
|
||||||
|
|
||||||
sbin_PROGRAMS += zhack
|
|
||||||
CPPCHECKTARGETS += zhack
|
|
||||||
|
|
||||||
zhack_SOURCES = \
|
|
||||||
%D%/zhack.c
|
|
||||||
|
|
||||||
zhack_LDADD = \
|
|
||||||
libzpool.la \
|
|
||||||
libzfs_core.la \
|
|
||||||
libnvpair.la
|
|
||||||
|
|
||||||
|
|
||||||
ztest_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
|
|
||||||
ztest_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
|
|
||||||
|
|
||||||
sbin_PROGRAMS += ztest
|
|
||||||
CPPCHECKTARGETS += ztest
|
|
||||||
|
|
||||||
ztest_SOURCES = \
|
|
||||||
%D%/ztest.c
|
|
||||||
|
|
||||||
ztest_LDADD = \
|
|
||||||
libzpool.la \
|
|
||||||
libzfs_core.la \
|
|
||||||
libnvpair.la
|
|
||||||
|
|
||||||
ztest_LDADD += -lm
|
|
||||||
ztest_LDFLAGS = -pthread
|
|
||||||
|
|
||||||
|
|
||||||
include $(srcdir)/%D%/raidz_test/Makefile.am
|
|
||||||
include $(srcdir)/%D%/zdb/Makefile.am
|
|
||||||
include $(srcdir)/%D%/zfs/Makefile.am
|
|
||||||
include $(srcdir)/%D%/zinject/Makefile.am
|
|
||||||
include $(srcdir)/%D%/zpool/Makefile.am
|
|
||||||
include $(srcdir)/%D%/zpool_influxdb/Makefile.am
|
|
||||||
include $(srcdir)/%D%/zstream/Makefile.am
|
|
||||||
|
|
||||||
|
|
||||||
if BUILD_LINUX
|
|
||||||
mounthelper_PROGRAMS += mount.zfs
|
|
||||||
CPPCHECKTARGETS += mount.zfs
|
|
||||||
|
|
||||||
mount_zfs_SOURCES = \
|
|
||||||
%D%/mount_zfs.c
|
|
||||||
|
|
||||||
mount_zfs_LDADD = \
|
|
||||||
libzfs.la \
|
|
||||||
libzfs_core.la \
|
|
||||||
libnvpair.la
|
|
||||||
|
|
||||||
mount_zfs_LDADD += $(LTLIBINTL)
|
|
||||||
|
|
||||||
CPPCHECKTARGETS += raidz_test
|
|
||||||
|
|
||||||
|
|
||||||
sbin_PROGRAMS += zgenhostid
|
|
||||||
CPPCHECKTARGETS += zgenhostid
|
|
||||||
|
|
||||||
zgenhostid_SOURCES = \
|
|
||||||
%D%/zgenhostid.c
|
|
||||||
|
|
||||||
|
|
||||||
dist_bin_SCRIPTS += %D%/zvol_wait
|
|
||||||
SHELLCHECKSCRIPTS += %D%/zvol_wait
|
|
||||||
|
|
||||||
|
|
||||||
include $(srcdir)/%D%/zed/Makefile.am
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
# TODO: #12084: SHELLCHECKDIRS = fsck_zfs vdev_id zpool
|
||||||
|
SHELLCHECKDIRS = fsck_zfs zpool
|
||||||
|
|
||||||
if USING_PYTHON
|
if USING_PYTHON
|
||||||
bin_SCRIPTS += arc_summary arcstat dbufstat zilstat
|
SUBDIRS += arcstat arc_summary dbufstat
|
||||||
CLEANFILES += arc_summary arcstat dbufstat zilstat
|
|
||||||
dist_noinst_DATA += %D%/arc_summary %D%/arcstat.in %D%/dbufstat.in %D%/zilstat.in
|
|
||||||
|
|
||||||
$(call SUBST,arcstat,%D%/)
|
|
||||||
$(call SUBST,dbufstat,%D%/)
|
|
||||||
$(call SUBST,zilstat,%D%/)
|
|
||||||
arc_summary: %D%/arc_summary
|
|
||||||
$(AM_V_at)cp $< $@
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_LINUX
|
||||||
|
SUBDIRS += mount_zfs zed zgenhostid zvol_id zvol_wait
|
||||||
|
CPPCHECKDIRS += mount_zfs zed zgenhostid zvol_id
|
||||||
|
SHELLCHECKDIRS += zed
|
||||||
|
endif
|
||||||
|
|
||||||
PHONY += cmd
|
PHONY = cppcheck
|
||||||
cmd: $(bin_SCRIPTS) $(bin_PROGRAMS) $(sbin_SCRIPTS) $(sbin_PROGRAMS) $(dist_bin_SCRIPTS) $(zfsexec_PROGRAMS) $(mounthelper_PROGRAMS)
|
cppcheck: $(CPPCHECKDIRS)
|
||||||
|
set -e ; for dir in $(CPPCHECKDIRS) ; do \
|
||||||
|
$(MAKE) -C $$dir cppcheck ; \
|
||||||
|
done
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
arc_summary
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
bin_SCRIPTS = arc_summary
|
||||||
|
|
||||||
|
CLEANFILES = arc_summary
|
||||||
|
EXTRA_DIST = arc_summary2 arc_summary3
|
||||||
|
|
||||||
|
if USING_PYTHON_2
|
||||||
|
SCRIPT = arc_summary2
|
||||||
|
else
|
||||||
|
SCRIPT = arc_summary3
|
||||||
|
endif
|
||||||
|
|
||||||
|
arc_summary: $(SCRIPT)
|
||||||
|
cp $< $@
|
||||||
Executable
+1180
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,7 @@ SECTION_HELP = 'print info from one section ('+' '.join(SECTIONS)+')'
|
|||||||
SECTION_PATHS = {'arc': 'arcstats',
|
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',
|
||||||
'zfetch': 'zfetchstats',
|
'zfetch': 'zfetchstats',
|
||||||
'zil': 'zil'}
|
'zil': 'zil'}
|
||||||
|
|
||||||
@@ -89,6 +90,8 @@ if sys.platform.startswith('freebsd'):
|
|||||||
# Requires py36-sysctl on FreeBSD
|
# Requires py36-sysctl on FreeBSD
|
||||||
import sysctl
|
import sysctl
|
||||||
|
|
||||||
|
VDEV_CACHE_SIZE = 'vdev.cache_size'
|
||||||
|
|
||||||
def is_value(ctl):
|
def is_value(ctl):
|
||||||
return ctl.type != sysctl.CTLTYPE_NODE
|
return ctl.type != sysctl.CTLTYPE_NODE
|
||||||
|
|
||||||
@@ -132,6 +135,8 @@ elif sys.platform.startswith('linux'):
|
|||||||
SPL_PATH = '/sys/module/spl/parameters'
|
SPL_PATH = '/sys/module/spl/parameters'
|
||||||
TUNABLES_PATH = '/sys/module/zfs/parameters'
|
TUNABLES_PATH = '/sys/module/zfs/parameters'
|
||||||
|
|
||||||
|
VDEV_CACHE_SIZE = 'zfs_vdev_cache_size'
|
||||||
|
|
||||||
def load_kstats(section):
|
def load_kstats(section):
|
||||||
path = os.path.join(KSTAT_PATH, section)
|
path = os.path.join(KSTAT_PATH, section)
|
||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
@@ -186,13 +191,21 @@ elif sys.platform.startswith('linux'):
|
|||||||
# there, so we fall back on modinfo
|
# there, so we fall back on modinfo
|
||||||
command = ["/sbin/modinfo", request, "-0"]
|
command = ["/sbin/modinfo", request, "-0"]
|
||||||
|
|
||||||
|
# The recommended way to do this is with subprocess.run(). However,
|
||||||
|
# some installed versions of Python are < 3.5, so we offer them
|
||||||
|
# the option of doing it the old way (for now)
|
||||||
info = ''
|
info = ''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
info = subprocess.run(command, stdout=subprocess.PIPE,
|
if 'run' in dir(subprocess):
|
||||||
check=True, universal_newlines=True)
|
info = subprocess.run(command, stdout=subprocess.PIPE,
|
||||||
raw_output = info.stdout.split('\0')
|
universal_newlines=True)
|
||||||
|
raw_output = info.stdout.split('\0')
|
||||||
|
else:
|
||||||
|
info = subprocess.check_output(command,
|
||||||
|
universal_newlines=True)
|
||||||
|
raw_output = info.split('\0')
|
||||||
|
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
print("Error: Descriptions not available",
|
print("Error: Descriptions not available",
|
||||||
@@ -260,34 +273,35 @@ def draw_graph(kstats_dict):
|
|||||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
arc_stats = isolate_section('arcstats', kstats_dict)
|
||||||
|
|
||||||
GRAPH_INDENT = ' '*4
|
GRAPH_INDENT = ' '*4
|
||||||
GRAPH_WIDTH = 70
|
GRAPH_WIDTH = 60
|
||||||
arc_max = int(arc_stats['c_max'])
|
|
||||||
arc_size = f_bytes(arc_stats['size'])
|
arc_size = f_bytes(arc_stats['size'])
|
||||||
arc_perc = f_perc(arc_stats['size'], arc_max)
|
arc_perc = f_perc(arc_stats['size'], arc_stats['c_max'])
|
||||||
data_size = f_bytes(arc_stats['data_size'])
|
mfu_size = f_bytes(arc_stats['mfu_size'])
|
||||||
meta_size = f_bytes(arc_stats['metadata_size'])
|
mru_size = f_bytes(arc_stats['mru_size'])
|
||||||
|
meta_limit = f_bytes(arc_stats['arc_meta_limit'])
|
||||||
|
meta_size = f_bytes(arc_stats['arc_meta_used'])
|
||||||
|
dnode_limit = f_bytes(arc_stats['arc_dnode_limit'])
|
||||||
dnode_size = f_bytes(arc_stats['dnode_size'])
|
dnode_size = f_bytes(arc_stats['dnode_size'])
|
||||||
|
|
||||||
info_form = ('ARC: {0} ({1}) Data: {2} Meta: {3} Dnode: {4}')
|
info_form = ('ARC: {0} ({1}) MFU: {2} MRU: {3} META: {4} ({5}) '
|
||||||
info_line = info_form.format(arc_size, arc_perc, data_size, meta_size,
|
'DNODE {6} ({7})')
|
||||||
dnode_size)
|
info_line = info_form.format(arc_size, arc_perc, mfu_size, mru_size,
|
||||||
|
meta_size, meta_limit, dnode_size,
|
||||||
|
dnode_limit)
|
||||||
info_spc = ' '*int((GRAPH_WIDTH-len(info_line))/2)
|
info_spc = ' '*int((GRAPH_WIDTH-len(info_line))/2)
|
||||||
info_line = GRAPH_INDENT+info_spc+info_line
|
info_line = GRAPH_INDENT+info_spc+info_line
|
||||||
|
|
||||||
graph_line = GRAPH_INDENT+'+'+('-'*(GRAPH_WIDTH-2))+'+'
|
graph_line = GRAPH_INDENT+'+'+('-'*(GRAPH_WIDTH-2))+'+'
|
||||||
|
|
||||||
arc_perc = float(int(arc_stats['size'])/arc_max)
|
mfu_perc = float(int(arc_stats['mfu_size'])/int(arc_stats['c_max']))
|
||||||
data_perc = float(int(arc_stats['data_size'])/arc_max)
|
mru_perc = float(int(arc_stats['mru_size'])/int(arc_stats['c_max']))
|
||||||
meta_perc = float(int(arc_stats['metadata_size'])/arc_max)
|
arc_perc = float(int(arc_stats['size'])/int(arc_stats['c_max']))
|
||||||
dnode_perc = float(int(arc_stats['dnode_size'])/arc_max)
|
|
||||||
total_ticks = float(arc_perc)*GRAPH_WIDTH
|
total_ticks = float(arc_perc)*GRAPH_WIDTH
|
||||||
data_ticks = data_perc*GRAPH_WIDTH
|
mfu_ticks = mfu_perc*GRAPH_WIDTH
|
||||||
meta_ticks = meta_perc*GRAPH_WIDTH
|
mru_ticks = mru_perc*GRAPH_WIDTH
|
||||||
dnode_ticks = dnode_perc*GRAPH_WIDTH
|
other_ticks = total_ticks-(mfu_ticks+mru_ticks)
|
||||||
other_ticks = total_ticks-(data_ticks+meta_ticks+dnode_ticks)
|
|
||||||
|
|
||||||
core_form = 'D'*int(data_ticks)+'M'*int(meta_ticks)+'N'*int(dnode_ticks)+\
|
core_form = 'F'*int(mfu_ticks)+'R'*int(mru_ticks)+'O'*int(other_ticks)
|
||||||
'O'*int(other_ticks)
|
|
||||||
core_spc = ' '*(GRAPH_WIDTH-(2+len(core_form)))
|
core_spc = ' '*(GRAPH_WIDTH-(2+len(core_form)))
|
||||||
core_line = GRAPH_INDENT+'|'+core_form+core_spc+'|'
|
core_line = GRAPH_INDENT+'|'+core_form+core_spc+'|'
|
||||||
|
|
||||||
@@ -537,132 +551,57 @@ def section_arc(kstats_dict):
|
|||||||
|
|
||||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
arc_stats = isolate_section('arcstats', kstats_dict)
|
||||||
|
|
||||||
memory_all = arc_stats['memory_all_bytes']
|
throttle = arc_stats['memory_throttle_count']
|
||||||
memory_free = arc_stats['memory_free_bytes']
|
|
||||||
memory_avail = arc_stats['memory_available_bytes']
|
if throttle == '0':
|
||||||
|
health = 'HEALTHY'
|
||||||
|
else:
|
||||||
|
health = 'THROTTLED'
|
||||||
|
|
||||||
|
prt_1('ARC status:', health)
|
||||||
|
prt_i1('Memory throttle count:', throttle)
|
||||||
|
print()
|
||||||
|
|
||||||
arc_size = arc_stats['size']
|
arc_size = arc_stats['size']
|
||||||
arc_target_size = arc_stats['c']
|
arc_target_size = arc_stats['c']
|
||||||
arc_max = arc_stats['c_max']
|
arc_max = arc_stats['c_max']
|
||||||
arc_min = arc_stats['c_min']
|
arc_min = arc_stats['c_min']
|
||||||
|
mfu_size = arc_stats['mfu_size']
|
||||||
|
mru_size = arc_stats['mru_size']
|
||||||
|
meta_limit = arc_stats['arc_meta_limit']
|
||||||
|
meta_size = arc_stats['arc_meta_used']
|
||||||
dnode_limit = arc_stats['arc_dnode_limit']
|
dnode_limit = arc_stats['arc_dnode_limit']
|
||||||
|
|
||||||
print('ARC status:')
|
|
||||||
prt_i1('Total memory size:', f_bytes(memory_all))
|
|
||||||
prt_i2('Min target size:', f_perc(arc_min, memory_all), f_bytes(arc_min))
|
|
||||||
prt_i2('Max target size:', f_perc(arc_max, memory_all), f_bytes(arc_max))
|
|
||||||
prt_i2('Target size (adaptive):',
|
|
||||||
f_perc(arc_size, arc_max), f_bytes(arc_target_size))
|
|
||||||
prt_i2('Current size:', f_perc(arc_size, arc_max), f_bytes(arc_size))
|
|
||||||
prt_i1('Free memory size:', f_bytes(memory_free))
|
|
||||||
prt_i1('Available memory size:', f_bytes(memory_avail))
|
|
||||||
print()
|
|
||||||
|
|
||||||
compressed_size = arc_stats['compressed_size']
|
|
||||||
overhead_size = arc_stats['overhead_size']
|
|
||||||
bonus_size = arc_stats['bonus_size']
|
|
||||||
dnode_size = arc_stats['dnode_size']
|
dnode_size = arc_stats['dnode_size']
|
||||||
dbuf_size = arc_stats['dbuf_size']
|
target_size_ratio = '{0}:1'.format(int(arc_max) // int(arc_min))
|
||||||
hdr_size = arc_stats['hdr_size']
|
|
||||||
l2_hdr_size = arc_stats['l2_hdr_size']
|
|
||||||
abd_chunk_waste_size = arc_stats['abd_chunk_waste_size']
|
|
||||||
|
|
||||||
prt_1('ARC structural breakdown (current size):', f_bytes(arc_size))
|
prt_2('ARC size (current):',
|
||||||
prt_i2('Compressed size:',
|
f_perc(arc_size, arc_max), f_bytes(arc_size))
|
||||||
f_perc(compressed_size, arc_size), f_bytes(compressed_size))
|
prt_i2('Target size (adaptive):',
|
||||||
prt_i2('Overhead size:',
|
f_perc(arc_target_size, arc_max), f_bytes(arc_target_size))
|
||||||
f_perc(overhead_size, arc_size), f_bytes(overhead_size))
|
prt_i2('Min size (hard limit):',
|
||||||
prt_i2('Bonus size:',
|
f_perc(arc_min, arc_max), f_bytes(arc_min))
|
||||||
f_perc(bonus_size, arc_size), f_bytes(bonus_size))
|
prt_i2('Max size (high water):',
|
||||||
prt_i2('Dnode size:',
|
target_size_ratio, f_bytes(arc_max))
|
||||||
f_perc(dnode_size, arc_size), f_bytes(dnode_size))
|
caches_size = int(mfu_size)+int(mru_size)
|
||||||
prt_i2('Dbuf size:',
|
prt_i2('Most Frequently Used (MFU) cache size:',
|
||||||
f_perc(dbuf_size, arc_size), f_bytes(dbuf_size))
|
f_perc(mfu_size, caches_size), f_bytes(mfu_size))
|
||||||
prt_i2('Header size:',
|
prt_i2('Most Recently Used (MRU) cache size:',
|
||||||
f_perc(hdr_size, arc_size), f_bytes(hdr_size))
|
f_perc(mru_size, caches_size), f_bytes(mru_size))
|
||||||
prt_i2('L2 header size:',
|
prt_i2('Metadata cache size (hard limit):',
|
||||||
f_perc(l2_hdr_size, arc_size), f_bytes(l2_hdr_size))
|
f_perc(meta_limit, arc_max), f_bytes(meta_limit))
|
||||||
prt_i2('ABD chunk waste size:',
|
prt_i2('Metadata cache size (current):',
|
||||||
f_perc(abd_chunk_waste_size, arc_size), f_bytes(abd_chunk_waste_size))
|
f_perc(meta_size, meta_limit), f_bytes(meta_size))
|
||||||
print()
|
prt_i2('Dnode cache size (hard limit):',
|
||||||
|
f_perc(dnode_limit, meta_limit), f_bytes(dnode_limit))
|
||||||
meta = arc_stats['meta']
|
prt_i2('Dnode cache size (current):',
|
||||||
pd = arc_stats['pd']
|
f_perc(dnode_size, dnode_limit), f_bytes(dnode_size))
|
||||||
pm = arc_stats['pm']
|
|
||||||
data_size = arc_stats['data_size']
|
|
||||||
metadata_size = arc_stats['metadata_size']
|
|
||||||
anon_data = arc_stats['anon_data']
|
|
||||||
anon_metadata = arc_stats['anon_metadata']
|
|
||||||
mfu_data = arc_stats['mfu_data']
|
|
||||||
mfu_metadata = arc_stats['mfu_metadata']
|
|
||||||
mfu_edata = arc_stats['mfu_evictable_data']
|
|
||||||
mfu_emetadata = arc_stats['mfu_evictable_metadata']
|
|
||||||
mru_data = arc_stats['mru_data']
|
|
||||||
mru_metadata = arc_stats['mru_metadata']
|
|
||||||
mru_edata = arc_stats['mru_evictable_data']
|
|
||||||
mru_emetadata = arc_stats['mru_evictable_metadata']
|
|
||||||
mfug_data = arc_stats['mfu_ghost_data']
|
|
||||||
mfug_metadata = arc_stats['mfu_ghost_metadata']
|
|
||||||
mrug_data = arc_stats['mru_ghost_data']
|
|
||||||
mrug_metadata = arc_stats['mru_ghost_metadata']
|
|
||||||
unc_data = arc_stats['uncached_data']
|
|
||||||
unc_metadata = arc_stats['uncached_metadata']
|
|
||||||
caches_size = int(anon_data)+int(anon_metadata)+\
|
|
||||||
int(mfu_data)+int(mfu_metadata)+int(mru_data)+int(mru_metadata)+\
|
|
||||||
int(unc_data)+int(unc_metadata)
|
|
||||||
|
|
||||||
prt_1('ARC types breakdown (compressed + overhead):', f_bytes(caches_size))
|
|
||||||
prt_i2('Data size:',
|
|
||||||
f_perc(data_size, caches_size), f_bytes(data_size))
|
|
||||||
prt_i2('Metadata size:',
|
|
||||||
f_perc(metadata_size, caches_size), f_bytes(metadata_size))
|
|
||||||
print()
|
|
||||||
|
|
||||||
prt_1('ARC states breakdown (compressed + overhead):', f_bytes(caches_size))
|
|
||||||
prt_i2('Anonymous data size:',
|
|
||||||
f_perc(anon_data, caches_size), f_bytes(anon_data))
|
|
||||||
prt_i2('Anonymous metadata size:',
|
|
||||||
f_perc(anon_metadata, caches_size), f_bytes(anon_metadata))
|
|
||||||
s = 4294967296
|
|
||||||
v = (s-int(pd))*(s-int(meta))/s
|
|
||||||
prt_i2('MFU data target:', f_perc(v, s),
|
|
||||||
f_bytes(v / 65536 * caches_size / 65536))
|
|
||||||
prt_i2('MFU data size:',
|
|
||||||
f_perc(mfu_data, caches_size), f_bytes(mfu_data))
|
|
||||||
prt_i2('MFU evictable data size:',
|
|
||||||
f_perc(mfu_edata, caches_size), f_bytes(mfu_edata))
|
|
||||||
prt_i1('MFU ghost data size:', f_bytes(mfug_data))
|
|
||||||
v = (s-int(pm))*int(meta)/s
|
|
||||||
prt_i2('MFU metadata target:', f_perc(v, s),
|
|
||||||
f_bytes(v / 65536 * caches_size / 65536))
|
|
||||||
prt_i2('MFU metadata size:',
|
|
||||||
f_perc(mfu_metadata, caches_size), f_bytes(mfu_metadata))
|
|
||||||
prt_i2('MFU evictable metadata size:',
|
|
||||||
f_perc(mfu_emetadata, caches_size), f_bytes(mfu_emetadata))
|
|
||||||
prt_i1('MFU ghost metadata size:', f_bytes(mfug_metadata))
|
|
||||||
v = int(pd)*(s-int(meta))/s
|
|
||||||
prt_i2('MRU data target:', f_perc(v, s),
|
|
||||||
f_bytes(v / 65536 * caches_size / 65536))
|
|
||||||
prt_i2('MRU data size:',
|
|
||||||
f_perc(mru_data, caches_size), f_bytes(mru_data))
|
|
||||||
prt_i2('MRU evictable data size:',
|
|
||||||
f_perc(mru_edata, caches_size), f_bytes(mru_edata))
|
|
||||||
prt_i1('MRU ghost data size:', f_bytes(mrug_data))
|
|
||||||
v = int(pm)*int(meta)/s
|
|
||||||
prt_i2('MRU metadata target:', f_perc(v, s),
|
|
||||||
f_bytes(v / 65536 * caches_size / 65536))
|
|
||||||
prt_i2('MRU metadata size:',
|
|
||||||
f_perc(mru_metadata, caches_size), f_bytes(mru_metadata))
|
|
||||||
prt_i2('MRU evictable metadata size:',
|
|
||||||
f_perc(mru_emetadata, caches_size), f_bytes(mru_emetadata))
|
|
||||||
prt_i1('MRU ghost metadata size:', f_bytes(mrug_metadata))
|
|
||||||
prt_i2('Uncached data size:',
|
|
||||||
f_perc(unc_data, caches_size), f_bytes(unc_data))
|
|
||||||
prt_i2('Uncached metadata size:',
|
|
||||||
f_perc(unc_metadata, caches_size), f_bytes(unc_metadata))
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
print('ARC hash breakdown:')
|
print('ARC hash breakdown:')
|
||||||
prt_i1('Elements:', f_hits(arc_stats['hash_elements']))
|
prt_i1('Elements max:', f_hits(arc_stats['hash_elements_max']))
|
||||||
|
prt_i2('Elements current:',
|
||||||
|
f_perc(arc_stats['hash_elements'], arc_stats['hash_elements_max']),
|
||||||
|
f_hits(arc_stats['hash_elements']))
|
||||||
prt_i1('Collisions:', f_hits(arc_stats['hash_collisions']))
|
prt_i1('Collisions:', f_hits(arc_stats['hash_collisions']))
|
||||||
|
|
||||||
prt_i1('Chain max:', f_hits(arc_stats['hash_chain_max']))
|
prt_i1('Chain max:', f_hits(arc_stats['hash_chain_max']))
|
||||||
@@ -670,9 +609,6 @@ def section_arc(kstats_dict):
|
|||||||
print()
|
print()
|
||||||
|
|
||||||
print('ARC misc:')
|
print('ARC misc:')
|
||||||
prt_i1('Memory throttles:', arc_stats['memory_throttle_count'])
|
|
||||||
prt_i1('Memory direct reclaims:', arc_stats['memory_direct_count'])
|
|
||||||
prt_i1('Memory indirect reclaims:', arc_stats['memory_indirect_count'])
|
|
||||||
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']))
|
||||||
@@ -698,119 +634,78 @@ def section_archits(kstats_dict):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
arc_stats = isolate_section('arcstats', kstats_dict)
|
||||||
all_accesses = int(arc_stats['hits'])+int(arc_stats['iohits'])+\
|
all_accesses = int(arc_stats['hits'])+int(arc_stats['misses'])
|
||||||
int(arc_stats['misses'])
|
actual_hits = int(arc_stats['mfu_hits'])+int(arc_stats['mru_hits'])
|
||||||
|
|
||||||
|
prt_1('ARC total accesses (hits + misses):', f_hits(all_accesses))
|
||||||
|
ta_todo = (('Cache hit ratio:', arc_stats['hits']),
|
||||||
|
('Cache miss ratio:', arc_stats['misses']),
|
||||||
|
('Actual hit ratio (MFU + MRU hits):', actual_hits))
|
||||||
|
|
||||||
prt_1('ARC total accesses:', f_hits(all_accesses))
|
|
||||||
ta_todo = (('Total hits:', arc_stats['hits']),
|
|
||||||
('Total I/O hits:', arc_stats['iohits']),
|
|
||||||
('Total misses:', arc_stats['misses']))
|
|
||||||
for title, value in ta_todo:
|
for title, value in ta_todo:
|
||||||
prt_i2(title, f_perc(value, all_accesses), f_hits(value))
|
prt_i2(title, f_perc(value, all_accesses), f_hits(value))
|
||||||
print()
|
|
||||||
|
|
||||||
dd_total = int(arc_stats['demand_data_hits']) +\
|
dd_total = int(arc_stats['demand_data_hits']) +\
|
||||||
int(arc_stats['demand_data_iohits']) +\
|
|
||||||
int(arc_stats['demand_data_misses'])
|
int(arc_stats['demand_data_misses'])
|
||||||
prt_2('ARC demand data accesses:', f_perc(dd_total, all_accesses),
|
prt_i2('Data demand efficiency:',
|
||||||
f_hits(dd_total))
|
f_perc(arc_stats['demand_data_hits'], dd_total),
|
||||||
dd_todo = (('Demand data hits:', arc_stats['demand_data_hits']),
|
f_hits(dd_total))
|
||||||
('Demand data I/O hits:', arc_stats['demand_data_iohits']),
|
|
||||||
('Demand data misses:', arc_stats['demand_data_misses']))
|
|
||||||
for title, value in dd_todo:
|
|
||||||
prt_i2(title, f_perc(value, dd_total), f_hits(value))
|
|
||||||
print()
|
|
||||||
|
|
||||||
dm_total = int(arc_stats['demand_metadata_hits']) +\
|
dp_total = int(arc_stats['prefetch_data_hits']) +\
|
||||||
int(arc_stats['demand_metadata_iohits']) +\
|
|
||||||
int(arc_stats['demand_metadata_misses'])
|
|
||||||
prt_2('ARC demand metadata accesses:', f_perc(dm_total, all_accesses),
|
|
||||||
f_hits(dm_total))
|
|
||||||
dm_todo = (('Demand metadata hits:', arc_stats['demand_metadata_hits']),
|
|
||||||
('Demand metadata I/O hits:',
|
|
||||||
arc_stats['demand_metadata_iohits']),
|
|
||||||
('Demand metadata misses:', arc_stats['demand_metadata_misses']))
|
|
||||||
for title, value in dm_todo:
|
|
||||||
prt_i2(title, f_perc(value, dm_total), f_hits(value))
|
|
||||||
print()
|
|
||||||
|
|
||||||
pd_total = int(arc_stats['prefetch_data_hits']) +\
|
|
||||||
int(arc_stats['prefetch_data_iohits']) +\
|
|
||||||
int(arc_stats['prefetch_data_misses'])
|
int(arc_stats['prefetch_data_misses'])
|
||||||
prt_2('ARC prefetch data accesses:', f_perc(pd_total, all_accesses),
|
prt_i2('Data prefetch efficiency:',
|
||||||
f_hits(pd_total))
|
f_perc(arc_stats['prefetch_data_hits'], dp_total),
|
||||||
pd_todo = (('Prefetch data hits:', arc_stats['prefetch_data_hits']),
|
f_hits(dp_total))
|
||||||
('Prefetch data I/O hits:', arc_stats['prefetch_data_iohits']),
|
|
||||||
('Prefetch data misses:', arc_stats['prefetch_data_misses']))
|
|
||||||
for title, value in pd_todo:
|
|
||||||
prt_i2(title, f_perc(value, pd_total), f_hits(value))
|
|
||||||
print()
|
|
||||||
|
|
||||||
pm_total = int(arc_stats['prefetch_metadata_hits']) +\
|
known_hits = int(arc_stats['mfu_hits']) +\
|
||||||
int(arc_stats['prefetch_metadata_iohits']) +\
|
int(arc_stats['mru_hits']) +\
|
||||||
int(arc_stats['prefetch_metadata_misses'])
|
int(arc_stats['mfu_ghost_hits']) +\
|
||||||
prt_2('ARC prefetch metadata accesses:', f_perc(pm_total, all_accesses),
|
int(arc_stats['mru_ghost_hits'])
|
||||||
f_hits(pm_total))
|
|
||||||
pm_todo = (('Prefetch metadata hits:',
|
|
||||||
arc_stats['prefetch_metadata_hits']),
|
|
||||||
('Prefetch metadata I/O hits:',
|
|
||||||
arc_stats['prefetch_metadata_iohits']),
|
|
||||||
('Prefetch metadata misses:',
|
|
||||||
arc_stats['prefetch_metadata_misses']))
|
|
||||||
for title, value in pm_todo:
|
|
||||||
prt_i2(title, f_perc(value, pm_total), f_hits(value))
|
|
||||||
print()
|
|
||||||
|
|
||||||
all_prefetches = int(arc_stats['predictive_prefetch'])+\
|
anon_hits = int(arc_stats['hits'])-known_hits
|
||||||
int(arc_stats['prescient_prefetch'])
|
|
||||||
prt_2('ARC predictive prefetches:',
|
|
||||||
f_perc(arc_stats['predictive_prefetch'], all_prefetches),
|
|
||||||
f_hits(arc_stats['predictive_prefetch']))
|
|
||||||
prt_i2('Demand hits after predictive:',
|
|
||||||
f_perc(arc_stats['demand_hit_predictive_prefetch'],
|
|
||||||
arc_stats['predictive_prefetch']),
|
|
||||||
f_hits(arc_stats['demand_hit_predictive_prefetch']))
|
|
||||||
prt_i2('Demand I/O hits after predictive:',
|
|
||||||
f_perc(arc_stats['demand_iohit_predictive_prefetch'],
|
|
||||||
arc_stats['predictive_prefetch']),
|
|
||||||
f_hits(arc_stats['demand_iohit_predictive_prefetch']))
|
|
||||||
never = int(arc_stats['predictive_prefetch']) -\
|
|
||||||
int(arc_stats['demand_hit_predictive_prefetch']) -\
|
|
||||||
int(arc_stats['demand_iohit_predictive_prefetch'])
|
|
||||||
prt_i2('Never demanded after predictive:',
|
|
||||||
f_perc(never, arc_stats['predictive_prefetch']),
|
|
||||||
f_hits(never))
|
|
||||||
print()
|
|
||||||
|
|
||||||
prt_2('ARC prescient prefetches:',
|
|
||||||
f_perc(arc_stats['prescient_prefetch'], all_prefetches),
|
|
||||||
f_hits(arc_stats['prescient_prefetch']))
|
|
||||||
prt_i2('Demand hits after prescient:',
|
|
||||||
f_perc(arc_stats['demand_hit_prescient_prefetch'],
|
|
||||||
arc_stats['prescient_prefetch']),
|
|
||||||
f_hits(arc_stats['demand_hit_prescient_prefetch']))
|
|
||||||
prt_i2('Demand I/O hits after prescient:',
|
|
||||||
f_perc(arc_stats['demand_iohit_prescient_prefetch'],
|
|
||||||
arc_stats['prescient_prefetch']),
|
|
||||||
f_hits(arc_stats['demand_iohit_prescient_prefetch']))
|
|
||||||
never = int(arc_stats['prescient_prefetch'])-\
|
|
||||||
int(arc_stats['demand_hit_prescient_prefetch'])-\
|
|
||||||
int(arc_stats['demand_iohit_prescient_prefetch'])
|
|
||||||
prt_i2('Never demanded after prescient:',
|
|
||||||
f_perc(never, arc_stats['prescient_prefetch']),
|
|
||||||
f_hits(never))
|
|
||||||
print()
|
print()
|
||||||
|
print('Cache hits by cache type:')
|
||||||
print('ARC states hits of all accesses:')
|
|
||||||
cl_todo = (('Most frequently used (MFU):', arc_stats['mfu_hits']),
|
cl_todo = (('Most frequently used (MFU):', arc_stats['mfu_hits']),
|
||||||
('Most recently used (MRU):', arc_stats['mru_hits']),
|
('Most recently used (MRU):', arc_stats['mru_hits']),
|
||||||
('Most frequently used (MFU) ghost:',
|
('Most frequently used (MFU) ghost:',
|
||||||
arc_stats['mfu_ghost_hits']),
|
arc_stats['mfu_ghost_hits']),
|
||||||
('Most recently used (MRU) ghost:',
|
('Most recently used (MRU) ghost:',
|
||||||
arc_stats['mru_ghost_hits']),
|
arc_stats['mru_ghost_hits']))
|
||||||
('Uncached:', arc_stats['uncached_hits']))
|
|
||||||
for title, value in cl_todo:
|
for title, value in cl_todo:
|
||||||
prt_i2(title, f_perc(value, all_accesses), f_hits(value))
|
prt_i2(title, f_perc(value, arc_stats['hits']), f_hits(value))
|
||||||
|
|
||||||
|
# For some reason, anon_hits can turn negative, which is weird. Until we
|
||||||
|
# have figured out why this happens, we just hide the problem, following
|
||||||
|
# the behavior of the original arc_summary.
|
||||||
|
if anon_hits >= 0:
|
||||||
|
prt_i2('Anonymously used:',
|
||||||
|
f_perc(anon_hits, arc_stats['hits']), f_hits(anon_hits))
|
||||||
|
|
||||||
|
print()
|
||||||
|
print('Cache hits by data type:')
|
||||||
|
dt_todo = (('Demand data:', arc_stats['demand_data_hits']),
|
||||||
|
('Demand prefetch data:', arc_stats['prefetch_data_hits']),
|
||||||
|
('Demand metadata:', arc_stats['demand_metadata_hits']),
|
||||||
|
('Demand prefetch metadata:',
|
||||||
|
arc_stats['prefetch_metadata_hits']))
|
||||||
|
|
||||||
|
for title, value in dt_todo:
|
||||||
|
prt_i2(title, f_perc(value, arc_stats['hits']), f_hits(value))
|
||||||
|
|
||||||
|
print()
|
||||||
|
print('Cache misses by data type:')
|
||||||
|
dm_todo = (('Demand data:', arc_stats['demand_data_misses']),
|
||||||
|
('Demand prefetch data:',
|
||||||
|
arc_stats['prefetch_data_misses']),
|
||||||
|
('Demand metadata:', arc_stats['demand_metadata_misses']),
|
||||||
|
('Demand prefetch metadata:',
|
||||||
|
arc_stats['prefetch_metadata_misses']))
|
||||||
|
|
||||||
|
for title, value in dm_todo:
|
||||||
|
prt_i2(title, f_perc(value, arc_stats['misses']), f_hits(value))
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
@@ -819,28 +714,13 @@ def section_dmu(kstats_dict):
|
|||||||
|
|
||||||
zfetch_stats = isolate_section('zfetchstats', kstats_dict)
|
zfetch_stats = isolate_section('zfetchstats', kstats_dict)
|
||||||
|
|
||||||
zfetch_access_total = int(zfetch_stats['hits']) +\
|
zfetch_access_total = int(zfetch_stats['hits'])+int(zfetch_stats['misses'])
|
||||||
int(zfetch_stats['future']) + int(zfetch_stats['stride']) +\
|
|
||||||
int(zfetch_stats['past']) + int(zfetch_stats['misses'])
|
|
||||||
|
|
||||||
prt_1('DMU predictive prefetcher calls:', f_hits(zfetch_access_total))
|
prt_1('DMU prefetch efficiency:', f_hits(zfetch_access_total))
|
||||||
prt_i2('Stream hits:',
|
prt_i2('Hit ratio:', f_perc(zfetch_stats['hits'], zfetch_access_total),
|
||||||
f_perc(zfetch_stats['hits'], zfetch_access_total),
|
|
||||||
f_hits(zfetch_stats['hits']))
|
f_hits(zfetch_stats['hits']))
|
||||||
future = int(zfetch_stats['future']) + int(zfetch_stats['stride'])
|
prt_i2('Miss ratio:', f_perc(zfetch_stats['misses'], zfetch_access_total),
|
||||||
prt_i2('Hits ahead of stream:', f_perc(future, zfetch_access_total),
|
|
||||||
f_hits(future))
|
|
||||||
prt_i2('Hits behind stream:',
|
|
||||||
f_perc(zfetch_stats['past'], zfetch_access_total),
|
|
||||||
f_hits(zfetch_stats['past']))
|
|
||||||
prt_i2('Stream misses:',
|
|
||||||
f_perc(zfetch_stats['misses'], zfetch_access_total),
|
|
||||||
f_hits(zfetch_stats['misses']))
|
f_hits(zfetch_stats['misses']))
|
||||||
prt_i2('Streams limit reached:',
|
|
||||||
f_perc(zfetch_stats['max_streams'], zfetch_stats['misses']),
|
|
||||||
f_hits(zfetch_stats['max_streams']))
|
|
||||||
prt_i1('Stream strides:', f_hits(zfetch_stats['stride']))
|
|
||||||
prt_i1('Prefetches issued', f_hits(zfetch_stats['io_issued']))
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
@@ -872,8 +752,7 @@ def section_l2arc(kstats_dict):
|
|||||||
('Free on write:', 'l2_free_on_write'),
|
('Free on write:', 'l2_free_on_write'),
|
||||||
('R/W clashes:', 'l2_rw_clash'),
|
('R/W clashes:', 'l2_rw_clash'),
|
||||||
('Bad checksums:', 'l2_cksum_bad'),
|
('Bad checksums:', 'l2_cksum_bad'),
|
||||||
('Read errors:', 'l2_io_error'),
|
('I/O errors:', 'l2_io_error'))
|
||||||
('Write errors:', 'l2_writes_error'))
|
|
||||||
|
|
||||||
for title, value in l2_todo:
|
for title, value in l2_todo:
|
||||||
prt_i1(title, f_hits(arc_stats[value]))
|
prt_i1(title, f_hits(arc_stats[value]))
|
||||||
@@ -909,20 +788,28 @@ def section_l2arc(kstats_dict):
|
|||||||
prt_i2('Miss ratio:',
|
prt_i2('Miss ratio:',
|
||||||
f_perc(arc_stats['l2_misses'], l2_access_total),
|
f_perc(arc_stats['l2_misses'], l2_access_total),
|
||||||
f_hits(arc_stats['l2_misses']))
|
f_hits(arc_stats['l2_misses']))
|
||||||
|
prt_i1('Feeds:', f_hits(arc_stats['l2_feeds']))
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print('L2ARC I/O:')
|
print('L2ARC writes:')
|
||||||
prt_i2('Reads:',
|
|
||||||
f_bytes(arc_stats['l2_read_bytes']),
|
if arc_stats['l2_writes_done'] != arc_stats['l2_writes_sent']:
|
||||||
f_hits(arc_stats['l2_hits']))
|
prt_i2('Writes sent:', 'FAULTED', f_hits(arc_stats['l2_writes_sent']))
|
||||||
prt_i2('Writes:',
|
prt_i2('Done ratio:',
|
||||||
f_bytes(arc_stats['l2_write_bytes']),
|
f_perc(arc_stats['l2_writes_done'],
|
||||||
f_hits(arc_stats['l2_writes_sent']))
|
arc_stats['l2_writes_sent']),
|
||||||
|
f_hits(arc_stats['l2_writes_done']))
|
||||||
|
prt_i2('Error ratio:',
|
||||||
|
f_perc(arc_stats['l2_writes_error'],
|
||||||
|
arc_stats['l2_writes_sent']),
|
||||||
|
f_hits(arc_stats['l2_writes_error']))
|
||||||
|
else:
|
||||||
|
prt_i2('Writes sent:', '100 %', f_hits(arc_stats['l2_writes_sent']))
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print('L2ARC evicts:')
|
print('L2ARC evicts:')
|
||||||
prt_i1('L1 cached:', f_hits(arc_stats['l2_evict_l1cached']))
|
prt_i1('Lock retries:', f_hits(arc_stats['l2_evict_lock_retry']))
|
||||||
prt_i1('While reading:', f_hits(arc_stats['l2_evict_reading']))
|
prt_i1('Upon reading:', f_hits(arc_stats['l2_evict_reading']))
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
@@ -982,6 +869,35 @@ def section_tunables(*_):
|
|||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def section_vdev(kstats_dict):
|
||||||
|
"""Collect information on VDEV caches"""
|
||||||
|
|
||||||
|
# Currently [Nov 2017] the VDEV cache is disabled, because it is actually
|
||||||
|
# harmful. When this is the case, we just skip the whole entry. See
|
||||||
|
# https://github.com/openzfs/zfs/blob/master/module/zfs/vdev_cache.c
|
||||||
|
# for details
|
||||||
|
tunables = get_vdev_params()
|
||||||
|
|
||||||
|
if tunables[VDEV_CACHE_SIZE] == '0':
|
||||||
|
print('VDEV cache disabled, skipping section\n')
|
||||||
|
return
|
||||||
|
|
||||||
|
vdev_stats = isolate_section('vdev_cache_stats', kstats_dict)
|
||||||
|
|
||||||
|
vdev_cache_total = int(vdev_stats['hits']) +\
|
||||||
|
int(vdev_stats['misses']) +\
|
||||||
|
int(vdev_stats['delegations'])
|
||||||
|
|
||||||
|
prt_1('VDEV cache summary:', f_hits(vdev_cache_total))
|
||||||
|
prt_i2('Hit ratio:', f_perc(vdev_stats['hits'], vdev_cache_total),
|
||||||
|
f_hits(vdev_stats['hits']))
|
||||||
|
prt_i2('Miss ratio:', f_perc(vdev_stats['misses'], vdev_cache_total),
|
||||||
|
f_hits(vdev_stats['misses']))
|
||||||
|
prt_i2('Delegations:', f_perc(vdev_stats['delegations'], vdev_cache_total),
|
||||||
|
f_hits(vdev_stats['delegations']))
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
def section_zil(kstats_dict):
|
def section_zil(kstats_dict):
|
||||||
"""Collect information on the ZFS Intent Log. Some of the information
|
"""Collect information on the ZFS Intent Log. Some of the information
|
||||||
taken from https://github.com/openzfs/zfs/blob/master/include/sys/zil.h
|
taken from https://github.com/openzfs/zfs/blob/master/include/sys/zil.h
|
||||||
@@ -1009,6 +925,7 @@ section_calls = {'arc': section_arc,
|
|||||||
'l2arc': section_l2arc,
|
'l2arc': section_l2arc,
|
||||||
'spl': section_spl,
|
'spl': section_spl,
|
||||||
'tunables': section_tunables,
|
'tunables': section_tunables,
|
||||||
|
'vdev': section_vdev,
|
||||||
'zil': section_zil}
|
'zil': section_zil}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
arcstat
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
include $(top_srcdir)/config/Substfiles.am
|
||||||
|
|
||||||
|
bin_SCRIPTS = arcstat
|
||||||
|
|
||||||
|
SUBSTFILES += $(bin_SCRIPTS)
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
# with the License.
|
# with the License.
|
||||||
#
|
#
|
||||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
# or https://opensource.org/licenses/CDDL-1.0.
|
# or http://www.opensolaris.org/os/licensing.
|
||||||
# See the License for the specific language governing permissions
|
# See the License for the specific language governing permissions
|
||||||
# and limitations under the License.
|
# and limitations under the License.
|
||||||
#
|
#
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
# @hdr is the array of fields that needs to be printed, so we
|
# @hdr is the array of fields that needs to be printed, so we
|
||||||
# just iterate over this array and print the values using our pretty printer.
|
# just iterate over this array and print the values using our pretty printer.
|
||||||
#
|
#
|
||||||
# This script must remain compatible with Python 3.6+.
|
# This script must remain compatible with Python 2.6+ and Python 3.4+.
|
||||||
#
|
#
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -62,64 +62,31 @@ from signal import signal, SIGINT, SIGWINCH, SIG_DFL
|
|||||||
cols = {
|
cols = {
|
||||||
# HDR: [Size, Scale, Description]
|
# HDR: [Size, Scale, Description]
|
||||||
"time": [8, -1, "Time"],
|
"time": [8, -1, "Time"],
|
||||||
"hits": [4, 1000, "ARC hits per second"],
|
"hits": [4, 1000, "ARC reads per second"],
|
||||||
"iohs": [4, 1000, "ARC I/O hits per second"],
|
|
||||||
"miss": [4, 1000, "ARC misses per second"],
|
"miss": [4, 1000, "ARC misses per second"],
|
||||||
"read": [4, 1000, "Total ARC accesses per second"],
|
"read": [4, 1000, "Total ARC accesses per second"],
|
||||||
"hit%": [4, 100, "ARC hit percentage"],
|
"hit%": [4, 100, "ARC hit percentage"],
|
||||||
"ioh%": [4, 100, "ARC I/O hit percentage"],
|
|
||||||
"miss%": [5, 100, "ARC miss percentage"],
|
"miss%": [5, 100, "ARC miss percentage"],
|
||||||
"dhit": [4, 1000, "Demand hits per second"],
|
"dhit": [4, 1000, "Demand hits per second"],
|
||||||
"dioh": [4, 1000, "Demand I/O hits per second"],
|
|
||||||
"dmis": [4, 1000, "Demand misses per second"],
|
"dmis": [4, 1000, "Demand misses per second"],
|
||||||
"dh%": [3, 100, "Demand hit percentage"],
|
"dh%": [3, 100, "Demand hit percentage"],
|
||||||
"di%": [3, 100, "Demand I/O hit percentage"],
|
|
||||||
"dm%": [3, 100, "Demand miss percentage"],
|
"dm%": [3, 100, "Demand miss percentage"],
|
||||||
"ddhit": [5, 1000, "Demand data hits per second"],
|
|
||||||
"ddioh": [5, 1000, "Demand data I/O hits per second"],
|
|
||||||
"ddmis": [5, 1000, "Demand data misses per second"],
|
|
||||||
"ddh%": [4, 100, "Demand data hit percentage"],
|
|
||||||
"ddi%": [4, 100, "Demand data I/O hit percentage"],
|
|
||||||
"ddm%": [4, 100, "Demand data miss percentage"],
|
|
||||||
"dmhit": [5, 1000, "Demand metadata hits per second"],
|
|
||||||
"dmioh": [5, 1000, "Demand metadata I/O hits per second"],
|
|
||||||
"dmmis": [5, 1000, "Demand metadata misses per second"],
|
|
||||||
"dmh%": [4, 100, "Demand metadata hit percentage"],
|
|
||||||
"dmi%": [4, 100, "Demand metadata I/O hit percentage"],
|
|
||||||
"dmm%": [4, 100, "Demand metadata miss percentage"],
|
|
||||||
"phit": [4, 1000, "Prefetch hits per second"],
|
"phit": [4, 1000, "Prefetch hits per second"],
|
||||||
"pioh": [4, 1000, "Prefetch I/O hits per second"],
|
|
||||||
"pmis": [4, 1000, "Prefetch misses per second"],
|
"pmis": [4, 1000, "Prefetch misses per second"],
|
||||||
"ph%": [3, 100, "Prefetch hits percentage"],
|
"ph%": [3, 100, "Prefetch hits percentage"],
|
||||||
"pi%": [3, 100, "Prefetch I/O hits percentage"],
|
|
||||||
"pm%": [3, 100, "Prefetch miss percentage"],
|
"pm%": [3, 100, "Prefetch miss percentage"],
|
||||||
"pdhit": [5, 1000, "Prefetch data hits per second"],
|
|
||||||
"pdioh": [5, 1000, "Prefetch data I/O hits per second"],
|
|
||||||
"pdmis": [5, 1000, "Prefetch data misses per second"],
|
|
||||||
"pdh%": [4, 100, "Prefetch data hits percentage"],
|
|
||||||
"pdi%": [4, 100, "Prefetch data I/O hits percentage"],
|
|
||||||
"pdm%": [4, 100, "Prefetch data miss percentage"],
|
|
||||||
"pmhit": [5, 1000, "Prefetch metadata hits per second"],
|
|
||||||
"pmioh": [5, 1000, "Prefetch metadata I/O hits per second"],
|
|
||||||
"pmmis": [5, 1000, "Prefetch metadata misses per second"],
|
|
||||||
"pmh%": [4, 100, "Prefetch metadata hits percentage"],
|
|
||||||
"pmi%": [4, 100, "Prefetch metadata I/O hits percentage"],
|
|
||||||
"pmm%": [4, 100, "Prefetch metadata miss percentage"],
|
|
||||||
"mhit": [4, 1000, "Metadata hits per second"],
|
"mhit": [4, 1000, "Metadata hits per second"],
|
||||||
"mioh": [4, 1000, "Metadata I/O hits per second"],
|
|
||||||
"mmis": [4, 1000, "Metadata misses per second"],
|
"mmis": [4, 1000, "Metadata misses per second"],
|
||||||
"mread": [5, 1000, "Metadata accesses per second"],
|
"mread": [5, 1000, "Metadata accesses per second"],
|
||||||
"mh%": [3, 100, "Metadata hit percentage"],
|
"mh%": [3, 100, "Metadata hit percentage"],
|
||||||
"mi%": [3, 100, "Metadata I/O hit percentage"],
|
|
||||||
"mm%": [3, 100, "Metadata miss percentage"],
|
"mm%": [3, 100, "Metadata miss percentage"],
|
||||||
"arcsz": [5, 1024, "ARC size"],
|
"arcsz": [5, 1024, "ARC size"],
|
||||||
"size": [5, 1024, "ARC size"],
|
"size": [4, 1024, "ARC size"],
|
||||||
"c": [5, 1024, "ARC target size"],
|
"c": [4, 1024, "ARC target size"],
|
||||||
"mfu": [4, 1000, "MFU list hits per second"],
|
"mfu": [4, 1000, "MFU list hits per second"],
|
||||||
"mru": [4, 1000, "MRU list hits per second"],
|
"mru": [4, 1000, "MRU list hits per second"],
|
||||||
"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"],
|
||||||
"unc": [4, 1000, "Uncached 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"],
|
"el2skip": [7, 1000, "evict skip, due to l2 writes, per second"],
|
||||||
"el2cach": [7, 1024, "Size of L2 cached evictions per second"],
|
"el2cach": [7, 1024, "Size of L2 cached evictions per second"],
|
||||||
@@ -129,11 +96,7 @@ cols = {
|
|||||||
"el2inel": [7, 1024, "Size of L2 ineligible 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"],
|
||||||
"ddread": [6, 1000, "Demand data accesses per second"],
|
|
||||||
"dmread": [6, 1000, "Demand metadata accesses per second"],
|
|
||||||
"pread": [5, 1000, "Prefetch accesses per second"],
|
"pread": [5, 1000, "Prefetch accesses per second"],
|
||||||
"pdread": [6, 1000, "Prefetch data accesses per second"],
|
|
||||||
"pmread": [6, 1000, "Prefetch metadata accesses per second"],
|
|
||||||
"l2hits": [6, 1000, "L2ARC hits per second"],
|
"l2hits": [6, 1000, "L2ARC hits per second"],
|
||||||
"l2miss": [6, 1000, "L2ARC misses per second"],
|
"l2miss": [6, 1000, "L2ARC misses per second"],
|
||||||
"l2read": [6, 1000, "Total L2ARC accesses per second"],
|
"l2read": [6, 1000, "Total L2ARC accesses per second"],
|
||||||
@@ -152,113 +115,24 @@ cols = {
|
|||||||
"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"],
|
||||||
"l2wbytes": [8, 1024, "Bytes written per second to the L2ARC"],
|
|
||||||
"grow": [4, 1000, "ARC grow disabled"],
|
"grow": [4, 1000, "ARC grow disabled"],
|
||||||
"need": [5, 1024, "ARC reclaim need"],
|
"need": [4, 1024, "ARC reclaim need"],
|
||||||
"free": [5, 1024, "ARC free memory"],
|
"free": [4, 1024, "ARC free memory"],
|
||||||
"avail": [5, 1024, "ARC available memory"],
|
"avail": [5, 1024, "ARC available memory"],
|
||||||
"waste": [5, 1024, "Wasted memory due to round up to pagesize"],
|
"waste": [5, 1024, "Wasted memory due to round up to pagesize"],
|
||||||
"ztotal": [6, 1000, "zfetch total prefetcher calls per second"],
|
|
||||||
"zhits": [5, 1000, "zfetch stream hits per second"],
|
|
||||||
"zahead": [6, 1000, "zfetch hits ahead of streams per second"],
|
|
||||||
"zpast": [5, 1000, "zfetch hits behind streams per second"],
|
|
||||||
"zmisses": [7, 1000, "zfetch stream misses per second"],
|
|
||||||
"zmax": [4, 1000, "zfetch limit reached per second"],
|
|
||||||
"zfuture": [7, 1000, "zfetch stream future per second"],
|
|
||||||
"zstride": [7, 1000, "zfetch stream strides per second"],
|
|
||||||
"zissued": [7, 1000, "zfetch prefetches issued per second"],
|
|
||||||
"zactive": [7, 1000, "zfetch prefetches active per second"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ARC structural breakdown from arc_summary
|
|
||||||
structfields = {
|
|
||||||
"cmp": ["compressed", "Compressed"],
|
|
||||||
"ovh": ["overhead", "Overhead"],
|
|
||||||
"bon": ["bonus", "Bonus"],
|
|
||||||
"dno": ["dnode", "Dnode"],
|
|
||||||
"dbu": ["dbuf", "Dbuf"],
|
|
||||||
"hdr": ["hdr", "Header"],
|
|
||||||
"l2h": ["l2_hdr", "L2 header"],
|
|
||||||
"abd": ["abd_chunk_waste", "ABD chunk waste"],
|
|
||||||
}
|
|
||||||
structstats = { # size stats
|
|
||||||
"percent": "size", # percentage of this value
|
|
||||||
"sz": ["_size", "size"],
|
|
||||||
}
|
|
||||||
|
|
||||||
# ARC types breakdown from arc_summary
|
|
||||||
typefields = {
|
|
||||||
"data": ["data", "ARC data"],
|
|
||||||
"meta": ["metadata", "ARC metadata"],
|
|
||||||
}
|
|
||||||
typestats = { # size stats
|
|
||||||
"percent": "cachessz", # percentage of this value
|
|
||||||
"tg": ["_target", "target"],
|
|
||||||
"sz": ["_size", "size"],
|
|
||||||
}
|
|
||||||
|
|
||||||
# ARC states breakdown from arc_summary
|
|
||||||
statefields = {
|
|
||||||
"ano": ["anon", "Anonymous"],
|
|
||||||
"mfu": ["mfu", "MFU"],
|
|
||||||
"mru": ["mru", "MRU"],
|
|
||||||
"unc": ["uncached", "Uncached"],
|
|
||||||
}
|
|
||||||
targetstats = {
|
|
||||||
"percent": "cachessz", # percentage of this value
|
|
||||||
"fields": ["mfu", "mru"], # only applicable to these fields
|
|
||||||
"tg": ["_target", "target"],
|
|
||||||
"dt": ["_data_target", "data target"],
|
|
||||||
"mt": ["_metadata_target", "metadata target"],
|
|
||||||
}
|
|
||||||
statestats = { # size stats
|
|
||||||
"percent": "cachessz", # percentage of this value
|
|
||||||
"sz": ["_size", "size"],
|
|
||||||
"da": ["_data", "data size"],
|
|
||||||
"me": ["_metadata", "metadata size"],
|
|
||||||
"ed": ["_evictable_data", "evictable data size"],
|
|
||||||
"em": ["_evictable_metadata", "evictable metadata size"],
|
|
||||||
}
|
|
||||||
ghoststats = {
|
|
||||||
"fields": ["mfu", "mru"], # only applicable to these fields
|
|
||||||
"gsz": ["_ghost_size", "ghost size"],
|
|
||||||
"gd": ["_ghost_data", "ghost data size"],
|
|
||||||
"gm": ["_ghost_metadata", "ghost metadata size"],
|
|
||||||
}
|
|
||||||
|
|
||||||
# fields and stats
|
|
||||||
fieldstats = [
|
|
||||||
[structfields, structstats],
|
|
||||||
[typefields, typestats],
|
|
||||||
[statefields, targetstats, statestats, ghoststats],
|
|
||||||
]
|
|
||||||
for fs in fieldstats:
|
|
||||||
fields, stats = fs[0], fs[1:]
|
|
||||||
for field, fieldval in fields.items():
|
|
||||||
for group in stats:
|
|
||||||
for stat, statval in group.items():
|
|
||||||
if stat in ["fields", "percent"] or \
|
|
||||||
("fields" in group and field not in group["fields"]):
|
|
||||||
continue
|
|
||||||
colname = field + stat
|
|
||||||
coldesc = fieldval[1] + " " + statval[1]
|
|
||||||
cols[colname] = [len(colname), 1024, coldesc]
|
|
||||||
if "percent" in group:
|
|
||||||
cols[colname + "%"] = [len(colname) + 1, 100, \
|
|
||||||
coldesc + " percentage"]
|
|
||||||
|
|
||||||
v = {}
|
v = {}
|
||||||
hdr = ["time", "read", "ddread", "ddh%", "dmread", "dmh%", "pread", "ph%",
|
hdr = ["time", "read", "miss", "miss%", "dmis", "dm%", "pmis", "pm%", "mmis",
|
||||||
"size", "c", "avail"]
|
"mm%", "size", "c", "avail"]
|
||||||
xhdr = ["time", "mfu", "mru", "mfug", "mrug", "unc", "eskip", "mtxmis",
|
xhdr = ["time", "mfu", "mru", "mfug", "mrug", "eskip", "mtxmis", "dread",
|
||||||
"dread", "pread", "read"]
|
"pread", "read"]
|
||||||
zhdr = ["time", "ztotal", "zhits", "zahead", "zpast", "zmisses", "zmax",
|
|
||||||
"zfuture", "zstride", "zissued", "zactive"]
|
|
||||||
sint = 1 # Default interval is 1 second
|
sint = 1 # Default interval is 1 second
|
||||||
count = 1 # Default count is 1
|
count = 1 # Default count is 1
|
||||||
hdr_intr = 20 # Print header every 20 lines of output
|
hdr_intr = 20 # Print header every 20 lines of output
|
||||||
opfile = None
|
opfile = None
|
||||||
sep = " " # Default separator is 2 spaces
|
sep = " " # Default separator is 2 spaces
|
||||||
|
version = "0.4"
|
||||||
l2exist = False
|
l2exist = False
|
||||||
cmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval "
|
cmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval "
|
||||||
"[count]]\n")
|
"[count]]\n")
|
||||||
@@ -278,8 +152,6 @@ if sys.platform.startswith('freebsd'):
|
|||||||
|
|
||||||
k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats')
|
k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats')
|
||||||
if ctl.type != sysctl.CTLTYPE_NODE]
|
if ctl.type != sysctl.CTLTYPE_NODE]
|
||||||
k += [ctl for ctl in sysctl.filter('kstat.zfs.misc.zfetchstats')
|
|
||||||
if ctl.type != sysctl.CTLTYPE_NODE]
|
|
||||||
|
|
||||||
if not k:
|
if not k:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -291,28 +163,19 @@ if sys.platform.startswith('freebsd'):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
name, value = s.name, s.value
|
name, value = s.name, s.value
|
||||||
|
# Trims 'kstat.zfs.misc.arcstats' from the name
|
||||||
if "arcstats" in name:
|
kstat[name[24:]] = int(value)
|
||||||
# Trims 'kstat.zfs.misc.arcstats' from the name
|
|
||||||
kstat[name[24:]] = int(value)
|
|
||||||
else:
|
|
||||||
kstat["zfetch_" + name[27:]] = int(value)
|
|
||||||
|
|
||||||
elif sys.platform.startswith('linux'):
|
elif sys.platform.startswith('linux'):
|
||||||
def kstat_update():
|
def kstat_update():
|
||||||
global kstat
|
global kstat
|
||||||
|
|
||||||
k1 = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
|
k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
|
||||||
|
|
||||||
k2 = ["zfetch_" + line.strip() for line in
|
if not k:
|
||||||
open('/proc/spl/kstat/zfs/zfetchstats')]
|
|
||||||
|
|
||||||
if k1 is None or k2 is None:
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
del k1[0:2]
|
del k[0:2]
|
||||||
del k2[0:2]
|
|
||||||
k = k1 + k2
|
|
||||||
kstat = {}
|
kstat = {}
|
||||||
|
|
||||||
for s in k:
|
for s in k:
|
||||||
@@ -340,7 +203,6 @@ def usage():
|
|||||||
sys.stderr.write("\t -v : List all possible field headers and definitions"
|
sys.stderr.write("\t -v : List all possible field headers and definitions"
|
||||||
"\n")
|
"\n")
|
||||||
sys.stderr.write("\t -x : Print extended stats\n")
|
sys.stderr.write("\t -x : Print extended stats\n")
|
||||||
sys.stderr.write("\t -z : Print zfetch stats\n")
|
|
||||||
sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n")
|
sys.stderr.write("\t -f : Specify specific fields to print (see -v)\n")
|
||||||
sys.stderr.write("\t -o : Redirect output to the specified file\n")
|
sys.stderr.write("\t -o : Redirect output to the specified file\n")
|
||||||
sys.stderr.write("\t -s : Override default field separator with custom "
|
sys.stderr.write("\t -s : Override default field separator with custom "
|
||||||
@@ -364,29 +226,6 @@ def snap_stats():
|
|||||||
kstat_update()
|
kstat_update()
|
||||||
|
|
||||||
cur = kstat
|
cur = kstat
|
||||||
|
|
||||||
# fill in additional values from arc_summary
|
|
||||||
cur["caches_size"] = caches_size = cur["anon_data"]+cur["anon_metadata"]+\
|
|
||||||
cur["mfu_data"]+cur["mfu_metadata"]+cur["mru_data"]+cur["mru_metadata"]+\
|
|
||||||
cur["uncached_data"]+cur["uncached_metadata"]
|
|
||||||
s = 4294967296
|
|
||||||
pd = cur["pd"]
|
|
||||||
pm = cur["pm"]
|
|
||||||
meta = cur["meta"]
|
|
||||||
v = (s-int(pd))*(s-int(meta))/s
|
|
||||||
cur["mfu_data_target"] = v / 65536 * caches_size / 65536
|
|
||||||
v = (s-int(pm))*int(meta)/s
|
|
||||||
cur["mfu_metadata_target"] = v / 65536 * caches_size / 65536
|
|
||||||
v = int(pd)*(s-int(meta))/s
|
|
||||||
cur["mru_data_target"] = v / 65536 * caches_size / 65536
|
|
||||||
v = int(pm)*int(meta)/s
|
|
||||||
cur["mru_metadata_target"] = v / 65536 * caches_size / 65536
|
|
||||||
|
|
||||||
cur["data_target"] = cur["mfu_data_target"] + cur["mru_data_target"]
|
|
||||||
cur["metadata_target"] = cur["mfu_metadata_target"] + cur["mru_metadata_target"]
|
|
||||||
cur["mfu_target"] = cur["mfu_data_target"] + cur["mfu_metadata_target"]
|
|
||||||
cur["mru_target"] = cur["mru_data_target"] + cur["mru_metadata_target"]
|
|
||||||
|
|
||||||
for key in cur:
|
for key in cur:
|
||||||
if re.match(key, "class"):
|
if re.match(key, "class"):
|
||||||
continue
|
continue
|
||||||
@@ -396,34 +235,31 @@ def snap_stats():
|
|||||||
d[key] = cur[key]
|
d[key] = cur[key]
|
||||||
|
|
||||||
|
|
||||||
def isint(num):
|
|
||||||
if isinstance(num, float):
|
|
||||||
return num.is_integer()
|
|
||||||
if isinstance(num, int):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def prettynum(sz, scale, num=0):
|
def prettynum(sz, scale, num=0):
|
||||||
suffix = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']
|
suffix = [' ', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']
|
||||||
index = 0
|
index = 0
|
||||||
|
save = 0
|
||||||
|
|
||||||
# Special case for date field
|
# Special case for date field
|
||||||
if scale == -1:
|
if scale == -1:
|
||||||
return "%s" % num
|
return "%s" % num
|
||||||
|
|
||||||
if scale != 100:
|
# Rounding error, return 0
|
||||||
while abs(num) > scale and index < 5:
|
elif 0 < num < 1:
|
||||||
num = num / scale
|
num = 0
|
||||||
index += 1
|
|
||||||
|
|
||||||
width = sz - (0 if index == 0 else 1)
|
while abs(num) > scale and index < 5:
|
||||||
intlen = len("%.0f" % num) # %.0f rounds to nearest int
|
save = num
|
||||||
if sint == 1 and isint(num) or width < intlen + 2:
|
num = num / scale
|
||||||
decimal = 0
|
index += 1
|
||||||
|
|
||||||
|
if index == 0:
|
||||||
|
return "%*d" % (sz, num)
|
||||||
|
|
||||||
|
if abs(save / scale) < 10:
|
||||||
|
return "%*.1f%s" % (sz - 1, num, suffix[index])
|
||||||
else:
|
else:
|
||||||
decimal = 1
|
return "%*d%s" % (sz - 1, num, suffix[index])
|
||||||
return "%*.*f%s" % (width, decimal, num, suffix[index])
|
|
||||||
|
|
||||||
|
|
||||||
def print_values():
|
def print_values():
|
||||||
@@ -435,7 +271,7 @@ def print_values():
|
|||||||
if pretty_print:
|
if pretty_print:
|
||||||
fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col])
|
fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col])
|
||||||
else:
|
else:
|
||||||
fmt = lambda col: str(v[col])
|
fmt = lambda col: v[col]
|
||||||
|
|
||||||
sys.stdout.write(sep.join(fmt(col) for col in hdr))
|
sys.stdout.write(sep.join(fmt(col) for col in hdr))
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
@@ -485,7 +321,6 @@ def init():
|
|||||||
global count
|
global count
|
||||||
global hdr
|
global hdr
|
||||||
global xhdr
|
global xhdr
|
||||||
global zhdr
|
|
||||||
global opfile
|
global opfile
|
||||||
global sep
|
global sep
|
||||||
global out
|
global out
|
||||||
@@ -497,17 +332,15 @@ def init():
|
|||||||
xflag = False
|
xflag = False
|
||||||
hflag = False
|
hflag = False
|
||||||
vflag = False
|
vflag = False
|
||||||
zflag = False
|
|
||||||
i = 1
|
i = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(
|
opts, args = getopt.getopt(
|
||||||
sys.argv[1:],
|
sys.argv[1:],
|
||||||
"axzo:hvs:f:p",
|
"axo:hvs:f:p",
|
||||||
[
|
[
|
||||||
"all",
|
"all",
|
||||||
"extended",
|
"extended",
|
||||||
"zfetch",
|
|
||||||
"outfile",
|
"outfile",
|
||||||
"help",
|
"help",
|
||||||
"verbose",
|
"verbose",
|
||||||
@@ -541,15 +374,13 @@ def init():
|
|||||||
i += 1
|
i += 1
|
||||||
if opt in ('-p', '--parsable'):
|
if opt in ('-p', '--parsable'):
|
||||||
pretty_print = False
|
pretty_print = False
|
||||||
if opt in ('-z', '--zfetch'):
|
|
||||||
zflag = True
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
argv = sys.argv[i:]
|
argv = sys.argv[i:]
|
||||||
sint = int(argv[0]) if argv else sint
|
sint = int(argv[0]) if argv else sint
|
||||||
count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1)
|
count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1)
|
||||||
|
|
||||||
if hflag or (xflag and zflag) or ((zflag or xflag) and desired_cols):
|
if hflag or (xflag and desired_cols):
|
||||||
usage()
|
usage()
|
||||||
|
|
||||||
if vflag:
|
if vflag:
|
||||||
@@ -558,9 +389,6 @@ def init():
|
|||||||
if xflag:
|
if xflag:
|
||||||
hdr = xhdr
|
hdr = xhdr
|
||||||
|
|
||||||
if zflag:
|
|
||||||
hdr = zhdr
|
|
||||||
|
|
||||||
update_hdr_intr()
|
update_hdr_intr()
|
||||||
|
|
||||||
# check if L2ARC exists
|
# check if L2ARC exists
|
||||||
@@ -614,80 +442,34 @@ def calculate():
|
|||||||
v = dict()
|
v = dict()
|
||||||
v["time"] = time.strftime("%H:%M:%S", time.localtime())
|
v["time"] = time.strftime("%H:%M:%S", time.localtime())
|
||||||
v["hits"] = d["hits"] / sint
|
v["hits"] = d["hits"] / sint
|
||||||
v["iohs"] = d["iohits"] / sint
|
|
||||||
v["miss"] = d["misses"] / sint
|
v["miss"] = d["misses"] / sint
|
||||||
v["read"] = v["hits"] + v["iohs"] + v["miss"]
|
v["read"] = v["hits"] + v["miss"]
|
||||||
v["hit%"] = 100 * v["hits"] / v["read"] if v["read"] > 0 else 0
|
v["hit%"] = 100 * v["hits"] / v["read"] if v["read"] > 0 else 0
|
||||||
v["ioh%"] = 100 * v["iohs"] / v["read"] if v["read"] > 0 else 0
|
v["miss%"] = 100 - v["hit%"] if v["read"] > 0 else 0
|
||||||
v["miss%"] = 100 - v["hit%"] - v["ioh%"] if v["read"] > 0 else 0
|
|
||||||
|
|
||||||
v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) / sint
|
v["dhit"] = (d["demand_data_hits"] + d["demand_metadata_hits"]) / sint
|
||||||
v["dioh"] = (d["demand_data_iohits"] + d["demand_metadata_iohits"]) / sint
|
|
||||||
v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) / sint
|
v["dmis"] = (d["demand_data_misses"] + d["demand_metadata_misses"]) / sint
|
||||||
|
|
||||||
v["dread"] = v["dhit"] + v["dioh"] + v["dmis"]
|
v["dread"] = v["dhit"] + v["dmis"]
|
||||||
v["dh%"] = 100 * v["dhit"] / v["dread"] if v["dread"] > 0 else 0
|
v["dh%"] = 100 * v["dhit"] / v["dread"] if v["dread"] > 0 else 0
|
||||||
v["di%"] = 100 * v["dioh"] / v["dread"] if v["dread"] > 0 else 0
|
v["dm%"] = 100 - v["dh%"] if v["dread"] > 0 else 0
|
||||||
v["dm%"] = 100 - v["dh%"] - v["di%"] if v["dread"] > 0 else 0
|
|
||||||
|
|
||||||
v["ddhit"] = d["demand_data_hits"] / sint
|
|
||||||
v["ddioh"] = d["demand_data_iohits"] / sint
|
|
||||||
v["ddmis"] = d["demand_data_misses"] / sint
|
|
||||||
|
|
||||||
v["ddread"] = v["ddhit"] + v["ddioh"] + v["ddmis"]
|
|
||||||
v["ddh%"] = 100 * v["ddhit"] / v["ddread"] if v["ddread"] > 0 else 0
|
|
||||||
v["ddi%"] = 100 * v["ddioh"] / v["ddread"] if v["ddread"] > 0 else 0
|
|
||||||
v["ddm%"] = 100 - v["ddh%"] - v["ddi%"] if v["ddread"] > 0 else 0
|
|
||||||
|
|
||||||
v["dmhit"] = d["demand_metadata_hits"] / sint
|
|
||||||
v["dmioh"] = d["demand_metadata_iohits"] / sint
|
|
||||||
v["dmmis"] = d["demand_metadata_misses"] / sint
|
|
||||||
|
|
||||||
v["dmread"] = v["dmhit"] + v["dmioh"] + v["dmmis"]
|
|
||||||
v["dmh%"] = 100 * v["dmhit"] / v["dmread"] if v["dmread"] > 0 else 0
|
|
||||||
v["dmi%"] = 100 * v["dmioh"] / v["dmread"] if v["dmread"] > 0 else 0
|
|
||||||
v["dmm%"] = 100 - v["dmh%"] - v["dmi%"] if v["dmread"] > 0 else 0
|
|
||||||
|
|
||||||
v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) / sint
|
v["phit"] = (d["prefetch_data_hits"] + d["prefetch_metadata_hits"]) / sint
|
||||||
v["pioh"] = (d["prefetch_data_iohits"] +
|
|
||||||
d["prefetch_metadata_iohits"]) / sint
|
|
||||||
v["pmis"] = (d["prefetch_data_misses"] +
|
v["pmis"] = (d["prefetch_data_misses"] +
|
||||||
d["prefetch_metadata_misses"]) / sint
|
d["prefetch_metadata_misses"]) / sint
|
||||||
|
|
||||||
v["pread"] = v["phit"] + v["pioh"] + v["pmis"]
|
v["pread"] = v["phit"] + v["pmis"]
|
||||||
v["ph%"] = 100 * v["phit"] / v["pread"] if v["pread"] > 0 else 0
|
v["ph%"] = 100 * v["phit"] / v["pread"] if v["pread"] > 0 else 0
|
||||||
v["pi%"] = 100 * v["pioh"] / v["pread"] if v["pread"] > 0 else 0
|
v["pm%"] = 100 - v["ph%"] if v["pread"] > 0 else 0
|
||||||
v["pm%"] = 100 - v["ph%"] - v["pi%"] if v["pread"] > 0 else 0
|
|
||||||
|
|
||||||
v["pdhit"] = d["prefetch_data_hits"] / sint
|
|
||||||
v["pdioh"] = d["prefetch_data_iohits"] / sint
|
|
||||||
v["pdmis"] = d["prefetch_data_misses"] / sint
|
|
||||||
|
|
||||||
v["pdread"] = v["pdhit"] + v["pdioh"] + v["pdmis"]
|
|
||||||
v["pdh%"] = 100 * v["pdhit"] / v["pdread"] if v["pdread"] > 0 else 0
|
|
||||||
v["pdi%"] = 100 * v["pdioh"] / v["pdread"] if v["pdread"] > 0 else 0
|
|
||||||
v["pdm%"] = 100 - v["pdh%"] - v["pdi%"] if v["pdread"] > 0 else 0
|
|
||||||
|
|
||||||
v["pmhit"] = d["prefetch_metadata_hits"] / sint
|
|
||||||
v["pmioh"] = d["prefetch_metadata_iohits"] / sint
|
|
||||||
v["pmmis"] = d["prefetch_metadata_misses"] / sint
|
|
||||||
|
|
||||||
v["pmread"] = v["pmhit"] + v["pmioh"] + v["pmmis"]
|
|
||||||
v["pmh%"] = 100 * v["pmhit"] / v["pmread"] if v["pmread"] > 0 else 0
|
|
||||||
v["pmi%"] = 100 * v["pmioh"] / v["pmread"] if v["pmread"] > 0 else 0
|
|
||||||
v["pmm%"] = 100 - v["pmh%"] - v["pmi%"] if v["pmread"] > 0 else 0
|
|
||||||
|
|
||||||
v["mhit"] = (d["prefetch_metadata_hits"] +
|
v["mhit"] = (d["prefetch_metadata_hits"] +
|
||||||
d["demand_metadata_hits"]) / sint
|
d["demand_metadata_hits"]) / sint
|
||||||
v["mioh"] = (d["prefetch_metadata_iohits"] +
|
|
||||||
d["demand_metadata_iohits"]) / sint
|
|
||||||
v["mmis"] = (d["prefetch_metadata_misses"] +
|
v["mmis"] = (d["prefetch_metadata_misses"] +
|
||||||
d["demand_metadata_misses"]) / sint
|
d["demand_metadata_misses"]) / sint
|
||||||
|
|
||||||
v["mread"] = v["mhit"] + v["mioh"] + v["mmis"]
|
v["mread"] = v["mhit"] + v["mmis"]
|
||||||
v["mh%"] = 100 * v["mhit"] / v["mread"] if v["mread"] > 0 else 0
|
v["mh%"] = 100 * v["mhit"] / v["mread"] if v["mread"] > 0 else 0
|
||||||
v["mi%"] = 100 * v["mioh"] / v["mread"] if v["mread"] > 0 else 0
|
v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0
|
||||||
v["mm%"] = 100 - v["mh%"] - v["mi%"] if v["mread"] > 0 else 0
|
|
||||||
|
|
||||||
v["arcsz"] = cur["size"]
|
v["arcsz"] = cur["size"]
|
||||||
v["size"] = cur["size"]
|
v["size"] = cur["size"]
|
||||||
@@ -696,7 +478,6 @@ def calculate():
|
|||||||
v["mru"] = d["mru_hits"] / sint
|
v["mru"] = d["mru_hits"] / sint
|
||||||
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["unc"] = d["uncached_hits"] / sint
|
|
||||||
v["eskip"] = d["evict_skip"] / sint
|
v["eskip"] = d["evict_skip"] / sint
|
||||||
v["el2skip"] = d["evict_l2_skip"] / sint
|
v["el2skip"] = d["evict_l2_skip"] / sint
|
||||||
v["el2cach"] = d["evict_l2_cached"] / sint
|
v["el2cach"] = d["evict_l2_cached"] / sint
|
||||||
@@ -705,33 +486,6 @@ def calculate():
|
|||||||
v["el2mru"] = d["evict_l2_eligible_mru"] / sint
|
v["el2mru"] = d["evict_l2_eligible_mru"] / sint
|
||||||
v["el2inel"] = d["evict_l2_ineligible"] / sint
|
v["el2inel"] = d["evict_l2_ineligible"] / sint
|
||||||
v["mtxmis"] = d["mutex_miss"] / sint
|
v["mtxmis"] = d["mutex_miss"] / sint
|
||||||
v["ztotal"] = (d["zfetch_hits"] + d["zfetch_future"] + d["zfetch_stride"] +
|
|
||||||
d["zfetch_past"] + d["zfetch_misses"]) / sint
|
|
||||||
v["zhits"] = d["zfetch_hits"] / sint
|
|
||||||
v["zahead"] = (d["zfetch_future"] + d["zfetch_stride"]) / sint
|
|
||||||
v["zpast"] = d["zfetch_past"] / sint
|
|
||||||
v["zmisses"] = d["zfetch_misses"] / sint
|
|
||||||
v["zmax"] = d["zfetch_max_streams"] / sint
|
|
||||||
v["zfuture"] = d["zfetch_future"] / sint
|
|
||||||
v["zstride"] = d["zfetch_stride"] / sint
|
|
||||||
v["zissued"] = d["zfetch_io_issued"] / sint
|
|
||||||
v["zactive"] = d["zfetch_io_active"] / sint
|
|
||||||
|
|
||||||
# ARC structural breakdown, ARC types breakdown, ARC states breakdown
|
|
||||||
v["cachessz"] = cur["caches_size"]
|
|
||||||
for fs in fieldstats:
|
|
||||||
fields, stats = fs[0], fs[1:]
|
|
||||||
for field, fieldval in fields.items():
|
|
||||||
for group in stats:
|
|
||||||
for stat, statval in group.items():
|
|
||||||
if stat in ["fields", "percent"] or \
|
|
||||||
("fields" in group and field not in group["fields"]):
|
|
||||||
continue
|
|
||||||
colname = field + stat
|
|
||||||
v[colname] = cur[fieldval[0] + statval[0]]
|
|
||||||
if "percent" in group:
|
|
||||||
v[colname + "%"] = 100 * v[colname] / \
|
|
||||||
v[group["percent"]] if v[group["percent"]] > 0 else 0
|
|
||||||
|
|
||||||
if l2exist:
|
if l2exist:
|
||||||
v["l2hits"] = d["l2_hits"] / sint
|
v["l2hits"] = d["l2_hits"] / sint
|
||||||
@@ -743,7 +497,6 @@ def calculate():
|
|||||||
v["l2asize"] = cur["l2_asize"]
|
v["l2asize"] = cur["l2_asize"]
|
||||||
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["l2wbytes"] = d["l2_write_bytes"] / sint
|
|
||||||
|
|
||||||
v["l2pref"] = cur["l2_prefetch_asize"]
|
v["l2pref"] = cur["l2_prefetch_asize"]
|
||||||
v["l2mfu"] = cur["l2_mfu_asize"]
|
v["l2mfu"] = cur["l2_mfu_asize"]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
dbufstat
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
include $(top_srcdir)/config/Substfiles.am
|
||||||
|
|
||||||
|
bin_SCRIPTS = dbufstat
|
||||||
|
|
||||||
|
SUBSTFILES += $(bin_SCRIPTS)
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
# with the License.
|
# with the License.
|
||||||
#
|
#
|
||||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
# or https://opensource.org/licenses/CDDL-1.0.
|
# or http://www.opensolaris.org/os/licensing.
|
||||||
# See the License for the specific language governing permissions
|
# See the License for the specific language governing permissions
|
||||||
# and limitations under the License.
|
# and limitations under the License.
|
||||||
#
|
#
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
# Copyright (C) 2013 Lawrence Livermore National Security, LLC.
|
# Copyright (C) 2013 Lawrence Livermore National Security, LLC.
|
||||||
# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||||
#
|
#
|
||||||
# This script must remain compatible with and Python 3.6+.
|
# This script must remain compatible with Python 2.6+ and Python 3.4+.
|
||||||
#
|
#
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@@ -37,7 +37,7 @@ import re
|
|||||||
|
|
||||||
bhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize"]
|
bhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize"]
|
||||||
bxhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize",
|
bxhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize",
|
||||||
"usize", "meta", "state", "dbholds", "dbc", "list", "atype", "flags",
|
"meta", "state", "dbholds", "dbc", "list", "atype", "flags",
|
||||||
"count", "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2",
|
"count", "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2",
|
||||||
"l2_dattr", "l2_asize", "l2_comp", "aholds", "dtype", "btype",
|
"l2_dattr", "l2_asize", "l2_comp", "aholds", "dtype", "btype",
|
||||||
"data_bs", "meta_bs", "bsize", "lvls", "dholds", "blocks", "dsize"]
|
"data_bs", "meta_bs", "bsize", "lvls", "dholds", "blocks", "dsize"]
|
||||||
@@ -47,17 +47,17 @@ dhdr = ["pool", "objset", "object", "dtype", "cached"]
|
|||||||
dxhdr = ["pool", "objset", "object", "dtype", "btype", "data_bs", "meta_bs",
|
dxhdr = ["pool", "objset", "object", "dtype", "btype", "data_bs", "meta_bs",
|
||||||
"bsize", "lvls", "dholds", "blocks", "dsize", "cached", "direct",
|
"bsize", "lvls", "dholds", "blocks", "dsize", "cached", "direct",
|
||||||
"indirect", "bonus", "spill"]
|
"indirect", "bonus", "spill"]
|
||||||
dincompat = ["level", "blkid", "offset", "dbsize", "usize", "meta", "state",
|
dincompat = ["level", "blkid", "offset", "dbsize", "meta", "state", "dbholds",
|
||||||
"dbholds", "dbc", "list", "atype", "flags", "count", "asize",
|
"dbc", "list", "atype", "flags", "count", "asize", "access",
|
||||||
"access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
|
"mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
|
||||||
"l2_asize", "l2_comp", "aholds"]
|
"l2_comp", "aholds"]
|
||||||
|
|
||||||
thdr = ["pool", "objset", "dtype", "cached"]
|
thdr = ["pool", "objset", "dtype", "cached"]
|
||||||
txhdr = ["pool", "objset", "dtype", "cached", "direct", "indirect",
|
txhdr = ["pool", "objset", "dtype", "cached", "direct", "indirect",
|
||||||
"bonus", "spill"]
|
"bonus", "spill"]
|
||||||
tincompat = ["object", "level", "blkid", "offset", "dbsize", "usize", "meta",
|
tincompat = ["object", "level", "blkid", "offset", "dbsize", "meta", "state",
|
||||||
"state", "dbc", "dbholds", "list", "atype", "flags", "count",
|
"dbc", "dbholds", "list", "atype", "flags", "count", "asize",
|
||||||
"asize", "access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
|
"access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
|
||||||
"l2_asize", "l2_comp", "aholds", "btype", "data_bs", "meta_bs",
|
"l2_asize", "l2_comp", "aholds", "btype", "data_bs", "meta_bs",
|
||||||
"bsize", "lvls", "dholds", "blocks", "dsize"]
|
"bsize", "lvls", "dholds", "blocks", "dsize"]
|
||||||
|
|
||||||
@@ -70,7 +70,6 @@ cols = {
|
|||||||
"blkid": [8, -1, "block number of buffer"],
|
"blkid": [8, -1, "block number of buffer"],
|
||||||
"offset": [12, 1024, "offset in object of buffer"],
|
"offset": [12, 1024, "offset in object of buffer"],
|
||||||
"dbsize": [7, 1024, "size of buffer"],
|
"dbsize": [7, 1024, "size of buffer"],
|
||||||
"usize": [7, 1024, "size of attached user data"],
|
|
||||||
"meta": [4, -1, "is this buffer metadata?"],
|
"meta": [4, -1, "is this buffer metadata?"],
|
||||||
"state": [5, -1, "state of buffer (read, cached, etc)"],
|
"state": [5, -1, "state of buffer (read, cached, etc)"],
|
||||||
"dbholds": [7, 1000, "number of holds on buffer"],
|
"dbholds": [7, 1000, "number of holds on buffer"],
|
||||||
@@ -400,7 +399,6 @@ def update_dict(d, k, line, labels):
|
|||||||
key = line[labels[k]]
|
key = line[labels[k]]
|
||||||
|
|
||||||
dbsize = int(line[labels['dbsize']])
|
dbsize = int(line[labels['dbsize']])
|
||||||
usize = int(line[labels['usize']])
|
|
||||||
blkid = int(line[labels['blkid']])
|
blkid = int(line[labels['blkid']])
|
||||||
level = int(line[labels['level']])
|
level = int(line[labels['level']])
|
||||||
|
|
||||||
@@ -418,7 +416,7 @@ def update_dict(d, k, line, labels):
|
|||||||
d[pool][objset][key]['indirect'] = 0
|
d[pool][objset][key]['indirect'] = 0
|
||||||
d[pool][objset][key]['spill'] = 0
|
d[pool][objset][key]['spill'] = 0
|
||||||
|
|
||||||
d[pool][objset][key]['cached'] += dbsize + usize
|
d[pool][objset][key]['cached'] += dbsize
|
||||||
|
|
||||||
if blkid == -1:
|
if blkid == -1:
|
||||||
d[pool][objset][key]['bonus'] += dbsize
|
d[pool][objset][key]['bonus'] += dbsize
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/fsck.zfs
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
include $(top_srcdir)/config/Substfiles.am
|
||||||
|
include $(top_srcdir)/config/Shellcheck.am
|
||||||
|
|
||||||
|
dist_sbin_SCRIPTS = fsck.zfs
|
||||||
|
|
||||||
|
SUBSTFILES += $(dist_sbin_SCRIPTS)
|
||||||
@@ -7,13 +7,13 @@
|
|||||||
# see fsck.zfs(8)
|
# see fsck.zfs(8)
|
||||||
#
|
#
|
||||||
|
|
||||||
if [ $# -eq 0 ]; then
|
if [ "$#" = "0" ]; then
|
||||||
echo "Usage: $0 [options] dataset…" >&2
|
echo "Usage: $0 [options] dataset…" >&2
|
||||||
exit 16
|
exit 16
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ret=0
|
ret=0
|
||||||
for dataset; do
|
for dataset in "$@"; do
|
||||||
case "$dataset" in
|
case "$dataset" in
|
||||||
-*)
|
-*)
|
||||||
continue
|
continue
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
mount.zfs
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
|
#
|
||||||
|
# Ignore the prefix for the mount helper. It must be installed in /sbin/
|
||||||
|
# because this path is hardcoded in the mount(8) for security reasons.
|
||||||
|
# However, if needed, the configure option --with-mounthelperdir= can be used
|
||||||
|
# to override the default install location.
|
||||||
|
#
|
||||||
|
sbindir=$(mounthelperdir)
|
||||||
|
sbin_PROGRAMS = mount.zfs
|
||||||
|
|
||||||
|
mount_zfs_SOURCES = \
|
||||||
|
mount_zfs.c
|
||||||
|
|
||||||
|
mount_zfs_LDADD = \
|
||||||
|
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||||
|
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||||
|
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
||||||
|
|
||||||
|
mount_zfs_LDADD += $(LTLIBINTL)
|
||||||
|
|
||||||
|
include $(top_srcdir)/config/CppCheck.am
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -74,7 +74,7 @@ parse_dataset(const char *target, char **dataset)
|
|||||||
|
|
||||||
nvlist_t *cfg = NULL;
|
nvlist_t *cfg = NULL;
|
||||||
if (zpool_read_label(fd, &cfg, NULL) == 0) {
|
if (zpool_read_label(fd, &cfg, NULL) == 0) {
|
||||||
const char *nm = NULL;
|
char *nm = NULL;
|
||||||
if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm))
|
if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm))
|
||||||
strlcpy(*dataset, nm, PATH_MAX);
|
strlcpy(*dataset, nm, PATH_MAX);
|
||||||
nvlist_free(cfg);
|
nvlist_free(cfg);
|
||||||
@@ -108,21 +108,20 @@ mtab_is_writeable(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mtab_update(const char *dataset, const char *mntpoint, const char *type,
|
mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
||||||
const char *mntopts)
|
|
||||||
{
|
{
|
||||||
struct mntent mnt;
|
struct mntent mnt;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
mnt.mnt_fsname = (char *)dataset;
|
mnt.mnt_fsname = dataset;
|
||||||
mnt.mnt_dir = (char *)mntpoint;
|
mnt.mnt_dir = mntpoint;
|
||||||
mnt.mnt_type = (char *)type;
|
mnt.mnt_type = type;
|
||||||
mnt.mnt_opts = (char *)(mntopts ?: "");
|
mnt.mnt_opts = mntopts ? mntopts : "";
|
||||||
mnt.mnt_freq = 0;
|
mnt.mnt_freq = 0;
|
||||||
mnt.mnt_passno = 0;
|
mnt.mnt_passno = 0;
|
||||||
|
|
||||||
fp = setmntent("/etc/mtab", "a+e");
|
fp = setmntent("/etc/mtab", "a+");
|
||||||
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 "
|
||||||
@@ -269,7 +268,8 @@ main(int argc, char **argv)
|
|||||||
return (MOUNT_USAGE);
|
return (MOUNT_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sloppy || libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
|
if (!zfsutil || sloppy ||
|
||||||
|
libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
|
||||||
zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt);
|
zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +336,7 @@ main(int argc, char **argv)
|
|||||||
dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt);
|
dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt);
|
||||||
|
|
||||||
if (!fake) {
|
if (!fake) {
|
||||||
if (!remount && !sloppy &&
|
if (zfsutil && !sloppy &&
|
||||||
!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
|
!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
|
||||||
error = zfs_mount_at(zhp, mntopts, mntflags, mntpoint);
|
error = zfs_mount_at(zhp, mntopts, mntflags, mntpoint);
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -389,8 +389,8 @@ main(int argc, char **argv)
|
|||||||
"mount the filesystem again.\n"), dataset);
|
"mount the filesystem again.\n"), dataset);
|
||||||
return (MOUNT_SYSERR);
|
return (MOUNT_SYSERR);
|
||||||
}
|
}
|
||||||
|
fallthrough;
|
||||||
#endif
|
#endif
|
||||||
zfs_fallthrough;
|
|
||||||
default:
|
default:
|
||||||
(void) fprintf(stderr, gettext("filesystem "
|
(void) fprintf(stderr, gettext("filesystem "
|
||||||
"'%s' can not be mounted: %s\n"), dataset,
|
"'%s' can not be mounted: %s\n"), dataset,
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/raidz_test
|
||||||
@@ -1,16 +1,22 @@
|
|||||||
raidz_test_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
|
include $(top_srcdir)/config/Rules.am
|
||||||
raidz_test_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
|
|
||||||
|
|
||||||
bin_PROGRAMS += raidz_test
|
# Includes kernel code, generate warnings for large stack frames
|
||||||
CPPCHECKTARGETS += raidz_test
|
AM_CFLAGS += $(FRAME_LARGER_THAN)
|
||||||
|
|
||||||
|
# Unconditionally enable ASSERTs
|
||||||
|
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
||||||
|
|
||||||
|
bin_PROGRAMS = raidz_test
|
||||||
|
|
||||||
raidz_test_SOURCES = \
|
raidz_test_SOURCES = \
|
||||||
%D%/raidz_bench.c \
|
raidz_test.h \
|
||||||
%D%/raidz_test.c \
|
raidz_test.c \
|
||||||
%D%/raidz_test.h
|
raidz_bench.c
|
||||||
|
|
||||||
raidz_test_LDADD = \
|
raidz_test_LDADD = \
|
||||||
libzpool.la \
|
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
||||||
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
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -63,7 +63,7 @@ bench_fini_raidz_maps(void)
|
|||||||
{
|
{
|
||||||
/* tear down golden zio */
|
/* tear down golden zio */
|
||||||
raidz_free(zio_bench.io_abd, max_data_size);
|
raidz_free(zio_bench.io_abd, max_data_size);
|
||||||
memset(&zio_bench, 0, sizeof (zio_t));
|
bzero(&zio_bench, sizeof (zio_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -84,10 +84,10 @@ run_gen_bench_impl(const char *impl)
|
|||||||
|
|
||||||
if (rto_opts.rto_expand) {
|
if (rto_opts.rto_expand) {
|
||||||
rm_bench = vdev_raidz_map_alloc_expanded(
|
rm_bench = vdev_raidz_map_alloc_expanded(
|
||||||
&zio_bench,
|
zio_bench.io_abd,
|
||||||
|
zio_bench.io_size, zio_bench.io_offset,
|
||||||
rto_opts.rto_ashift, ncols+1, ncols,
|
rto_opts.rto_ashift, ncols+1, ncols,
|
||||||
fn+1, rto_opts.rto_expand_offset,
|
fn+1, rto_opts.rto_expand_offset);
|
||||||
0, B_FALSE);
|
|
||||||
} else {
|
} else {
|
||||||
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
||||||
BENCH_ASHIFT, ncols, fn+1);
|
BENCH_ASHIFT, ncols, fn+1);
|
||||||
@@ -172,10 +172,10 @@ run_rec_bench_impl(const char *impl)
|
|||||||
|
|
||||||
if (rto_opts.rto_expand) {
|
if (rto_opts.rto_expand) {
|
||||||
rm_bench = vdev_raidz_map_alloc_expanded(
|
rm_bench = vdev_raidz_map_alloc_expanded(
|
||||||
&zio_bench,
|
zio_bench.io_abd,
|
||||||
|
zio_bench.io_size, zio_bench.io_offset,
|
||||||
BENCH_ASHIFT, ncols+1, ncols,
|
BENCH_ASHIFT, ncols+1, ncols,
|
||||||
PARITY_PQR,
|
PARITY_PQR, rto_opts.rto_expand_offset);
|
||||||
rto_opts.rto_expand_offset, 0, B_FALSE);
|
|
||||||
} else {
|
} else {
|
||||||
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
rm_bench = vdev_raidz_map_alloc(&zio_bench,
|
||||||
BENCH_ASHIFT, ncols, PARITY_PQR);
|
BENCH_ASHIFT, ncols, PARITY_PQR);
|
||||||
|
|||||||
+214
-33
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -37,11 +37,11 @@
|
|||||||
static int *rand_data;
|
static int *rand_data;
|
||||||
raidz_test_opts_t rto_opts;
|
raidz_test_opts_t rto_opts;
|
||||||
|
|
||||||
static char pid_s[16];
|
static char gdb[256];
|
||||||
|
static const char gdb_tmpl[] = "gdb -ex \"set pagination 0\" -p %d";
|
||||||
|
|
||||||
static void sig_handler(int signo)
|
static void sig_handler(int signo)
|
||||||
{
|
{
|
||||||
int old_errno = errno;
|
|
||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
/*
|
/*
|
||||||
* Restore default action and re-raise signal so SIGSEGV and
|
* Restore default action and re-raise signal so SIGSEGV and
|
||||||
@@ -52,32 +52,22 @@ static void sig_handler(int signo)
|
|||||||
action.sa_flags = 0;
|
action.sa_flags = 0;
|
||||||
(void) sigaction(signo, &action, NULL);
|
(void) sigaction(signo, &action, NULL);
|
||||||
|
|
||||||
if (rto_opts.rto_gdb) {
|
if (rto_opts.rto_gdb)
|
||||||
pid_t pid = fork();
|
if (system(gdb)) { }
|
||||||
if (pid == 0) {
|
|
||||||
execlp("gdb", "gdb", "-ex", "set pagination 0",
|
|
||||||
"-p", pid_s, NULL);
|
|
||||||
_exit(-1);
|
|
||||||
} else if (pid > 0)
|
|
||||||
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
raise(signo);
|
raise(signo);
|
||||||
errno = old_errno;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_opts(raidz_test_opts_t *opts, boolean_t force)
|
static void print_opts(raidz_test_opts_t *opts, boolean_t force)
|
||||||
{
|
{
|
||||||
const char *verbose;
|
char *verbose;
|
||||||
switch (opts->rto_v) {
|
switch (opts->rto_v) {
|
||||||
case D_ALL:
|
case 0:
|
||||||
verbose = "no";
|
verbose = "no";
|
||||||
break;
|
break;
|
||||||
case D_INFO:
|
case 1:
|
||||||
verbose = "info";
|
verbose = "info";
|
||||||
break;
|
break;
|
||||||
case D_DEBUG:
|
|
||||||
default:
|
default:
|
||||||
verbose = "debug";
|
verbose = "debug";
|
||||||
break;
|
break;
|
||||||
@@ -120,7 +110,7 @@ static void usage(boolean_t requested)
|
|||||||
"\t[-B benchmark all raidz implementations]\n"
|
"\t[-B benchmark all raidz implementations]\n"
|
||||||
"\t[-e use expanded raidz map (default: %s)]\n"
|
"\t[-e use expanded raidz map (default: %s)]\n"
|
||||||
"\t[-r expanded raidz map reflow offset (default: %llx)]\n"
|
"\t[-r expanded raidz map reflow offset (default: %llx)]\n"
|
||||||
"\t[-v increase verbosity (default: %d)]\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"
|
||||||
"\t[-D debug (attach gdb on SIGSEGV)]\n"
|
"\t[-D debug (attach gdb on SIGSEGV)]\n"
|
||||||
@@ -132,7 +122,7 @@ static void usage(boolean_t requested)
|
|||||||
rto_opts.rto_sweep ? "yes" : "no", /* -S */
|
rto_opts.rto_sweep ? "yes" : "no", /* -S */
|
||||||
rto_opts.rto_expand ? "yes" : "no", /* -e */
|
rto_opts.rto_expand ? "yes" : "no", /* -e */
|
||||||
(u_longlong_t)o->rto_expand_offset, /* -r */
|
(u_longlong_t)o->rto_expand_offset, /* -r */
|
||||||
o->rto_v); /* -v */
|
o->rto_v); /* -d */
|
||||||
|
|
||||||
exit(requested ? 0 : 1);
|
exit(requested ? 0 : 1);
|
||||||
}
|
}
|
||||||
@@ -141,11 +131,14 @@ static void process_options(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
size_t value;
|
size_t value;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
raidz_test_opts_t *o = &rto_opts;
|
raidz_test_opts_t *o = &rto_opts;
|
||||||
|
|
||||||
memcpy(o, &rto_opts_defaults, 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:er:o:d:s:t:")) != -1) {
|
||||||
|
value = 0;
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
case 'a':
|
||||||
value = strtoull(optarg, NULL, 0);
|
value = strtoull(optarg, NULL, 0);
|
||||||
@@ -264,8 +257,12 @@ cmp_data(raidz_test_opts_t *opts, raidz_map_t *rm)
|
|||||||
static int
|
static int
|
||||||
init_rand(void *data, size_t size, void *private)
|
init_rand(void *data, size_t size, void *private)
|
||||||
{
|
{
|
||||||
(void) private;
|
int i;
|
||||||
memcpy(data, rand_data, size);
|
int *dst = (int *)data;
|
||||||
|
|
||||||
|
for (i = 0; i < size / sizeof (int); i++)
|
||||||
|
dst[i] = rand_data[i];
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,12 +324,14 @@ init_raidz_golden_map(raidz_test_opts_t *opts, const int parity)
|
|||||||
|
|
||||||
if (opts->rto_expand) {
|
if (opts->rto_expand) {
|
||||||
opts->rm_golden =
|
opts->rm_golden =
|
||||||
vdev_raidz_map_alloc_expanded(opts->zio_golden,
|
vdev_raidz_map_alloc_expanded(opts->zio_golden->io_abd,
|
||||||
|
opts->zio_golden->io_size, opts->zio_golden->io_offset,
|
||||||
opts->rto_ashift, total_ncols+1, total_ncols,
|
opts->rto_ashift, total_ncols+1, total_ncols,
|
||||||
parity, opts->rto_expand_offset, 0, B_FALSE);
|
parity, opts->rto_expand_offset);
|
||||||
rm_test = vdev_raidz_map_alloc_expanded(zio_test,
|
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,
|
opts->rto_ashift, total_ncols+1, total_ncols,
|
||||||
parity, opts->rto_expand_offset, 0, B_FALSE);
|
parity, opts->rto_expand_offset);
|
||||||
} else {
|
} else {
|
||||||
opts->rm_golden = vdev_raidz_map_alloc(opts->zio_golden,
|
opts->rm_golden = vdev_raidz_map_alloc(opts->zio_golden,
|
||||||
opts->rto_ashift, total_ncols, parity);
|
opts->rto_ashift, total_ncols, parity);
|
||||||
@@ -359,6 +358,187 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -378,9 +558,10 @@ init_raidz_map(raidz_test_opts_t *opts, zio_t **zio, const int parity)
|
|||||||
init_zio_abd(*zio);
|
init_zio_abd(*zio);
|
||||||
|
|
||||||
if (opts->rto_expand) {
|
if (opts->rto_expand) {
|
||||||
rm = vdev_raidz_map_alloc_expanded(*zio,
|
rm = vdev_raidz_map_alloc_expanded((*zio)->io_abd,
|
||||||
|
(*zio)->io_size, (*zio)->io_offset,
|
||||||
opts->rto_ashift, total_ncols+1, total_ncols,
|
opts->rto_ashift, total_ncols+1, total_ncols,
|
||||||
parity, opts->rto_expand_offset, 0, B_FALSE);
|
parity, opts->rto_expand_offset);
|
||||||
} else {
|
} else {
|
||||||
rm = vdev_raidz_map_alloc(*zio, opts->rto_ashift,
|
rm = vdev_raidz_map_alloc(*zio, opts->rto_ashift,
|
||||||
total_ncols, parity);
|
total_ncols, parity);
|
||||||
@@ -653,7 +834,7 @@ static kcondvar_t sem_cv;
|
|||||||
static int max_free_slots;
|
static int max_free_slots;
|
||||||
static int free_slots;
|
static int free_slots;
|
||||||
|
|
||||||
static __attribute__((noreturn)) void
|
static void
|
||||||
sweep_thread(void *arg)
|
sweep_thread(void *arg)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -753,7 +934,7 @@ run_sweep(void)
|
|||||||
opts = umem_zalloc(sizeof (raidz_test_opts_t), UMEM_NOFAIL);
|
opts = umem_zalloc(sizeof (raidz_test_opts_t), UMEM_NOFAIL);
|
||||||
opts->rto_ashift = ashift_v[a];
|
opts->rto_ashift = ashift_v[a];
|
||||||
opts->rto_dcols = dcols_v[d];
|
opts->rto_dcols = dcols_v[d];
|
||||||
opts->rto_offset = (1ULL << 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 = rto_opts.rto_expand;
|
||||||
opts->rto_expand_offset = rto_opts.rto_expand_offset;
|
opts->rto_expand_offset = rto_opts.rto_expand_offset;
|
||||||
@@ -797,8 +978,8 @@ main(int argc, char **argv)
|
|||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
/* init gdb pid string early */
|
/* init gdb string early */
|
||||||
(void) sprintf(pid_s, "%d", getpid());
|
(void) sprintf(gdb, gdb_tmpl, getpid());
|
||||||
|
|
||||||
action.sa_handler = sig_handler;
|
action.sa_handler = sig_handler;
|
||||||
sigemptyset(&action.sa_mask);
|
sigemptyset(&action.sa_mask);
|
||||||
|
|||||||
+16
-15
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include <sys/spa.h>
|
#include <sys/spa.h>
|
||||||
|
|
||||||
static const char *const raidz_impl_names[] = {
|
static const char *raidz_impl_names[] = {
|
||||||
"original",
|
"original",
|
||||||
"scalar",
|
"scalar",
|
||||||
"sse2",
|
"sse2",
|
||||||
@@ -42,18 +42,12 @@ static const char *const raidz_impl_names[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
enum raidz_verbosity {
|
|
||||||
D_ALL,
|
|
||||||
D_INFO,
|
|
||||||
D_DEBUG,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct raidz_test_opts {
|
typedef struct raidz_test_opts {
|
||||||
size_t rto_ashift;
|
size_t rto_ashift;
|
||||||
uint64_t rto_offset;
|
uint64_t rto_offset;
|
||||||
size_t rto_dcols;
|
size_t rto_dcols;
|
||||||
size_t rto_dsize;
|
size_t rto_dsize;
|
||||||
enum raidz_verbosity 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;
|
||||||
@@ -74,7 +68,7 @@ static const raidz_test_opts_t rto_opts_defaults = {
|
|||||||
.rto_offset = 1ULL << 0,
|
.rto_offset = 1ULL << 0,
|
||||||
.rto_dcols = 8,
|
.rto_dcols = 8,
|
||||||
.rto_dsize = 1<<19,
|
.rto_dsize = 1<<19,
|
||||||
.rto_v = D_ALL,
|
.rto_v = 0,
|
||||||
.rto_sweep = 0,
|
.rto_sweep = 0,
|
||||||
.rto_benchmark = 0,
|
.rto_benchmark = 0,
|
||||||
.rto_expand = 0,
|
.rto_expand = 0,
|
||||||
@@ -92,19 +86,23 @@ static inline size_t ilog2(size_t a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define LOG(lvl, ...) \
|
#define D_ALL 0
|
||||||
|
#define D_INFO 1
|
||||||
|
#define D_DEBUG 2
|
||||||
|
|
||||||
|
#define LOG(lvl, a...) \
|
||||||
{ \
|
{ \
|
||||||
if (rto_opts.rto_v >= lvl) \
|
if (rto_opts.rto_v >= lvl) \
|
||||||
(void) fprintf(stdout, __VA_ARGS__); \
|
(void) fprintf(stdout, a); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
#define LOG_OPT(lvl, opt, ...) \
|
#define LOG_OPT(lvl, opt, a...) \
|
||||||
{ \
|
{ \
|
||||||
if (opt->rto_v >= lvl) \
|
if (opt->rto_v >= lvl) \
|
||||||
(void) fprintf(stdout, __VA_ARGS__); \
|
(void) fprintf(stdout, a); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
#define ERR(...) (void) fprintf(stderr, __VA_ARGS__)
|
#define ERR(a...) (void) fprintf(stderr, a)
|
||||||
|
|
||||||
|
|
||||||
#define DBLSEP "================\n"
|
#define DBLSEP "================\n"
|
||||||
@@ -119,4 +117,7 @@ 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 */
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
include $(top_srcdir)/config/Shellcheck.am
|
||||||
|
|
||||||
|
dist_udev_SCRIPTS = vdev_id
|
||||||
@@ -124,7 +124,6 @@ TOPOLOGY=
|
|||||||
BAY=
|
BAY=
|
||||||
ENCL_ID=""
|
ENCL_ID=""
|
||||||
UNIQ_ENCL_ID=""
|
UNIQ_ENCL_ID=""
|
||||||
ZPAD=1
|
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
@@ -155,7 +154,7 @@ map_slot() {
|
|||||||
if [ -z "$MAPPED_SLOT" ] ; then
|
if [ -z "$MAPPED_SLOT" ] ; then
|
||||||
MAPPED_SLOT=$LINUX_SLOT
|
MAPPED_SLOT=$LINUX_SLOT
|
||||||
fi
|
fi
|
||||||
printf "%0${ZPAD}d" "${MAPPED_SLOT}"
|
printf "%d" "${MAPPED_SLOT}"
|
||||||
}
|
}
|
||||||
|
|
||||||
map_channel() {
|
map_channel() {
|
||||||
@@ -431,15 +430,6 @@ sas_handler() {
|
|||||||
d=$(eval echo '$'{$i})
|
d=$(eval echo '$'{$i})
|
||||||
SLOT=$(echo "$d" | sed -e 's/^.*://')
|
SLOT=$(echo "$d" | sed -e 's/^.*://')
|
||||||
;;
|
;;
|
||||||
"bay_lun")
|
|
||||||
# Like 'bay' but with the LUN number appened. Added for SAS
|
|
||||||
# multi-actuator HDDs, where one physical drive has multiple
|
|
||||||
# LUNs, thus multiple logical drives share the same bay number
|
|
||||||
i=$((i + 2))
|
|
||||||
d=$(eval echo '$'{$i})
|
|
||||||
LUN="-lun$(echo "$d" | sed -e 's/^.*://')"
|
|
||||||
SLOT=$(cat "$end_device_dir/bay_identifier" 2>/dev/null)
|
|
||||||
;;
|
|
||||||
"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
|
||||||
@@ -470,7 +460,7 @@ sas_handler() {
|
|||||||
if [ -z "$CHAN" ] ; then
|
if [ -z "$CHAN" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo "${CHAN}"-"${JBOD}"-"${SLOT}${LUN}${PART}"
|
echo "${CHAN}"-"${JBOD}"-"${SLOT}${PART}"
|
||||||
else
|
else
|
||||||
CHAN=$(map_channel "$PCI_ID" "$PORT")
|
CHAN=$(map_channel "$PCI_ID" "$PORT")
|
||||||
SLOT=$(map_slot "$SLOT" "$CHAN")
|
SLOT=$(map_slot "$SLOT" "$CHAN")
|
||||||
@@ -478,7 +468,7 @@ sas_handler() {
|
|||||||
if [ -z "$CHAN" ] ; then
|
if [ -z "$CHAN" ] ; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo "${CHAN}${SLOT}${LUN}${PART}"
|
echo "${CHAN}${SLOT}${PART}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,8 +748,6 @@ if [ -z "$BAY" ] ; then
|
|||||||
BAY=$(awk '($1 == "slot") {print $2; exit}' "$CONFIG")
|
BAY=$(awk '($1 == "slot") {print $2; exit}' "$CONFIG")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ZPAD=$(awk '($1 == "zpad_slot") {print $2; exit}' "$CONFIG")
|
|
||||||
|
|
||||||
TOPOLOGY=${TOPOLOGY:-sas_direct}
|
TOPOLOGY=${TOPOLOGY:-sas_direct}
|
||||||
|
|
||||||
# Should we create /dev/by-enclosure symlinks?
|
# Should we create /dev/by-enclosure symlinks?
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/zdb
|
||||||
+12
-12
@@ -1,18 +1,18 @@
|
|||||||
zdb_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
|
include $(top_srcdir)/config/Rules.am
|
||||||
zdb_CFLAGS = $(AM_CFLAGS) $(LIBCRYPTO_CFLAGS)
|
|
||||||
|
|
||||||
sbin_PROGRAMS += zdb
|
# Unconditionally enable debugging for zdb
|
||||||
CPPCHECKTARGETS += zdb
|
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
||||||
|
|
||||||
|
sbin_PROGRAMS = zdb
|
||||||
|
|
||||||
zdb_SOURCES = \
|
zdb_SOURCES = \
|
||||||
%D%/zdb.c \
|
zdb.c \
|
||||||
%D%/zdb.h \
|
zdb_il.c \
|
||||||
%D%/zdb_il.c
|
zdb.h
|
||||||
|
|
||||||
zdb_LDADD = \
|
zdb_LDADD = \
|
||||||
libzdb.la \
|
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
||||||
libzpool.la \
|
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||||
libzfs_core.la \
|
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
||||||
libnvpair.la
|
|
||||||
|
|
||||||
zdb_LDADD += $(LIBCRYPTO_LIBS)
|
include $(top_srcdir)/config/CppCheck.am
|
||||||
|
|||||||
+736
-1864
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
|
|||||||
+30
-141
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -60,26 +60,25 @@ print_log_bp(const blkptr_t *bp, const char *prefix)
|
|||||||
(void) printf("%s%s\n", prefix, blkbuf);
|
(void) printf("%s%s\n", prefix, blkbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
(void) zilog;
|
const lr_create_t *lr = arg;
|
||||||
const lr_create_t *lrc = arg;
|
|
||||||
const _lr_create_t *lr = &lrc->lr_create;
|
|
||||||
time_t crtime = lr->lr_crtime[0];
|
time_t crtime = lr->lr_crtime[0];
|
||||||
const char *name, *link;
|
char *name, *link;
|
||||||
lr_attr_t *lrattr;
|
lr_attr_t *lrattr;
|
||||||
|
|
||||||
name = (const char *)&lrc->lr_data[0];
|
name = (char *)(lr + 1);
|
||||||
|
|
||||||
if (lr->lr_common.lrc_txtype == TX_CREATE_ATTR ||
|
if (lr->lr_common.lrc_txtype == TX_CREATE_ATTR ||
|
||||||
lr->lr_common.lrc_txtype == TX_MKDIR_ATTR) {
|
lr->lr_common.lrc_txtype == TX_MKDIR_ATTR) {
|
||||||
lrattr = (lr_attr_t *)&lrc->lr_data[0];
|
lrattr = (lr_attr_t *)(lr + 1);
|
||||||
name += ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
|
name += ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txtype == TX_SYMLINK) {
|
if (txtype == TX_SYMLINK) {
|
||||||
link = (const char *)&lrc->lr_data[strlen(name) + 1];
|
link = name + strlen(name) + 1;
|
||||||
(void) printf("%s%s -> %s\n", tab_prefix, name, link);
|
(void) printf("%s%s -> %s\n", tab_prefix, name, link);
|
||||||
} else if (txtype != TX_MKXATTR) {
|
} else if (txtype != TX_MKXATTR) {
|
||||||
(void) printf("%s%s\n", tab_prefix, name);
|
(void) printf("%s%s\n", tab_prefix, name);
|
||||||
@@ -97,53 +96,44 @@ zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
(u_longlong_t)lr->lr_gen, (u_longlong_t)lr->lr_rdev);
|
(u_longlong_t)lr->lr_gen, (u_longlong_t)lr->lr_rdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_remove(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_remove(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_remove_t *lr = arg;
|
const lr_remove_t *lr = arg;
|
||||||
|
|
||||||
(void) printf("%sdoid %llu, name %s\n", tab_prefix,
|
(void) printf("%sdoid %llu, name %s\n", tab_prefix,
|
||||||
(u_longlong_t)lr->lr_doid, (const char *)&lr->lr_data[0]);
|
(u_longlong_t)lr->lr_doid, (char *)(lr + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_link(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_link(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_link_t *lr = arg;
|
const lr_link_t *lr = arg;
|
||||||
|
|
||||||
(void) printf("%sdoid %llu, link_obj %llu, name %s\n", tab_prefix,
|
(void) printf("%sdoid %llu, link_obj %llu, name %s\n", tab_prefix,
|
||||||
(u_longlong_t)lr->lr_doid, (u_longlong_t)lr->lr_link_obj,
|
(u_longlong_t)lr->lr_doid, (u_longlong_t)lr->lr_link_obj,
|
||||||
(const char *)&lr->lr_data[0]);
|
(char *)(lr + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_rename(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_rename(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
(void) zilog, (void) txtype;
|
const lr_rename_t *lr = arg;
|
||||||
const lr_rename_t *lrr = arg;
|
char *snm = (char *)(lr + 1);
|
||||||
const _lr_rename_t *lr = &lrr->lr_rename;
|
char *tnm = snm + strlen(snm) + 1;
|
||||||
const char *snm = (const char *)&lrr->lr_data[0];
|
|
||||||
const char *tnm = (const char *)&lrr->lr_data[strlen(snm) + 1];
|
|
||||||
|
|
||||||
(void) printf("%ssdoid %llu, tdoid %llu\n", tab_prefix,
|
(void) printf("%ssdoid %llu, tdoid %llu\n", tab_prefix,
|
||||||
(u_longlong_t)lr->lr_sdoid, (u_longlong_t)lr->lr_tdoid);
|
(u_longlong_t)lr->lr_sdoid, (u_longlong_t)lr->lr_tdoid);
|
||||||
(void) printf("%ssrc %s tgt %s\n", tab_prefix, snm, tnm);
|
(void) printf("%ssrc %s tgt %s\n", tab_prefix, snm, tnm);
|
||||||
switch (txtype) {
|
|
||||||
case TX_RENAME_EXCHANGE:
|
|
||||||
(void) printf("%sflags RENAME_EXCHANGE\n", tab_prefix);
|
|
||||||
break;
|
|
||||||
case TX_RENAME_WHITEOUT:
|
|
||||||
(void) printf("%sflags RENAME_WHITEOUT\n", tab_prefix);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
zil_prt_rec_write_cb(void *data, size_t len, void *unused)
|
zil_prt_rec_write_cb(void *data, size_t len, void *unused)
|
||||||
{
|
{
|
||||||
(void) unused;
|
|
||||||
char *cdata = data;
|
char *cdata = data;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
@@ -156,6 +146,7 @@ zil_prt_rec_write_cb(void *data, size_t len, void *unused)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
@@ -170,31 +161,28 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
|
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
|
||||||
(u_longlong_t)lr->lr_length);
|
(u_longlong_t)lr->lr_length);
|
||||||
|
|
||||||
if (txtype == TX_WRITE2 || verbose < 4)
|
if (txtype == TX_WRITE2 || verbose < 5)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
|
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
|
||||||
(void) printf("%shas blkptr, %s\n", tab_prefix,
|
(void) printf("%shas blkptr, %s\n", tab_prefix,
|
||||||
!BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
|
!BP_IS_HOLE(bp) &&
|
||||||
spa_min_claim_txg(zilog->zl_spa) ?
|
bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa) ?
|
||||||
"will claim" : "won't claim");
|
"will claim" : "won't claim");
|
||||||
print_log_bp(bp, tab_prefix);
|
print_log_bp(bp, tab_prefix);
|
||||||
|
|
||||||
if (verbose < 5)
|
|
||||||
return;
|
|
||||||
if (BP_IS_HOLE(bp)) {
|
if (BP_IS_HOLE(bp)) {
|
||||||
(void) printf("\t\t\tLSIZE 0x%llx\n",
|
(void) printf("\t\t\tLSIZE 0x%llx\n",
|
||||||
(u_longlong_t)BP_GET_LSIZE(bp));
|
(u_longlong_t)BP_GET_LSIZE(bp));
|
||||||
(void) printf("%s<hole>\n", tab_prefix);
|
(void) printf("%s<hole>\n", tab_prefix);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (BP_GET_LOGICAL_BIRTH(bp) < zilog->zl_header->zh_claim_txg) {
|
if (bp->blk_birth < zilog->zl_header->zh_claim_txg) {
|
||||||
(void) printf("%s<block already committed>\n",
|
(void) printf("%s<block already committed>\n",
|
||||||
tab_prefix);
|
tab_prefix);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT3U(BP_GET_LSIZE(bp), !=, 0);
|
|
||||||
SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os),
|
SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os),
|
||||||
lr->lr_foid, ZB_ZIL_LEVEL,
|
lr->lr_foid, ZB_ZIL_LEVEL,
|
||||||
lr->lr_offset / BP_GET_LSIZE(bp));
|
lr->lr_offset / BP_GET_LSIZE(bp));
|
||||||
@@ -206,12 +194,9 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
if (verbose < 5)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* data is stored after the end of the lr_write record */
|
/* data is stored after the end of the lr_write record */
|
||||||
data = abd_alloc(lr->lr_length, B_FALSE);
|
data = abd_alloc(lr->lr_length, B_FALSE);
|
||||||
abd_copy_from_buf(data, &lr->lr_data[0], lr->lr_length);
|
abd_copy_from_buf(data, lr + 1, lr->lr_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) printf("%s", tab_prefix);
|
(void) printf("%s", tab_prefix);
|
||||||
@@ -224,32 +209,10 @@ out:
|
|||||||
abd_free(data);
|
abd_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* ARGSUSED */
|
||||||
zil_prt_rec_write_enc(zilog_t *zilog, int txtype, const void *arg)
|
|
||||||
{
|
|
||||||
(void) txtype;
|
|
||||||
const lr_write_t *lr = arg;
|
|
||||||
const blkptr_t *bp = &lr->lr_blkptr;
|
|
||||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
|
||||||
|
|
||||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
|
||||||
|
|
||||||
if (verbose < 4)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
|
|
||||||
(void) printf("%shas blkptr, %s\n", tab_prefix,
|
|
||||||
!BP_IS_HOLE(bp) && BP_GET_LOGICAL_BIRTH(bp) >=
|
|
||||||
spa_min_claim_txg(zilog->zl_spa) ?
|
|
||||||
"will claim" : "won't claim");
|
|
||||||
print_log_bp(bp, tab_prefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_truncate(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_truncate(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_truncate_t *lr = arg;
|
const lr_truncate_t *lr = arg;
|
||||||
|
|
||||||
(void) printf("%sfoid %llu, offset 0x%llx, length 0x%llx\n", tab_prefix,
|
(void) printf("%sfoid %llu, offset 0x%llx, length 0x%llx\n", tab_prefix,
|
||||||
@@ -257,10 +220,10 @@ zil_prt_rec_truncate(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
(u_longlong_t)lr->lr_length);
|
(u_longlong_t)lr->lr_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_setattr(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_setattr(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_setattr_t *lr = arg;
|
const lr_setattr_t *lr = arg;
|
||||||
time_t atime = (time_t)lr->lr_atime[0];
|
time_t atime = (time_t)lr->lr_atime[0];
|
||||||
time_t mtime = (time_t)lr->lr_mtime[0];
|
time_t mtime = (time_t)lr->lr_mtime[0];
|
||||||
@@ -303,83 +266,19 @@ zil_prt_rec_setattr(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* ARGSUSED */
|
||||||
zil_prt_rec_setsaxattr(zilog_t *zilog, int txtype, const void *arg)
|
|
||||||
{
|
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_setsaxattr_t *lr = arg;
|
|
||||||
|
|
||||||
const char *name = (const char *)&lr->lr_data[0];
|
|
||||||
(void) printf("%sfoid %llu\n", tab_prefix,
|
|
||||||
(u_longlong_t)lr->lr_foid);
|
|
||||||
|
|
||||||
(void) printf("%sXAT_NAME %s\n", tab_prefix, name);
|
|
||||||
if (lr->lr_size == 0) {
|
|
||||||
(void) printf("%sXAT_VALUE NULL\n", tab_prefix);
|
|
||||||
} else {
|
|
||||||
(void) printf("%sXAT_VALUE ", tab_prefix);
|
|
||||||
const char *val = (const char *)&lr->lr_data[strlen(name) + 1];
|
|
||||||
for (int i = 0; i < lr->lr_size; i++) {
|
|
||||||
(void) printf("%c", *val);
|
|
||||||
val++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zil_prt_rec_acl(zilog_t *zilog, int txtype, const void *arg)
|
zil_prt_rec_acl(zilog_t *zilog, int txtype, const void *arg)
|
||||||
{
|
{
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_acl_t *lr = arg;
|
const lr_acl_t *lr = arg;
|
||||||
|
|
||||||
(void) printf("%sfoid %llu, aclcnt %llu\n", tab_prefix,
|
(void) printf("%sfoid %llu, aclcnt %llu\n", tab_prefix,
|
||||||
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_aclcnt);
|
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_aclcnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
zil_prt_rec_clone_range(zilog_t *zilog, int txtype, const void *arg)
|
|
||||||
{
|
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_clone_range_t *lr = arg;
|
|
||||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
|
||||||
|
|
||||||
(void) printf("%sfoid %llu, offset %llx, length %llx, blksize %llx\n",
|
|
||||||
tab_prefix, (u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
|
|
||||||
(u_longlong_t)lr->lr_length, (u_longlong_t)lr->lr_blksz);
|
|
||||||
|
|
||||||
if (verbose < 4)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < lr->lr_nbps; i++) {
|
|
||||||
(void) printf("%s[%u/%llu] ", tab_prefix, i + 1,
|
|
||||||
(u_longlong_t)lr->lr_nbps);
|
|
||||||
print_log_bp(&lr->lr_bps[i], "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
zil_prt_rec_clone_range_enc(zilog_t *zilog, int txtype, const void *arg)
|
|
||||||
{
|
|
||||||
(void) zilog, (void) txtype;
|
|
||||||
const lr_clone_range_t *lr = arg;
|
|
||||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
|
||||||
|
|
||||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
|
||||||
|
|
||||||
if (verbose < 4)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < lr->lr_nbps; i++) {
|
|
||||||
(void) printf("%s[%u/%llu] ", tab_prefix, i + 1,
|
|
||||||
(u_longlong_t)lr->lr_nbps);
|
|
||||||
print_log_bp(&lr->lr_bps[i], "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef void (*zil_prt_rec_func_t)(zilog_t *, int, const void *);
|
typedef void (*zil_prt_rec_func_t)(zilog_t *, int, const void *);
|
||||||
typedef struct zil_rec_info {
|
typedef struct zil_rec_info {
|
||||||
zil_prt_rec_func_t zri_print;
|
zil_prt_rec_func_t zri_print;
|
||||||
zil_prt_rec_func_t zri_print_enc;
|
|
||||||
const char *zri_name;
|
const char *zri_name;
|
||||||
uint64_t zri_count;
|
uint64_t zri_count;
|
||||||
} zil_rec_info_t;
|
} zil_rec_info_t;
|
||||||
@@ -394,9 +293,7 @@ static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
|||||||
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_RMDIR "},
|
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_RMDIR "},
|
||||||
{.zri_print = zil_prt_rec_link, .zri_name = "TX_LINK "},
|
{.zri_print = zil_prt_rec_link, .zri_name = "TX_LINK "},
|
||||||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME "},
|
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME "},
|
||||||
{.zri_print = zil_prt_rec_write,
|
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE "},
|
||||||
.zri_print_enc = zil_prt_rec_write_enc,
|
|
||||||
.zri_name = "TX_WRITE "},
|
|
||||||
{.zri_print = zil_prt_rec_truncate, .zri_name = "TX_TRUNCATE "},
|
{.zri_print = zil_prt_rec_truncate, .zri_name = "TX_TRUNCATE "},
|
||||||
{.zri_print = zil_prt_rec_setattr, .zri_name = "TX_SETATTR "},
|
{.zri_print = zil_prt_rec_setattr, .zri_name = "TX_SETATTR "},
|
||||||
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_V0 "},
|
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_V0 "},
|
||||||
@@ -408,19 +305,12 @@ static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
|||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ATTR "},
|
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ATTR "},
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ACL_ATTR "},
|
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ACL_ATTR "},
|
||||||
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE2 "},
|
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE2 "},
|
||||||
{.zri_print = zil_prt_rec_setsaxattr,
|
|
||||||
.zri_name = "TX_SETSAXATTR "},
|
|
||||||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME_EXCHANGE "},
|
|
||||||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME_WHITEOUT "},
|
|
||||||
{.zri_print = zil_prt_rec_clone_range,
|
|
||||||
.zri_print_enc = zil_prt_rec_clone_range_enc,
|
|
||||||
.zri_name = "TX_CLONE_RANGE "},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
||||||
{
|
{
|
||||||
(void) arg, (void) claim_txg;
|
|
||||||
int txtype;
|
int txtype;
|
||||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||||
|
|
||||||
@@ -440,8 +330,6 @@ print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
|||||||
if (txtype && verbose >= 3) {
|
if (txtype && verbose >= 3) {
|
||||||
if (!zilog->zl_os->os_encrypted) {
|
if (!zilog->zl_os->os_encrypted) {
|
||||||
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
|
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
|
||||||
} else if (zil_rec_info[txtype].zri_print_enc) {
|
|
||||||
zil_rec_info[txtype].zri_print_enc(zilog, txtype, lr);
|
|
||||||
} else {
|
} else {
|
||||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
(void) printf("%s(encrypted)\n", tab_prefix);
|
||||||
}
|
}
|
||||||
@@ -453,11 +341,11 @@ print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
|
print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
|
||||||
uint64_t claim_txg)
|
uint64_t claim_txg)
|
||||||
{
|
{
|
||||||
(void) arg;
|
|
||||||
char blkbuf[BP_SPRINTF_LEN + 10];
|
char blkbuf[BP_SPRINTF_LEN + 10];
|
||||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||||
const char *claim;
|
const char *claim;
|
||||||
@@ -475,7 +363,7 @@ print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
|
|||||||
|
|
||||||
if (claim_txg != 0)
|
if (claim_txg != 0)
|
||||||
claim = "already claimed";
|
claim = "already claimed";
|
||||||
else if (BP_GET_LOGICAL_BIRTH(bp) >= spa_min_claim_txg(zilog->zl_spa))
|
else if (bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa))
|
||||||
claim = "will claim";
|
claim = "will claim";
|
||||||
else
|
else
|
||||||
claim = "won't claim";
|
claim = "won't claim";
|
||||||
@@ -508,6 +396,7 @@ print_log_stats(int verbose)
|
|||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
dump_intent_log(zilog_t *zilog)
|
dump_intent_log(zilog_t *zilog)
|
||||||
{
|
{
|
||||||
|
|||||||
+44
-37
@@ -1,46 +1,53 @@
|
|||||||
include $(srcdir)/%D%/zed.d/Makefile.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
include $(top_srcdir)/config/Shellcheck.am
|
||||||
|
|
||||||
zed_CFLAGS = $(AM_CFLAGS)
|
AM_CFLAGS += $(LIBUDEV_CFLAGS) $(LIBUUID_CFLAGS)
|
||||||
zed_CFLAGS += $(LIBUDEV_CFLAGS) $(LIBUUID_CFLAGS)
|
|
||||||
|
|
||||||
sbin_PROGRAMS += zed
|
SUBDIRS = zed.d
|
||||||
CPPCHECKTARGETS += zed
|
SHELLCHECKDIRS = $(SUBDIRS)
|
||||||
|
|
||||||
zed_SOURCES = \
|
sbin_PROGRAMS = zed
|
||||||
%D%/zed.c \
|
|
||||||
%D%/zed.h \
|
ZED_SRC = \
|
||||||
%D%/zed_conf.c \
|
zed.c \
|
||||||
%D%/zed_conf.h \
|
zed.h \
|
||||||
%D%/zed_disk_event.c \
|
zed_conf.c \
|
||||||
%D%/zed_disk_event.h \
|
zed_conf.h \
|
||||||
%D%/zed_event.c \
|
zed_disk_event.c \
|
||||||
%D%/zed_event.h \
|
zed_disk_event.h \
|
||||||
%D%/zed_exec.c \
|
zed_event.c \
|
||||||
%D%/zed_exec.h \
|
zed_event.h \
|
||||||
%D%/zed_file.c \
|
zed_exec.c \
|
||||||
%D%/zed_file.h \
|
zed_exec.h \
|
||||||
%D%/zed_log.c \
|
zed_file.c \
|
||||||
%D%/zed_log.h \
|
zed_file.h \
|
||||||
%D%/zed_strings.c \
|
zed_log.c \
|
||||||
%D%/zed_strings.h \
|
zed_log.h \
|
||||||
\
|
zed_strings.c \
|
||||||
%D%/agents/fmd_api.c \
|
zed_strings.h
|
||||||
%D%/agents/fmd_api.h \
|
|
||||||
%D%/agents/fmd_serd.c \
|
FMA_SRC = \
|
||||||
%D%/agents/fmd_serd.h \
|
agents/zfs_agents.c \
|
||||||
%D%/agents/zfs_agents.c \
|
agents/zfs_agents.h \
|
||||||
%D%/agents/zfs_agents.h \
|
agents/zfs_diagnosis.c \
|
||||||
%D%/agents/zfs_diagnosis.c \
|
agents/zfs_mod.c \
|
||||||
%D%/agents/zfs_mod.c \
|
agents/zfs_retire.c \
|
||||||
%D%/agents/zfs_retire.c
|
agents/fmd_api.c \
|
||||||
|
agents/fmd_api.h \
|
||||||
|
agents/fmd_serd.c \
|
||||||
|
agents/fmd_serd.h
|
||||||
|
|
||||||
|
zed_SOURCES = $(ZED_SRC) $(FMA_SRC)
|
||||||
|
|
||||||
zed_LDADD = \
|
zed_LDADD = \
|
||||||
libzfs.la \
|
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||||
libzfs_core.la \
|
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||||
libnvpair.la \
|
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
libuutil.la
|
$(abs_top_builddir)/lib/libuutil/libuutil.la
|
||||||
|
|
||||||
zed_LDADD += -lrt $(LIBATOMIC_LIBS) $(LIBUDEV_LIBS) $(LIBUUID_LIBS)
|
zed_LDADD += -lrt $(LIBATOMIC_LIBS) $(LIBUDEV_LIBS) $(LIBUUID_LIBS)
|
||||||
zed_LDFLAGS = -pthread
|
zed_LDFLAGS = -pthread
|
||||||
|
|
||||||
dist_noinst_DATA += %D%/agents/README.md
|
EXTRA_DIST = agents/README.md
|
||||||
|
|
||||||
|
include $(top_srcdir)/config/CppCheck.am
|
||||||
|
|||||||
+45
-61
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016, Intel Corporation.
|
* Copyright (c) 2016, Intel Corporation.
|
||||||
* Copyright (c) 2023, Klara Inc.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -39,7 +38,7 @@
|
|||||||
#include <sys/fm/protocol.h>
|
#include <sys/fm/protocol.h>
|
||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <strings.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "fmd_api.h"
|
#include "fmd_api.h"
|
||||||
@@ -98,7 +97,6 @@ _umem_logging_init(void)
|
|||||||
int
|
int
|
||||||
fmd_hdl_register(fmd_hdl_t *hdl, int version, const fmd_hdl_info_t *mip)
|
fmd_hdl_register(fmd_hdl_t *hdl, int version, const fmd_hdl_info_t *mip)
|
||||||
{
|
{
|
||||||
(void) version;
|
|
||||||
fmd_module_t *mp = (fmd_module_t *)hdl;
|
fmd_module_t *mp = (fmd_module_t *)hdl;
|
||||||
|
|
||||||
mp->mod_info = mip;
|
mp->mod_info = mip;
|
||||||
@@ -181,21 +179,18 @@ fmd_hdl_getspecific(fmd_hdl_t *hdl)
|
|||||||
void *
|
void *
|
||||||
fmd_hdl_alloc(fmd_hdl_t *hdl, size_t size, int flags)
|
fmd_hdl_alloc(fmd_hdl_t *hdl, size_t size, int flags)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
return (umem_alloc(size, flags));
|
return (umem_alloc(size, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
fmd_hdl_zalloc(fmd_hdl_t *hdl, size_t size, int flags)
|
fmd_hdl_zalloc(fmd_hdl_t *hdl, size_t size, int flags)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
return (umem_zalloc(size, flags));
|
return (umem_zalloc(size, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fmd_hdl_free(fmd_hdl_t *hdl, void *data, size_t size)
|
fmd_hdl_free(fmd_hdl_t *hdl, void *data, size_t size)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
umem_free(data, size);
|
umem_free(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,8 +217,6 @@ fmd_hdl_debug(fmd_hdl_t *hdl, const char *format, ...)
|
|||||||
int32_t
|
int32_t
|
||||||
fmd_prop_get_int32(fmd_hdl_t *hdl, const char *name)
|
fmd_prop_get_int32(fmd_hdl_t *hdl, const char *name)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These can be looked up in mp->modinfo->fmdi_props
|
* These can be looked up in mp->modinfo->fmdi_props
|
||||||
* For now we just hard code for phase 2. In the
|
* For now we just hard code for phase 2. In the
|
||||||
@@ -232,6 +225,26 @@ fmd_prop_get_int32(fmd_hdl_t *hdl, const char *name)
|
|||||||
if (strcmp(name, "spare_on_remove") == 0)
|
if (strcmp(name, "spare_on_remove") == 0)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
|
if (strcmp(name, "io_N") == 0 || strcmp(name, "checksum_N") == 0)
|
||||||
|
return (10); /* N = 10 events */
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
fmd_prop_get_int64(fmd_hdl_t *hdl, const char *name)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* These can be looked up in mp->modinfo->fmdi_props
|
||||||
|
* For now we just hard code for phase 2. In the
|
||||||
|
* future, there can be a ZED based override.
|
||||||
|
*/
|
||||||
|
if (strcmp(name, "remove_timeout") == 0)
|
||||||
|
return (15ULL * 1000ULL * 1000ULL * 1000ULL); /* 15 sec */
|
||||||
|
|
||||||
|
if (strcmp(name, "io_T") == 0 || strcmp(name, "checksum_T") == 0)
|
||||||
|
return (1000ULL * 1000ULL * 1000ULL * 600ULL); /* 10 min */
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,24 +334,22 @@ fmd_case_uuresolved(fmd_hdl_t *hdl, const char *uuid)
|
|||||||
fmd_hdl_debug(hdl, "case resolved by uuid (%s)", uuid);
|
fmd_hdl_debug(hdl, "case resolved by uuid (%s)", uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean_t
|
int
|
||||||
fmd_case_solved(fmd_hdl_t *hdl, fmd_case_t *cp)
|
fmd_case_solved(fmd_hdl_t *hdl, fmd_case_t *cp)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
return ((cp->ci_state >= FMD_CASE_SOLVED) ? FMD_B_TRUE : FMD_B_FALSE);
|
||||||
return (cp->ci_state >= FMD_CASE_SOLVED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fmd_case_add_ereport(fmd_hdl_t *hdl, fmd_case_t *cp, fmd_event_t *ep)
|
fmd_case_add_ereport(fmd_hdl_t *hdl, fmd_case_t *cp, fmd_event_t *ep)
|
||||||
{
|
{
|
||||||
(void) hdl, (void) cp, (void) ep;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code)
|
zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code)
|
||||||
{
|
{
|
||||||
nvlist_t *rsrc;
|
nvlist_t *rsrc;
|
||||||
const char *strval;
|
char *strval;
|
||||||
uint64_t guid;
|
uint64_t guid;
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
|
|
||||||
@@ -351,7 +362,7 @@ zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code)
|
|||||||
if (code != NULL)
|
if (code != NULL)
|
||||||
zed_log_msg(LOG_INFO, "\t%s: %s", FM_SUSPECT_DIAG_CODE, code);
|
zed_log_msg(LOG_INFO, "\t%s: %s", FM_SUSPECT_DIAG_CODE, code);
|
||||||
if (nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &byte) == 0)
|
if (nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &byte) == 0)
|
||||||
zed_log_msg(LOG_INFO, "\t%s: %hhu", FM_FAULT_CERTAINTY, byte);
|
zed_log_msg(LOG_INFO, "\t%s: %llu", FM_FAULT_CERTAINTY, byte);
|
||||||
if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) {
|
if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) {
|
||||||
if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &strval) == 0)
|
if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &strval) == 0)
|
||||||
zed_log_msg(LOG_INFO, "\t%s: %s", FM_FMRI_SCHEME,
|
zed_log_msg(LOG_INFO, "\t%s: %s", FM_FMRI_SCHEME,
|
||||||
@@ -368,8 +379,7 @@ zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code)
|
|||||||
static const char *
|
static const char *
|
||||||
fmd_fault_mkcode(nvlist_t *fault)
|
fmd_fault_mkcode(nvlist_t *fault)
|
||||||
{
|
{
|
||||||
const char *class;
|
char *class, *code = "-";
|
||||||
const char *code = "-";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: message codes come from: openzfs/usr/src/cmd/fm/dicts/ZFS.po
|
* Note: message codes come from: openzfs/usr/src/cmd/fm/dicts/ZFS.po
|
||||||
@@ -418,8 +428,7 @@ fmd_case_add_suspect(fmd_hdl_t *hdl, fmd_case_t *cp, nvlist_t *fault)
|
|||||||
err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code);
|
err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code);
|
||||||
err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
|
err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2);
|
||||||
err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, 1);
|
err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, 1);
|
||||||
err |= nvlist_add_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST,
|
err |= nvlist_add_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST, &fault, 1);
|
||||||
(const nvlist_t **)&fault, 1);
|
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
zed_log_die("failed to populate nvlist");
|
zed_log_die("failed to populate nvlist");
|
||||||
@@ -434,21 +443,19 @@ fmd_case_add_suspect(fmd_hdl_t *hdl, fmd_case_t *cp, nvlist_t *fault)
|
|||||||
void
|
void
|
||||||
fmd_case_setspecific(fmd_hdl_t *hdl, fmd_case_t *cp, void *data)
|
fmd_case_setspecific(fmd_hdl_t *hdl, fmd_case_t *cp, void *data)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
cp->ci_data = data;
|
cp->ci_data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
fmd_case_getspecific(fmd_hdl_t *hdl, fmd_case_t *cp)
|
fmd_case_getspecific(fmd_hdl_t *hdl, fmd_case_t *cp)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
return (cp->ci_data);
|
return (cp->ci_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fmd_buf_create(fmd_hdl_t *hdl, fmd_case_t *cp, const char *name, size_t size)
|
fmd_buf_create(fmd_hdl_t *hdl, fmd_case_t *cp, const char *name, size_t size)
|
||||||
{
|
{
|
||||||
assert(strcmp(name, "data") == 0), (void) name;
|
assert(strcmp(name, "data") == 0);
|
||||||
assert(cp->ci_bufptr == NULL);
|
assert(cp->ci_bufptr == NULL);
|
||||||
assert(size < (1024 * 1024));
|
assert(size < (1024 * 1024));
|
||||||
|
|
||||||
@@ -460,24 +467,22 @@ void
|
|||||||
fmd_buf_read(fmd_hdl_t *hdl, fmd_case_t *cp,
|
fmd_buf_read(fmd_hdl_t *hdl, fmd_case_t *cp,
|
||||||
const char *name, void *buf, size_t size)
|
const char *name, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
assert(strcmp(name, "data") == 0);
|
||||||
assert(strcmp(name, "data") == 0), (void) name;
|
|
||||||
assert(cp->ci_bufptr != NULL);
|
assert(cp->ci_bufptr != NULL);
|
||||||
assert(size <= cp->ci_bufsiz);
|
assert(size <= cp->ci_bufsiz);
|
||||||
|
|
||||||
memcpy(buf, cp->ci_bufptr, size);
|
bcopy(cp->ci_bufptr, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fmd_buf_write(fmd_hdl_t *hdl, fmd_case_t *cp,
|
fmd_buf_write(fmd_hdl_t *hdl, fmd_case_t *cp,
|
||||||
const char *name, const void *buf, size_t size)
|
const char *name, const void *buf, size_t size)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
assert(strcmp(name, "data") == 0);
|
||||||
assert(strcmp(name, "data") == 0), (void) name;
|
|
||||||
assert(cp->ci_bufptr != NULL);
|
assert(cp->ci_bufptr != NULL);
|
||||||
assert(cp->ci_bufsiz >= size);
|
assert(cp->ci_bufsiz >= size);
|
||||||
|
|
||||||
memcpy(cp->ci_bufptr, buf, size);
|
bcopy(buf, cp->ci_bufptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SERD Engines */
|
/* SERD Engines */
|
||||||
@@ -514,19 +519,6 @@ fmd_serd_exists(fmd_hdl_t *hdl, const char *name)
|
|||||||
return (fmd_serd_eng_lookup(&mp->mod_serds, name) != NULL);
|
return (fmd_serd_eng_lookup(&mp->mod_serds, name) != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
fmd_serd_active(fmd_hdl_t *hdl, const char *name)
|
|
||||||
{
|
|
||||||
fmd_module_t *mp = (fmd_module_t *)hdl;
|
|
||||||
fmd_serd_eng_t *sgp;
|
|
||||||
|
|
||||||
if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
|
|
||||||
zed_log_msg(LOG_ERR, "serd engine '%s' does not exist", name);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
return (fmd_serd_eng_fired(sgp) || !fmd_serd_eng_empty(sgp));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
fmd_serd_reset(fmd_hdl_t *hdl, const char *name)
|
fmd_serd_reset(fmd_hdl_t *hdl, const char *name)
|
||||||
{
|
{
|
||||||
@@ -535,10 +527,12 @@ fmd_serd_reset(fmd_hdl_t *hdl, const char *name)
|
|||||||
|
|
||||||
if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
|
if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
|
||||||
zed_log_msg(LOG_ERR, "serd engine '%s' does not exist", name);
|
zed_log_msg(LOG_ERR, "serd engine '%s' does not exist", name);
|
||||||
} else {
|
return;
|
||||||
fmd_serd_eng_reset(sgp);
|
|
||||||
fmd_hdl_debug(hdl, "serd_reset %s", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmd_serd_eng_reset(sgp);
|
||||||
|
|
||||||
|
fmd_hdl_debug(hdl, "serd_reset %s", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -546,21 +540,16 @@ fmd_serd_record(fmd_hdl_t *hdl, const char *name, fmd_event_t *ep)
|
|||||||
{
|
{
|
||||||
fmd_module_t *mp = (fmd_module_t *)hdl;
|
fmd_module_t *mp = (fmd_module_t *)hdl;
|
||||||
fmd_serd_eng_t *sgp;
|
fmd_serd_eng_t *sgp;
|
||||||
|
int err;
|
||||||
|
|
||||||
if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
|
if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) {
|
||||||
zed_log_msg(LOG_ERR, "failed to add record to SERD engine '%s'",
|
zed_log_msg(LOG_ERR, "failed to add record to SERD engine '%s'",
|
||||||
name);
|
name);
|
||||||
return (0);
|
return (FMD_B_FALSE);
|
||||||
}
|
}
|
||||||
return (fmd_serd_eng_record(sgp, ep->ev_hrt));
|
err = fmd_serd_eng_record(sgp, ep->ev_hrt);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
return (err);
|
||||||
fmd_serd_gc(fmd_hdl_t *hdl)
|
|
||||||
{
|
|
||||||
fmd_module_t *mp = (fmd_module_t *)hdl;
|
|
||||||
|
|
||||||
fmd_serd_hash_apply(&mp->mod_serds, fmd_serd_eng_gc, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FMD Timers */
|
/* FMD Timers */
|
||||||
@@ -574,10 +563,10 @@ _timer_notify(union sigval sv)
|
|||||||
const fmd_hdl_ops_t *ops = mp->mod_info->fmdi_ops;
|
const fmd_hdl_ops_t *ops = mp->mod_info->fmdi_ops;
|
||||||
struct itimerspec its;
|
struct itimerspec its;
|
||||||
|
|
||||||
fmd_hdl_debug(hdl, "%s timer fired (%p)", mp->mod_name, ftp->ft_tid);
|
fmd_hdl_debug(hdl, "timer fired (%p)", ftp->ft_tid);
|
||||||
|
|
||||||
/* disarm the timer */
|
/* disarm the timer */
|
||||||
memset(&its, 0, sizeof (struct itimerspec));
|
bzero(&its, sizeof (struct itimerspec));
|
||||||
timer_settime(ftp->ft_tid, 0, &its, NULL);
|
timer_settime(ftp->ft_tid, 0, &its, NULL);
|
||||||
|
|
||||||
/* Note that the fmdo_timeout can remove this timer */
|
/* Note that the fmdo_timeout can remove this timer */
|
||||||
@@ -593,7 +582,6 @@ _timer_notify(union sigval sv)
|
|||||||
fmd_timer_t *
|
fmd_timer_t *
|
||||||
fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta)
|
fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta)
|
||||||
{
|
{
|
||||||
(void) ep;
|
|
||||||
struct sigevent sev;
|
struct sigevent sev;
|
||||||
struct itimerspec its;
|
struct itimerspec its;
|
||||||
fmd_timer_t *ftp;
|
fmd_timer_t *ftp;
|
||||||
@@ -611,7 +599,6 @@ fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta)
|
|||||||
sev.sigev_notify_function = _timer_notify;
|
sev.sigev_notify_function = _timer_notify;
|
||||||
sev.sigev_notify_attributes = NULL;
|
sev.sigev_notify_attributes = NULL;
|
||||||
sev.sigev_value.sival_ptr = ftp;
|
sev.sigev_value.sival_ptr = ftp;
|
||||||
sev.sigev_signo = 0;
|
|
||||||
|
|
||||||
timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid);
|
timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid);
|
||||||
timer_settime(ftp->ft_tid, 0, &its, NULL);
|
timer_settime(ftp->ft_tid, 0, &its, NULL);
|
||||||
@@ -638,7 +625,6 @@ nvlist_t *
|
|||||||
fmd_nvl_create_fault(fmd_hdl_t *hdl, const char *class, uint8_t certainty,
|
fmd_nvl_create_fault(fmd_hdl_t *hdl, const char *class, uint8_t certainty,
|
||||||
nvlist_t *asru, nvlist_t *fru, nvlist_t *resource)
|
nvlist_t *asru, nvlist_t *fru, nvlist_t *resource)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
nvlist_t *nvl;
|
nvlist_t *nvl;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@@ -702,8 +688,7 @@ fmd_strmatch(const char *s, const char *p)
|
|||||||
int
|
int
|
||||||
fmd_nvl_class_match(fmd_hdl_t *hdl, nvlist_t *nvl, const char *pattern)
|
fmd_nvl_class_match(fmd_hdl_t *hdl, nvlist_t *nvl, const char *pattern)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
char *class;
|
||||||
const char *class;
|
|
||||||
|
|
||||||
return (nvl != NULL &&
|
return (nvl != NULL &&
|
||||||
nvlist_lookup_string(nvl, FM_CLASS, &class) == 0 &&
|
nvlist_lookup_string(nvl, FM_CLASS, &class) == 0 &&
|
||||||
@@ -713,7 +698,6 @@ fmd_nvl_class_match(fmd_hdl_t *hdl, nvlist_t *nvl, const char *pattern)
|
|||||||
nvlist_t *
|
nvlist_t *
|
||||||
fmd_nvl_alloc(fmd_hdl_t *hdl, int flags)
|
fmd_nvl_alloc(fmd_hdl_t *hdl, int flags)
|
||||||
{
|
{
|
||||||
(void) hdl, (void) flags;
|
|
||||||
nvlist_t *nvl = NULL;
|
nvlist_t *nvl = NULL;
|
||||||
|
|
||||||
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
|
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -72,6 +72,10 @@ typedef struct fmd_case {
|
|||||||
} fmd_case_t;
|
} fmd_case_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define FMD_B_FALSE 0 /* false value for booleans as int */
|
||||||
|
#define FMD_B_TRUE 1 /* true value for booleans as int */
|
||||||
|
|
||||||
|
|
||||||
#define FMD_CASE_UNSOLVED 0 /* case is not yet solved (waiting) */
|
#define FMD_CASE_UNSOLVED 0 /* case is not yet solved (waiting) */
|
||||||
#define FMD_CASE_SOLVED 1 /* case is solved (suspects added) */
|
#define FMD_CASE_SOLVED 1 /* case is solved (suspects added) */
|
||||||
#define FMD_CASE_CLOSE_WAIT 2 /* case is executing fmdo_close() */
|
#define FMD_CASE_CLOSE_WAIT 2 /* case is executing fmdo_close() */
|
||||||
@@ -151,6 +155,7 @@ extern void fmd_hdl_vdebug(fmd_hdl_t *, const char *, va_list);
|
|||||||
extern void fmd_hdl_debug(fmd_hdl_t *, const char *, ...);
|
extern void fmd_hdl_debug(fmd_hdl_t *, const char *, ...);
|
||||||
|
|
||||||
extern int32_t fmd_prop_get_int32(fmd_hdl_t *, const char *);
|
extern int32_t fmd_prop_get_int32(fmd_hdl_t *, const char *);
|
||||||
|
extern int64_t fmd_prop_get_int64(fmd_hdl_t *, const char *);
|
||||||
|
|
||||||
#define FMD_STAT_NOALLOC 0x0 /* fmd should use caller's memory */
|
#define FMD_STAT_NOALLOC 0x0 /* fmd should use caller's memory */
|
||||||
#define FMD_STAT_ALLOC 0x1 /* fmd should allocate stats memory */
|
#define FMD_STAT_ALLOC 0x1 /* fmd should allocate stats memory */
|
||||||
@@ -171,7 +176,8 @@ extern int fmd_case_uuclosed(fmd_hdl_t *, const char *);
|
|||||||
extern int fmd_case_uuisresolved(fmd_hdl_t *, const char *);
|
extern int fmd_case_uuisresolved(fmd_hdl_t *, const char *);
|
||||||
extern void fmd_case_uuresolved(fmd_hdl_t *, const char *);
|
extern void fmd_case_uuresolved(fmd_hdl_t *, const char *);
|
||||||
|
|
||||||
extern boolean_t fmd_case_solved(fmd_hdl_t *, fmd_case_t *);
|
extern int fmd_case_solved(fmd_hdl_t *, fmd_case_t *);
|
||||||
|
extern int fmd_case_closed(fmd_hdl_t *, fmd_case_t *);
|
||||||
|
|
||||||
extern void fmd_case_add_ereport(fmd_hdl_t *, fmd_case_t *, fmd_event_t *);
|
extern void fmd_case_add_ereport(fmd_hdl_t *, fmd_case_t *, fmd_event_t *);
|
||||||
extern void fmd_case_add_serd(fmd_hdl_t *, fmd_case_t *, const char *);
|
extern void fmd_case_add_serd(fmd_hdl_t *, fmd_case_t *, const char *);
|
||||||
@@ -194,12 +200,10 @@ extern size_t fmd_buf_size(fmd_hdl_t *, fmd_case_t *, const char *);
|
|||||||
extern void fmd_serd_create(fmd_hdl_t *, const char *, uint_t, hrtime_t);
|
extern void fmd_serd_create(fmd_hdl_t *, const char *, uint_t, hrtime_t);
|
||||||
extern void fmd_serd_destroy(fmd_hdl_t *, const char *);
|
extern void fmd_serd_destroy(fmd_hdl_t *, const char *);
|
||||||
extern int fmd_serd_exists(fmd_hdl_t *, const char *);
|
extern int fmd_serd_exists(fmd_hdl_t *, const char *);
|
||||||
extern int fmd_serd_active(fmd_hdl_t *, const char *);
|
|
||||||
extern void fmd_serd_reset(fmd_hdl_t *, const char *);
|
extern void fmd_serd_reset(fmd_hdl_t *, const char *);
|
||||||
extern int fmd_serd_record(fmd_hdl_t *, const char *, fmd_event_t *);
|
extern int fmd_serd_record(fmd_hdl_t *, const char *, fmd_event_t *);
|
||||||
extern int fmd_serd_fired(fmd_hdl_t *, const char *);
|
extern int fmd_serd_fired(fmd_hdl_t *, const char *);
|
||||||
extern int fmd_serd_empty(fmd_hdl_t *, const char *);
|
extern int fmd_serd_empty(fmd_hdl_t *, const char *);
|
||||||
extern void fmd_serd_gc(fmd_hdl_t *);
|
|
||||||
|
|
||||||
extern id_t fmd_timer_install(fmd_hdl_t *, void *, fmd_event_t *, hrtime_t);
|
extern id_t fmd_timer_install(fmd_hdl_t *, void *, fmd_event_t *, hrtime_t);
|
||||||
extern void fmd_timer_remove(fmd_hdl_t *, id_t);
|
extern void fmd_timer_remove(fmd_hdl_t *, id_t);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* with the License.
|
* with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <strings.h>
|
||||||
#include <sys/list.h>
|
#include <sys/list.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
@@ -74,18 +74,9 @@ fmd_serd_eng_alloc(const char *name, uint64_t n, hrtime_t t)
|
|||||||
fmd_serd_eng_t *sgp;
|
fmd_serd_eng_t *sgp;
|
||||||
|
|
||||||
sgp = malloc(sizeof (fmd_serd_eng_t));
|
sgp = malloc(sizeof (fmd_serd_eng_t));
|
||||||
if (sgp == NULL) {
|
bzero(sgp, sizeof (fmd_serd_eng_t));
|
||||||
perror("malloc");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
memset(sgp, 0, sizeof (fmd_serd_eng_t));
|
|
||||||
|
|
||||||
sgp->sg_name = strdup(name);
|
sgp->sg_name = strdup(name);
|
||||||
if (sgp->sg_name == NULL) {
|
|
||||||
perror("strdup");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
sgp->sg_flags = FMD_SERD_DIRTY;
|
sgp->sg_flags = FMD_SERD_DIRTY;
|
||||||
sgp->sg_n = n;
|
sgp->sg_n = n;
|
||||||
sgp->sg_t = t;
|
sgp->sg_t = t;
|
||||||
@@ -132,12 +123,6 @@ fmd_serd_hash_create(fmd_serd_hash_t *shp)
|
|||||||
shp->sh_hashlen = FMD_STR_BUCKETS;
|
shp->sh_hashlen = FMD_STR_BUCKETS;
|
||||||
shp->sh_hash = calloc(shp->sh_hashlen, sizeof (void *));
|
shp->sh_hash = calloc(shp->sh_hashlen, sizeof (void *));
|
||||||
shp->sh_count = 0;
|
shp->sh_count = 0;
|
||||||
|
|
||||||
if (shp->sh_hash == NULL) {
|
|
||||||
perror("calloc");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -154,7 +139,7 @@ fmd_serd_hash_destroy(fmd_serd_hash_t *shp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(shp->sh_hash);
|
free(shp->sh_hash);
|
||||||
memset(shp, 0, sizeof (fmd_serd_hash_t));
|
bzero(shp, sizeof (fmd_serd_hash_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -249,17 +234,13 @@ fmd_serd_eng_record(fmd_serd_eng_t *sgp, hrtime_t hrt)
|
|||||||
if (sgp->sg_flags & FMD_SERD_FIRED) {
|
if (sgp->sg_flags & FMD_SERD_FIRED) {
|
||||||
serd_log_msg(" SERD Engine: record %s already fired!",
|
serd_log_msg(" SERD Engine: record %s already fired!",
|
||||||
sgp->sg_name);
|
sgp->sg_name);
|
||||||
return (B_FALSE);
|
return (FMD_B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sgp->sg_count >= sgp->sg_n)
|
while (sgp->sg_count >= sgp->sg_n)
|
||||||
fmd_serd_eng_discard(sgp, list_tail(&sgp->sg_list));
|
fmd_serd_eng_discard(sgp, list_tail(&sgp->sg_list));
|
||||||
|
|
||||||
sep = malloc(sizeof (fmd_serd_elem_t));
|
sep = malloc(sizeof (fmd_serd_elem_t));
|
||||||
if (sep == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
sep->se_hrt = hrt;
|
sep->se_hrt = hrt;
|
||||||
|
|
||||||
list_insert_head(&sgp->sg_list, sep);
|
list_insert_head(&sgp->sg_list, sep);
|
||||||
@@ -278,11 +259,11 @@ fmd_serd_eng_record(fmd_serd_eng_t *sgp, hrtime_t hrt)
|
|||||||
fmd_event_delta(oep->se_hrt, sep->se_hrt) <= sgp->sg_t) {
|
fmd_event_delta(oep->se_hrt, sep->se_hrt) <= sgp->sg_t) {
|
||||||
sgp->sg_flags |= FMD_SERD_FIRED | FMD_SERD_DIRTY;
|
sgp->sg_flags |= FMD_SERD_FIRED | FMD_SERD_DIRTY;
|
||||||
serd_log_msg(" SERD Engine: fired %s", sgp->sg_name);
|
serd_log_msg(" SERD Engine: fired %s", sgp->sg_name);
|
||||||
return (B_TRUE);
|
return (FMD_B_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
sgp->sg_flags |= FMD_SERD_DIRTY;
|
sgp->sg_flags |= FMD_SERD_DIRTY;
|
||||||
return (B_FALSE);
|
return (FMD_B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -310,9 +291,8 @@ fmd_serd_eng_reset(fmd_serd_eng_t *sgp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fmd_serd_eng_gc(fmd_serd_eng_t *sgp, void *arg)
|
fmd_serd_eng_gc(fmd_serd_eng_t *sgp)
|
||||||
{
|
{
|
||||||
(void) arg;
|
|
||||||
fmd_serd_elem_t *sep, *nep;
|
fmd_serd_elem_t *sep, *nep;
|
||||||
hrtime_t hrt;
|
hrtime_t hrt;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* with the License.
|
* with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -77,7 +77,7 @@ extern int fmd_serd_eng_fired(fmd_serd_eng_t *);
|
|||||||
extern int fmd_serd_eng_empty(fmd_serd_eng_t *);
|
extern int fmd_serd_eng_empty(fmd_serd_eng_t *);
|
||||||
|
|
||||||
extern void fmd_serd_eng_reset(fmd_serd_eng_t *);
|
extern void fmd_serd_eng_reset(fmd_serd_eng_t *);
|
||||||
extern void fmd_serd_eng_gc(fmd_serd_eng_t *, void *);
|
extern void fmd_serd_eng_gc(fmd_serd_eng_t *);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-46
@@ -64,7 +64,7 @@ typedef enum device_type {
|
|||||||
typedef struct guid_search {
|
typedef struct guid_search {
|
||||||
uint64_t gs_pool_guid;
|
uint64_t gs_pool_guid;
|
||||||
uint64_t gs_vdev_guid;
|
uint64_t gs_vdev_guid;
|
||||||
const char *gs_devid;
|
char *gs_devid;
|
||||||
device_type_t gs_vdev_type;
|
device_type_t gs_vdev_type;
|
||||||
uint64_t gs_vdev_expandtime; /* vdev expansion time */
|
uint64_t gs_vdev_expandtime; /* vdev expansion time */
|
||||||
} guid_search_t;
|
} guid_search_t;
|
||||||
@@ -77,10 +77,9 @@ static boolean_t
|
|||||||
zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||||
{
|
{
|
||||||
guid_search_t *gsp = arg;
|
guid_search_t *gsp = arg;
|
||||||
const char *path = NULL;
|
char *path = NULL;
|
||||||
uint_t c, children;
|
uint_t c, children;
|
||||||
nvlist_t **child;
|
nvlist_t **child;
|
||||||
uint64_t vdev_guid;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First iterate over any children.
|
* First iterate over any children.
|
||||||
@@ -101,7 +100,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
|||||||
&child, &children) == 0) {
|
&child, &children) == 0) {
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++) {
|
||||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
||||||
gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
|
gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
|
||||||
return (B_TRUE);
|
return (B_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +109,7 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
|||||||
&child, &children) == 0) {
|
&child, &children) == 0) {
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++) {
|
||||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
||||||
gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
|
gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
|
||||||
return (B_TRUE);
|
return (B_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,21 +126,6 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
|||||||
&gsp->gs_vdev_expandtime);
|
&gsp->gs_vdev_expandtime);
|
||||||
return (B_TRUE);
|
return (B_TRUE);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Otherwise, on a vdev guid match, grab the devid and expansion
|
|
||||||
* time. The devid might be missing on removal since its not part
|
|
||||||
* of blkid cache and L2ARC VDEV does not contain pool guid in its
|
|
||||||
* blkid, so this is a special case for L2ARC VDEV.
|
|
||||||
*/
|
|
||||||
else if (gsp->gs_vdev_guid != 0 && gsp->gs_devid == NULL &&
|
|
||||||
nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &vdev_guid) == 0 &&
|
|
||||||
gsp->gs_vdev_guid == vdev_guid) {
|
|
||||||
(void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID,
|
|
||||||
&gsp->gs_devid);
|
|
||||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
|
|
||||||
&gsp->gs_vdev_expandtime);
|
|
||||||
return (B_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (B_FALSE);
|
return (B_FALSE);
|
||||||
}
|
}
|
||||||
@@ -164,13 +148,13 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
|
|||||||
/*
|
/*
|
||||||
* if a match was found then grab the pool guid
|
* if a match was found then grab the pool guid
|
||||||
*/
|
*/
|
||||||
if (gsp->gs_vdev_guid && gsp->gs_devid) {
|
if (gsp->gs_vdev_guid) {
|
||||||
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
|
(void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
|
||||||
&gsp->gs_pool_guid);
|
&gsp->gs_pool_guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
return (gsp->gs_devid != NULL && gsp->gs_vdev_guid != 0);
|
return (gsp->gs_vdev_guid != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -211,13 +195,11 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
uint64_t pool_guid = 0, vdev_guid = 0;
|
uint64_t pool_guid = 0, vdev_guid = 0;
|
||||||
guid_search_t search = { 0 };
|
guid_search_t search = { 0 };
|
||||||
device_type_t devtype = DEVICE_TYPE_PRIMARY;
|
device_type_t devtype = DEVICE_TYPE_PRIMARY;
|
||||||
const char *devid = NULL;
|
|
||||||
|
|
||||||
class = "resource.fs.zfs.removed";
|
class = "resource.fs.zfs.removed";
|
||||||
subclass = "";
|
subclass = "";
|
||||||
|
|
||||||
(void) nvlist_add_string(payload, FM_CLASS, class);
|
(void) nvlist_add_string(payload, FM_CLASS, class);
|
||||||
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid);
|
|
||||||
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
|
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
|
||||||
(void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid);
|
(void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid);
|
||||||
|
|
||||||
@@ -227,24 +209,20 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
|
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If devid is missing but vdev_guid is available, find devid
|
|
||||||
* and pool_guid from vdev_guid.
|
|
||||||
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
|
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
|
||||||
* ZFS_EV_POOL_GUID may be missing so find them.
|
* ZFS_EV_POOL_GUID may be missing so find them.
|
||||||
*/
|
*/
|
||||||
if (devid == NULL || pool_guid == 0 || vdev_guid == 0) {
|
if (pool_guid == 0 || vdev_guid == 0) {
|
||||||
if (devid == NULL)
|
if ((nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
||||||
search.gs_vdev_guid = vdev_guid;
|
&search.gs_devid) == 0) &&
|
||||||
else
|
(zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search)
|
||||||
search.gs_devid = devid;
|
== 1)) {
|
||||||
zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
|
if (pool_guid == 0)
|
||||||
if (devid == NULL)
|
pool_guid = search.gs_pool_guid;
|
||||||
devid = search.gs_devid;
|
if (vdev_guid == 0)
|
||||||
if (pool_guid == 0)
|
vdev_guid = search.gs_vdev_guid;
|
||||||
pool_guid = search.gs_pool_guid;
|
devtype = search.gs_vdev_type;
|
||||||
if (vdev_guid == 0)
|
}
|
||||||
vdev_guid = search.gs_vdev_guid;
|
|
||||||
devtype = search.gs_vdev_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -257,9 +235,7 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
search.gs_vdev_expandtime + 10 > tv.tv_sec) {
|
search.gs_vdev_expandtime + 10 > tv.tv_sec) {
|
||||||
zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' "
|
zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' "
|
||||||
"for recently expanded device '%s'", EC_DEV_REMOVE,
|
"for recently expanded device '%s'", EC_DEV_REMOVE,
|
||||||
devid);
|
search.gs_devid);
|
||||||
fnvlist_free(payload);
|
|
||||||
free(event);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,8 +327,6 @@ zfs_agent_dispatch(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
static void *
|
static void *
|
||||||
zfs_agent_consumer_thread(void *arg)
|
zfs_agent_consumer_thread(void *arg)
|
||||||
{
|
{
|
||||||
(void) arg;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
agent_event_t *event;
|
agent_event_t *event;
|
||||||
|
|
||||||
@@ -369,7 +343,9 @@ zfs_agent_consumer_thread(void *arg)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((event = list_remove_head(&agent_events)) != NULL) {
|
if ((event = (list_head(&agent_events))) != NULL) {
|
||||||
|
list_remove(&agent_events, event);
|
||||||
|
|
||||||
(void) pthread_mutex_unlock(&agent_lock);
|
(void) pthread_mutex_unlock(&agent_lock);
|
||||||
|
|
||||||
/* dispatch to all event subscribers */
|
/* dispatch to all event subscribers */
|
||||||
@@ -432,7 +408,8 @@ zfs_agent_fini(void)
|
|||||||
(void) pthread_join(g_agents_tid, NULL);
|
(void) pthread_join(g_agents_tid, NULL);
|
||||||
|
|
||||||
/* drain any pending events */
|
/* drain any pending events */
|
||||||
while ((event = list_remove_head(&agent_events)) != NULL) {
|
while ((event = (list_head(&agent_events))) != NULL) {
|
||||||
|
list_remove(&agent_events, event);
|
||||||
nvlist_free(event->ae_nvl);
|
nvlist_free(event->ae_nvl);
|
||||||
free(event);
|
free(event);
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-248
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -23,11 +23,11 @@
|
|||||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2016, Intel Corporation.
|
* Copyright (c) 2016, Intel Corporation.
|
||||||
* Copyright (c) 2023, Klara Inc.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
#include <libuutil.h>
|
#include <libuutil.h>
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -35,29 +35,14 @@
|
|||||||
#include <sys/fs/zfs.h>
|
#include <sys/fs/zfs.h>
|
||||||
#include <sys/fm/protocol.h>
|
#include <sys/fm/protocol.h>
|
||||||
#include <sys/fm/fs/zfs.h>
|
#include <sys/fm/fs/zfs.h>
|
||||||
#include <sys/zio.h>
|
|
||||||
|
|
||||||
#include "zfs_agents.h"
|
#include "zfs_agents.h"
|
||||||
#include "fmd_api.h"
|
#include "fmd_api.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default values for the serd engine when processing checksum or io errors. The
|
* Our serd engines are named 'zfs_<pool_guid>_<vdev_guid>_{checksum,io}'. This
|
||||||
* semantics are N <events> in T <seconds>.
|
* #define reserves enough space for two 64-bit hex values plus the length of
|
||||||
*/
|
* the longest string.
|
||||||
#define DEFAULT_CHECKSUM_N 10 /* events */
|
|
||||||
#define DEFAULT_CHECKSUM_T 600 /* seconds */
|
|
||||||
#define DEFAULT_IO_N 10 /* events */
|
|
||||||
#define DEFAULT_IO_T 600 /* seconds */
|
|
||||||
#define DEFAULT_SLOW_IO_N 10 /* events */
|
|
||||||
#define DEFAULT_SLOW_IO_T 30 /* seconds */
|
|
||||||
|
|
||||||
#define CASE_GC_TIMEOUT_SECS 43200 /* 12 hours */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Our serd engines are named in the following format:
|
|
||||||
* 'zfs_<pool_guid>_<vdev_guid>_{checksum,io,slow_io}'
|
|
||||||
* This #define reserves enough space for two 64-bit hex values plus the
|
|
||||||
* length of the longest string.
|
|
||||||
*/
|
*/
|
||||||
#define MAX_SERDLEN (16 * 2 + sizeof ("zfs___checksum"))
|
#define MAX_SERDLEN (16 * 2 + sizeof ("zfs___checksum"))
|
||||||
|
|
||||||
@@ -71,11 +56,9 @@ typedef struct zfs_case_data {
|
|||||||
uint64_t zc_ena;
|
uint64_t zc_ena;
|
||||||
uint64_t zc_pool_guid;
|
uint64_t zc_pool_guid;
|
||||||
uint64_t zc_vdev_guid;
|
uint64_t zc_vdev_guid;
|
||||||
uint64_t zc_parent_guid;
|
|
||||||
int zc_pool_state;
|
int zc_pool_state;
|
||||||
char zc_serd_checksum[MAX_SERDLEN];
|
char zc_serd_checksum[MAX_SERDLEN];
|
||||||
char zc_serd_io[MAX_SERDLEN];
|
char zc_serd_io[MAX_SERDLEN];
|
||||||
char zc_serd_slow_io[MAX_SERDLEN];
|
|
||||||
int zc_has_remove_timer;
|
int zc_has_remove_timer;
|
||||||
} zfs_case_data_t;
|
} zfs_case_data_t;
|
||||||
|
|
||||||
@@ -122,8 +105,7 @@ zfs_de_stats_t zfs_stats = {
|
|||||||
{ "resource_drops", FMD_TYPE_UINT64, "resource related ereports" }
|
{ "resource_drops", FMD_TYPE_UINT64, "resource related ereports" }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* wait 15 seconds after a removal */
|
static hrtime_t zfs_remove_timeout;
|
||||||
static hrtime_t zfs_remove_timeout = SEC2NSEC(15);
|
|
||||||
|
|
||||||
uu_list_pool_t *zfs_case_pool;
|
uu_list_pool_t *zfs_case_pool;
|
||||||
uu_list_t *zfs_cases;
|
uu_list_t *zfs_cases;
|
||||||
@@ -133,13 +115,11 @@ uu_list_t *zfs_cases;
|
|||||||
#define ZFS_MAKE_EREPORT(type) \
|
#define ZFS_MAKE_EREPORT(type) \
|
||||||
FM_EREPORT_CLASS "." ZFS_ERROR_CLASS "." type
|
FM_EREPORT_CLASS "." ZFS_ERROR_CLASS "." type
|
||||||
|
|
||||||
static void zfs_purge_cases(fmd_hdl_t *hdl);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write out the persistent representation of an active case.
|
* Write out the persistent representation of an active case.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
zfs_case_serialize(zfs_case_t *zcp)
|
zfs_case_serialize(fmd_hdl_t *hdl, zfs_case_t *zcp)
|
||||||
{
|
{
|
||||||
zcp->zc_data.zc_version = CASE_DATA_VERSION_SERD;
|
zcp->zc_data.zc_version = CASE_DATA_VERSION_SERD;
|
||||||
}
|
}
|
||||||
@@ -181,64 +161,6 @@ zfs_case_unserialize(fmd_hdl_t *hdl, fmd_case_t *cp)
|
|||||||
return (zcp);
|
return (zcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Return count of other unique SERD cases under same vdev parent
|
|
||||||
*/
|
|
||||||
static uint_t
|
|
||||||
zfs_other_serd_cases(fmd_hdl_t *hdl, const zfs_case_data_t *zfs_case)
|
|
||||||
{
|
|
||||||
zfs_case_t *zcp;
|
|
||||||
uint_t cases = 0;
|
|
||||||
static hrtime_t next_check = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note that plumbing in some external GC would require adding locking,
|
|
||||||
* since most of this module code is not thread safe and assumes there
|
|
||||||
* is only one thread running against the module. So we perform GC here
|
|
||||||
* inline periodically so that future delay induced faults will be
|
|
||||||
* possible once the issue causing multiple vdev delays is resolved.
|
|
||||||
*/
|
|
||||||
if (gethrestime_sec() > next_check) {
|
|
||||||
/* Periodically purge old SERD entries and stale cases */
|
|
||||||
fmd_serd_gc(hdl);
|
|
||||||
zfs_purge_cases(hdl);
|
|
||||||
next_check = gethrestime_sec() + CASE_GC_TIMEOUT_SECS;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (zcp = uu_list_first(zfs_cases); zcp != NULL;
|
|
||||||
zcp = uu_list_next(zfs_cases, zcp)) {
|
|
||||||
zfs_case_data_t *zcd = &zcp->zc_data;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* must be same pool and parent vdev but different leaf vdev
|
|
||||||
*/
|
|
||||||
if (zcd->zc_pool_guid != zfs_case->zc_pool_guid ||
|
|
||||||
zcd->zc_parent_guid != zfs_case->zc_parent_guid ||
|
|
||||||
zcd->zc_vdev_guid == zfs_case->zc_vdev_guid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if there is another active serd case besides zfs_case
|
|
||||||
*
|
|
||||||
* Only one serd engine will be assigned to the case
|
|
||||||
*/
|
|
||||||
if (zcd->zc_serd_checksum[0] == zfs_case->zc_serd_checksum[0] &&
|
|
||||||
fmd_serd_active(hdl, zcd->zc_serd_checksum)) {
|
|
||||||
cases++;
|
|
||||||
}
|
|
||||||
if (zcd->zc_serd_io[0] == zfs_case->zc_serd_io[0] &&
|
|
||||||
fmd_serd_active(hdl, zcd->zc_serd_io)) {
|
|
||||||
cases++;
|
|
||||||
}
|
|
||||||
if (zcd->zc_serd_slow_io[0] == zfs_case->zc_serd_slow_io[0] &&
|
|
||||||
fmd_serd_active(hdl, zcd->zc_serd_slow_io)) {
|
|
||||||
cases++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (cases);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over any active cases. If any cases are associated with a pool or
|
* Iterate over any active cases. If any cases are associated with a pool or
|
||||||
* vdev which is no longer present on the system, close the associated case.
|
* vdev which is no longer present on the system, close the associated case.
|
||||||
@@ -287,10 +209,10 @@ zfs_mark_vdev(uint64_t pool_guid, nvlist_t *vd, er_timeval_t *loaded)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
static int
|
static int
|
||||||
zfs_mark_pool(zpool_handle_t *zhp, void *unused)
|
zfs_mark_pool(zpool_handle_t *zhp, void *unused)
|
||||||
{
|
{
|
||||||
(void) unused;
|
|
||||||
zfs_case_t *zcp;
|
zfs_case_t *zcp;
|
||||||
uint64_t pool_guid;
|
uint64_t pool_guid;
|
||||||
uint64_t *tod;
|
uint64_t *tod;
|
||||||
@@ -445,21 +367,14 @@ zfs_serd_name(char *buf, uint64_t pool_guid, uint64_t vdev_guid,
|
|||||||
(long long unsigned int)vdev_guid, type);
|
(long long unsigned int)vdev_guid, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
zfs_case_retire(fmd_hdl_t *hdl, zfs_case_t *zcp)
|
|
||||||
{
|
|
||||||
fmd_hdl_debug(hdl, "retiring case");
|
|
||||||
|
|
||||||
fmd_case_close(hdl, zcp->zc_case);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Solve a given ZFS case. This first checks to make sure the diagnosis is
|
* Solve a given ZFS case. This first checks to make sure the diagnosis is
|
||||||
* still valid, as well as cleaning up any pending timer associated with the
|
* still valid, as well as cleaning up any pending timer associated with the
|
||||||
* case.
|
* case.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname)
|
zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname,
|
||||||
|
boolean_t checkunusable)
|
||||||
{
|
{
|
||||||
nvlist_t *detector, *fault;
|
nvlist_t *detector, *fault;
|
||||||
boolean_t serialize;
|
boolean_t serialize;
|
||||||
@@ -497,7 +412,7 @@ zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname)
|
|||||||
serialize = B_TRUE;
|
serialize = B_TRUE;
|
||||||
}
|
}
|
||||||
if (serialize)
|
if (serialize)
|
||||||
zfs_case_serialize(zcp);
|
zfs_case_serialize(hdl, zcp);
|
||||||
|
|
||||||
nvlist_free(detector);
|
nvlist_free(detector);
|
||||||
}
|
}
|
||||||
@@ -509,10 +424,10 @@ timeval_earlier(er_timeval_t *a, er_timeval_t *b)
|
|||||||
(a->ertv_sec == b->ertv_sec && a->ertv_nsec < b->ertv_nsec));
|
(a->ertv_sec == b->ertv_sec && a->ertv_nsec < b->ertv_nsec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
static void
|
static void
|
||||||
zfs_ereport_when(fmd_hdl_t *hdl, nvlist_t *nvl, er_timeval_t *when)
|
zfs_ereport_when(fmd_hdl_t *hdl, nvlist_t *nvl, er_timeval_t *when)
|
||||||
{
|
{
|
||||||
(void) hdl;
|
|
||||||
int64_t *tod;
|
int64_t *tod;
|
||||||
uint_t nelem;
|
uint_t nelem;
|
||||||
|
|
||||||
@@ -525,51 +440,22 @@ zfs_ereport_when(fmd_hdl_t *hdl, nvlist_t *nvl, er_timeval_t *when)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Record the specified event in the SERD engine and return a
|
|
||||||
* boolean value indicating whether or not the engine fired as
|
|
||||||
* the result of inserting this event.
|
|
||||||
*
|
|
||||||
* When the pool has similar active cases on other vdevs, then
|
|
||||||
* the fired state is disregarded and the case is retired.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
zfs_fm_serd_record(fmd_hdl_t *hdl, const char *name, fmd_event_t *ep,
|
|
||||||
zfs_case_t *zcp, const char *err_type)
|
|
||||||
{
|
|
||||||
int fired = fmd_serd_record(hdl, name, ep);
|
|
||||||
int peers = 0;
|
|
||||||
|
|
||||||
if (fired && (peers = zfs_other_serd_cases(hdl, &zcp->zc_data)) > 0) {
|
|
||||||
fmd_hdl_debug(hdl, "pool %llu is tracking %d other %s cases "
|
|
||||||
"-- skip faulting the vdev %llu",
|
|
||||||
(u_longlong_t)zcp->zc_data.zc_pool_guid,
|
|
||||||
peers, err_type,
|
|
||||||
(u_longlong_t)zcp->zc_data.zc_vdev_guid);
|
|
||||||
zfs_case_retire(hdl, zcp);
|
|
||||||
fired = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (fired);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main fmd entry point.
|
* Main fmd entry point.
|
||||||
*/
|
*/
|
||||||
|
/*ARGSUSED*/
|
||||||
static void
|
static void
|
||||||
zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
||||||
{
|
{
|
||||||
zfs_case_t *zcp, *dcp;
|
zfs_case_t *zcp, *dcp;
|
||||||
int32_t pool_state;
|
int32_t pool_state;
|
||||||
uint64_t ena, pool_guid, vdev_guid, parent_guid;
|
uint64_t ena, pool_guid, vdev_guid;
|
||||||
uint64_t checksum_n, checksum_t;
|
|
||||||
uint64_t io_n, io_t;
|
|
||||||
er_timeval_t pool_load;
|
er_timeval_t pool_load;
|
||||||
er_timeval_t er_when;
|
er_timeval_t er_when;
|
||||||
nvlist_t *detector;
|
nvlist_t *detector;
|
||||||
boolean_t pool_found = B_FALSE;
|
boolean_t pool_found = B_FALSE;
|
||||||
boolean_t isresource;
|
boolean_t isresource;
|
||||||
const char *type;
|
char *type;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We subscribe to notifications for vdev or pool removal. In these
|
* We subscribe to notifications for vdev or pool removal. In these
|
||||||
@@ -651,9 +537,6 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
if (nvlist_lookup_uint64(nvl,
|
if (nvlist_lookup_uint64(nvl,
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
||||||
vdev_guid = 0;
|
vdev_guid = 0;
|
||||||
if (nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_PARENT_GUID, &parent_guid) != 0)
|
|
||||||
parent_guid = 0;
|
|
||||||
if (nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &ena) != 0)
|
if (nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &ena) != 0)
|
||||||
ena = 0;
|
ena = 0;
|
||||||
|
|
||||||
@@ -740,7 +623,9 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
if (strcmp(class,
|
if (strcmp(class,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DATA)) == 0 ||
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DATA)) == 0 ||
|
||||||
strcmp(class,
|
strcmp(class,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE)) == 0) {
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE)) == 0 ||
|
||||||
|
strcmp(class,
|
||||||
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DELAY)) == 0) {
|
||||||
zfs_stats.resource_drops.fmds_value.ui64++;
|
zfs_stats.resource_drops.fmds_value.ui64++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -764,7 +649,6 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
data.zc_ena = ena;
|
data.zc_ena = ena;
|
||||||
data.zc_pool_guid = pool_guid;
|
data.zc_pool_guid = pool_guid;
|
||||||
data.zc_vdev_guid = vdev_guid;
|
data.zc_vdev_guid = vdev_guid;
|
||||||
data.zc_parent_guid = parent_guid;
|
|
||||||
data.zc_pool_state = (int)pool_state;
|
data.zc_pool_state = (int)pool_state;
|
||||||
|
|
||||||
fmd_buf_write(hdl, cs, CASE_DATA, &data, sizeof (data));
|
fmd_buf_write(hdl, cs, CASE_DATA, &data, sizeof (data));
|
||||||
@@ -802,16 +686,13 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
if (zcp->zc_data.zc_has_remove_timer) {
|
if (zcp->zc_data.zc_has_remove_timer) {
|
||||||
fmd_timer_remove(hdl, zcp->zc_remove_timer);
|
fmd_timer_remove(hdl, zcp->zc_remove_timer);
|
||||||
zcp->zc_data.zc_has_remove_timer = 0;
|
zcp->zc_data.zc_has_remove_timer = 0;
|
||||||
zfs_case_serialize(zcp);
|
zfs_case_serialize(hdl, zcp);
|
||||||
}
|
}
|
||||||
if (zcp->zc_data.zc_serd_io[0] != '\0')
|
if (zcp->zc_data.zc_serd_io[0] != '\0')
|
||||||
fmd_serd_reset(hdl, zcp->zc_data.zc_serd_io);
|
fmd_serd_reset(hdl, zcp->zc_data.zc_serd_io);
|
||||||
if (zcp->zc_data.zc_serd_checksum[0] != '\0')
|
if (zcp->zc_data.zc_serd_checksum[0] != '\0')
|
||||||
fmd_serd_reset(hdl,
|
fmd_serd_reset(hdl,
|
||||||
zcp->zc_data.zc_serd_checksum);
|
zcp->zc_data.zc_serd_checksum);
|
||||||
if (zcp->zc_data.zc_serd_slow_io[0] != '\0')
|
|
||||||
fmd_serd_reset(hdl,
|
|
||||||
zcp->zc_data.zc_serd_slow_io);
|
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl,
|
} else if (fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_RSRC(FM_RESOURCE_STATECHANGE))) {
|
ZFS_MAKE_RSRC(FM_RESOURCE_STATECHANGE))) {
|
||||||
uint64_t state = 0;
|
uint64_t state = 0;
|
||||||
@@ -840,11 +721,7 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
if (fmd_case_solved(hdl, zcp->zc_case))
|
if (fmd_case_solved(hdl, zcp->zc_case))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (vdev_guid)
|
fmd_hdl_debug(hdl, "error event '%s'", class);
|
||||||
fmd_hdl_debug(hdl, "error event '%s', vdev %llu", class,
|
|
||||||
vdev_guid);
|
|
||||||
else
|
|
||||||
fmd_hdl_debug(hdl, "error event '%s'", class);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if we should solve the case and generate a fault. We solve
|
* Determine if we should solve the case and generate a fault. We solve
|
||||||
@@ -874,18 +751,18 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
fmd_case_close(hdl, dcp->zc_case);
|
fmd_case_close(hdl, dcp->zc_case);
|
||||||
}
|
}
|
||||||
|
|
||||||
zfs_case_solve(hdl, zcp, "fault.fs.zfs.pool");
|
zfs_case_solve(hdl, zcp, "fault.fs.zfs.pool", B_TRUE);
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl,
|
} else if (fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_LOG_REPLAY))) {
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_LOG_REPLAY))) {
|
||||||
/*
|
/*
|
||||||
* Pool level fault for reading the intent logs.
|
* Pool level fault for reading the intent logs.
|
||||||
*/
|
*/
|
||||||
zfs_case_solve(hdl, zcp, "fault.fs.zfs.log_replay");
|
zfs_case_solve(hdl, zcp, "fault.fs.zfs.log_replay", B_TRUE);
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl, "ereport.fs.zfs.vdev.*")) {
|
} else if (fmd_nvl_class_match(hdl, nvl, "ereport.fs.zfs.vdev.*")) {
|
||||||
/*
|
/*
|
||||||
* Device fault.
|
* Device fault.
|
||||||
*/
|
*/
|
||||||
zfs_case_solve(hdl, zcp, "fault.fs.zfs.device");
|
zfs_case_solve(hdl, zcp, "fault.fs.zfs.device", B_TRUE);
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl,
|
} else if (fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO)) ||
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO)) ||
|
||||||
fmd_nvl_class_match(hdl, nvl,
|
fmd_nvl_class_match(hdl, nvl,
|
||||||
@@ -893,12 +770,9 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
fmd_nvl_class_match(hdl, nvl,
|
fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO_FAILURE)) ||
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO_FAILURE)) ||
|
||||||
fmd_nvl_class_match(hdl, nvl,
|
fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DELAY)) ||
|
|
||||||
fmd_nvl_class_match(hdl, nvl,
|
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
|
||||||
const char *failmode = NULL;
|
char *failmode = NULL;
|
||||||
boolean_t checkremove = B_FALSE;
|
boolean_t checkremove = B_FALSE;
|
||||||
uint32_t pri = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is a checksum or I/O error, then toss it into the
|
* If this is a checksum or I/O error, then toss it into the
|
||||||
@@ -910,111 +784,30 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
if (fmd_nvl_class_match(hdl, nvl,
|
if (fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO))) {
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO))) {
|
||||||
if (zcp->zc_data.zc_serd_io[0] == '\0') {
|
if (zcp->zc_data.zc_serd_io[0] == '\0') {
|
||||||
if (nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_N,
|
|
||||||
&io_n) != 0) {
|
|
||||||
io_n = DEFAULT_IO_N;
|
|
||||||
}
|
|
||||||
if (nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_IO_T,
|
|
||||||
&io_t) != 0) {
|
|
||||||
io_t = DEFAULT_IO_T;
|
|
||||||
}
|
|
||||||
zfs_serd_name(zcp->zc_data.zc_serd_io,
|
zfs_serd_name(zcp->zc_data.zc_serd_io,
|
||||||
pool_guid, vdev_guid, "io");
|
pool_guid, vdev_guid, "io");
|
||||||
fmd_serd_create(hdl, zcp->zc_data.zc_serd_io,
|
fmd_serd_create(hdl, zcp->zc_data.zc_serd_io,
|
||||||
io_n,
|
fmd_prop_get_int32(hdl, "io_N"),
|
||||||
SEC2NSEC(io_t));
|
fmd_prop_get_int64(hdl, "io_T"));
|
||||||
zfs_case_serialize(zcp);
|
zfs_case_serialize(hdl, zcp);
|
||||||
}
|
}
|
||||||
if (zfs_fm_serd_record(hdl, zcp->zc_data.zc_serd_io,
|
if (fmd_serd_record(hdl, zcp->zc_data.zc_serd_io, ep))
|
||||||
ep, zcp, "io error")) {
|
|
||||||
checkremove = B_TRUE;
|
checkremove = B_TRUE;
|
||||||
}
|
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl,
|
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_DELAY))) {
|
|
||||||
uint64_t slow_io_n, slow_io_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a slow io SERD engine when the VDEV has the
|
|
||||||
* 'vdev_slow_io_n' and 'vdev_slow_io_n' properties.
|
|
||||||
*/
|
|
||||||
if (zcp->zc_data.zc_serd_slow_io[0] == '\0' &&
|
|
||||||
nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_N,
|
|
||||||
&slow_io_n) == 0 &&
|
|
||||||
nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_SLOW_IO_T,
|
|
||||||
&slow_io_t) == 0) {
|
|
||||||
zfs_serd_name(zcp->zc_data.zc_serd_slow_io,
|
|
||||||
pool_guid, vdev_guid, "slow_io");
|
|
||||||
fmd_serd_create(hdl,
|
|
||||||
zcp->zc_data.zc_serd_slow_io,
|
|
||||||
slow_io_n,
|
|
||||||
SEC2NSEC(slow_io_t));
|
|
||||||
zfs_case_serialize(zcp);
|
|
||||||
}
|
|
||||||
/* Pass event to SERD engine and see if this triggers */
|
|
||||||
if (zcp->zc_data.zc_serd_slow_io[0] != '\0' &&
|
|
||||||
zfs_fm_serd_record(hdl,
|
|
||||||
zcp->zc_data.zc_serd_slow_io, ep, zcp, "slow io")) {
|
|
||||||
zfs_case_solve(hdl, zcp,
|
|
||||||
"fault.fs.zfs.vdev.slow_io");
|
|
||||||
}
|
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl,
|
} else if (fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CHECKSUM))) {
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CHECKSUM))) {
|
||||||
uint64_t flags = 0;
|
|
||||||
int32_t flags32 = 0;
|
|
||||||
/*
|
|
||||||
* We ignore ereports for checksum errors generated by
|
|
||||||
* scrub/resilver I/O to avoid potentially further
|
|
||||||
* degrading the pool while it's being repaired.
|
|
||||||
*
|
|
||||||
* Note that FM_EREPORT_PAYLOAD_ZFS_ZIO_FLAGS used to
|
|
||||||
* be int32. To allow newer zed to work on older
|
|
||||||
* kernels, if we don't find the flags, we look for
|
|
||||||
* the older ones too.
|
|
||||||
*/
|
|
||||||
if (((nvlist_lookup_uint32(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_ZIO_PRIORITY, &pri) == 0) &&
|
|
||||||
(pri == ZIO_PRIORITY_SCRUB ||
|
|
||||||
pri == ZIO_PRIORITY_REBUILD)) ||
|
|
||||||
((nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_ZIO_FLAGS, &flags) == 0) &&
|
|
||||||
(flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER))) ||
|
|
||||||
((nvlist_lookup_int32(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_ZIO_FLAGS, &flags32) == 0) &&
|
|
||||||
(flags32 & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER)))) {
|
|
||||||
fmd_hdl_debug(hdl, "ignoring '%s' for "
|
|
||||||
"scrub/resilver I/O", class);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zcp->zc_data.zc_serd_checksum[0] == '\0') {
|
if (zcp->zc_data.zc_serd_checksum[0] == '\0') {
|
||||||
if (nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_N,
|
|
||||||
&checksum_n) != 0) {
|
|
||||||
checksum_n = DEFAULT_CHECKSUM_N;
|
|
||||||
}
|
|
||||||
if (nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_CKSUM_T,
|
|
||||||
&checksum_t) != 0) {
|
|
||||||
checksum_t = DEFAULT_CHECKSUM_T;
|
|
||||||
}
|
|
||||||
|
|
||||||
zfs_serd_name(zcp->zc_data.zc_serd_checksum,
|
zfs_serd_name(zcp->zc_data.zc_serd_checksum,
|
||||||
pool_guid, vdev_guid, "checksum");
|
pool_guid, vdev_guid, "checksum");
|
||||||
fmd_serd_create(hdl,
|
fmd_serd_create(hdl,
|
||||||
zcp->zc_data.zc_serd_checksum,
|
zcp->zc_data.zc_serd_checksum,
|
||||||
checksum_n,
|
fmd_prop_get_int32(hdl, "checksum_N"),
|
||||||
SEC2NSEC(checksum_t));
|
fmd_prop_get_int64(hdl, "checksum_T"));
|
||||||
zfs_case_serialize(zcp);
|
zfs_case_serialize(hdl, zcp);
|
||||||
}
|
}
|
||||||
if (zfs_fm_serd_record(hdl,
|
if (fmd_serd_record(hdl,
|
||||||
zcp->zc_data.zc_serd_checksum, ep, zcp,
|
zcp->zc_data.zc_serd_checksum, ep)) {
|
||||||
"checksum")) {
|
|
||||||
zfs_case_solve(hdl, zcp,
|
zfs_case_solve(hdl, zcp,
|
||||||
"fault.fs.zfs.vdev.checksum");
|
"fault.fs.zfs.vdev.checksum", B_FALSE);
|
||||||
}
|
}
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl,
|
} else if (fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO_FAILURE)) &&
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO_FAILURE)) &&
|
||||||
@@ -1024,11 +817,12 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
if (strncmp(failmode, FM_EREPORT_FAILMODE_CONTINUE,
|
if (strncmp(failmode, FM_EREPORT_FAILMODE_CONTINUE,
|
||||||
strlen(FM_EREPORT_FAILMODE_CONTINUE)) == 0) {
|
strlen(FM_EREPORT_FAILMODE_CONTINUE)) == 0) {
|
||||||
zfs_case_solve(hdl, zcp,
|
zfs_case_solve(hdl, zcp,
|
||||||
"fault.fs.zfs.io_failure_continue");
|
"fault.fs.zfs.io_failure_continue",
|
||||||
|
B_FALSE);
|
||||||
} else if (strncmp(failmode, FM_EREPORT_FAILMODE_WAIT,
|
} else if (strncmp(failmode, FM_EREPORT_FAILMODE_WAIT,
|
||||||
strlen(FM_EREPORT_FAILMODE_WAIT)) == 0) {
|
strlen(FM_EREPORT_FAILMODE_WAIT)) == 0) {
|
||||||
zfs_case_solve(hdl, zcp,
|
zfs_case_solve(hdl, zcp,
|
||||||
"fault.fs.zfs.io_failure_wait");
|
"fault.fs.zfs.io_failure_wait", B_FALSE);
|
||||||
}
|
}
|
||||||
} else if (fmd_nvl_class_match(hdl, nvl,
|
} else if (fmd_nvl_class_match(hdl, nvl,
|
||||||
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
|
ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
|
||||||
@@ -1050,7 +844,7 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
zfs_remove_timeout);
|
zfs_remove_timeout);
|
||||||
if (!zcp->zc_data.zc_has_remove_timer) {
|
if (!zcp->zc_data.zc_has_remove_timer) {
|
||||||
zcp->zc_data.zc_has_remove_timer = 1;
|
zcp->zc_data.zc_has_remove_timer = 1;
|
||||||
zfs_case_serialize(zcp);
|
zfs_case_serialize(hdl, zcp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1060,13 +854,14 @@ zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
|
|||||||
* The timeout is fired when we diagnosed an I/O error, and it was not due to
|
* The timeout is fired when we diagnosed an I/O error, and it was not due to
|
||||||
* device removal (which would cause the timeout to be cancelled).
|
* device removal (which would cause the timeout to be cancelled).
|
||||||
*/
|
*/
|
||||||
|
/* ARGSUSED */
|
||||||
static void
|
static void
|
||||||
zfs_fm_timeout(fmd_hdl_t *hdl, id_t id, void *data)
|
zfs_fm_timeout(fmd_hdl_t *hdl, id_t id, void *data)
|
||||||
{
|
{
|
||||||
zfs_case_t *zcp = data;
|
zfs_case_t *zcp = data;
|
||||||
|
|
||||||
if (id == zcp->zc_remove_timer)
|
if (id == zcp->zc_remove_timer)
|
||||||
zfs_case_solve(hdl, zcp, "fault.fs.zfs.vdev.io");
|
zfs_case_solve(hdl, zcp, "fault.fs.zfs.vdev.io", B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1082,8 +877,6 @@ zfs_fm_close(fmd_hdl_t *hdl, fmd_case_t *cs)
|
|||||||
fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_checksum);
|
fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_checksum);
|
||||||
if (zcp->zc_data.zc_serd_io[0] != '\0')
|
if (zcp->zc_data.zc_serd_io[0] != '\0')
|
||||||
fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_io);
|
fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_io);
|
||||||
if (zcp->zc_data.zc_serd_slow_io[0] != '\0')
|
|
||||||
fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_slow_io);
|
|
||||||
if (zcp->zc_data.zc_has_remove_timer)
|
if (zcp->zc_data.zc_has_remove_timer)
|
||||||
fmd_timer_remove(hdl, zcp->zc_remove_timer);
|
fmd_timer_remove(hdl, zcp->zc_remove_timer);
|
||||||
|
|
||||||
@@ -1092,15 +885,30 @@ zfs_fm_close(fmd_hdl_t *hdl, fmd_case_t *cs)
|
|||||||
fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
|
fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use the fmd gc entry point to look for old cases that no longer apply.
|
||||||
|
* This allows us to keep our set of case data small in a long running system.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
zfs_fm_gc(fmd_hdl_t *hdl)
|
||||||
|
{
|
||||||
|
zfs_purge_cases(hdl);
|
||||||
|
}
|
||||||
|
|
||||||
static const fmd_hdl_ops_t fmd_ops = {
|
static const fmd_hdl_ops_t fmd_ops = {
|
||||||
zfs_fm_recv, /* fmdo_recv */
|
zfs_fm_recv, /* fmdo_recv */
|
||||||
zfs_fm_timeout, /* fmdo_timeout */
|
zfs_fm_timeout, /* fmdo_timeout */
|
||||||
zfs_fm_close, /* fmdo_close */
|
zfs_fm_close, /* fmdo_close */
|
||||||
NULL, /* fmdo_stats */
|
NULL, /* fmdo_stats */
|
||||||
NULL, /* fmdo_gc */
|
zfs_fm_gc, /* fmdo_gc */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const fmd_prop_t fmd_props[] = {
|
static const fmd_prop_t fmd_props[] = {
|
||||||
|
{ "checksum_N", FMD_TYPE_UINT32, "10" },
|
||||||
|
{ "checksum_T", FMD_TYPE_TIME, "10min" },
|
||||||
|
{ "io_N", FMD_TYPE_UINT32, "10" },
|
||||||
|
{ "io_T", FMD_TYPE_TIME, "10min" },
|
||||||
|
{ "remove_timeout", FMD_TYPE_TIME, "15sec" },
|
||||||
{ NULL, 0, NULL }
|
{ NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1141,6 +949,8 @@ _zfs_diagnosis_init(fmd_hdl_t *hdl)
|
|||||||
|
|
||||||
(void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (zfs_stats) /
|
(void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (zfs_stats) /
|
||||||
sizeof (fmd_stat_t), (fmd_stat_t *)&zfs_stats);
|
sizeof (fmd_stat_t), (fmd_stat_t *)&zfs_stats);
|
||||||
|
|
||||||
|
zfs_remove_timeout = fmd_prop_get_int64(hdl, "remove_timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
+75
-307
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -24,7 +24,6 @@
|
|||||||
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2016, 2017, Intel Corporation.
|
* Copyright (c) 2016, 2017, Intel Corporation.
|
||||||
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||||
* Copyright (c) 2023, Klara Inc.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -134,11 +133,6 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
|
|||||||
if (zfs_toplevel_state(zhp) < VDEV_STATE_DEGRADED) {
|
if (zfs_toplevel_state(zhp) < VDEV_STATE_DEGRADED) {
|
||||||
unavailpool_t *uap;
|
unavailpool_t *uap;
|
||||||
uap = malloc(sizeof (unavailpool_t));
|
uap = malloc(sizeof (unavailpool_t));
|
||||||
if (uap == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
uap->uap_zhp = zhp;
|
uap->uap_zhp = zhp;
|
||||||
list_insert_tail((list_t *)data, uap);
|
list_insert_tail((list_t *)data, uap);
|
||||||
} else {
|
} else {
|
||||||
@@ -147,17 +141,6 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Write an array of strings to the zed log
|
|
||||||
*/
|
|
||||||
static void lines_to_zed_log_msg(char **lines, int lines_cnt)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < lines_cnt; i++) {
|
|
||||||
zed_log_msg(LOG_INFO, "%s", lines[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Two stage replace on Linux
|
* Two stage replace on Linux
|
||||||
* since we get disk notifications
|
* since we get disk notifications
|
||||||
@@ -195,31 +178,22 @@ static void lines_to_zed_log_msg(char **lines, int lines_cnt)
|
|||||||
static void
|
static void
|
||||||
zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||||
{
|
{
|
||||||
const char *path;
|
char *path;
|
||||||
vdev_state_t newstate;
|
vdev_state_t newstate;
|
||||||
nvlist_t *nvroot, *newvd;
|
nvlist_t *nvroot, *newvd;
|
||||||
pendingdev_t *device;
|
pendingdev_t *device;
|
||||||
uint64_t wholedisk = 0ULL;
|
uint64_t wholedisk = 0ULL;
|
||||||
uint64_t offline = 0ULL, faulted = 0ULL;
|
uint64_t offline = 0ULL, faulted = 0ULL;
|
||||||
uint64_t guid = 0ULL;
|
uint64_t guid = 0ULL;
|
||||||
uint64_t is_spare = 0;
|
char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL;
|
||||||
const char *physpath = NULL, *new_devid = NULL, *enc_sysfs_path = NULL;
|
|
||||||
char rawpath[PATH_MAX], fullpath[PATH_MAX];
|
char rawpath[PATH_MAX], fullpath[PATH_MAX];
|
||||||
char pathbuf[PATH_MAX];
|
char devpath[PATH_MAX];
|
||||||
int ret;
|
int ret;
|
||||||
int online_flag = ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE;
|
|
||||||
boolean_t is_sd = B_FALSE;
|
boolean_t is_sd = B_FALSE;
|
||||||
boolean_t is_mpath_wholedisk = B_FALSE;
|
boolean_t is_mpath_wholedisk = B_FALSE;
|
||||||
uint_t c;
|
uint_t c;
|
||||||
vdev_stat_t *vs;
|
vdev_stat_t *vs;
|
||||||
char **lines = NULL;
|
|
||||||
int lines_cnt = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the persistent path, typically under the '/dev/disk/by-id' or
|
|
||||||
* '/dev/disk/by-vdev' directories. Note that this path can change
|
|
||||||
* when a vdev is replaced with a new disk.
|
|
||||||
*/
|
|
||||||
if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0)
|
if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -233,18 +207,13 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_PHYS_PATH, &physpath);
|
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_PHYS_PATH, &physpath);
|
||||||
|
|
||||||
update_vdev_config_dev_sysfs_path(vdev, path,
|
|
||||||
ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
|
|
||||||
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
|
(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
|
||||||
&enc_sysfs_path);
|
&enc_sysfs_path);
|
||||||
|
|
||||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
|
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
|
||||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_OFFLINE, &offline);
|
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_OFFLINE, &offline);
|
||||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_FAULTED, &faulted);
|
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_FAULTED, &faulted);
|
||||||
|
|
||||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &guid);
|
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_GUID, &guid);
|
||||||
(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_IS_SPARE, &is_spare);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special case:
|
* Special case:
|
||||||
@@ -335,13 +304,11 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_spare)
|
|
||||||
online_flag |= ZFS_ONLINE_SPARE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to online the device.
|
* Attempt to online the device.
|
||||||
*/
|
*/
|
||||||
if (zpool_vdev_online(zhp, fullpath, online_flag, &newstate) == 0 &&
|
if (zpool_vdev_online(zhp, fullpath,
|
||||||
|
ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE, &newstate) == 0 &&
|
||||||
(newstate == VDEV_STATE_HEALTHY ||
|
(newstate == VDEV_STATE_HEALTHY ||
|
||||||
newstate == VDEV_STATE_DEGRADED)) {
|
newstate == VDEV_STATE_DEGRADED)) {
|
||||||
zed_log_msg(LOG_INFO,
|
zed_log_msg(LOG_INFO,
|
||||||
@@ -380,27 +347,24 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
(void) snprintf(rawpath, sizeof (rawpath), "%s%s",
|
(void) snprintf(rawpath, sizeof (rawpath), "%s%s",
|
||||||
is_sd ? DEV_BYVDEV_PATH : DEV_BYPATH_PATH, physpath);
|
is_sd ? DEV_BYVDEV_PATH : DEV_BYPATH_PATH, physpath);
|
||||||
|
|
||||||
if (realpath(rawpath, pathbuf) == NULL && !is_mpath_wholedisk) {
|
if (realpath(rawpath, devpath) == NULL && !is_mpath_wholedisk) {
|
||||||
zed_log_msg(LOG_INFO, " realpath: %s failed (%s)",
|
zed_log_msg(LOG_INFO, " realpath: %s failed (%s)",
|
||||||
rawpath, strerror(errno));
|
rawpath, strerror(errno));
|
||||||
|
|
||||||
int err = zpool_vdev_online(zhp, fullpath,
|
(void) zpool_vdev_online(zhp, fullpath, ZFS_ONLINE_FORCEFAULT,
|
||||||
ZFS_ONLINE_FORCEFAULT, &newstate);
|
&newstate);
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO, " zpool_vdev_online: %s FORCEFAULT (%s) "
|
zed_log_msg(LOG_INFO, " zpool_vdev_online: %s FORCEFAULT (%s)",
|
||||||
"err %d, new state %d",
|
fullpath, libzfs_error_description(g_zfshdl));
|
||||||
fullpath, libzfs_error_description(g_zfshdl), err,
|
|
||||||
err ? (int)newstate : 0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only autoreplace bad disks */
|
/* Only autoreplace bad disks */
|
||||||
if ((vs->vs_state != VDEV_STATE_DEGRADED) &&
|
if ((vs->vs_state != VDEV_STATE_DEGRADED) &&
|
||||||
(vs->vs_state != VDEV_STATE_FAULTED) &&
|
(vs->vs_state != VDEV_STATE_FAULTED) &&
|
||||||
(vs->vs_state != VDEV_STATE_REMOVED) &&
|
|
||||||
(vs->vs_state != VDEV_STATE_CANT_OPEN)) {
|
(vs->vs_state != VDEV_STATE_CANT_OPEN)) {
|
||||||
zed_log_msg(LOG_INFO, " not autoreplacing since disk isn't in "
|
zed_log_msg(LOG_INFO, " not autoreplacing since disk isn't in "
|
||||||
"a bad state (currently %llu)", vs->vs_state);
|
"a bad state (currently %d)", vs->vs_state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,22 +372,6 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
|
|
||||||
if (is_mpath_wholedisk) {
|
if (is_mpath_wholedisk) {
|
||||||
/* Don't label device mapper or multipath disks. */
|
/* Don't label device mapper or multipath disks. */
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
" it's a multipath wholedisk, don't label");
|
|
||||||
if (zpool_prepare_disk(zhp, vdev, "autoreplace", &lines,
|
|
||||||
&lines_cnt) != 0) {
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
" zpool_prepare_disk: could not "
|
|
||||||
"prepare '%s' (%s)", fullpath,
|
|
||||||
libzfs_error_description(g_zfshdl));
|
|
||||||
if (lines_cnt > 0) {
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
" zfs_prepare_disk output:");
|
|
||||||
lines_to_zed_log_msg(lines, lines_cnt);
|
|
||||||
}
|
|
||||||
libzfs_free_str_array(lines, lines_cnt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (!labeled) {
|
} else if (!labeled) {
|
||||||
/*
|
/*
|
||||||
* we're auto-replacing a raw disk, so label it first
|
* we're auto-replacing a raw disk, so label it first
|
||||||
@@ -440,24 +388,16 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
* to trigger a ZFS fault for the device (and any hot spare
|
* to trigger a ZFS fault for the device (and any hot spare
|
||||||
* replacement).
|
* replacement).
|
||||||
*/
|
*/
|
||||||
leafname = strrchr(pathbuf, '/') + 1;
|
leafname = strrchr(devpath, '/') + 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is a request to label a whole disk, then attempt to
|
* If this is a request to label a whole disk, then attempt to
|
||||||
* write out the label.
|
* write out the label.
|
||||||
*/
|
*/
|
||||||
if (zpool_prepare_and_label_disk(g_zfshdl, zhp, leafname,
|
if (zpool_label_disk(g_zfshdl, zhp, leafname) != 0) {
|
||||||
vdev, "autoreplace", &lines, &lines_cnt) != 0) {
|
zed_log_msg(LOG_INFO, " zpool_label_disk: could not "
|
||||||
zed_log_msg(LOG_WARNING,
|
|
||||||
" zpool_prepare_and_label_disk: could not "
|
|
||||||
"label '%s' (%s)", leafname,
|
"label '%s' (%s)", leafname,
|
||||||
libzfs_error_description(g_zfshdl));
|
libzfs_error_description(g_zfshdl));
|
||||||
if (lines_cnt > 0) {
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
" zfs_prepare_disk output:");
|
|
||||||
lines_to_zed_log_msg(lines, lines_cnt);
|
|
||||||
}
|
|
||||||
libzfs_free_str_array(lines, lines_cnt);
|
|
||||||
|
|
||||||
(void) zpool_vdev_online(zhp, fullpath,
|
(void) zpool_vdev_online(zhp, fullpath,
|
||||||
ZFS_ONLINE_FORCEFAULT, &newstate);
|
ZFS_ONLINE_FORCEFAULT, &newstate);
|
||||||
@@ -471,16 +411,11 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
* completed.
|
* completed.
|
||||||
*/
|
*/
|
||||||
device = malloc(sizeof (pendingdev_t));
|
device = malloc(sizeof (pendingdev_t));
|
||||||
if (device == NULL) {
|
|
||||||
perror("malloc");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) strlcpy(device->pd_physpath, physpath,
|
(void) strlcpy(device->pd_physpath, physpath,
|
||||||
sizeof (device->pd_physpath));
|
sizeof (device->pd_physpath));
|
||||||
list_insert_tail(&g_device_list, device);
|
list_insert_tail(&g_device_list, device);
|
||||||
|
|
||||||
zed_log_msg(LOG_NOTICE, " zpool_label_disk: async '%s' (%llu)",
|
zed_log_msg(LOG_INFO, " zpool_label_disk: async '%s' (%llu)",
|
||||||
leafname, (u_longlong_t)guid);
|
leafname, (u_longlong_t)guid);
|
||||||
|
|
||||||
return; /* resumes at EC_DEV_ADD.ESC_DISK for partition */
|
return; /* resumes at EC_DEV_ADD.ESC_DISK for partition */
|
||||||
@@ -503,8 +438,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
/* unexpected partition slice encountered */
|
/* unexpected partition slice encountered */
|
||||||
zed_log_msg(LOG_WARNING, "labeled disk %s was "
|
zed_log_msg(LOG_INFO, "labeled disk %s unexpected here",
|
||||||
"unexpected here", fullpath);
|
fullpath);
|
||||||
(void) zpool_vdev_online(zhp, fullpath,
|
(void) zpool_vdev_online(zhp, fullpath,
|
||||||
ZFS_ONLINE_FORCEFAULT, &newstate);
|
ZFS_ONLINE_FORCEFAULT, &newstate);
|
||||||
return;
|
return;
|
||||||
@@ -513,21 +448,10 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
zed_log_msg(LOG_INFO, " zpool_label_disk: resume '%s' (%llu)",
|
zed_log_msg(LOG_INFO, " zpool_label_disk: resume '%s' (%llu)",
|
||||||
physpath, (u_longlong_t)guid);
|
physpath, (u_longlong_t)guid);
|
||||||
|
|
||||||
/*
|
(void) snprintf(devpath, sizeof (devpath), "%s%s",
|
||||||
* Paths that begin with '/dev/disk/by-id/' will change and so
|
DEV_BYID_PATH, new_devid);
|
||||||
* they must be updated before calling zpool_vdev_attach().
|
|
||||||
*/
|
|
||||||
if (strncmp(path, DEV_BYID_PATH, strlen(DEV_BYID_PATH)) == 0) {
|
|
||||||
(void) snprintf(pathbuf, sizeof (pathbuf), "%s%s",
|
|
||||||
DEV_BYID_PATH, new_devid);
|
|
||||||
zed_log_msg(LOG_INFO, " zpool_label_disk: path '%s' "
|
|
||||||
"replaced by '%s'", path, pathbuf);
|
|
||||||
path = pathbuf;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
libzfs_free_str_array(lines, lines_cnt);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct the root vdev to pass to zpool_vdev_attach(). While adding
|
* Construct the root vdev to pass to zpool_vdev_attach(). While adding
|
||||||
* the entire vdev structure is harmless, we construct a reduced set of
|
* the entire vdev structure is harmless, we construct a reduced set of
|
||||||
@@ -552,8 +476,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH, enc_sysfs_path) != 0) ||
|
ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH, enc_sysfs_path) != 0) ||
|
||||||
nvlist_add_uint64(newvd, ZPOOL_CONFIG_WHOLE_DISK, wholedisk) != 0 ||
|
nvlist_add_uint64(newvd, ZPOOL_CONFIG_WHOLE_DISK, wholedisk) != 0 ||
|
||||||
nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) != 0 ||
|
nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) != 0 ||
|
||||||
nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
|
nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &newvd,
|
||||||
(const nvlist_t **)&newvd, 1) != 0) {
|
1) != 0) {
|
||||||
zed_log_msg(LOG_WARNING, "zfs_mod: unable to add nvlist pairs");
|
zed_log_msg(LOG_WARNING, "zfs_mod: unable to add nvlist pairs");
|
||||||
nvlist_free(newvd);
|
nvlist_free(newvd);
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
@@ -566,11 +490,9 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
* Wait for udev to verify the links exist, then auto-replace
|
* Wait for udev to verify the links exist, then auto-replace
|
||||||
* the leaf disk at same physical location.
|
* the leaf disk at same physical location.
|
||||||
*/
|
*/
|
||||||
if (zpool_label_disk_wait(path, DISK_LABEL_WAIT) != 0) {
|
if (zpool_label_disk_wait(path, 3000) != 0) {
|
||||||
zed_log_msg(LOG_WARNING, "zfs_mod: pool '%s', after labeling "
|
zed_log_msg(LOG_WARNING, "zfs_mod: expected replacement "
|
||||||
"replacement disk, the expected disk partition link '%s' "
|
"disk %s is missing", path);
|
||||||
"is missing after waiting %u ms",
|
|
||||||
zpool_get_name(zhp), path, DISK_LABEL_WAIT);
|
|
||||||
nvlist_free(nvroot);
|
nvlist_free(nvroot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -585,7 +507,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
B_TRUE, B_FALSE);
|
B_TRUE, B_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
zed_log_msg(LOG_WARNING, " 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" :
|
||||||
libzfs_error_description(g_zfshdl));
|
libzfs_error_description(g_zfshdl));
|
||||||
|
|
||||||
@@ -603,20 +525,16 @@ typedef struct dev_data {
|
|||||||
boolean_t dd_islabeled;
|
boolean_t dd_islabeled;
|
||||||
uint64_t dd_pool_guid;
|
uint64_t dd_pool_guid;
|
||||||
uint64_t dd_vdev_guid;
|
uint64_t dd_vdev_guid;
|
||||||
uint64_t dd_new_vdev_guid;
|
|
||||||
const char *dd_new_devid;
|
const char *dd_new_devid;
|
||||||
uint64_t dd_num_spares;
|
|
||||||
} dev_data_t;
|
} dev_data_t;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||||
{
|
{
|
||||||
dev_data_t *dp = data;
|
dev_data_t *dp = data;
|
||||||
const char *path = NULL;
|
char *path = NULL;
|
||||||
uint_t c, children;
|
uint_t c, children;
|
||||||
nvlist_t **child;
|
nvlist_t **child;
|
||||||
uint64_t guid = 0;
|
|
||||||
uint64_t isspare = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First iterate over any children.
|
* First iterate over any children.
|
||||||
@@ -642,16 +560,19 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* once a vdev was matched and processed there is nothing left to do */
|
/* once a vdev was matched and processed there is nothing left to do */
|
||||||
if (dp->dd_found && dp->dd_num_spares == 0)
|
if (dp->dd_found)
|
||||||
return;
|
return;
|
||||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &guid);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Match by GUID if available otherwise fallback to devid or physical
|
* Match by GUID if available otherwise fallback to devid or physical
|
||||||
*/
|
*/
|
||||||
if (dp->dd_vdev_guid != 0) {
|
if (dp->dd_vdev_guid != 0) {
|
||||||
if (guid != dp->dd_vdev_guid)
|
uint64_t guid;
|
||||||
|
|
||||||
|
if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
|
||||||
|
&guid) != 0 || guid != dp->dd_vdev_guid) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched on %llu", guid);
|
zed_log_msg(LOG_INFO, " zfs_iter_vdev: matched on %llu", guid);
|
||||||
dp->dd_found = B_TRUE;
|
dp->dd_found = B_TRUE;
|
||||||
|
|
||||||
@@ -661,21 +582,11 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
|||||||
* illumos, substring matching is not required to accommodate
|
* illumos, substring matching is not required to accommodate
|
||||||
* the partition suffix. An exact match will be present in
|
* the partition suffix. An exact match will be present in
|
||||||
* the dp->dd_compare value.
|
* the dp->dd_compare value.
|
||||||
* If the attached disk already contains a vdev GUID, it means
|
|
||||||
* the disk is not clean. In such a scenario, the physical path
|
|
||||||
* would be a match that makes the disk faulted when trying to
|
|
||||||
* online it. So, we would only want to proceed if either GUID
|
|
||||||
* matches with the last attached disk or the disk is in clean
|
|
||||||
* state.
|
|
||||||
*/
|
*/
|
||||||
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
|
if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
|
||||||
strcmp(dp->dd_compare, path) != 0) {
|
strcmp(dp->dd_compare, path) != 0) {
|
||||||
return;
|
zed_log_msg(LOG_INFO, " %s: no match (%s != vdev %s)",
|
||||||
}
|
__func__, dp->dd_compare, path);
|
||||||
if (dp->dd_new_vdev_guid != 0 && dp->dd_new_vdev_guid != guid) {
|
|
||||||
zed_log_msg(LOG_INFO, " %s: no match (GUID:%llu"
|
|
||||||
" != vdev GUID:%llu)", __func__,
|
|
||||||
dp->dd_new_vdev_guid, guid);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,17 +594,13 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
|||||||
dp->dd_prop, path);
|
dp->dd_prop, path);
|
||||||
dp->dd_found = B_TRUE;
|
dp->dd_found = B_TRUE;
|
||||||
|
|
||||||
/* pass the new devid for use by auto-replacing code */
|
/* pass the new devid for use by replacing code */
|
||||||
if (dp->dd_new_devid != NULL) {
|
if (dp->dd_new_devid != NULL) {
|
||||||
(void) nvlist_add_string(nvl, "new_devid",
|
(void) nvlist_add_string(nvl, "new_devid",
|
||||||
dp->dd_new_devid);
|
dp->dd_new_devid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dp->dd_found == B_TRUE && nvlist_lookup_uint64(nvl,
|
|
||||||
ZPOOL_CONFIG_IS_SPARE, &isspare) == 0 && isspare)
|
|
||||||
dp->dd_num_spares++;
|
|
||||||
|
|
||||||
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
|
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,7 +609,7 @@ zfs_enable_ds(void *arg)
|
|||||||
{
|
{
|
||||||
unavailpool_t *pool = (unavailpool_t *)arg;
|
unavailpool_t *pool = (unavailpool_t *)arg;
|
||||||
|
|
||||||
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0, 512);
|
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0);
|
||||||
zpool_close(pool->uap_zhp);
|
zpool_close(pool->uap_zhp);
|
||||||
free(pool);
|
free(pool);
|
||||||
}
|
}
|
||||||
@@ -754,9 +661,7 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
|
return (dp->dd_found); /* cease iteration after a match */
|
||||||
/* cease iteration after a match */
|
|
||||||
return (dp->dd_found && dp->dd_num_spares == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -765,7 +670,7 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
|
|||||||
*/
|
*/
|
||||||
static boolean_t
|
static boolean_t
|
||||||
devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
|
devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
|
||||||
boolean_t is_slice, uint64_t new_vdev_guid)
|
boolean_t is_slice)
|
||||||
{
|
{
|
||||||
dev_data_t data = { 0 };
|
dev_data_t data = { 0 };
|
||||||
|
|
||||||
@@ -775,7 +680,6 @@ devphys_iter(const char *physical, const char *devid, zfs_process_func_t func,
|
|||||||
data.dd_found = B_FALSE;
|
data.dd_found = B_FALSE;
|
||||||
data.dd_islabeled = is_slice;
|
data.dd_islabeled = is_slice;
|
||||||
data.dd_new_devid = devid; /* used by auto replace code */
|
data.dd_new_devid = devid; /* used by auto replace code */
|
||||||
data.dd_new_vdev_guid = new_vdev_guid;
|
|
||||||
|
|
||||||
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
|
(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
|
||||||
|
|
||||||
@@ -910,9 +814,9 @@ guid_iter(uint64_t pool_guid, uint64_t vdev_guid, const char *devid,
|
|||||||
* phys_path: 'pci-0000:04:00.0-sas-0x4433221106000000-lun-0'
|
* phys_path: 'pci-0000:04:00.0-sas-0x4433221106000000-lun-0'
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
zfs_deliver_add(nvlist_t *nvl)
|
zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
|
||||||
{
|
{
|
||||||
const char *devpath = NULL, *devid = NULL;
|
char *devpath = NULL, *devid = NULL;
|
||||||
uint64_t pool_guid = 0, vdev_guid = 0;
|
uint64_t pool_guid = 0, vdev_guid = 0;
|
||||||
boolean_t is_slice;
|
boolean_t is_slice;
|
||||||
|
|
||||||
@@ -944,7 +848,7 @@ zfs_deliver_add(nvlist_t *nvl)
|
|||||||
if (devid_iter(devid, zfs_process_add, is_slice))
|
if (devid_iter(devid, zfs_process_add, is_slice))
|
||||||
return (0);
|
return (0);
|
||||||
if (devpath != NULL && devphys_iter(devpath, devid, zfs_process_add,
|
if (devpath != NULL && devphys_iter(devpath, devid, zfs_process_add,
|
||||||
is_slice, vdev_guid))
|
is_slice))
|
||||||
return (0);
|
return (0);
|
||||||
if (vdev_guid != 0)
|
if (vdev_guid != 0)
|
||||||
(void) guid_iter(pool_guid, vdev_guid, devid, zfs_process_add,
|
(void) guid_iter(pool_guid, vdev_guid, devid, zfs_process_add,
|
||||||
@@ -990,98 +894,21 @@ zfs_deliver_check(nvlist_t *nvl)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Given a path to a vdev, lookup the vdev's physical size from its
|
|
||||||
* config nvlist.
|
|
||||||
*
|
|
||||||
* Returns the vdev's physical size in bytes on success, 0 on error.
|
|
||||||
*/
|
|
||||||
static uint64_t
|
|
||||||
vdev_size_from_config(zpool_handle_t *zhp, const char *vdev_path)
|
|
||||||
{
|
|
||||||
nvlist_t *nvl = NULL;
|
|
||||||
boolean_t avail_spare, l2cache, log;
|
|
||||||
vdev_stat_t *vs = NULL;
|
|
||||||
uint_t c;
|
|
||||||
|
|
||||||
nvl = zpool_find_vdev(zhp, vdev_path, &avail_spare, &l2cache, &log);
|
|
||||||
if (!nvl)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
verify(nvlist_lookup_uint64_array(nvl, ZPOOL_CONFIG_VDEV_STATS,
|
|
||||||
(uint64_t **)&vs, &c) == 0);
|
|
||||||
if (!vs) {
|
|
||||||
zed_log_msg(LOG_INFO, "%s: no nvlist for '%s'", __func__,
|
|
||||||
vdev_path);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (vs->vs_pspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given a path to a vdev, lookup if the vdev is a "whole disk" in the
|
|
||||||
* config nvlist. "whole disk" means that ZFS was passed a whole disk
|
|
||||||
* at pool creation time, which it partitioned up and has full control over.
|
|
||||||
* Thus a partition with wholedisk=1 set tells us that zfs created the
|
|
||||||
* partition at creation time. A partition without whole disk set would have
|
|
||||||
* been created by externally (like with fdisk) and passed to ZFS.
|
|
||||||
*
|
|
||||||
* Returns the whole disk value (either 0 or 1).
|
|
||||||
*/
|
|
||||||
static uint64_t
|
|
||||||
vdev_whole_disk_from_config(zpool_handle_t *zhp, const char *vdev_path)
|
|
||||||
{
|
|
||||||
nvlist_t *nvl = NULL;
|
|
||||||
boolean_t avail_spare, l2cache, log;
|
|
||||||
uint64_t wholedisk = 0;
|
|
||||||
|
|
||||||
nvl = zpool_find_vdev(zhp, vdev_path, &avail_spare, &l2cache, &log);
|
|
||||||
if (!nvl)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
|
|
||||||
|
|
||||||
return (wholedisk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the device size grew more than 1% then return true.
|
|
||||||
*/
|
|
||||||
#define DEVICE_GREW(oldsize, newsize) \
|
|
||||||
((newsize > oldsize) && \
|
|
||||||
((newsize / (newsize - oldsize)) <= 100))
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
||||||
{
|
{
|
||||||
|
char *devname = data;
|
||||||
boolean_t avail_spare, l2cache;
|
boolean_t avail_spare, l2cache;
|
||||||
nvlist_t *udev_nvl = data;
|
|
||||||
nvlist_t *tgt;
|
nvlist_t *tgt;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
const char *tmp_devname;
|
|
||||||
char devname[MAXPATHLEN] = "";
|
|
||||||
uint64_t guid;
|
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(udev_nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
|
|
||||||
sprintf(devname, "%llu", (u_longlong_t)guid);
|
|
||||||
} else if (nvlist_lookup_string(udev_nvl, DEV_PHYS_PATH,
|
|
||||||
&tmp_devname) == 0) {
|
|
||||||
strlcpy(devname, tmp_devname, MAXPATHLEN);
|
|
||||||
zfs_append_partition(devname, MAXPATHLEN);
|
|
||||||
} else {
|
|
||||||
zed_log_msg(LOG_INFO, "%s: no guid or physpath", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: searching for '%s' in '%s'",
|
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: searching for '%s' in '%s'",
|
||||||
devname, zpool_get_name(zhp));
|
devname, zpool_get_name(zhp));
|
||||||
|
|
||||||
if ((tgt = zpool_find_vdev_by_physpath(zhp, devname,
|
if ((tgt = zpool_find_vdev_by_physpath(zhp, devname,
|
||||||
&avail_spare, &l2cache, NULL)) != NULL) {
|
&avail_spare, &l2cache, NULL)) != NULL) {
|
||||||
const char *path;
|
char *path, fullpath[MAXPATHLEN];
|
||||||
char fullpath[MAXPATHLEN];
|
uint64_t wholedisk;
|
||||||
uint64_t wholedisk = 0;
|
|
||||||
|
|
||||||
error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path);
|
error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path);
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -1089,15 +916,16 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
|
error = nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
|
||||||
&wholedisk);
|
&wholedisk);
|
||||||
|
if (error)
|
||||||
|
wholedisk = 0;
|
||||||
|
|
||||||
if (wholedisk) {
|
if (wholedisk) {
|
||||||
char *tmp;
|
|
||||||
path = strrchr(path, '/');
|
path = strrchr(path, '/');
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
tmp = zfs_strip_partition(path + 1);
|
path = zfs_strip_partition(path + 1);
|
||||||
if (tmp == NULL) {
|
if (path == NULL) {
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -1106,8 +934,8 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) strlcpy(fullpath, tmp, sizeof (fullpath));
|
(void) strlcpy(fullpath, path, sizeof (fullpath));
|
||||||
free(tmp);
|
free(path);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to reopen the pool associated with this
|
* We need to reopen the pool associated with this
|
||||||
@@ -1125,75 +953,12 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
|||||||
vdev_state_t newstate;
|
vdev_state_t newstate;
|
||||||
|
|
||||||
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
|
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
|
||||||
/*
|
error = zpool_vdev_online(zhp, fullpath, 0,
|
||||||
* If this disk size has not changed, then
|
&newstate);
|
||||||
* there's no need to do an autoexpand. To
|
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: "
|
||||||
* check we look at the disk's size in its
|
"setting device '%s' to ONLINE state "
|
||||||
* config, and compare it to the disk size
|
"in pool '%s': %d", fullpath,
|
||||||
* that udev is reporting.
|
zpool_get_name(zhp), error);
|
||||||
*/
|
|
||||||
uint64_t udev_size = 0, conf_size = 0,
|
|
||||||
wholedisk = 0, udev_parent_size = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the size of our disk that udev is
|
|
||||||
* reporting.
|
|
||||||
*/
|
|
||||||
if (nvlist_lookup_uint64(udev_nvl, DEV_SIZE,
|
|
||||||
&udev_size) != 0) {
|
|
||||||
udev_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the size of our disk's parent device
|
|
||||||
* from udev (where sda1's parent is sda).
|
|
||||||
*/
|
|
||||||
if (nvlist_lookup_uint64(udev_nvl,
|
|
||||||
DEV_PARENT_SIZE, &udev_parent_size) != 0) {
|
|
||||||
udev_parent_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
conf_size = vdev_size_from_config(zhp,
|
|
||||||
fullpath);
|
|
||||||
|
|
||||||
wholedisk = vdev_whole_disk_from_config(zhp,
|
|
||||||
fullpath);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Only attempt an autoexpand if the vdev size
|
|
||||||
* changed. There are two different cases
|
|
||||||
* to consider.
|
|
||||||
*
|
|
||||||
* 1. wholedisk=1
|
|
||||||
* If you do a 'zpool create' on a whole disk
|
|
||||||
* (like /dev/sda), then zfs will create
|
|
||||||
* partitions on the disk (like /dev/sda1). In
|
|
||||||
* that case, wholedisk=1 will be set in the
|
|
||||||
* partition's nvlist config. So zed will need
|
|
||||||
* to see if your parent device (/dev/sda)
|
|
||||||
* expanded in size, and if so, then attempt
|
|
||||||
* the autoexpand.
|
|
||||||
*
|
|
||||||
* 2. wholedisk=0
|
|
||||||
* If you do a 'zpool create' on an existing
|
|
||||||
* partition, or a device that doesn't allow
|
|
||||||
* partitions, then wholedisk=0, and you will
|
|
||||||
* simply need to check if the device itself
|
|
||||||
* expanded in size.
|
|
||||||
*/
|
|
||||||
if (DEVICE_GREW(conf_size, udev_size) ||
|
|
||||||
(wholedisk && DEVICE_GREW(conf_size,
|
|
||||||
udev_parent_size))) {
|
|
||||||
error = zpool_vdev_online(zhp, fullpath,
|
|
||||||
0, &newstate);
|
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
"%s: autoexpanding '%s' from %llu"
|
|
||||||
" to %llu bytes in pool '%s': %d",
|
|
||||||
__func__, fullpath, conf_size,
|
|
||||||
MAX(udev_size, udev_parent_size),
|
|
||||||
zpool_get_name(zhp), error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
@@ -1212,8 +977,7 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
|||||||
static int
|
static int
|
||||||
zfs_deliver_dle(nvlist_t *nvl)
|
zfs_deliver_dle(nvlist_t *nvl)
|
||||||
{
|
{
|
||||||
const char *devname;
|
char *devname, name[MAXPATHLEN];
|
||||||
char name[MAXPATHLEN];
|
|
||||||
uint64_t guid;
|
uint64_t guid;
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
|
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
|
||||||
@@ -1222,11 +986,10 @@ zfs_deliver_dle(nvlist_t *nvl)
|
|||||||
strlcpy(name, devname, MAXPATHLEN);
|
strlcpy(name, devname, MAXPATHLEN);
|
||||||
zfs_append_partition(name, MAXPATHLEN);
|
zfs_append_partition(name, MAXPATHLEN);
|
||||||
} else {
|
} else {
|
||||||
sprintf(name, "unknown");
|
|
||||||
zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath");
|
zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zpool_iter(g_zfshdl, zfsdle_vdev_online, nvl) != 1) {
|
if (zpool_iter(g_zfshdl, zfsdle_vdev_online, name) != 1) {
|
||||||
zed_log_msg(LOG_INFO, "zfs_deliver_dle: device '%s' not "
|
zed_log_msg(LOG_INFO, "zfs_deliver_dle: device '%s' not "
|
||||||
"found", name);
|
"found", name);
|
||||||
return (1);
|
return (1);
|
||||||
@@ -1250,15 +1013,18 @@ static int
|
|||||||
zfs_slm_deliver_event(const char *class, const char *subclass, nvlist_t *nvl)
|
zfs_slm_deliver_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
boolean_t is_check = B_FALSE, is_dle = B_FALSE;
|
boolean_t is_lofi = B_FALSE, is_check = B_FALSE, is_dle = B_FALSE;
|
||||||
|
|
||||||
if (strcmp(class, EC_DEV_ADD) == 0) {
|
if (strcmp(class, EC_DEV_ADD) == 0) {
|
||||||
/*
|
/*
|
||||||
* We're mainly interested in disk additions, but we also listen
|
* We're mainly interested in disk additions, but we also listen
|
||||||
* for new loop devices, to allow for simplified testing.
|
* for new loop devices, to allow for simplified testing.
|
||||||
*/
|
*/
|
||||||
if (strcmp(subclass, ESC_DISK) != 0 &&
|
if (strcmp(subclass, ESC_DISK) == 0)
|
||||||
strcmp(subclass, ESC_LOFI) != 0)
|
is_lofi = B_FALSE;
|
||||||
|
else if (strcmp(subclass, ESC_LOFI) == 0)
|
||||||
|
is_lofi = B_TRUE;
|
||||||
|
else
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
is_check = B_FALSE;
|
is_check = B_FALSE;
|
||||||
@@ -1282,16 +1048,15 @@ zfs_slm_deliver_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
else if (is_check)
|
else if (is_check)
|
||||||
ret = zfs_deliver_check(nvl);
|
ret = zfs_deliver_check(nvl);
|
||||||
else
|
else
|
||||||
ret = zfs_deliver_add(nvl);
|
ret = zfs_deliver_add(nvl, is_lofi);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
static void *
|
static void *
|
||||||
zfs_enum_pools(void *arg)
|
zfs_enum_pools(void *arg)
|
||||||
{
|
{
|
||||||
(void) arg;
|
|
||||||
|
|
||||||
(void) zpool_iter(g_zfshdl, zfs_unavail_pool, (void *)&g_pool_list);
|
(void) zpool_iter(g_zfshdl, zfs_unavail_pool, (void *)&g_pool_list);
|
||||||
/*
|
/*
|
||||||
* Linux - instead of using a thread pool, each list entry
|
* Linux - instead of using a thread pool, each list entry
|
||||||
@@ -1310,7 +1075,7 @@ zfs_enum_pools(void *arg)
|
|||||||
* For now, each agent has its own libzfs instance
|
* For now, each agent has its own libzfs instance
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
zfs_slm_init(void)
|
zfs_slm_init()
|
||||||
{
|
{
|
||||||
if ((g_zfshdl = libzfs_init()) == NULL)
|
if ((g_zfshdl = libzfs_init()) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -1336,7 +1101,7 @@ zfs_slm_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
zfs_slm_fini(void)
|
zfs_slm_fini()
|
||||||
{
|
{
|
||||||
unavailpool_t *pool;
|
unavailpool_t *pool;
|
||||||
pendingdev_t *device;
|
pendingdev_t *device;
|
||||||
@@ -1349,14 +1114,17 @@ zfs_slm_fini(void)
|
|||||||
tpool_destroy(g_tpool);
|
tpool_destroy(g_tpool);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((pool = list_remove_head(&g_pool_list)) != NULL) {
|
while ((pool = (list_head(&g_pool_list))) != NULL) {
|
||||||
|
list_remove(&g_pool_list, pool);
|
||||||
zpool_close(pool->uap_zhp);
|
zpool_close(pool->uap_zhp);
|
||||||
free(pool);
|
free(pool);
|
||||||
}
|
}
|
||||||
list_destroy(&g_pool_list);
|
list_destroy(&g_pool_list);
|
||||||
|
|
||||||
while ((device = list_remove_head(&g_device_list)) != NULL)
|
while ((device = (list_head(&g_device_list))) != NULL) {
|
||||||
|
list_remove(&g_device_list, device);
|
||||||
free(device);
|
free(device);
|
||||||
|
}
|
||||||
list_destroy(&g_device_list);
|
list_destroy(&g_device_list);
|
||||||
|
|
||||||
libzfs_fini(g_zfshdl);
|
libzfs_fini(g_zfshdl);
|
||||||
|
|||||||
+20
-126
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -38,7 +38,6 @@
|
|||||||
#include <sys/fs/zfs.h>
|
#include <sys/fs/zfs.h>
|
||||||
#include <sys/fm/protocol.h>
|
#include <sys/fm/protocol.h>
|
||||||
#include <sys/fm/fs/zfs.h>
|
#include <sys/fm/fs/zfs.h>
|
||||||
#include <libzutil.h>
|
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
@@ -76,8 +75,6 @@ typedef struct find_cbdata {
|
|||||||
uint64_t cb_guid;
|
uint64_t cb_guid;
|
||||||
zpool_handle_t *cb_zhp;
|
zpool_handle_t *cb_zhp;
|
||||||
nvlist_t *cb_vdev;
|
nvlist_t *cb_vdev;
|
||||||
uint64_t cb_vdev_guid;
|
|
||||||
uint64_t cb_num_spares;
|
|
||||||
} find_cbdata_t;
|
} find_cbdata_t;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -143,64 +140,6 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
remove_spares(zpool_handle_t *zhp, void *data)
|
|
||||||
{
|
|
||||||
nvlist_t *config, *nvroot;
|
|
||||||
nvlist_t **spares;
|
|
||||||
uint_t nspares;
|
|
||||||
char *devname;
|
|
||||||
find_cbdata_t *cbp = data;
|
|
||||||
uint64_t spareguid = 0;
|
|
||||||
vdev_stat_t *vs;
|
|
||||||
unsigned int c;
|
|
||||||
|
|
||||||
config = zpool_get_config(zhp, NULL);
|
|
||||||
if (nvlist_lookup_nvlist(config,
|
|
||||||
ZPOOL_CONFIG_VDEV_TREE, &nvroot) != 0) {
|
|
||||||
zpool_close(zhp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
|
||||||
&spares, &nspares) != 0) {
|
|
||||||
zpool_close(zhp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nspares; i++) {
|
|
||||||
if (nvlist_lookup_uint64(spares[i], ZPOOL_CONFIG_GUID,
|
|
||||||
&spareguid) == 0 && spareguid == cbp->cb_vdev_guid) {
|
|
||||||
devname = zpool_vdev_name(NULL, zhp, spares[i],
|
|
||||||
B_FALSE);
|
|
||||||
nvlist_lookup_uint64_array(spares[i],
|
|
||||||
ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c);
|
|
||||||
if (vs->vs_state != VDEV_STATE_REMOVED &&
|
|
||||||
zpool_vdev_remove_wanted(zhp, devname) == 0)
|
|
||||||
cbp->cb_num_spares++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zpool_close(zhp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Given a vdev guid, find and remove all spares associated with it.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
find_and_remove_spares(libzfs_handle_t *zhdl, uint64_t vdev_guid)
|
|
||||||
{
|
|
||||||
find_cbdata_t cb;
|
|
||||||
|
|
||||||
cb.cb_num_spares = 0;
|
|
||||||
cb.cb_vdev_guid = vdev_guid;
|
|
||||||
zpool_iter(zhdl, remove_spares, &cb);
|
|
||||||
|
|
||||||
return (cb.cb_num_spares);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a (pool, vdev) GUID pair, find the matching pool and vdev.
|
* Given a (pool, vdev) GUID pair, find the matching pool and vdev.
|
||||||
*/
|
*/
|
||||||
@@ -282,7 +221,7 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
|||||||
*/
|
*/
|
||||||
for (s = 0; s < nspares; s++) {
|
for (s = 0; s < nspares; s++) {
|
||||||
boolean_t rebuild = B_FALSE;
|
boolean_t rebuild = B_FALSE;
|
||||||
const char *spare_name, *type;
|
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)
|
||||||
@@ -299,10 +238,10 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
|||||||
ZPOOL_CONFIG_ASHIFT, ashift);
|
ZPOOL_CONFIG_ASHIFT, ashift);
|
||||||
|
|
||||||
(void) nvlist_add_nvlist_array(replacement,
|
(void) nvlist_add_nvlist_array(replacement,
|
||||||
ZPOOL_CONFIG_CHILDREN, (const nvlist_t **)&spares[s], 1);
|
ZPOOL_CONFIG_CHILDREN, &spares[s], 1);
|
||||||
|
|
||||||
fmd_hdl_debug(hdl, "zpool_vdev_replace '%s' with spare '%s'",
|
fmd_hdl_debug(hdl, "zpool_vdev_replace '%s' with spare '%s'",
|
||||||
dev_name, zfs_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, rebuild) == 0) {
|
||||||
@@ -323,6 +262,7 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
|||||||
* ASRU is now usable. ZFS has found the device to be present and
|
* ASRU is now usable. ZFS has found the device to be present and
|
||||||
* functioning.
|
* functioning.
|
||||||
*/
|
*/
|
||||||
|
/*ARGSUSED*/
|
||||||
static void
|
static void
|
||||||
zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl)
|
zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl)
|
||||||
{
|
{
|
||||||
@@ -361,11 +301,11 @@ zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl)
|
|||||||
vdev_guid, pool_guid);
|
vdev_guid, pool_guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
static void
|
static void
|
||||||
zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||||
const char *class)
|
const char *class)
|
||||||
{
|
{
|
||||||
(void) ep;
|
|
||||||
uint64_t pool_guid, vdev_guid;
|
uint64_t pool_guid, vdev_guid;
|
||||||
zpool_handle_t *zhp;
|
zpool_handle_t *zhp;
|
||||||
nvlist_t *resource, *fault;
|
nvlist_t *resource, *fault;
|
||||||
@@ -375,23 +315,18 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
libzfs_handle_t *zhdl = zdp->zrd_hdl;
|
libzfs_handle_t *zhdl = zdp->zrd_hdl;
|
||||||
boolean_t fault_device, degrade_device;
|
boolean_t fault_device, degrade_device;
|
||||||
boolean_t is_repair;
|
boolean_t is_repair;
|
||||||
boolean_t l2arc = B_FALSE;
|
char *scheme;
|
||||||
boolean_t spare = B_FALSE;
|
|
||||||
const char *scheme;
|
|
||||||
nvlist_t *vdev = NULL;
|
nvlist_t *vdev = NULL;
|
||||||
const char *uuid;
|
char *uuid;
|
||||||
int repair_done = 0;
|
int repair_done = 0;
|
||||||
boolean_t retire;
|
boolean_t retire;
|
||||||
boolean_t is_disk;
|
boolean_t is_disk;
|
||||||
vdev_aux_t aux;
|
vdev_aux_t aux;
|
||||||
uint64_t state = 0;
|
uint64_t state = 0;
|
||||||
vdev_stat_t *vs;
|
|
||||||
unsigned int c;
|
|
||||||
|
|
||||||
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
|
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
|
||||||
|
|
||||||
(void) nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE,
|
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE, &state);
|
||||||
&state);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is a resource notifying us of device removal then simply
|
* If this is a resource notifying us of device removal then simply
|
||||||
@@ -401,34 +336,13 @@ 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 || state == VDEV_STATE_FAULTED))) {
|
||||||
const char *devtype;
|
char *devtype;
|
||||||
char *devname;
|
char *devname;
|
||||||
|
|
||||||
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
|
|
||||||
&devtype) == 0) {
|
|
||||||
if (strcmp(devtype, VDEV_TYPE_SPARE) == 0)
|
|
||||||
spare = B_TRUE;
|
|
||||||
else if (strcmp(devtype, VDEV_TYPE_L2CACHE) == 0)
|
|
||||||
l2arc = B_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nvl,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (vdev_guid == 0) {
|
|
||||||
fmd_hdl_debug(hdl, "Got a zero GUID");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spare) {
|
|
||||||
int nspares = find_and_remove_spares(zhdl, vdev_guid);
|
|
||||||
fmd_hdl_debug(hdl, "%d spares removed", nspares);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
|
if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
|
||||||
&pool_guid) != 0)
|
&pool_guid) != 0 ||
|
||||||
|
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID,
|
||||||
|
&vdev_guid) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((zhp = find_by_guid(zhdl, pool_guid, vdev_guid,
|
if ((zhp = find_by_guid(zhdl, pool_guid, vdev_guid,
|
||||||
@@ -437,30 +351,13 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
|
|
||||||
devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE);
|
devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE);
|
||||||
|
|
||||||
nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS,
|
/* Can't replace l2arc with a spare: offline the device */
|
||||||
(uint64_t **)&vs, &c);
|
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
|
||||||
|
&devtype) == 0 && strcmp(devtype, VDEV_TYPE_L2CACHE) == 0) {
|
||||||
/*
|
fmd_hdl_debug(hdl, "zpool_vdev_offline '%s'", devname);
|
||||||
* If state removed is requested for already removed vdev,
|
zpool_vdev_offline(zhp, devname, B_TRUE);
|
||||||
* its a loopback event from spa_async_remove(). Just
|
} else if (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
|
||||||
* ignore it.
|
replace_with_spare(hdl, zhp, vdev) == B_FALSE) {
|
||||||
*/
|
|
||||||
if ((vs->vs_state == VDEV_STATE_REMOVED && state ==
|
|
||||||
VDEV_STATE_REMOVED) || vs->vs_state == VDEV_STATE_OFFLINE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Remove the vdev since device is unplugged */
|
|
||||||
int remove_status = 0;
|
|
||||||
if (l2arc || (strcmp(class, "resource.fs.zfs.removed") == 0)) {
|
|
||||||
remove_status = zpool_vdev_remove_wanted(zhp, devname);
|
|
||||||
fmd_hdl_debug(hdl, "zpool_vdev_remove_wanted '%s'"
|
|
||||||
", err:%d", devname, libzfs_errno(zhdl));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace the vdev with a spare if its not a l2arc */
|
|
||||||
if (!l2arc && !remove_status &&
|
|
||||||
(!fmd_prop_get_int32(hdl, "spare_on_remove") ||
|
|
||||||
replace_with_spare(hdl, zhp, vdev) == B_FALSE)) {
|
|
||||||
/* Could not handle with spare */
|
/* Could not handle with spare */
|
||||||
fmd_hdl_debug(hdl, "no spare for '%s'", devname);
|
fmd_hdl_debug(hdl, "no spare for '%s'", devname);
|
||||||
}
|
}
|
||||||
@@ -523,9 +420,6 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
} else if (fmd_nvl_class_match(hdl, fault,
|
} else if (fmd_nvl_class_match(hdl, fault,
|
||||||
"fault.fs.zfs.vdev.checksum")) {
|
"fault.fs.zfs.vdev.checksum")) {
|
||||||
degrade_device = B_TRUE;
|
degrade_device = B_TRUE;
|
||||||
} else if (fmd_nvl_class_match(hdl, fault,
|
|
||||||
"fault.fs.zfs.vdev.slow_io")) {
|
|
||||||
degrade_device = B_TRUE;
|
|
||||||
} else if (fmd_nvl_class_match(hdl, fault,
|
} else if (fmd_nvl_class_match(hdl, fault,
|
||||||
"fault.fs.zfs.device")) {
|
"fault.fs.zfs.device")) {
|
||||||
fault_device = B_FALSE;
|
fault_device = B_FALSE;
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ static volatile sig_atomic_t _got_hup = 0;
|
|||||||
static void
|
static void
|
||||||
_exit_handler(int signum)
|
_exit_handler(int signum)
|
||||||
{
|
{
|
||||||
(void) signum;
|
|
||||||
_got_exit = 1;
|
_got_exit = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +45,6 @@ _exit_handler(int signum)
|
|||||||
static void
|
static void
|
||||||
_hup_handler(int signum)
|
_hup_handler(int signum)
|
||||||
{
|
{
|
||||||
(void) signum;
|
|
||||||
_got_hup = 1;
|
_got_hup = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-35
@@ -1,59 +1,57 @@
|
|||||||
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
include $(top_srcdir)/config/Substfiles.am
|
||||||
|
include $(top_srcdir)/config/Shellcheck.am
|
||||||
|
|
||||||
|
EXTRA_DIST += README
|
||||||
|
|
||||||
zedconfdir = $(sysconfdir)/zfs/zed.d
|
zedconfdir = $(sysconfdir)/zfs/zed.d
|
||||||
|
|
||||||
dist_zedconf_DATA = \
|
dist_zedconf_DATA = \
|
||||||
%D%/zed-functions.sh \
|
zed-functions.sh \
|
||||||
%D%/zed.rc
|
zed.rc
|
||||||
|
|
||||||
zedexecdir = $(zfsexecdir)/zed.d
|
zedexecdir = $(zfsexecdir)/zed.d
|
||||||
|
|
||||||
dist_zedexec_SCRIPTS = \
|
dist_zedexec_SCRIPTS = \
|
||||||
%D%/all-debug.sh \
|
all-debug.sh \
|
||||||
%D%/all-syslog.sh \
|
all-syslog.sh \
|
||||||
%D%/data-notify.sh \
|
data-notify.sh \
|
||||||
%D%/deadman-slot_off.sh \
|
generic-notify.sh \
|
||||||
%D%/generic-notify.sh \
|
resilver_finish-notify.sh \
|
||||||
%D%/pool_import-led.sh \
|
scrub_finish-notify.sh \
|
||||||
%D%/resilver_finish-notify.sh \
|
statechange-led.sh \
|
||||||
%D%/resilver_finish-start-scrub.sh \
|
statechange-notify.sh \
|
||||||
%D%/scrub_finish-notify.sh \
|
vdev_clear-led.sh \
|
||||||
%D%/statechange-led.sh \
|
vdev_attach-led.sh \
|
||||||
%D%/statechange-notify.sh \
|
pool_import-led.sh \
|
||||||
%D%/statechange-slot_off.sh \
|
resilver_finish-start-scrub.sh \
|
||||||
%D%/trim_finish-notify.sh \
|
trim_finish-notify.sh
|
||||||
%D%/vdev_attach-led.sh \
|
|
||||||
%D%/vdev_clear-led.sh
|
|
||||||
|
|
||||||
nodist_zedexec_SCRIPTS = \
|
nodist_zedexec_SCRIPTS = history_event-zfs-list-cacher.sh
|
||||||
%D%/history_event-zfs-list-cacher.sh
|
|
||||||
|
|
||||||
SUBSTFILES += $(nodist_zedexec_SCRIPTS)
|
SUBSTFILES += $(nodist_zedexec_SCRIPTS)
|
||||||
|
|
||||||
zedconfdefaults = \
|
zedconfdefaults = \
|
||||||
all-syslog.sh \
|
all-syslog.sh \
|
||||||
data-notify.sh \
|
data-notify.sh \
|
||||||
deadman-slot_off.sh \
|
|
||||||
history_event-zfs-list-cacher.sh \
|
history_event-zfs-list-cacher.sh \
|
||||||
pool_import-led.sh \
|
|
||||||
resilver_finish-notify.sh \
|
resilver_finish-notify.sh \
|
||||||
resilver_finish-start-scrub.sh \
|
|
||||||
scrub_finish-notify.sh \
|
scrub_finish-notify.sh \
|
||||||
statechange-led.sh \
|
statechange-led.sh \
|
||||||
statechange-notify.sh \
|
statechange-notify.sh \
|
||||||
statechange-slot_off.sh \
|
vdev_clear-led.sh \
|
||||||
vdev_attach-led.sh \
|
vdev_attach-led.sh \
|
||||||
vdev_clear-led.sh
|
pool_import-led.sh \
|
||||||
|
resilver_finish-start-scrub.sh
|
||||||
|
|
||||||
dist_noinst_DATA += %D%/README
|
install-data-hook:
|
||||||
|
|
||||||
INSTALL_DATA_HOOKS += zed-install-data-hook
|
|
||||||
zed-install-data-hook:
|
|
||||||
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
||||||
set -x; for f in $(zedconfdefaults); do \
|
for f in $(zedconfdefaults); do \
|
||||||
[ -f "$(DESTDIR)$(zedconfdir)/$${f}" ] ||\
|
test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \
|
||||||
[ -L "$(DESTDIR)$(zedconfdir)/$${f}" ] || \
|
-L "$(DESTDIR)$(zedconfdir)/$${f}" || \
|
||||||
$(LN_S) "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
||||||
done
|
done
|
||||||
|
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
|
||||||
|
|
||||||
SHELLCHECKSCRIPTS += $(dist_zedconf_DATA) $(dist_zedexec_SCRIPTS) $(nodist_zedexec_SCRIPTS)
|
|
||||||
$(call SHELLCHECK_OPTS,$(dist_zedconf_DATA) $(dist_zedexec_SCRIPTS) $(nodist_zedexec_SCRIPTS)): SHELLCHECK_SHELL = sh
|
|
||||||
# False positive: 1>&"${ZED_FLOCK_FD}" looks suspiciously similar to a >&filename bash extension
|
# False positive: 1>&"${ZED_FLOCK_FD}" looks suspiciously similar to a >&filename bash extension
|
||||||
$(call SHELLCHECK_OPTS,$(dist_zedconf_DATA) $(dist_zedexec_SCRIPTS) $(nodist_zedexec_SCRIPTS)): CHECKBASHISMS_IGNORE = -e 'should be >word 2>&1' -e '&"$${ZED_FLOCK_FD}"'
|
CHECKBASHISMS_IGNORE = -e 'should be >word 2>&1' -e '&"$${ZED_FLOCK_FD}"'
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Log all environment variables to ZED_DEBUG_LOG.
|
# Log all environment variables to ZED_DEBUG_LOG.
|
||||||
#
|
#
|
||||||
@@ -15,7 +14,7 @@ zed_exit_if_ignoring_this_event
|
|||||||
|
|
||||||
zed_lock "${ZED_DEBUG_LOG}"
|
zed_lock "${ZED_DEBUG_LOG}"
|
||||||
{
|
{
|
||||||
env | sort
|
printenv | sort
|
||||||
echo
|
echo
|
||||||
} 1>&"${ZED_FLOCK_FD}"
|
} 1>&"${ZED_FLOCK_FD}"
|
||||||
zed_unlock "${ZED_DEBUG_LOG}"
|
zed_unlock "${ZED_DEBUG_LOG}"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
# Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
# Copyright (c) 2020 by Delphix. All rights reserved.
|
# Copyright (c) 2020 by Delphix. All rights reserved.
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Send notification in response to a DATA error.
|
# Send notification in response to a DATA error.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# shellcheck disable=SC3014,SC2154,SC2086,SC2034
|
|
||||||
#
|
|
||||||
# Turn off disk's enclosure slot if an I/O is hung triggering the deadman.
|
|
||||||
#
|
|
||||||
# It's possible for outstanding I/O to a misbehaving SCSI disk to neither
|
|
||||||
# promptly complete or return an error. This can occur due to retry and
|
|
||||||
# recovery actions taken by the SCSI layer, driver, or disk. When it occurs
|
|
||||||
# the pool will be unresponsive even though there may be sufficient redundancy
|
|
||||||
# configured to proceeded without this single disk.
|
|
||||||
#
|
|
||||||
# When a hung I/O is detected by the kmods it will be posted as a deadman
|
|
||||||
# event. By default an I/O is considered to be hung after 5 minutes. This
|
|
||||||
# value can be changed with the zfs_deadman_ziotime_ms module parameter.
|
|
||||||
# If ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN is set the disk's enclosure
|
|
||||||
# slot will be powered off causing the outstanding I/O to fail. The ZED
|
|
||||||
# will then handle this like a normal disk failure and FAULT the vdev.
|
|
||||||
#
|
|
||||||
# We assume the user will be responsible for turning the slot back on
|
|
||||||
# after replacing the disk.
|
|
||||||
#
|
|
||||||
# Note that this script requires that your enclosure be supported by the
|
|
||||||
# Linux SCSI Enclosure services (SES) driver. The script will do nothing
|
|
||||||
# if you have no enclosure, or if your enclosure isn't supported.
|
|
||||||
#
|
|
||||||
# Exit codes:
|
|
||||||
# 0: slot successfully powered off
|
|
||||||
# 1: enclosure not available
|
|
||||||
# 2: ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN disabled
|
|
||||||
# 3: System not configured to wait on deadman
|
|
||||||
# 4: The enclosure sysfs path passed from ZFS does not exist
|
|
||||||
# 5: Enclosure slot didn't actually turn off after we told it to
|
|
||||||
|
|
||||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
|
||||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
|
||||||
|
|
||||||
if [ ! -d /sys/class/enclosure ] ; then
|
|
||||||
# No JBOD enclosure or NVMe slots
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN}" != "1" ] ; then
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$ZEVENT_POOL_FAILMODE" != "wait" ] ; then
|
|
||||||
exit 3
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" ] ; then
|
|
||||||
exit 4
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Turn off the slot and wait for sysfs to report that the slot is off.
|
|
||||||
# It can take ~400ms on some enclosures and multiple retries may be needed.
|
|
||||||
for i in $(seq 1 20) ; do
|
|
||||||
echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status"
|
|
||||||
|
|
||||||
for j in $(seq 1 5) ; do
|
|
||||||
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then
|
|
||||||
break 2
|
|
||||||
fi
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" != "off" ] ; then
|
|
||||||
exit 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
zed_log_msg "powered down slot $ZEVENT_VDEV_ENC_SYSFS_PATH for $ZEVENT_VDEV_PATH"
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Send notification in response to a given zevent.
|
# Send notification in response to a given zevent.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Track changes to enumerated pools for use in early-boot
|
# Track changes to enumerated pools for use in early-boot
|
||||||
set -ef
|
set -ef
|
||||||
@@ -73,7 +72,7 @@ PROPS="name,mountpoint,canmount,atime,relatime,devices,exec\
|
|||||||
,org.openzfs.systemd:wanted-by,org.openzfs.systemd:required-by\
|
,org.openzfs.systemd:wanted-by,org.openzfs.systemd:required-by\
|
||||||
,org.openzfs.systemd:nofail,org.openzfs.systemd:ignore"
|
,org.openzfs.systemd:nofail,org.openzfs.systemd:ignore"
|
||||||
|
|
||||||
"${ZFS}" list -H -t filesystem -o "${PROPS}" -r "${ZEVENT_POOL}" > "${FSLIST_TMP}"
|
"${ZFS}" list -H -t filesystem -o $PROPS -r "${ZEVENT_POOL}" > "${FSLIST_TMP}"
|
||||||
|
|
||||||
# Sort the output so that it is stable
|
# Sort the output so that it is stable
|
||||||
sort "${FSLIST_TMP}" -o "${FSLIST_TMP}"
|
sort "${FSLIST_TMP}" -o "${FSLIST_TMP}"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
# resilver_finish-start-scrub.sh
|
# resilver_finish-start-scrub.sh
|
||||||
# Run a scrub after a resilver
|
# Run a scrub after a resilver
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Send notification in response to a RESILVER_FINISH or SCRUB_FINISH.
|
# Send notification in response to a RESILVER_FINISH or SCRUB_FINISH.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Turn off/on vdevs' enclosure fault LEDs when their pool's state changes.
|
# Turn off/on vdevs' enclosure fault LEDs when their pool's state changes.
|
||||||
#
|
#
|
||||||
@@ -121,15 +120,12 @@ state_to_val()
|
|||||||
{
|
{
|
||||||
state="$1"
|
state="$1"
|
||||||
case "$state" in
|
case "$state" in
|
||||||
FAULTED|DEGRADED|UNAVAIL|REMOVED)
|
FAULTED|DEGRADED|UNAVAIL)
|
||||||
echo 1
|
echo 1
|
||||||
;;
|
;;
|
||||||
ONLINE)
|
ONLINE)
|
||||||
echo 0
|
echo 0
|
||||||
;;
|
;;
|
||||||
*)
|
|
||||||
echo "invalid state: $state"
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,24 +138,26 @@ nvme_dev_to_slot()
|
|||||||
dev="$1"
|
dev="$1"
|
||||||
|
|
||||||
# Get the address "0000:01:00.0"
|
# Get the address "0000:01:00.0"
|
||||||
read -r address < "/sys/class/block/$dev/device/address"
|
address=$(cat "/sys/class/block/$dev/device/address")
|
||||||
|
|
||||||
find /sys/bus/pci/slots -regex '.*/[0-9]+/address$' | \
|
# For each /sys/bus/pci/slots subdir that is an actual number
|
||||||
while read -r sys_addr; do
|
# (rather than weird directories like "1-3/").
|
||||||
read -r this_address < "$sys_addr"
|
# shellcheck disable=SC2010
|
||||||
|
for i in $(ls /sys/bus/pci/slots/ | grep -E "^[0-9]+$") ; do
|
||||||
|
this_address=$(cat "/sys/bus/pci/slots/$i/address")
|
||||||
|
|
||||||
# The format of address is a little different between
|
# The format of address is a little different between
|
||||||
# /sys/class/block/$dev/device/address and
|
# /sys/class/block/$dev/device/address and
|
||||||
# /sys/bus/pci/slots/
|
# /sys/bus/pci/slots/
|
||||||
#
|
#
|
||||||
# address= "0000:01:00.0"
|
# address= "0000:01:00.0"
|
||||||
# this_address = "0000:01:00"
|
# this_address = "0000:01:00"
|
||||||
#
|
#
|
||||||
if echo "$address" | grep -Eq ^"$this_address" ; then
|
if echo "$address" | grep -Eq ^"$this_address" ; then
|
||||||
echo "${sys_addr%/*}"
|
echo "/sys/bus/pci/slots/$i"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# CDDL HEADER START
|
# CDDL HEADER START
|
||||||
#
|
#
|
||||||
@@ -38,7 +37,7 @@ if [ "${ZEVENT_VDEV_STATE_STR}" != "FAULTED" ] \
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
umask 077
|
umask 077
|
||||||
note_subject="ZFS device fault for pool ${ZEVENT_POOL} on $(hostname)"
|
note_subject="ZFS device fault for pool ${ZEVENT_POOL_GUID} on $(hostname)"
|
||||||
note_pathname="$(mktemp)"
|
note_pathname="$(mktemp)"
|
||||||
{
|
{
|
||||||
if [ "${ZEVENT_VDEV_STATE_STR}" = "FAULTED" ] ; then
|
if [ "${ZEVENT_VDEV_STATE_STR}" = "FAULTED" ] ; then
|
||||||
@@ -66,7 +65,7 @@ note_pathname="$(mktemp)"
|
|||||||
[ -n "${ZEVENT_VDEV_GUID}" ] && echo " vguid: ${ZEVENT_VDEV_GUID}"
|
[ -n "${ZEVENT_VDEV_GUID}" ] && echo " vguid: ${ZEVENT_VDEV_GUID}"
|
||||||
[ -n "${ZEVENT_VDEV_DEVID}" ] && echo " devid: ${ZEVENT_VDEV_DEVID}"
|
[ -n "${ZEVENT_VDEV_DEVID}" ] && echo " devid: ${ZEVENT_VDEV_DEVID}"
|
||||||
|
|
||||||
echo " pool: ${ZEVENT_POOL} (${ZEVENT_POOL_GUID})"
|
echo " pool: ${ZEVENT_POOL_GUID}"
|
||||||
|
|
||||||
} > "${note_pathname}"
|
} > "${note_pathname}"
|
||||||
|
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# shellcheck disable=SC3014,SC2154,SC2086,SC2034
|
|
||||||
#
|
|
||||||
# Turn off disk's enclosure slot if it becomes FAULTED.
|
|
||||||
#
|
|
||||||
# Bad SCSI disks can often "disappear and reappear" causing all sorts of chaos
|
|
||||||
# as they flip between FAULTED and ONLINE. If
|
|
||||||
# ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT is set in zed.rc, and the disk gets
|
|
||||||
# FAULTED, then power down the slot via sysfs:
|
|
||||||
#
|
|
||||||
# /sys/class/enclosure/<enclosure>/<slot>/power_status
|
|
||||||
#
|
|
||||||
# We assume the user will be responsible for turning the slot back on again.
|
|
||||||
#
|
|
||||||
# Note that this script requires that your enclosure be supported by the
|
|
||||||
# Linux SCSI Enclosure services (SES) driver. The script will do nothing
|
|
||||||
# if you have no enclosure, or if your enclosure isn't supported.
|
|
||||||
#
|
|
||||||
# Exit codes:
|
|
||||||
# 0: slot successfully powered off
|
|
||||||
# 1: enclosure not available
|
|
||||||
# 2: ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT disabled
|
|
||||||
# 3: vdev was not FAULTED
|
|
||||||
# 4: The enclosure sysfs path passed from ZFS does not exist
|
|
||||||
# 5: Enclosure slot didn't actually turn off after we told it to
|
|
||||||
|
|
||||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
|
||||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
|
||||||
|
|
||||||
if [ ! -d /sys/class/enclosure ] ; then
|
|
||||||
# No JBOD enclosure or NVMe slots
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT}" != "1" ] ; then
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$ZEVENT_VDEV_STATE_STR" != "FAULTED" ] ; then
|
|
||||||
exit 3
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" ] ; then
|
|
||||||
exit 4
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Turn off the slot and wait for sysfs to report that the slot is off.
|
|
||||||
# It can take ~400ms on some enclosures and multiple retries may be needed.
|
|
||||||
for i in $(seq 1 20) ; do
|
|
||||||
echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status"
|
|
||||||
|
|
||||||
for j in $(seq 1 5) ; do
|
|
||||||
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then
|
|
||||||
break 2
|
|
||||||
fi
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" != "off" ] ; then
|
|
||||||
exit 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
zed_log_msg "powered down slot $ZEVENT_VDEV_ENC_SYSFS_PATH for $ZEVENT_VDEV_PATH"
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154
|
|
||||||
#
|
#
|
||||||
# Send notification in response to a TRIM_FINISH. The event
|
# Send notification in response to a TRIM_FINISH. The event
|
||||||
# will be received for each vdev in the pool which was trimmed.
|
# will be received for each vdev in the pool which was trimmed.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# shellcheck disable=SC2154,SC3043
|
# shellcheck disable=SC2039
|
||||||
# zed-functions.sh
|
# zed-functions.sh
|
||||||
#
|
#
|
||||||
# ZED helper functions for use in ZEDLETs
|
# ZED helper functions for use in ZEDLETs
|
||||||
@@ -76,7 +76,8 @@ zed_log_msg()
|
|||||||
#
|
#
|
||||||
zed_log_err()
|
zed_log_err()
|
||||||
{
|
{
|
||||||
zed_log_msg "error: ${0##*/}:""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"
|
logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "error:" \
|
||||||
|
"${0##*/}:""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -205,14 +206,6 @@ zed_notify()
|
|||||||
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
|
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
|
||||||
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
|
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
|
||||||
|
|
||||||
zed_notify_ntfy "${subject}" "${pathname}"; rv=$?
|
|
||||||
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
|
|
||||||
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
|
|
||||||
|
|
||||||
zed_notify_gotify "${subject}" "${pathname}"; rv=$?
|
|
||||||
[ "${rv}" -eq 0 ] && num_success=$((num_success + 1))
|
|
||||||
[ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1))
|
|
||||||
|
|
||||||
[ "${num_success}" -gt 0 ] && return 0
|
[ "${num_success}" -gt 0 ] && return 0
|
||||||
[ "${num_failure}" -gt 0 ] && return 1
|
[ "${num_failure}" -gt 0 ] && return 1
|
||||||
return 2
|
return 2
|
||||||
@@ -231,8 +224,6 @@ zed_notify()
|
|||||||
# ZED_EMAIL_OPTS. This undergoes the following keyword substitutions:
|
# ZED_EMAIL_OPTS. This undergoes the following keyword substitutions:
|
||||||
# - @ADDRESS@ is replaced with the space-delimited recipient email address(es)
|
# - @ADDRESS@ is replaced with the space-delimited recipient email address(es)
|
||||||
# - @SUBJECT@ is replaced with the notification subject
|
# - @SUBJECT@ is replaced with the notification subject
|
||||||
# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification
|
|
||||||
#
|
|
||||||
#
|
#
|
||||||
# Arguments
|
# Arguments
|
||||||
# subject: notification subject
|
# subject: notification subject
|
||||||
@@ -250,7 +241,7 @@ zed_notify()
|
|||||||
#
|
#
|
||||||
zed_notify_email()
|
zed_notify_email()
|
||||||
{
|
{
|
||||||
local subject="${1:-"ZED notification"}"
|
local subject="$1"
|
||||||
local pathname="${2:-"/dev/null"}"
|
local pathname="${2:-"/dev/null"}"
|
||||||
|
|
||||||
: "${ZED_EMAIL_PROG:="mail"}"
|
: "${ZED_EMAIL_PROG:="mail"}"
|
||||||
@@ -271,23 +262,12 @@ zed_notify_email()
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# construct cmdline options
|
ZED_EMAIL_OPTS="$(echo "${ZED_EMAIL_OPTS}" \
|
||||||
ZED_EMAIL_OPTS_PARSED="$(echo "${ZED_EMAIL_OPTS}" \
|
|
||||||
| sed -e "s/@ADDRESS@/${ZED_EMAIL_ADDR}/g" \
|
| sed -e "s/@ADDRESS@/${ZED_EMAIL_ADDR}/g" \
|
||||||
-e "s/@SUBJECT@/${subject}/g")"
|
-e "s/@SUBJECT@/${subject}/g")"
|
||||||
|
|
||||||
# pipe message to email prog
|
# shellcheck disable=SC2086
|
||||||
# shellcheck disable=SC2086,SC2248
|
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS} < "${pathname}" >/dev/null 2>&1
|
||||||
{
|
|
||||||
# no subject passed as option?
|
|
||||||
if [ "${ZED_EMAIL_OPTS%@SUBJECT@*}" = "${ZED_EMAIL_OPTS}" ] ; then
|
|
||||||
# inject subject header
|
|
||||||
printf "Subject: %s\n" "${subject}"
|
|
||||||
fi
|
|
||||||
# output message
|
|
||||||
cat "${pathname}"
|
|
||||||
} |
|
|
||||||
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS_PARSED} >/dev/null 2>&1
|
|
||||||
rv=$?
|
rv=$?
|
||||||
if [ "${rv}" -ne 0 ]; then
|
if [ "${rv}" -ne 0 ]; then
|
||||||
zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}"
|
zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}"
|
||||||
@@ -535,191 +515,6 @@ zed_notify_pushover()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# zed_notify_ntfy (subject, pathname)
|
|
||||||
#
|
|
||||||
# Send a notification via Ntfy.sh <https://ntfy.sh/>.
|
|
||||||
# The ntfy topic (ZED_NTFY_TOPIC) identifies the topic that the notification
|
|
||||||
# will be sent to Ntfy.sh server. The ntfy url (ZED_NTFY_URL) defines the
|
|
||||||
# self-hosted or provided hosted ntfy service location. The ntfy access token
|
|
||||||
# <https://docs.ntfy.sh/publish/#access-tokens> (ZED_NTFY_ACCESS_TOKEN) reprsents an
|
|
||||||
# access token that could be used if a topic is read/write protected. If a
|
|
||||||
# topic can be written to publicaly, a ZED_NTFY_ACCESS_TOKEN is not required.
|
|
||||||
#
|
|
||||||
# Requires curl and sed executables to be installed in the standard PATH.
|
|
||||||
#
|
|
||||||
# References
|
|
||||||
# https://docs.ntfy.sh
|
|
||||||
#
|
|
||||||
# Arguments
|
|
||||||
# subject: notification subject
|
|
||||||
# pathname: pathname containing the notification message (OPTIONAL)
|
|
||||||
#
|
|
||||||
# Globals
|
|
||||||
# ZED_NTFY_TOPIC
|
|
||||||
# ZED_NTFY_ACCESS_TOKEN (OPTIONAL)
|
|
||||||
# ZED_NTFY_URL
|
|
||||||
#
|
|
||||||
# Return
|
|
||||||
# 0: notification sent
|
|
||||||
# 1: notification failed
|
|
||||||
# 2: not configured
|
|
||||||
#
|
|
||||||
zed_notify_ntfy()
|
|
||||||
{
|
|
||||||
local subject="$1"
|
|
||||||
local pathname="${2:-"/dev/null"}"
|
|
||||||
local msg_body
|
|
||||||
local msg_out
|
|
||||||
local msg_err
|
|
||||||
|
|
||||||
[ -n "${ZED_NTFY_TOPIC}" ] || return 2
|
|
||||||
local url="${ZED_NTFY_URL:-"https://ntfy.sh"}/${ZED_NTFY_TOPIC}"
|
|
||||||
|
|
||||||
if [ ! -r "${pathname}" ]; then
|
|
||||||
zed_log_err "ntfy cannot read \"${pathname}\""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
zed_check_cmd "curl" "sed" || return 1
|
|
||||||
|
|
||||||
# Read the message body in.
|
|
||||||
#
|
|
||||||
msg_body="$(cat "${pathname}")"
|
|
||||||
|
|
||||||
if [ -z "${msg_body}" ]
|
|
||||||
then
|
|
||||||
msg_body=$subject
|
|
||||||
subject=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Send the POST request and check for errors.
|
|
||||||
#
|
|
||||||
if [ -n "${ZED_NTFY_ACCESS_TOKEN}" ]; then
|
|
||||||
msg_out="$( \
|
|
||||||
curl \
|
|
||||||
-u ":${ZED_NTFY_ACCESS_TOKEN}" \
|
|
||||||
-H "Title: ${subject}" \
|
|
||||||
-d "${msg_body}" \
|
|
||||||
-H "Priority: high" \
|
|
||||||
"${url}" \
|
|
||||||
2>/dev/null \
|
|
||||||
)"; rv=$?
|
|
||||||
else
|
|
||||||
msg_out="$( \
|
|
||||||
curl \
|
|
||||||
-H "Title: ${subject}" \
|
|
||||||
-d "${msg_body}" \
|
|
||||||
-H "Priority: high" \
|
|
||||||
"${url}" \
|
|
||||||
2>/dev/null \
|
|
||||||
)"; rv=$?
|
|
||||||
fi
|
|
||||||
if [ "${rv}" -ne 0 ]; then
|
|
||||||
zed_log_err "curl exit=${rv}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
msg_err="$(echo "${msg_out}" \
|
|
||||||
| sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"
|
|
||||||
if [ -n "${msg_err}" ]; then
|
|
||||||
zed_log_err "ntfy \"${msg_err}"\"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# zed_notify_gotify (subject, pathname)
|
|
||||||
#
|
|
||||||
# Send a notification via Gotify <https://gotify.net/>.
|
|
||||||
# The Gotify URL (ZED_GOTIFY_URL) defines a self-hosted Gotify location.
|
|
||||||
# The Gotify application token (ZED_GOTIFY_APPTOKEN) defines a
|
|
||||||
# Gotify application token which is associated with a message.
|
|
||||||
# The optional Gotify priority value (ZED_GOTIFY_PRIORITY) overrides the
|
|
||||||
# default or configured priority at the Gotify server for the application.
|
|
||||||
#
|
|
||||||
# Requires curl and sed executables to be installed in the standard PATH.
|
|
||||||
#
|
|
||||||
# References
|
|
||||||
# https://gotify.net/docs/index
|
|
||||||
#
|
|
||||||
# Arguments
|
|
||||||
# subject: notification subject
|
|
||||||
# pathname: pathname containing the notification message (OPTIONAL)
|
|
||||||
#
|
|
||||||
# Globals
|
|
||||||
# ZED_GOTIFY_URL
|
|
||||||
# ZED_GOTIFY_APPTOKEN
|
|
||||||
# ZED_GOTIFY_PRIORITY
|
|
||||||
#
|
|
||||||
# Return
|
|
||||||
# 0: notification sent
|
|
||||||
# 1: notification failed
|
|
||||||
# 2: not configured
|
|
||||||
#
|
|
||||||
zed_notify_gotify()
|
|
||||||
{
|
|
||||||
local subject="$1"
|
|
||||||
local pathname="${2:-"/dev/null"}"
|
|
||||||
local msg_body
|
|
||||||
local msg_out
|
|
||||||
local msg_err
|
|
||||||
|
|
||||||
[ -n "${ZED_GOTIFY_URL}" ] && [ -n "${ZED_GOTIFY_APPTOKEN}" ] || return 2
|
|
||||||
local url="${ZED_GOTIFY_URL}/message?token=${ZED_GOTIFY_APPTOKEN}"
|
|
||||||
|
|
||||||
if [ ! -r "${pathname}" ]; then
|
|
||||||
zed_log_err "gotify cannot read \"${pathname}\""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
zed_check_cmd "curl" "sed" || return 1
|
|
||||||
|
|
||||||
# Read the message body in.
|
|
||||||
#
|
|
||||||
msg_body="$(cat "${pathname}")"
|
|
||||||
|
|
||||||
if [ -z "${msg_body}" ]
|
|
||||||
then
|
|
||||||
msg_body=$subject
|
|
||||||
subject=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Send the POST request and check for errors.
|
|
||||||
#
|
|
||||||
if [ -n "${ZED_GOTIFY_PRIORITY}" ]; then
|
|
||||||
msg_out="$( \
|
|
||||||
curl \
|
|
||||||
--form-string "title=${subject}" \
|
|
||||||
--form-string "message=${msg_body}" \
|
|
||||||
--form-string "priority=${ZED_GOTIFY_PRIORITY}" \
|
|
||||||
"${url}" \
|
|
||||||
2>/dev/null \
|
|
||||||
)"; rv=$?
|
|
||||||
else
|
|
||||||
msg_out="$( \
|
|
||||||
curl \
|
|
||||||
--form-string "title=${subject}" \
|
|
||||||
--form-string "message=${msg_body}" \
|
|
||||||
"${url}" \
|
|
||||||
2>/dev/null \
|
|
||||||
)"; rv=$?
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${rv}" -ne 0 ]; then
|
|
||||||
zed_log_err "curl exit=${rv}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
msg_err="$(echo "${msg_out}" \
|
|
||||||
| sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')"
|
|
||||||
if [ -n "${msg_err}" ]; then
|
|
||||||
zed_log_err "gotify \"${msg_err}"\"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# zed_rate_limit (tag, [interval])
|
# zed_rate_limit (tag, [interval])
|
||||||
#
|
#
|
||||||
# Check whether an event of a given type [tag] has already occurred within the
|
# Check whether an event of a given type [tag] has already occurred within the
|
||||||
|
|||||||
+3
-58
@@ -1,7 +1,8 @@
|
|||||||
##
|
##
|
||||||
# zed.rc – ZEDLET configuration.
|
# zed.rc
|
||||||
|
#
|
||||||
|
# This file should be owned by root and permissioned 0600.
|
||||||
##
|
##
|
||||||
# shellcheck disable=SC2034
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Absolute path to the debug output file.
|
# Absolute path to the debug output file.
|
||||||
@@ -29,7 +30,6 @@ ZED_EMAIL_ADDR="root"
|
|||||||
# The string @SUBJECT@ will be replaced with the notification subject;
|
# The string @SUBJECT@ will be replaced with the notification subject;
|
||||||
# this should be protected with quotes to prevent word-splitting.
|
# this should be protected with quotes to prevent word-splitting.
|
||||||
# Email will only be sent if ZED_EMAIL_ADDR is defined.
|
# Email will only be sent if ZED_EMAIL_ADDR is defined.
|
||||||
# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification
|
|
||||||
#
|
#
|
||||||
#ZED_EMAIL_OPTS="-s '@SUBJECT@' @ADDRESS@"
|
#ZED_EMAIL_OPTS="-s '@SUBJECT@' @ADDRESS@"
|
||||||
|
|
||||||
@@ -142,58 +142,3 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
|
|||||||
# Disabled by default, 1 to enable and 0 to disable.
|
# Disabled by default, 1 to enable and 0 to disable.
|
||||||
#ZED_SYSLOG_DISPLAY_GUIDS=1
|
#ZED_SYSLOG_DISPLAY_GUIDS=1
|
||||||
|
|
||||||
##
|
|
||||||
# Power off the drive's slot in the enclosure if it becomes FAULTED. This can
|
|
||||||
# help silence misbehaving drives. This assumes your drive enclosure fully
|
|
||||||
# supports slot power control via sysfs.
|
|
||||||
#ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT=1
|
|
||||||
|
|
||||||
##
|
|
||||||
# Power off the drive's slot in the enclosure if there is a hung I/O which
|
|
||||||
# exceeds the deadman timeout. This can help prevent a single misbehaving
|
|
||||||
# drive from rendering a redundant pool unavailable. This assumes your drive
|
|
||||||
# enclosure fully supports slot power control via sysfs.
|
|
||||||
#ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN=1
|
|
||||||
|
|
||||||
##
|
|
||||||
# Ntfy topic
|
|
||||||
# This defines which topic will receive the ntfy notification.
|
|
||||||
# <https://docs.ntfy.sh/publish/>
|
|
||||||
# Disabled by default; uncomment to enable.
|
|
||||||
#ZED_NTFY_TOPIC=""
|
|
||||||
|
|
||||||
##
|
|
||||||
# Ntfy access token (optional for public topics)
|
|
||||||
# This defines an access token which can be used
|
|
||||||
# to allow you to authenticate when sending to topics
|
|
||||||
# <https://docs.ntfy.sh/publish/#access-tokens>
|
|
||||||
# Disabled by default; uncomment to enable.
|
|
||||||
#ZED_NTFY_ACCESS_TOKEN=""
|
|
||||||
|
|
||||||
##
|
|
||||||
# Ntfy Service URL
|
|
||||||
# This defines which service the ntfy call will be directed toward
|
|
||||||
# <https://docs.ntfy.sh/install/>
|
|
||||||
# https://ntfy.sh by default; uncomment to enable an alternative service url.
|
|
||||||
#ZED_NTFY_URL="https://ntfy.sh"
|
|
||||||
|
|
||||||
##
|
|
||||||
# Gotify server URL
|
|
||||||
# This defines a URL that the Gotify call will be directed toward.
|
|
||||||
# <https://gotify.net/docs/index>
|
|
||||||
# Disabled by default; uncomment to enable.
|
|
||||||
#ZED_GOTIFY_URL=""
|
|
||||||
|
|
||||||
##
|
|
||||||
# Gotify application token
|
|
||||||
# This defines a Gotify application token which a message is associated with.
|
|
||||||
# This token is generated when an application is created on the Gotify server.
|
|
||||||
# Disabled by default; uncomment to enable.
|
|
||||||
#ZED_GOTIFY_APPTOKEN=""
|
|
||||||
|
|
||||||
##
|
|
||||||
# Gotify priority (optional)
|
|
||||||
# If defined, this overrides the default priority of the
|
|
||||||
# Gotify application associated with ZED_GOTIFY_APPTOKEN.
|
|
||||||
# Value is an integer 0 and up.
|
|
||||||
#ZED_GOTIFY_PRIORITY=""
|
|
||||||
|
|||||||
+3
-17
@@ -48,7 +48,6 @@ zed_conf_init(struct zed_conf *zcp)
|
|||||||
zcp->zevent_fd = -1; /* opened in zed_event_init() */
|
zcp->zevent_fd = -1; /* opened in zed_event_init() */
|
||||||
|
|
||||||
zcp->max_jobs = 16;
|
zcp->max_jobs = 16;
|
||||||
zcp->max_zevent_buf_len = 1 << 20;
|
|
||||||
|
|
||||||
if (!(zcp->pid_file = strdup(ZED_PID_FILE)) ||
|
if (!(zcp->pid_file = strdup(ZED_PID_FILE)) ||
|
||||||
!(zcp->zedlet_dir = strdup(ZED_ZEDLET_DIR)) ||
|
!(zcp->zedlet_dir = strdup(ZED_ZEDLET_DIR)) ||
|
||||||
@@ -142,8 +141,6 @@ _zed_conf_display_help(const char *prog, boolean_t got_err)
|
|||||||
.v = ZED_STATE_FILE },
|
.v = ZED_STATE_FILE },
|
||||||
{ .o = "-j JOBS", .d = "Start at most JOBS at once.",
|
{ .o = "-j JOBS", .d = "Start at most JOBS at once.",
|
||||||
.v = "16" },
|
.v = "16" },
|
||||||
{ .o = "-b LEN", .d = "Cap kernel event buffer at LEN entries.",
|
|
||||||
.v = "1048576" },
|
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -233,7 +230,7 @@ _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:b:";
|
const char * const opts = ":hLVd:p:P:s:vfFMZIj:";
|
||||||
int opt;
|
int opt;
|
||||||
unsigned long raw;
|
unsigned long raw;
|
||||||
|
|
||||||
@@ -294,17 +291,6 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
|||||||
zcp->max_jobs = raw;
|
zcp->max_jobs = raw;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'b':
|
|
||||||
errno = 0;
|
|
||||||
raw = strtoul(optarg, NULL, 0);
|
|
||||||
if (errno == ERANGE || raw > INT32_MAX) {
|
|
||||||
zed_log_die("%lu is too large", raw);
|
|
||||||
} if (raw == 0) {
|
|
||||||
zcp->max_zevent_buf_len = INT32_MAX;
|
|
||||||
} else {
|
|
||||||
zcp->max_zevent_buf_len = raw;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
if (optopt == '?')
|
if (optopt == '?')
|
||||||
@@ -657,7 +643,7 @@ zed_conf_read_state(struct zed_conf *zcp, uint64_t *eidp, int64_t etime[])
|
|||||||
} else if (n != len) {
|
} else if (n != len) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
zed_log_msg(LOG_WARNING,
|
zed_log_msg(LOG_WARNING,
|
||||||
"Failed to read state file \"%s\": Read %zd of %zd bytes",
|
"Failed to read state file \"%s\": Read %d of %d bytes",
|
||||||
zcp->state_file, n, len);
|
zcp->state_file, n, len);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@@ -706,7 +692,7 @@ zed_conf_write_state(struct zed_conf *zcp, uint64_t eid, int64_t etime[])
|
|||||||
if (n != len) {
|
if (n != len) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
zed_log_msg(LOG_WARNING,
|
zed_log_msg(LOG_WARNING,
|
||||||
"Failed to write state file \"%s\": Wrote %zd of %zd bytes",
|
"Failed to write state file \"%s\": Wrote %d of %d bytes",
|
||||||
zcp->state_file, n, len);
|
zcp->state_file, n, len);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ struct zed_conf {
|
|||||||
int zevent_fd; /* fd for access to zevents */
|
int zevent_fd; /* fd for access to zevents */
|
||||||
|
|
||||||
int16_t max_jobs; /* max zedlets to run at one time */
|
int16_t max_jobs; /* max zedlets to run at one time */
|
||||||
int32_t max_zevent_buf_len; /* max size of kernel event list */
|
|
||||||
|
|
||||||
boolean_t do_force:1; /* true if force enabled */
|
boolean_t do_force:1; /* true if force enabled */
|
||||||
boolean_t do_foreground:1; /* true if run in foreground */
|
boolean_t do_foreground:1; /* true if run in foreground */
|
||||||
|
|||||||
+20
-61
@@ -49,7 +49,7 @@ struct udev_monitor *g_mon;
|
|||||||
#define DEV_BYID_PATH "/dev/disk/by-id/"
|
#define DEV_BYID_PATH "/dev/disk/by-id/"
|
||||||
|
|
||||||
/* 64MB is minimum usable disk for ZFS */
|
/* 64MB is minimum usable disk for ZFS */
|
||||||
#define MINIMUM_SECTORS 131072ULL
|
#define MINIMUM_SECTORS 131072
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -60,7 +60,7 @@ struct udev_monitor *g_mon;
|
|||||||
static void
|
static void
|
||||||
zed_udev_event(const char *class, const char *subclass, nvlist_t *nvl)
|
zed_udev_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||||
{
|
{
|
||||||
const char *strval;
|
char *strval;
|
||||||
uint64_t numval;
|
uint64_t numval;
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO, "zed_disk_event:");
|
zed_log_msg(LOG_INFO, "zed_disk_event:");
|
||||||
@@ -78,8 +78,6 @@ zed_udev_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
zed_log_msg(LOG_INFO, "\t%s: %s", DEV_PHYS_PATH, strval);
|
zed_log_msg(LOG_INFO, "\t%s: %s", DEV_PHYS_PATH, strval);
|
||||||
if (nvlist_lookup_uint64(nvl, DEV_SIZE, &numval) == 0)
|
if (nvlist_lookup_uint64(nvl, DEV_SIZE, &numval) == 0)
|
||||||
zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_SIZE, numval);
|
zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_SIZE, numval);
|
||||||
if (nvlist_lookup_uint64(nvl, DEV_PARENT_SIZE, &numval) == 0)
|
|
||||||
zed_log_msg(LOG_INFO, "\t%s: %llu", DEV_PARENT_SIZE, numval);
|
|
||||||
if (nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &numval) == 0)
|
if (nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &numval) == 0)
|
||||||
zed_log_msg(LOG_INFO, "\t%s: %llu", ZFS_EV_POOL_GUID, numval);
|
zed_log_msg(LOG_INFO, "\t%s: %llu", ZFS_EV_POOL_GUID, numval);
|
||||||
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &numval) == 0)
|
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &numval) == 0)
|
||||||
@@ -132,21 +130,6 @@ dev_event_nvlist(struct udev_device *dev)
|
|||||||
|
|
||||||
numval *= strtoull(value, NULL, 10);
|
numval *= strtoull(value, NULL, 10);
|
||||||
(void) nvlist_add_uint64(nvl, DEV_SIZE, numval);
|
(void) nvlist_add_uint64(nvl, DEV_SIZE, numval);
|
||||||
|
|
||||||
/*
|
|
||||||
* If the device has a parent, then get the parent block
|
|
||||||
* device's size as well. For example, /dev/sda1's parent
|
|
||||||
* is /dev/sda.
|
|
||||||
*/
|
|
||||||
struct udev_device *parent_dev = udev_device_get_parent(dev);
|
|
||||||
if (parent_dev != NULL &&
|
|
||||||
(value = udev_device_get_sysattr_value(parent_dev, "size"))
|
|
||||||
!= NULL) {
|
|
||||||
uint64_t numval = DEV_BSIZE;
|
|
||||||
|
|
||||||
numval *= strtoull(value, NULL, 10);
|
|
||||||
(void) nvlist_add_uint64(nvl, DEV_PARENT_SIZE, numval);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -179,15 +162,14 @@ static void *
|
|||||||
zed_udev_monitor(void *arg)
|
zed_udev_monitor(void *arg)
|
||||||
{
|
{
|
||||||
struct udev_monitor *mon = arg;
|
struct udev_monitor *mon = arg;
|
||||||
const char *tmp;
|
char *tmp, *tmp2;
|
||||||
char *tmp2;
|
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO, "Waiting for new udev disk events...");
|
zed_log_msg(LOG_INFO, "Waiting for new udev disk events...");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct udev_device *dev;
|
struct udev_device *dev;
|
||||||
const char *action, *type, *part, *sectors;
|
const char *action, *type, *part, *sectors;
|
||||||
const char *bus, *uuid, *devpath;
|
const char *bus, *uuid;
|
||||||
const char *class, *subclass;
|
const char *class, *subclass;
|
||||||
nvlist_t *nvl;
|
nvlist_t *nvl;
|
||||||
boolean_t is_zfs = B_FALSE;
|
boolean_t is_zfs = B_FALSE;
|
||||||
@@ -226,12 +208,6 @@ zed_udev_monitor(void *arg)
|
|||||||
* if this is a disk and it is partitioned, then the
|
* if this is a disk and it is partitioned, then the
|
||||||
* zfs label will reside in a DEVTYPE=partition and
|
* zfs label will reside in a DEVTYPE=partition and
|
||||||
* we can skip passing this event
|
* we can skip passing this event
|
||||||
*
|
|
||||||
* Special case: Blank disks are sometimes reported with
|
|
||||||
* an erroneous 'atari' partition, and should not be
|
|
||||||
* excluded from being used as an autoreplace disk:
|
|
||||||
*
|
|
||||||
* https://github.com/openzfs/zfs/issues/13497
|
|
||||||
*/
|
*/
|
||||||
type = udev_device_get_property_value(dev, "DEVTYPE");
|
type = udev_device_get_property_value(dev, "DEVTYPE");
|
||||||
part = udev_device_get_property_value(dev,
|
part = udev_device_get_property_value(dev,
|
||||||
@@ -239,23 +215,14 @@ zed_udev_monitor(void *arg)
|
|||||||
if (type != NULL && type[0] != '\0' &&
|
if (type != NULL && type[0] != '\0' &&
|
||||||
strcmp(type, "disk") == 0 &&
|
strcmp(type, "disk") == 0 &&
|
||||||
part != NULL && part[0] != '\0') {
|
part != NULL && part[0] != '\0') {
|
||||||
const char *devname =
|
zed_log_msg(LOG_INFO,
|
||||||
udev_device_get_property_value(dev, "DEVNAME");
|
"%s: skip %s since it has a %s partition already",
|
||||||
|
__func__,
|
||||||
if (strcmp(part, "atari") == 0) {
|
udev_device_get_property_value(dev, "DEVNAME"),
|
||||||
zed_log_msg(LOG_INFO,
|
part);
|
||||||
"%s: %s is reporting an atari partition, "
|
/* skip and wait for partition event */
|
||||||
"but we're going to assume it's a false "
|
udev_device_unref(dev);
|
||||||
"positive and still use it (issue #13497)",
|
continue;
|
||||||
__func__, devname);
|
|
||||||
} else {
|
|
||||||
zed_log_msg(LOG_INFO,
|
|
||||||
"%s: skip %s since it has a %s partition "
|
|
||||||
"already", __func__, devname, part);
|
|
||||||
/* skip and wait for partition event */
|
|
||||||
udev_device_unref(dev);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -281,19 +248,10 @@ zed_udev_monitor(void *arg)
|
|||||||
* device id string is required in the message schema
|
* device id string is required in the message schema
|
||||||
* for matching with vdevs. Preflight here for expected
|
* for matching with vdevs. Preflight here for expected
|
||||||
* udev information.
|
* udev information.
|
||||||
*
|
|
||||||
* Special case:
|
|
||||||
* NVMe devices don't have ID_BUS set (at least on RHEL 7-8),
|
|
||||||
* but they are valid for autoreplace. Add a special case for
|
|
||||||
* them by searching for "/nvme/" in the udev DEVPATH:
|
|
||||||
*
|
|
||||||
* DEVPATH=/devices/pci0000:00/0000:00:1e.0/nvme/nvme2/nvme2n1
|
|
||||||
*/
|
*/
|
||||||
bus = udev_device_get_property_value(dev, "ID_BUS");
|
bus = udev_device_get_property_value(dev, "ID_BUS");
|
||||||
uuid = udev_device_get_property_value(dev, "DM_UUID");
|
uuid = udev_device_get_property_value(dev, "DM_UUID");
|
||||||
devpath = udev_device_get_devpath(dev);
|
if (!is_zfs && (bus == NULL && uuid == NULL)) {
|
||||||
if (!is_zfs && (bus == NULL && uuid == NULL &&
|
|
||||||
strstr(devpath, "/nvme/") == NULL)) {
|
|
||||||
zed_log_msg(LOG_INFO, "zed_udev_monitor: %s no devid "
|
zed_log_msg(LOG_INFO, "zed_udev_monitor: %s no devid "
|
||||||
"source", udev_device_get_devnode(dev));
|
"source", udev_device_get_devnode(dev));
|
||||||
udev_device_unref(dev);
|
udev_device_unref(dev);
|
||||||
@@ -338,7 +296,7 @@ zed_udev_monitor(void *arg)
|
|||||||
if (strcmp(class, EC_DEV_STATUS) == 0 &&
|
if (strcmp(class, EC_DEV_STATUS) == 0 &&
|
||||||
udev_device_get_property_value(dev, "DM_UUID") &&
|
udev_device_get_property_value(dev, "DM_UUID") &&
|
||||||
udev_device_get_property_value(dev, "MPATH_SBIN_PATH")) {
|
udev_device_get_property_value(dev, "MPATH_SBIN_PATH")) {
|
||||||
tmp = udev_device_get_devnode(dev);
|
tmp = (char *)udev_device_get_devnode(dev);
|
||||||
tmp2 = zfs_get_underlying_path(tmp);
|
tmp2 = zfs_get_underlying_path(tmp);
|
||||||
if (tmp && tmp2 && (strcmp(tmp, tmp2) != 0)) {
|
if (tmp && tmp2 && (strcmp(tmp, tmp2) != 0)) {
|
||||||
/*
|
/*
|
||||||
@@ -355,7 +313,8 @@ zed_udev_monitor(void *arg)
|
|||||||
class = EC_DEV_ADD;
|
class = EC_DEV_ADD;
|
||||||
subclass = ESC_DISK;
|
subclass = ESC_DISK;
|
||||||
} else {
|
} else {
|
||||||
tmp = udev_device_get_property_value(dev,
|
tmp = (char *)
|
||||||
|
udev_device_get_property_value(dev,
|
||||||
"DM_NR_VALID_PATHS");
|
"DM_NR_VALID_PATHS");
|
||||||
/* treat as a multipath remove */
|
/* treat as a multipath remove */
|
||||||
if (tmp != NULL && strcmp(tmp, "0") == 0) {
|
if (tmp != NULL && strcmp(tmp, "0") == 0) {
|
||||||
@@ -403,7 +362,7 @@ zed_udev_monitor(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
zed_disk_event_init(void)
|
zed_disk_event_init()
|
||||||
{
|
{
|
||||||
int fd, fflags;
|
int fd, fflags;
|
||||||
|
|
||||||
@@ -439,7 +398,7 @@ zed_disk_event_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
zed_disk_event_fini(void)
|
zed_disk_event_fini()
|
||||||
{
|
{
|
||||||
/* cancel monitor thread at recvmsg() */
|
/* cancel monitor thread at recvmsg() */
|
||||||
(void) pthread_cancel(g_mon_tid);
|
(void) pthread_cancel(g_mon_tid);
|
||||||
@@ -457,13 +416,13 @@ zed_disk_event_fini(void)
|
|||||||
#include "zed_disk_event.h"
|
#include "zed_disk_event.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
zed_disk_event_init(void)
|
zed_disk_event_init()
|
||||||
{
|
{
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
zed_disk_event_fini(void)
|
zed_disk_event_fini()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-59
@@ -35,12 +35,9 @@
|
|||||||
#include "zed_strings.h"
|
#include "zed_strings.h"
|
||||||
|
|
||||||
#include "agents/zfs_agents.h"
|
#include "agents/zfs_agents.h"
|
||||||
#include <libzutil.h>
|
|
||||||
|
|
||||||
#define MAXBUF 4096
|
#define MAXBUF 4096
|
||||||
|
|
||||||
static int max_zevent_buf_len = 1 << 20;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the libzfs interface.
|
* Open the libzfs interface.
|
||||||
*/
|
*/
|
||||||
@@ -73,9 +70,6 @@ zed_event_init(struct zed_conf *zcp)
|
|||||||
zed_log_die("Failed to initialize disk events");
|
zed_log_die("Failed to initialize disk events");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zcp->max_zevent_buf_len != 0)
|
|
||||||
max_zevent_buf_len = zcp->max_zevent_buf_len;
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +105,7 @@ _bump_event_queue_length(void)
|
|||||||
{
|
{
|
||||||
int zzlm = -1, wr;
|
int zzlm = -1, wr;
|
||||||
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
|
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
|
||||||
long int qlen, orig_qlen;
|
long int qlen;
|
||||||
|
|
||||||
zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR);
|
zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR);
|
||||||
if (zzlm < 0)
|
if (zzlm < 0)
|
||||||
@@ -122,7 +116,7 @@ _bump_event_queue_length(void)
|
|||||||
qlen_buf[sizeof (qlen_buf) - 1] = '\0';
|
qlen_buf[sizeof (qlen_buf) - 1] = '\0';
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
orig_qlen = qlen = strtol(qlen_buf, NULL, 10);
|
qlen = strtol(qlen_buf, NULL, 10);
|
||||||
if (errno == ERANGE)
|
if (errno == ERANGE)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@@ -131,21 +125,11 @@ _bump_event_queue_length(void)
|
|||||||
else
|
else
|
||||||
qlen *= 2;
|
qlen *= 2;
|
||||||
|
|
||||||
/*
|
if (qlen > INT_MAX)
|
||||||
* Don't consume all of kernel memory with event logs if something
|
qlen = INT_MAX;
|
||||||
* goes wrong.
|
|
||||||
*/
|
|
||||||
if (qlen > max_zevent_buf_len)
|
|
||||||
qlen = max_zevent_buf_len;
|
|
||||||
if (qlen == orig_qlen)
|
|
||||||
goto done;
|
|
||||||
wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen);
|
wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen);
|
||||||
if (wr >= sizeof (qlen_buf)) {
|
|
||||||
wr = sizeof (qlen_buf) - 1;
|
|
||||||
zed_log_msg(LOG_WARNING, "Truncation in %s()", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pwrite(zzlm, qlen_buf, wr + 1, 0) < 0)
|
if (pwrite(zzlm, qlen_buf, wr, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
zed_log_msg(LOG_WARNING, "Bumping queue length to %ld", qlen);
|
zed_log_msg(LOG_WARNING, "Bumping queue length to %ld", qlen);
|
||||||
@@ -613,7 +597,7 @@ _zed_event_add_string_array(uint64_t eid, zed_strings_t *zsp,
|
|||||||
char buf[MAXBUF];
|
char buf[MAXBUF];
|
||||||
int buflen = sizeof (buf);
|
int buflen = sizeof (buf);
|
||||||
const char *name;
|
const char *name;
|
||||||
const char **strp;
|
char **strp;
|
||||||
uint_t nelem;
|
uint_t nelem;
|
||||||
uint_t i;
|
uint_t i;
|
||||||
char *p;
|
char *p;
|
||||||
@@ -653,7 +637,7 @@ _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
|
|||||||
uint16_t i16;
|
uint16_t i16;
|
||||||
uint32_t i32;
|
uint32_t i32;
|
||||||
uint64_t i64;
|
uint64_t i64;
|
||||||
const char *str;
|
char *str;
|
||||||
|
|
||||||
assert(zsp != NULL);
|
assert(zsp != NULL);
|
||||||
assert(nvp != NULL);
|
assert(nvp != NULL);
|
||||||
@@ -900,21 +884,21 @@ _zed_event_get_subclass(const char *class)
|
|||||||
static void
|
static void
|
||||||
_zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
|
_zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
|
||||||
{
|
{
|
||||||
struct tm stp;
|
struct tm *stp;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
assert(zsp != NULL);
|
assert(zsp != NULL);
|
||||||
assert(etime != NULL);
|
assert(etime != NULL);
|
||||||
|
|
||||||
_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_SECS",
|
_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_SECS",
|
||||||
"%" PRId64, etime[0]);
|
"%lld", (long long int) etime[0]);
|
||||||
_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_NSECS",
|
_zed_event_add_var(eid, zsp, ZEVENT_VAR_PREFIX, "TIME_NSECS",
|
||||||
"%" PRId64, etime[1]);
|
"%lld", (long long int) etime[1]);
|
||||||
|
|
||||||
if (!localtime_r((const time_t *) &etime[0], &stp)) {
|
if (!(stp = localtime((const time_t *) &etime[0]))) {
|
||||||
zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
|
zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
|
||||||
ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "localtime error");
|
ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "localtime error");
|
||||||
} else if (!strftime(buf, sizeof (buf), "%Y-%m-%d %H:%M:%S%z", &stp)) {
|
} else if (!strftime(buf, sizeof (buf), "%Y-%m-%d %H:%M:%S%z", stp)) {
|
||||||
zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
|
zed_log_msg(LOG_WARNING, "Failed to add %s%s for eid=%llu: %s",
|
||||||
ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "strftime error");
|
ZEVENT_VAR_PREFIX, "TIME_STRING", eid, "strftime error");
|
||||||
} else {
|
} else {
|
||||||
@@ -923,25 +907,6 @@ _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
_zed_event_update_enc_sysfs_path(nvlist_t *nvl)
|
|
||||||
{
|
|
||||||
const char *vdev_path;
|
|
||||||
|
|
||||||
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_PATH,
|
|
||||||
&vdev_path) != 0) {
|
|
||||||
return; /* some other kind of event, ignore it */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vdev_path == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
update_vdev_config_dev_sysfs_path(nvl, vdev_path,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_ENC_SYSFS_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Service the next zevent, blocking until one is available.
|
* Service the next zevent, blocking until one is available.
|
||||||
*/
|
*/
|
||||||
@@ -955,7 +920,7 @@ zed_event_service(struct zed_conf *zcp)
|
|||||||
uint64_t eid;
|
uint64_t eid;
|
||||||
int64_t *etime;
|
int64_t *etime;
|
||||||
uint_t nelem;
|
uint_t nelem;
|
||||||
const char *class;
|
char *class;
|
||||||
const char *subclass;
|
const char *subclass;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
@@ -989,17 +954,6 @@ zed_event_service(struct zed_conf *zcp)
|
|||||||
zed_log_msg(LOG_WARNING,
|
zed_log_msg(LOG_WARNING,
|
||||||
"Failed to lookup zevent class (eid=%llu)", eid);
|
"Failed to lookup zevent class (eid=%llu)", eid);
|
||||||
} else {
|
} else {
|
||||||
/*
|
|
||||||
* Special case: If we can dynamically detect an enclosure sysfs
|
|
||||||
* path, then use that value rather than the one stored in the
|
|
||||||
* vd->vdev_enc_sysfs_path. There have been rare cases where
|
|
||||||
* vd->vdev_enc_sysfs_path becomes outdated. However, there
|
|
||||||
* will be other times when we can not dynamically detect the
|
|
||||||
* sysfs path (like if a disk disappears) and have to rely on
|
|
||||||
* the old value for things like turning on the fault LED.
|
|
||||||
*/
|
|
||||||
_zed_event_update_enc_sysfs_path(nvl);
|
|
||||||
|
|
||||||
/* let internal modules see this event first */
|
/* let internal modules see this event first */
|
||||||
zfs_agent_post_event(class, NULL, nvl);
|
zfs_agent_post_event(class, NULL, nvl);
|
||||||
|
|
||||||
|
|||||||
+2
-9
@@ -175,10 +175,6 @@ _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog,
|
|||||||
node->pid = pid;
|
node->pid = pid;
|
||||||
node->eid = eid;
|
node->eid = eid;
|
||||||
node->name = strdup(prog);
|
node->name = strdup(prog);
|
||||||
if (node->name == NULL) {
|
|
||||||
perror("strdup");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
avl_add(&_launched_processes, node);
|
avl_add(&_launched_processes, node);
|
||||||
}
|
}
|
||||||
@@ -191,14 +187,11 @@ _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
_nop(int sig)
|
_nop(int sig)
|
||||||
{
|
{}
|
||||||
(void) sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
_reap_children(void *arg)
|
_reap_children(void *arg)
|
||||||
{
|
{
|
||||||
(void) arg;
|
|
||||||
struct launched_process_node node, *pnode;
|
struct launched_process_node node, *pnode;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status;
|
||||||
@@ -267,7 +260,7 @@ _reap_children(void *arg)
|
|||||||
zed_log_msg(LOG_INFO,
|
zed_log_msg(LOG_INFO,
|
||||||
"Finished \"%s\" eid=%llu pid=%d "
|
"Finished \"%s\" eid=%llu pid=%d "
|
||||||
"time=%llu.%06us status=0x%X",
|
"time=%llu.%06us status=0x%X",
|
||||||
node.name, node.eid, pid,
|
node.name, node.eid,
|
||||||
(unsigned long long) usage.ru_utime.tv_sec,
|
(unsigned long long) usage.ru_utime.tv_sec,
|
||||||
(unsigned int) usage.ru_utime.tv_usec,
|
(unsigned int) usage.ru_utime.tv_usec,
|
||||||
(unsigned int) status);
|
(unsigned int) status);
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ void zed_log_syslog_close(void);
|
|||||||
|
|
||||||
void zed_log_msg(int priority, const char *fmt, ...);
|
void zed_log_msg(int priority, const char *fmt, ...);
|
||||||
|
|
||||||
__attribute__((format(printf, 1, 2), __noreturn__))
|
|
||||||
void zed_log_die(const char *fmt, ...);
|
void zed_log_die(const char *fmt, ...);
|
||||||
|
|
||||||
#endif /* !ZED_LOG_H */
|
#endif /* !ZED_LOG_H */
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
/zfs
|
||||||
+15
-12
@@ -1,22 +1,25 @@
|
|||||||
sbin_PROGRAMS += zfs
|
include $(top_srcdir)/config/Rules.am
|
||||||
CPPCHECKTARGETS += zfs
|
|
||||||
|
sbin_PROGRAMS = zfs
|
||||||
|
|
||||||
zfs_SOURCES = \
|
zfs_SOURCES = \
|
||||||
%D%/zfs_iter.c \
|
zfs_iter.c \
|
||||||
%D%/zfs_iter.h \
|
zfs_iter.h \
|
||||||
%D%/zfs_main.c \
|
zfs_main.c \
|
||||||
%D%/zfs_project.c \
|
zfs_util.h \
|
||||||
%D%/zfs_projectutil.h \
|
zfs_project.c \
|
||||||
%D%/zfs_util.h
|
zfs_projectutil.h
|
||||||
|
|
||||||
zfs_LDADD = \
|
zfs_LDADD = \
|
||||||
libzfs.la \
|
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||||
libzfs_core.la \
|
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||||
libnvpair.la \
|
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
libuutil.la
|
$(abs_top_builddir)/lib/libuutil/libuutil.la
|
||||||
|
|
||||||
zfs_LDADD += $(LTLIBINTL)
|
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
|
||||||
|
|||||||
+27
-69
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
|
|
||||||
@@ -143,20 +144,19 @@ zfs_callback(zfs_handle_t *zhp, void *data)
|
|||||||
(cb->cb_types &
|
(cb->cb_types &
|
||||||
(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) &&
|
(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) &&
|
||||||
zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
|
zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
|
||||||
(void) zfs_iter_filesystems_v2(zhp, cb->cb_flags,
|
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
|
||||||
zfs_callback, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
|
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
|
||||||
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps) {
|
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps) {
|
||||||
(void) zfs_iter_snapshots_v2(zhp, cb->cb_flags,
|
(void) zfs_iter_snapshots(zhp,
|
||||||
|
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0,
|
||||||
zfs_callback, data, 0, 0);
|
zfs_callback, data, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
|
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
|
||||||
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks) {
|
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks) {
|
||||||
(void) zfs_iter_bookmarks_v2(zhp, cb->cb_flags,
|
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
|
||||||
zfs_callback, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cb->cb_depth--;
|
cb->cb_depth--;
|
||||||
@@ -175,7 +175,7 @@ zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
|
|||||||
zfs_sort_column_t *col;
|
zfs_sort_column_t *col;
|
||||||
zfs_prop_t prop;
|
zfs_prop_t prop;
|
||||||
|
|
||||||
if ((prop = zfs_name_to_prop(name)) == ZPROP_USERPROP &&
|
if ((prop = zfs_name_to_prop(name)) == ZPROP_INVAL &&
|
||||||
!zfs_prop_user(name))
|
!zfs_prop_user(name))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
|
|||||||
|
|
||||||
col->sc_prop = prop;
|
col->sc_prop = prop;
|
||||||
col->sc_reverse = reverse;
|
col->sc_reverse = reverse;
|
||||||
if (prop == ZPROP_USERPROP) {
|
if (prop == ZPROP_INVAL) {
|
||||||
col->sc_user_prop = safe_malloc(strlen(name) + 1);
|
col->sc_user_prop = safe_malloc(strlen(name) + 1);
|
||||||
(void) strcpy(col->sc_user_prop, name);
|
(void) strcpy(col->sc_user_prop, name);
|
||||||
}
|
}
|
||||||
@@ -212,62 +212,16 @@ zfs_free_sort_columns(zfs_sort_column_t *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int
|
||||||
* Return true if all of the properties to be sorted are populated by
|
zfs_sort_only_by_name(const zfs_sort_column_t *sc)
|
||||||
* dsl_dataset_fast_stat(). Note that sc == NULL (no sort) means we
|
|
||||||
* don't need any extra properties, so returns true.
|
|
||||||
*/
|
|
||||||
boolean_t
|
|
||||||
zfs_sort_only_by_fast(const zfs_sort_column_t *sc)
|
|
||||||
{
|
{
|
||||||
while (sc != NULL) {
|
return (sc != NULL && sc->sc_next == NULL &&
|
||||||
switch (sc->sc_prop) {
|
sc->sc_prop == ZFS_PROP_NAME);
|
||||||
case ZFS_PROP_NAME:
|
|
||||||
case ZFS_PROP_GUID:
|
|
||||||
case ZFS_PROP_CREATETXG:
|
|
||||||
case ZFS_PROP_NUMCLONES:
|
|
||||||
case ZFS_PROP_INCONSISTENT:
|
|
||||||
case ZFS_PROP_REDACTED:
|
|
||||||
case ZFS_PROP_ORIGIN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return (B_FALSE);
|
|
||||||
}
|
|
||||||
sc = sc->sc_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (B_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean_t
|
|
||||||
zfs_list_only_by_fast(const zprop_list_t *p)
|
|
||||||
{
|
|
||||||
if (p == NULL) {
|
|
||||||
/* NULL means 'all' so we can't use simple mode */
|
|
||||||
return (B_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (p != NULL) {
|
|
||||||
switch (p->pl_prop) {
|
|
||||||
case ZFS_PROP_NAME:
|
|
||||||
case ZFS_PROP_GUID:
|
|
||||||
case ZFS_PROP_CREATETXG:
|
|
||||||
case ZFS_PROP_NUMCLONES:
|
|
||||||
case ZFS_PROP_INCONSISTENT:
|
|
||||||
case ZFS_PROP_REDACTED:
|
|
||||||
case ZFS_PROP_ORIGIN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return (B_FALSE);
|
|
||||||
}
|
|
||||||
p = p->pl_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (B_TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
zfs_compare(const void *larg, const void *rarg)
|
zfs_compare(const void *larg, const void *rarg, void *unused)
|
||||||
{
|
{
|
||||||
zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
|
zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
|
||||||
zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
|
zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
|
||||||
@@ -348,8 +302,8 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
|||||||
|
|
||||||
for (psc = sc; psc != NULL; psc = psc->sc_next) {
|
for (psc = sc; psc != NULL; psc = psc->sc_next) {
|
||||||
char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN];
|
char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN];
|
||||||
const char *lstr, *rstr;
|
char *lstr, *rstr;
|
||||||
uint64_t lnum = 0, rnum = 0;
|
uint64_t lnum, rnum;
|
||||||
boolean_t lvalid, rvalid;
|
boolean_t lvalid, rvalid;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -359,7 +313,7 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
|||||||
* Otherwise, we compare 'lnum' and 'rnum'.
|
* Otherwise, we compare 'lnum' and 'rnum'.
|
||||||
*/
|
*/
|
||||||
lstr = rstr = NULL;
|
lstr = rstr = NULL;
|
||||||
if (psc->sc_prop == ZPROP_USERPROP) {
|
if (psc->sc_prop == ZPROP_INVAL) {
|
||||||
nvlist_t *luser, *ruser;
|
nvlist_t *luser, *ruser;
|
||||||
nvlist_t *lval, *rval;
|
nvlist_t *lval, *rval;
|
||||||
|
|
||||||
@@ -400,9 +354,11 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
|||||||
zfs_get_type(r), B_FALSE);
|
zfs_get_type(r), B_FALSE);
|
||||||
|
|
||||||
if (lvalid)
|
if (lvalid)
|
||||||
lnum = zfs_prop_get_int(l, psc->sc_prop);
|
(void) zfs_prop_get_numeric(l, psc->sc_prop,
|
||||||
|
&lnum, NULL, NULL, 0);
|
||||||
if (rvalid)
|
if (rvalid)
|
||||||
rnum = zfs_prop_get_int(r, psc->sc_prop);
|
(void) zfs_prop_get_numeric(r, psc->sc_prop,
|
||||||
|
&rnum, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lvalid && !rvalid)
|
if (!lvalid && !rvalid)
|
||||||
@@ -426,7 +382,7 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (zfs_compare(larg, rarg));
|
return (zfs_compare(larg, rarg, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -498,21 +454,23 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
|||||||
cb.cb_flags |= ZFS_ITER_RECURSE;
|
cb.cb_flags |= ZFS_ITER_RECURSE;
|
||||||
ret = zfs_iter_root(g_zfs, zfs_callback, &cb);
|
ret = zfs_iter_root(g_zfs, zfs_callback, &cb);
|
||||||
} else {
|
} else {
|
||||||
zfs_handle_t *zhp = NULL;
|
int i;
|
||||||
zfs_type_t argtype = types;
|
zfs_handle_t *zhp;
|
||||||
|
zfs_type_t argtype;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're recursive, then we always allow filesystems as
|
* If we're recursive, then we always allow filesystems as
|
||||||
* arguments. If we also are interested in snapshots or
|
* arguments. If we also are interested in snapshots or
|
||||||
* bookmarks, then we can take volumes as well.
|
* bookmarks, then we can take volumes as well.
|
||||||
*/
|
*/
|
||||||
|
argtype = types;
|
||||||
if (flags & ZFS_ITER_RECURSE) {
|
if (flags & ZFS_ITER_RECURSE) {
|
||||||
argtype |= ZFS_TYPE_FILESYSTEM;
|
argtype |= ZFS_TYPE_FILESYSTEM;
|
||||||
if (types & (ZFS_TYPE_SNAPSHOT | ZFS_TYPE_BOOKMARK))
|
if (types & (ZFS_TYPE_SNAPSHOT | ZFS_TYPE_BOOKMARK))
|
||||||
argtype |= ZFS_TYPE_VOLUME;
|
argtype |= ZFS_TYPE_VOLUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (flags & ZFS_ITER_ARGS_CAN_BE_PATHS) {
|
if (flags & ZFS_ITER_ARGS_CAN_BE_PATHS) {
|
||||||
zhp = zfs_path_to_zhandle(g_zfs, argv[i],
|
zhp = zfs_path_to_zhandle(g_zfs, argv[i],
|
||||||
argtype);
|
argtype);
|
||||||
|
|||||||
+10
-3
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -40,12 +40,19 @@ typedef struct zfs_sort_column {
|
|||||||
boolean_t sc_reverse;
|
boolean_t sc_reverse;
|
||||||
} zfs_sort_column_t;
|
} zfs_sort_column_t;
|
||||||
|
|
||||||
|
#define ZFS_ITER_RECURSE (1 << 0)
|
||||||
|
#define ZFS_ITER_ARGS_CAN_BE_PATHS (1 << 1)
|
||||||
|
#define ZFS_ITER_PROP_LISTSNAPS (1 << 2)
|
||||||
|
#define ZFS_ITER_DEPTH_LIMIT (1 << 3)
|
||||||
|
#define ZFS_ITER_RECVD_PROPS (1 << 4)
|
||||||
|
#define ZFS_ITER_LITERAL_PROPS (1 << 5)
|
||||||
|
#define ZFS_ITER_SIMPLE (1 << 6)
|
||||||
|
|
||||||
int zfs_for_each(int, char **, int options, zfs_type_t,
|
int zfs_for_each(int, char **, int options, zfs_type_t,
|
||||||
zfs_sort_column_t *, zprop_list_t **, int, zfs_iter_f, void *);
|
zfs_sort_column_t *, zprop_list_t **, int, zfs_iter_f, void *);
|
||||||
int zfs_add_sort_column(zfs_sort_column_t **, const char *, boolean_t);
|
int zfs_add_sort_column(zfs_sort_column_t **, const char *, boolean_t);
|
||||||
void zfs_free_sort_columns(zfs_sort_column_t *);
|
void zfs_free_sort_columns(zfs_sort_column_t *);
|
||||||
boolean_t zfs_sort_only_by_fast(const zfs_sort_column_t *);
|
int zfs_sort_only_by_name(const zfs_sort_column_t *);
|
||||||
boolean_t zfs_list_only_by_fast(const zprop_list_t *);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+533
-1115
File diff suppressed because it is too large
Load Diff
+6
-12
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <strings.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@@ -207,6 +207,7 @@ static int
|
|||||||
zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
|
zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
|
||||||
list_t *head)
|
list_t *head)
|
||||||
{
|
{
|
||||||
|
char fullname[PATH_MAX];
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -226,28 +227,21 @@ zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
|
|||||||
zpc->zpc_ignore_noent = B_TRUE;
|
zpc->zpc_ignore_noent = B_TRUE;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
while (!ret && (ent = readdir(dir)) != NULL) {
|
while (!ret && (ent = readdir(dir)) != NULL) {
|
||||||
char *fullname;
|
|
||||||
|
|
||||||
/* skip "." and ".." */
|
/* skip "." and ".." */
|
||||||
if (strcmp(ent->d_name, ".") == 0 ||
|
if (strcmp(ent->d_name, ".") == 0 ||
|
||||||
strcmp(ent->d_name, "..") == 0)
|
strcmp(ent->d_name, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strlen(ent->d_name) + strlen(name) + 1 >= PATH_MAX) {
|
if (strlen(ent->d_name) + strlen(name) >=
|
||||||
|
sizeof (fullname) + 1) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asprintf(&fullname, "%s/%s", name, ent->d_name) == -1) {
|
sprintf(fullname, "%s/%s", name, ent->d_name);
|
||||||
errno = ENOMEM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = zfs_project_handle_one(fullname, zpc);
|
ret = zfs_project_handle_one(fullname, zpc);
|
||||||
if (!ret && zpc->zpc_recursive && ent->d_type == DT_DIR)
|
if (!ret && zpc->zpc_recursive && ent->d_type == DT_DIR)
|
||||||
zfs_project_item_alloc(head, fullname);
|
zfs_project_item_alloc(head, fullname);
|
||||||
|
|
||||||
free(fullname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno && !ret) {
|
if (errno && !ret) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
*
|
*
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
* or https://opensource.org/licenses/CDDL-1.0.
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
* See the License for the specific language governing permissions
|
* See the License for the specific language governing permissions
|
||||||
* and limitations under the License.
|
* and limitations under the License.
|
||||||
*
|
*
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user