mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 11:18:52 +03:00
Compare commits
270 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8c2b7ebc6 | |||
| 2af898ee24 | |||
| c32c2f17d0 | |||
| 2254b2bbbe | |||
| 5c4ec382a7 | |||
| e22bfd8149 | |||
| f45ad7bff6 | |||
| 0a3a4d067a | |||
| ba8024a284 | |||
| edc2675aed | |||
| 98bb45e27a | |||
| 44f463824b | |||
| b0d579bc55 | |||
| 7e5def8ae0 | |||
| 89019a846b | |||
| 41f7723e9c | |||
| 2b8c3cb0c8 | |||
| f325d76e96 | |||
| e3fb781c5f | |||
| 14a5e48fb9 | |||
| 01937958ce | |||
| edb504f9db | |||
| 2428fbbfcf | |||
| 16d298188f | |||
| f42f8702ce | |||
| 9e58d5ef38 | |||
| 320f9de8ab | |||
| 262275ab26 | |||
| 55f39a01e6 | |||
| b884768e46 | |||
| f8f4e13776 | |||
| 5f07d51751 | |||
| b2f003c4f4 | |||
| 9014da2b01 | |||
| 45579c9515 | |||
| b32f1279d4 | |||
| 1b0cd07131 | |||
| 8c6867dae4 | |||
| 99310c0aa0 | |||
| d126980e5f | |||
| 88ef5b238b | |||
| 30d8b85702 | |||
| 45f0437912 | |||
| dc3eea871a | |||
| d2c8103a68 | |||
| 3ea1f7f193 | |||
| 4356dd23a9 | |||
| 75318ec497 | |||
| c1629734ab | |||
| 778290d5bc | |||
| 98bc8e0b23 | |||
| caafa436eb | |||
| fe8de1c8a6 | |||
| 1bd93ea1e0 | |||
| 6857950e46 | |||
| 716ce2b89e | |||
| 9daae583d8 | |||
| b5ee3df776 | |||
| 17cd9a8e0c | |||
| 2a16d4cfaf | |||
| 3350a33908 | |||
| 3eef58c9b6 | |||
| 4805781c74 | |||
| b06f40ea9b | |||
| 6b5cc49d81 | |||
| ef7a79488a | |||
| a2f759146d | |||
| f79c0de208 | |||
| 1667816089 | |||
| d1ed1be3cd | |||
| e749242a99 | |||
| 9267ef84fd | |||
| 0ee129199f | |||
| 245be00597 | |||
| c38d702330 | |||
| 3f729907c8 | |||
| cca220d7c6 | |||
| 4ed30958ce | |||
| 2f118072cb | |||
| 7440f10ec1 | |||
| 8bb800d6b4 | |||
| bbf61c118f | |||
| d296b09456 | |||
| 5ac017fc04 | |||
| f5ecab3aef | |||
| fd01167ffd | |||
| 3b118f0a34 | |||
| ebe443c8ff | |||
| 63f3396233 | |||
| 2deb4526ee | |||
| a1662ffcaa | |||
| ea921bf6a6 | |||
| 6e627cc468 | |||
| 3eb3a13628 | |||
| c234706270 | |||
| 6059ba27c4 | |||
| 927f40d089 | |||
| 6356d50e67 | |||
| bd69ae3b53 | |||
| 9a2e90c9fc | |||
| 240ccfc13a | |||
| c30e716c81 | |||
| 267fd7b0f1 | |||
| dc0176eeec | |||
| 0a0af41bd9 | |||
| 3808006edf | |||
| c17922b8a9 | |||
| 8d7f17798d | |||
| 6dc40e2ada | |||
| 792f88131c | |||
| 33bb1e8256 | |||
| bcaba38e42 | |||
| 5e3085e360 | |||
| 99920d823e | |||
| 338523dd6e | |||
| 2644784f49 | |||
| b1f61f05b4 | |||
| e5ba614d05 | |||
| 30ac8de48a | |||
| c705d8386b | |||
| d5b10b3ef3 | |||
| 5a84c60fb9 | |||
| 26941ce90b | |||
| 07ce5d7390 | |||
| 1d805a534b | |||
| a9ff89e05c | |||
| d85011ed69 | |||
| b3da003ebf | |||
| 478754a8f5 | |||
| 31ff122aa2 | |||
| 18c662b845 | |||
| c797f0898e | |||
| 5e566c5772 | |||
| 23227313a2 | |||
| 3713b73335 | |||
| 310e63dfd1 | |||
| a196b3bc3d | |||
| a58e1284d8 | |||
| f1dde3fb20 | |||
| 5f38142e7b | |||
| 29b79dcfe9 | |||
| ecc972c7f0 | |||
| 6c891ade8b | |||
| 03658d5081 | |||
| 5d62588032 | |||
| 6897ea475f | |||
| 3790bfa80f | |||
| 6b278f3223 | |||
| f1236ebf35 | |||
| 184087f822 | |||
| 834815e9f7 | |||
| 0f1ff38476 | |||
| e3b28e16ce | |||
| 2f62fdd644 | |||
| 137b3e6cff | |||
| d1630dda58 | |||
| 701ebd014a | |||
| 5b8ec2cf39 | |||
| 9d1a39cec6 | |||
| 2a7b736dce | |||
| ecc8af1812 | |||
| 129e3e8dc3 | |||
| 9fb09f79e5 | |||
| a2ee6568c6 | |||
| 9c1a8eaa51 | |||
| a8fa31b50b | |||
| 8d82a19def | |||
| c2aacf2087 | |||
| 9a6c57845a | |||
| d27a40d28f | |||
| aebc5df418 | |||
| 7a8bef3983 | |||
| d486dee89e | |||
| 7de8fb33a2 | |||
| 904c03672b | |||
| 03955e3488 | |||
| 88e4e0d5dd | |||
| 03f638a8ef | |||
| 5dc25de668 | |||
| 53e5890cff | |||
| a94447ddf3 | |||
| 7192ec7942 | |||
| 06acbbc429 | |||
| 6116bbd744 | |||
| a803eacf26 | |||
| 504bfc8b49 | |||
| 53a8cbd70e | |||
| 505b97ae20 | |||
| 30a64ebaed | |||
| da16fc5739 | |||
| 3c7fa6ca33 | |||
| 36e0ddb744 | |||
| cf21b5b5b2 | |||
| 1030f807ba | |||
| d45702bcfa | |||
| ddd20dbe0b | |||
| 4a98780933 | |||
| 6db8f1a0d1 | |||
| e06711412b | |||
| 68ba1d2fa9 | |||
| 4e11137989 | |||
| be9be1cc3e | |||
| eab4536081 | |||
| 954516cec1 | |||
| 841cb5ee2a | |||
| d4cf31275b | |||
| fedc1d96a8 | |||
| 59511072b4 | |||
| a5c8119eba | |||
| d7881a6dca | |||
| 951e62169e | |||
| 9add19b37d | |||
| b2d633202d | |||
| 414f4a9c54 | |||
| 1c4f5e7d92 | |||
| 246e515cf8 | |||
| 2d41e75e52 | |||
| d834d6811b | |||
| 029a1b0c20 | |||
| c45254b0ec | |||
| 318fdeb51f | |||
| d3d20bf442 | |||
| 99598264fc | |||
| abe30b7b40 | |||
| f90ee0ca3d | |||
| 4ed955e280 | |||
| 1721f13e76 | |||
| 6e893ef62a | |||
| e0eaaf8144 | |||
| cb8a074dcb | |||
| c3ac4ccabb | |||
| 8d688ce66a | |||
| b544fe4123 | |||
| 926c6ec453 | |||
| 91b2f6ab1c | |||
| 851a7cd833 | |||
| 83d4d1a784 | |||
| 80cc2f6111 | |||
| b97948276d | |||
| 4cfc086e4d | |||
| 25d232f407 | |||
| edd7c24623 | |||
| bef6a8bc3a | |||
| 266b181e75 | |||
| c474f5e9a7 | |||
| 4e6a9e4598 | |||
| 661907e6bc | |||
| d3e7d981d4 | |||
| a2a0440918 | |||
| 45d1abc74d | |||
| 89950722c6 | |||
| 4810a108e8 | |||
| ae5b4a05ff | |||
| 3468fdbd34 | |||
| fb3f1fdbd6 | |||
| 426563be70 | |||
| aec4318870 | |||
| 2d9b57d39f | |||
| 4bdb8fcfa8 | |||
| 58c1c40a5e | |||
| 751575fe6f | |||
| 751941e248 | |||
| ef605a5517 | |||
| 8eb6dcec7d | |||
| 07cbcd5089 | |||
| 12acabe2a4 | |||
| 20c88dc3ef | |||
| 0c8fedeb35 | |||
| affb7141d7 | |||
| e0031d86b7 |
@@ -1,10 +0,0 @@
|
|||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.{c,h}]
|
|
||||||
tab_width = 8
|
|
||||||
indent_style = tab
|
|
||||||
+66
-122
@@ -1,12 +1,10 @@
|
|||||||
# Contributing to OpenZFS
|
# Contributing to ZFS on Linux
|
||||||
<p align="center">
|
<p align="center"><img src="http://zfsonlinux.org/images/zfs-linux.png"/></p>
|
||||||
<img alt="OpenZFS Logo"
|
|
||||||
src="https://openzfs.github.io/openzfs-docs/_static/img/logo/480px-Open-ZFS-Secondary-Logo-Colour-halfsize.png"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
*First of all, thank you for taking the time to contribute!*
|
*First of all, thank you for taking the time to contribute!*
|
||||||
|
|
||||||
By using the following guidelines, you can help us make OpenZFS even better.
|
By using the following guidelines, you can help us make ZFS on Linux even
|
||||||
|
better.
|
||||||
|
|
||||||
## Table Of Contents
|
## Table Of Contents
|
||||||
[What should I know before I get
|
[What should I know before I get
|
||||||
@@ -29,22 +27,19 @@ started?](#what-should-i-know-before-i-get-started)
|
|||||||
* [Commit Message Formats](#commit-message-formats)
|
* [Commit Message Formats](#commit-message-formats)
|
||||||
* [New Changes](#new-changes)
|
* [New Changes](#new-changes)
|
||||||
* [OpenZFS Patch Ports](#openzfs-patch-ports)
|
* [OpenZFS Patch Ports](#openzfs-patch-ports)
|
||||||
* [Coverity Defect Fixes](#coverity-defect-fixes)
|
|
||||||
* [Signed Off By](#signed-off-by)
|
|
||||||
|
|
||||||
Helpful resources
|
Helpful resources
|
||||||
|
|
||||||
* [OpenZFS Documentation](https://openzfs.github.io/openzfs-docs/)
|
* [ZFS on Linux wiki](https://github.com/zfsonlinux/zfs/wiki)
|
||||||
* [OpenZFS Developer Resources](http://open-zfs.org/wiki/Developer_resources)
|
* [OpenZFS Documentation](http://open-zfs.org/wiki/Developer_resources)
|
||||||
* [Git and GitHub for beginners](https://openzfs.github.io/openzfs-docs/Developer%20Resources/Git%20and%20GitHub%20for%20beginners.html)
|
|
||||||
|
|
||||||
## What should I know before I get started?
|
## What should I know before I get started?
|
||||||
|
|
||||||
### Get ZFS
|
### Get ZFS
|
||||||
You can build zfs packages by following [these
|
You can build zfs packages by following [these
|
||||||
instructions](https://openzfs.github.io/openzfs-docs/Developer%20Resources/Building%20ZFS.html),
|
instructions](https://github.com/zfsonlinux/zfs/wiki/Building-ZFS),
|
||||||
or install stable packages from [your distribution's
|
or install stable packages from [your distribution's
|
||||||
repository](https://openzfs.github.io/openzfs-docs/Getting%20Started/index.html).
|
repository](https://github.com/zfsonlinux/zfs/wiki/Getting-Started).
|
||||||
|
|
||||||
### Debug ZFS
|
### Debug ZFS
|
||||||
A variety of methods and tools are available to aid ZFS developers.
|
A variety of methods and tools are available to aid ZFS developers.
|
||||||
@@ -53,30 +48,28 @@ configure option should be set. This will enable additional correctness
|
|||||||
checks and all the ASSERTs to help quickly catch potential issues.
|
checks and all the ASSERTs to help quickly catch potential issues.
|
||||||
|
|
||||||
In addition, there are numerous utilities and debugging files which
|
In addition, there are numerous utilities and debugging files which
|
||||||
provide visibility into the inner workings of ZFS. The most useful
|
provide visibility in to the inner workings of ZFS. The most useful
|
||||||
of these tools are discussed in detail on the [Troubleshooting
|
of these tools are discussed in detail on the [debugging ZFS wiki
|
||||||
page](https://openzfs.github.io/openzfs-docs/Basic%20Concepts/Troubleshooting.html).
|
page](https://github.com/zfsonlinux/zfs/wiki/Debugging).
|
||||||
|
|
||||||
### Where can I ask for help?
|
### Where can I ask for help?
|
||||||
The [zfs-discuss mailing
|
The [mailing list](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists)
|
||||||
list](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html)
|
is the best place to ask for help.
|
||||||
or IRC are the best places to ask for help. Please do not file
|
|
||||||
support requests on the GitHub issue tracker.
|
|
||||||
|
|
||||||
## How Can I Contribute?
|
## How Can I Contribute?
|
||||||
|
|
||||||
### Reporting Bugs
|
### Reporting Bugs
|
||||||
*Please* contact us via the [zfs-discuss mailing
|
*Please* contact us via the [mailing
|
||||||
list](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html)
|
list](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists) if you aren't
|
||||||
or IRC if you aren't certain that you are experiencing a bug.
|
certain that you are experiencing a bug.
|
||||||
|
|
||||||
If you run into an issue, please search our [issue
|
If you run into an issue, please search our [issue
|
||||||
tracker](https://github.com/openzfs/zfs/issues) *first* to ensure the
|
tracker](https://github.com/zfsonlinux/zfs/issues) *first* to ensure the
|
||||||
issue hasn't been reported before. Open a new issue only if you haven't
|
issue hasn't been reported before. Open a new issue only if you haven't
|
||||||
found anything similar to your issue.
|
found anything similar to your issue.
|
||||||
|
|
||||||
You can open a new issue and search existing issues using the public [issue
|
You can open a new issue and search existing issues using the public [issue
|
||||||
tracker](https://github.com/openzfs/zfs/issues).
|
tracker](https://github.com/zfsonlinux/zfs/issues).
|
||||||
|
|
||||||
#### When opening a new issue, please include the following information at the top of the issue:
|
#### When opening a new issue, please include the following information at the top of the issue:
|
||||||
* What distribution (with version) you are using.
|
* What distribution (with version) you are using.
|
||||||
@@ -108,13 +101,13 @@ information like:
|
|||||||
* Stack traces which may be logged to `dmesg`.
|
* Stack traces which may be logged to `dmesg`.
|
||||||
|
|
||||||
### Suggesting Enhancements
|
### Suggesting Enhancements
|
||||||
OpenZFS is a widely deployed production filesystem which is under active
|
ZFS on Linux is a widely deployed production filesystem which is under
|
||||||
development. The team's primary focus is on fixing known issues, improving
|
active development. The team's primary focus is on fixing known issues,
|
||||||
performance, and adding compelling new features.
|
improving performance, and adding compelling new features.
|
||||||
|
|
||||||
You can view the list of proposed features
|
You can view the list of proposed features
|
||||||
by filtering the issue tracker by the ["Type: Feature"
|
by filtering the issue tracker by the ["Feature"
|
||||||
label](https://github.com/openzfs/zfs/issues?q=is%3Aopen+is%3Aissue+label%3A%22Type%3A+Feature%22).
|
label](https://github.com/zfsonlinux/zfs/issues?q=is%3Aopen+is%3Aissue+label%3AFeature).
|
||||||
If you have an idea for a feature first check this list. If your idea already
|
If you have an idea for a feature first check this list. If your idea already
|
||||||
appears then add a +1 to the top most comment, this helps us gauge interest
|
appears then add a +1 to the top most comment, this helps us gauge interest
|
||||||
in that feature.
|
in that feature.
|
||||||
@@ -123,11 +116,8 @@ Otherwise, open a new issue and describe your proposed feature. Why is this
|
|||||||
feature needed? What problem does it solve?
|
feature needed? What problem does it solve?
|
||||||
|
|
||||||
### Pull Requests
|
### Pull Requests
|
||||||
|
* All pull requests must be based on the current master branch and apply
|
||||||
#### General
|
without conflicts.
|
||||||
|
|
||||||
* All pull requests, except backports and releases, must be based on the current master branch
|
|
||||||
and should apply without conflicts.
|
|
||||||
* Please attempt to limit pull requests to a single commit which resolves
|
* Please attempt to limit pull requests to a single commit which resolves
|
||||||
one specific issue.
|
one specific issue.
|
||||||
* Make sure your commit messages are in the correct format. See the
|
* Make sure your commit messages are in the correct format. See the
|
||||||
@@ -139,28 +129,16 @@ logically independent patches which build on each other. This makes large
|
|||||||
changes easier to review and approve which speeds up the merging process.
|
changes easier to review and approve which speeds up the merging process.
|
||||||
* Try to keep pull requests simple. Simple code with comments is much easier
|
* Try to keep pull requests simple. Simple code with comments is much easier
|
||||||
to review and approve.
|
to review and approve.
|
||||||
* All proposed changes must be approved by an OpenZFS organization member.
|
|
||||||
* If you have an idea you'd like to discuss or which requires additional testing, consider opening it as a draft pull request.
|
|
||||||
Once everything is in good shape and the details have been worked out you can remove its draft status.
|
|
||||||
Any required reviews can then be finalized and the pull request merged.
|
|
||||||
|
|
||||||
#### Tests and Benchmarks
|
|
||||||
* 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.
|
|
||||||
* To verify your changes conform to the [style guidelines](
|
|
||||||
https://github.com/openzfs/zfs/blob/master/.github/CONTRIBUTING.md#style-guides
|
|
||||||
), please run `make checkstyle` and resolve any warnings.
|
|
||||||
* 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.
|
* 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 required [ZFS
|
* The pull request must pass all required [ZFS
|
||||||
Buildbot](http://build.zfsonlinux.org/) builders before
|
Buildbot](http://build.zfsonlinux.org/) builders before
|
||||||
being accepted. If you are experiencing intermittent TEST
|
being accepted. If you are experiencing intermittent TEST
|
||||||
builder failures, you may be experiencing a [test suite
|
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).
|
issue](https://github.com/zfsonlinux/zfs/issues?q=is%3Aissue+is%3Aopen+label%3A%22Test+Suite%22).
|
||||||
There are also various [buildbot options](https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.html)
|
There are also various [buildbot options](https://github.com/zfsonlinux/zfs/wiki/Buildbot-Options)
|
||||||
to control how changes are tested.
|
to control how changes are tested.
|
||||||
|
* All proposed changes must be approved by a ZFS on Linux organization member.
|
||||||
|
|
||||||
### 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
|
||||||
@@ -170,41 +148,16 @@ range of realistic workloads, configurations and architectures we're better
|
|||||||
able quickly identify and resolve potential issues.
|
able quickly identify and resolve potential issues.
|
||||||
|
|
||||||
Users can also run the [ZFS Test
|
Users can also run the [ZFS Test
|
||||||
Suite](https://github.com/openzfs/zfs/tree/master/tests) on their systems
|
Suite](https://github.com/zfsonlinux/zfs/tree/master/tests) on their systems
|
||||||
to verify ZFS is behaving as intended.
|
to verify ZFS is behaving as intended.
|
||||||
|
|
||||||
## Style Guides
|
## Style Guides
|
||||||
|
|
||||||
### Repository Structure
|
|
||||||
|
|
||||||
OpenZFS uses a standardised branching structure.
|
|
||||||
- The "development and main branch", is the branch all development should be based on.
|
|
||||||
- "Release branches" contain the latest released code for said version.
|
|
||||||
- "Staging branches" contain selected commits prior to being released.
|
|
||||||
|
|
||||||
**Branch Names:**
|
|
||||||
- Development and Main branch: `master`
|
|
||||||
- Release branches: `zfs-$VERSION-release`
|
|
||||||
- Staging branches: `zfs-$VERSION-staging`
|
|
||||||
|
|
||||||
`$VERSION` should be replaced with the `major.minor` version number.
|
|
||||||
_(This is the version number without the `.patch` version at the end)_
|
|
||||||
|
|
||||||
### Coding Conventions
|
### Coding Conventions
|
||||||
We currently use [C Style and Coding Standards for
|
We currently use [C Style and Coding Standards for
|
||||||
SunOS](http://www.cis.upenn.edu/%7Elee/06cse480/data/cstyle.ms.pdf) as our
|
SunOS](http://www.cis.upenn.edu/%7Elee/06cse480/data/cstyle.ms.pdf) as our
|
||||||
coding convention.
|
coding convention.
|
||||||
|
|
||||||
This repository has an `.editorconfig` file. If your editor [supports
|
|
||||||
editorconfig](https://editorconfig.org/#download), it will
|
|
||||||
automatically respect most of this project's whitespace preferences.
|
|
||||||
|
|
||||||
Additionally, Git can help warn on whitespace problems as well:
|
|
||||||
|
|
||||||
```
|
|
||||||
git config --local core.whitespace trailing-space,space-before-tab,indent-with-non-tab,-tab-in-indent
|
|
||||||
```
|
|
||||||
|
|
||||||
### Commit Message Formats
|
### Commit Message Formats
|
||||||
#### New Changes
|
#### New Changes
|
||||||
Commit messages for new changes must meet the following guidelines:
|
Commit messages for new changes must meet the following guidelines:
|
||||||
@@ -214,10 +167,18 @@ first line in the commit message.
|
|||||||
please summarize important information such as why the proposed
|
please summarize important information such as why the proposed
|
||||||
approach was chosen or a brief description of the bug you are resolving.
|
approach was chosen or a brief description of the bug you are resolving.
|
||||||
Each line of the body must be 72 characters or less.
|
Each line of the body must be 72 characters or less.
|
||||||
* The last line must be a `Signed-off-by:` tag. See the
|
* The last line must be a `Signed-off-by:` tag with the developer's
|
||||||
[Signed Off By](#signed-off-by) section for more information.
|
name followed by their email. This is the developer's certification
|
||||||
|
that they have the right to submit the patch for inclusion into
|
||||||
|
the code base and indicates agreement to the [Developer's Certificate
|
||||||
|
of Origin](https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin).
|
||||||
|
Code without a proper signoff cannot be merged.
|
||||||
|
|
||||||
An example commit message for new changes is provided below.
|
Git can append the `Signed-off-by` line to your commit messages. Simply
|
||||||
|
provide the `-s` or `--signoff` option when performing a `git commit`.
|
||||||
|
For more information about writing commit messages, visit [How to Write
|
||||||
|
a Git Commit Message](https://chris.beams.io/posts/git-commit/).
|
||||||
|
An example commit message is provided below.
|
||||||
|
|
||||||
```
|
```
|
||||||
This line is a brief summary of your change
|
This line is a brief summary of your change
|
||||||
@@ -230,52 +191,35 @@ attempting to solve.
|
|||||||
Signed-off-by: Contributor <contributor@email.com>
|
Signed-off-by: Contributor <contributor@email.com>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Coverity Defect Fixes
|
#### OpenZFS Patch Ports
|
||||||
If you are submitting a fix to a
|
If you are porting an OpenZFS patch, the commit message must meet
|
||||||
[Coverity defect](https://scan.coverity.com/projects/zfsonlinux-zfs),
|
the following guidelines:
|
||||||
the commit message should meet the following guidelines:
|
* The first line must be the summary line from the OpenZFS commit.
|
||||||
* Provides a subject line in the format of
|
It must begin with `OpenZFS dddd - ` where `dddd` is the OpenZFS issue number.
|
||||||
`Fix coverity defects: CID dddd, dddd...` where `dddd` represents
|
* Provides a `Authored by:` line to attribute the patch to the original author.
|
||||||
each CID fixed by the commit.
|
* Provides the `Reviewed by:` and `Approved by:` lines from the original
|
||||||
* Provides a body which lists each Coverity defect and how it was corrected.
|
OpenZFS commit.
|
||||||
* The last line must be a `Signed-off-by:` tag. See the
|
* Provides a `Ported-by:` line with the developer's name followed by
|
||||||
[Signed Off By](#signed-off-by) section for more information.
|
their email.
|
||||||
|
* Provides a `OpenZFS-issue:` line which is a link to the original illumos
|
||||||
|
issue.
|
||||||
|
* Provides a `OpenZFS-commit:` line which links back to the original OpenZFS
|
||||||
|
commit.
|
||||||
|
* If necessary, provide some porting notes to describe any deviations from
|
||||||
|
the original OpenZFS commit.
|
||||||
|
|
||||||
An example Coverity defect fix commit message is provided below.
|
An example OpenZFS patch port commit message is provided below.
|
||||||
```
|
```
|
||||||
Fix coverity defects: CID 12345, 67890
|
OpenZFS 1234 - Summary from the original OpenZFS commit
|
||||||
|
|
||||||
CID 12345: Logically dead code (DEADCODE)
|
Authored by: Original Author <original@email.com>
|
||||||
|
Reviewed by: Reviewer One <reviewer1@email.com>
|
||||||
|
Reviewed by: Reviewer Two <reviewer2@email.com>
|
||||||
|
Approved by: Approver One <approver1@email.com>
|
||||||
|
Ported-by: ZFS Contributor <contributor@email.com>
|
||||||
|
|
||||||
Removed the if(var != 0) block because the condition could never be
|
Provide some porting notes here if necessary.
|
||||||
satisfied.
|
|
||||||
|
|
||||||
CID 67890: Resource Leak (RESOURCE_LEAK)
|
OpenZFS-issue: https://www.illumos.org/issues/1234
|
||||||
|
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/abcd1234
|
||||||
Ensure free is called after allocating memory in function().
|
|
||||||
|
|
||||||
Signed-off-by: Contributor <contributor@email.com>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Signed Off By
|
|
||||||
A line tagged as `Signed-off-by:` must contain the developer's
|
|
||||||
name followed by their email. This is the developer's certification
|
|
||||||
that they have the right to submit the patch for inclusion into
|
|
||||||
the code base and indicates agreement to the [Developer's Certificate
|
|
||||||
of Origin](https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin).
|
|
||||||
Code without a proper signoff cannot be merged.
|
|
||||||
|
|
||||||
Git can append the `Signed-off-by` line to your commit messages. Simply
|
|
||||||
provide the `-s` or `--signoff` option when performing a `git commit`.
|
|
||||||
For more information about writing commit messages, visit [How to Write
|
|
||||||
a Git Commit Message](https://chris.beams.io/posts/git-commit/).
|
|
||||||
|
|
||||||
#### Co-authored By
|
|
||||||
If someone else had part in your pull request, please add the following to the commit:
|
|
||||||
`Co-authored-by: Name <gitregistered@email.address>`
|
|
||||||
This is useful if their authorship was lost during squashing, rebasing, etc.,
|
|
||||||
but may be used in any situation where there are co-authors.
|
|
||||||
|
|
||||||
The email address used here should be the same as on the GitHub profile of said user.
|
|
||||||
If said user does not have their email address public, please use the following instead:
|
|
||||||
`Co-authored-by: Name <[username]@users.noreply.github.com>`
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<!--
|
||||||
|
Thank you for reporting an issue.
|
||||||
|
|
||||||
|
*IMPORTANT* - Please search our issue tracker *before* making a new issue.
|
||||||
|
If you cannot find a similar issue, then create a new issue.
|
||||||
|
https://github.com/zfsonlinux/zfs/issues
|
||||||
|
|
||||||
|
*IMPORTANT* - This issue tracker is for *bugs* and *issues* only.
|
||||||
|
Please search the wiki and the mailing list archives before asking
|
||||||
|
questions on the mailing list.
|
||||||
|
https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists
|
||||||
|
|
||||||
|
Please fill in as much of the template as possible.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### System information
|
||||||
|
<!-- add version after "|" character -->
|
||||||
|
Type | Version/Name
|
||||||
|
--- | ---
|
||||||
|
Distribution Name |
|
||||||
|
Distribution Version |
|
||||||
|
Linux Kernel |
|
||||||
|
Architecture |
|
||||||
|
ZFS Version |
|
||||||
|
SPL Version |
|
||||||
|
<!--
|
||||||
|
Commands to find ZFS/SPL versions:
|
||||||
|
modinfo zfs | grep -iw version
|
||||||
|
modinfo spl | grep -iw version
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Describe the problem you're observing
|
||||||
|
|
||||||
|
### Describe how to reproduce the problem
|
||||||
|
|
||||||
|
### Include any warning/errors/backtraces from the system logs
|
||||||
|
<!--
|
||||||
|
*IMPORTANT* - Please mark logs and text output from terminal commands
|
||||||
|
or else Github will not display them correctly.
|
||||||
|
An example is provided below.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
this is an example how log text should be marked (wrap it with ```)
|
||||||
|
```
|
||||||
|
-->
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve OpenZFS
|
|
||||||
title: ''
|
|
||||||
labels: 'Type: Defect'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- Please fill out the following template, which will help other contributors address your issue. -->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Thank you for reporting an issue.
|
|
||||||
|
|
||||||
*IMPORTANT* - Please check our issue tracker before opening a new issue.
|
|
||||||
Additional valuable information can be found in the OpenZFS documentation
|
|
||||||
and mailing list archives.
|
|
||||||
|
|
||||||
Please fill in as much of the template as possible.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### System information
|
|
||||||
<!-- add version after "|" character -->
|
|
||||||
Type | Version/Name
|
|
||||||
--- | ---
|
|
||||||
Distribution Name |
|
|
||||||
Distribution Version |
|
|
||||||
Linux Kernel |
|
|
||||||
Architecture |
|
|
||||||
ZFS Version |
|
|
||||||
SPL Version |
|
|
||||||
<!--
|
|
||||||
Commands to find ZFS/SPL versions:
|
|
||||||
modinfo zfs | grep -iw version
|
|
||||||
modinfo spl | grep -iw version
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Describe the problem you're observing
|
|
||||||
|
|
||||||
### Describe how to reproduce the problem
|
|
||||||
|
|
||||||
### Include any warning/errors/backtraces from the system logs
|
|
||||||
<!--
|
|
||||||
*IMPORTANT* - Please mark logs and text output from terminal commands
|
|
||||||
or else Github will not display them correctly.
|
|
||||||
An example is provided below.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```
|
|
||||||
this is an example how log text should be marked (wrap it with ```)
|
|
||||||
```
|
|
||||||
-->
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: OpenZFS Community Support Mailing list (Linux)
|
|
||||||
url: https://zfsonlinux.topicbox.com/groups/zfs-discuss
|
|
||||||
about: Get community support for OpenZFS on Linux
|
|
||||||
- name: FreeBSD Community Support Mailing list
|
|
||||||
url: https://lists.freebsd.org/mailman/listinfo/freebsd-fs
|
|
||||||
about: Get community support for OpenZFS on FreeBSD
|
|
||||||
- name: OpenZFS on IRC
|
|
||||||
url: https://webchat.freenode.net/#openzfs
|
|
||||||
about: Use IRC to get community support for OpenZFS
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest a feature for OpenZFS
|
|
||||||
title: ''
|
|
||||||
labels: 'Type: Feature'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Thank you for suggesting a feature.
|
|
||||||
|
|
||||||
Please check our issue tracker before opening a new feature request.
|
|
||||||
Filling out the following template will help other contributors better understand your proposed feature.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Describe the feature would like to see added to OpenZFS
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Provide a clear and concise description of the feature.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### How will this feature improve OpenZFS?
|
|
||||||
|
|
||||||
<!--
|
|
||||||
What problem does this feature solve?
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Additional context
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Any additional information you can add about the proposal?
|
|
||||||
-->
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
name: Code Question
|
|
||||||
about: Ask a question about the code
|
|
||||||
title: ''
|
|
||||||
labels: 'Type: Question'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Thank you for taking an interest in the OpenZFS codebase.
|
|
||||||
|
|
||||||
Please be aware that most questions are preferably asked in the mailing list first.
|
|
||||||
This form is primarily meant for asking questions about the code itself.
|
|
||||||
|
|
||||||
Please also check our issue tracker before opening a new question.
|
|
||||||
Filling out the following template will help other contributors better understand your question.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Ask your question!
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Please provide a clear and concise question.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Which portion of the codebase does your question involve?
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Optional: Please describe what portion of the codebase your issue involved.
|
|
||||||
Example: "Testsuite", "Buildbots", "CLI", a code snippet etc.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Additional context
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Any additional information you want to add?
|
|
||||||
-->
|
|
||||||
@@ -1,25 +1,22 @@
|
|||||||
<!--- Please fill out the following template, which will help other contributors review your Pull Request. -->
|
|
||||||
|
|
||||||
<!--- Provide a general summary of your changes in the Title above -->
|
<!--- Provide a general summary of your changes in the Title above -->
|
||||||
|
|
||||||
<!---
|
<!---
|
||||||
Documentation on ZFS Buildbot options can be found at
|
Documentation on ZFS Buildbot options can be found at
|
||||||
https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.html
|
https://github.com/zfsonlinux/zfs/wiki/Buildbot-Options
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
### Description
|
||||||
|
<!--- Describe your changes in detail -->
|
||||||
|
|
||||||
### Motivation and Context
|
### Motivation and Context
|
||||||
<!--- Why is this change required? What problem does it solve? -->
|
<!--- Why is this change required? What problem does it solve? -->
|
||||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||||
|
|
||||||
### Description
|
|
||||||
<!--- Describe your changes in detail -->
|
|
||||||
|
|
||||||
### How Has This Been Tested?
|
### How Has This Been Tested?
|
||||||
<!--- Please describe in detail how you tested your changes. -->
|
<!--- Please describe in detail how you tested your changes. -->
|
||||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||||
<!--- see how your change affects other areas of the code, etc. -->
|
<!--- see how your change affects other areas of the code, etc. -->
|
||||||
<!--- If your change is a performance enhancement, please provide benchmarks here. -->
|
<!--- If your change is a performance enhancement, please provide benchmarks here. -->
|
||||||
<!--- Please think about using the draft PR feature if appropriate -->
|
|
||||||
|
|
||||||
### Types of changes
|
### Types of changes
|
||||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||||
@@ -33,9 +30,10 @@ https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.
|
|||||||
### Checklist:
|
### Checklist:
|
||||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||||
- [ ] My code follows the ZFS on Linux [code style requirements](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md#coding-conventions).
|
- [ ] My code follows the ZFS on Linux code style requirements.
|
||||||
- [ ] I have updated the documentation accordingly.
|
- [ ] I have updated the documentation accordingly.
|
||||||
- [ ] I have read the [**contributing** document](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md).
|
- [ ] I have read the **CONTRIBUTING** document.
|
||||||
- [ ] I have added [tests](https://github.com/zfsonlinux/zfs/tree/master/tests) to cover my changes.
|
- [ ] I have added tests to cover my changes.
|
||||||
- [ ] I have run the ZFS Test Suite with this change applied.
|
- [ ] All new and existing tests passed.
|
||||||
- [ ] All commit messages are properly formatted and contain [`Signed-off-by`](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md#signed-off-by).
|
- [ ] All commit messages are properly formatted and contain `Signed-off-by`.
|
||||||
|
- [ ] Change has been approved by a ZFS on Linux member.
|
||||||
|
|||||||
+17
-12
@@ -1,25 +1,30 @@
|
|||||||
codecov:
|
codecov:
|
||||||
notify:
|
notify:
|
||||||
require_ci_to_pass: false # always post
|
require_ci_to_pass: no
|
||||||
after_n_builds: 2 # user and kernel
|
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
precision: 0 # 0 decimals of precision
|
precision: 2
|
||||||
round: nearest # Round to nearest precision point
|
round: down
|
||||||
range: "50...90" # red -> yellow -> green
|
range: "50...100"
|
||||||
|
|
||||||
status:
|
status:
|
||||||
project:
|
project:
|
||||||
default:
|
default:
|
||||||
threshold: 1% # allow 1% coverage variance
|
threshold: 1%
|
||||||
|
|
||||||
patch:
|
patch:
|
||||||
default:
|
default:
|
||||||
threshold: 1% # allow 1% coverage variance
|
threshold: 1%
|
||||||
|
|
||||||
|
parsers:
|
||||||
|
gcov:
|
||||||
|
branch_detection:
|
||||||
|
conditional: yes
|
||||||
|
loop: yes
|
||||||
|
method: no
|
||||||
|
macro: no
|
||||||
|
|
||||||
comment:
|
comment:
|
||||||
layout: "reach, diff, flags, footer"
|
layout: "header, sunburst, diff"
|
||||||
behavior: once # update if exists; post new; skip if deleted
|
behavior: default
|
||||||
require_changes: yes # only post when coverage changes
|
require_changes: no
|
||||||
|
|
||||||
# ignore: Please place any ignores in config/ax_code_coverage.m4 instead
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
# Number of days of inactivity before an issue becomes stale
|
|
||||||
daysUntilStale: 365
|
|
||||||
# Number of days of inactivity before a stale issue is closed
|
|
||||||
daysUntilClose: 90
|
|
||||||
# Limit to only `issues` or `pulls`
|
|
||||||
only: issues
|
|
||||||
# Issues with these labels will never be considered stale
|
|
||||||
exemptLabels:
|
|
||||||
- "Type: Feature"
|
|
||||||
- "Type: Understood"
|
|
||||||
# Label to use when marking an issue as stale
|
|
||||||
staleLabel: "Status: Stale"
|
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
|
||||||
markComment: >
|
|
||||||
This issue has been automatically marked as "stale" because it has not had
|
|
||||||
any activity for a while. It will be closed in 90 days if no further activity occurs.
|
|
||||||
Thank you for your contributions.
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
preprocessorErrorDirective:./module/zfs/vdev_raidz_math_avx512f.c:243
|
||||||
|
preprocessorErrorDirective:./module/zfs/vdev_raidz_math_sse2.c:266
|
||||||
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
name: checkstyle
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
checkstyle:
|
|
||||||
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 gawk alien fakeroot linux-headers-$(uname -r)
|
|
||||||
sudo apt-get install --yes -qq zlib1g-dev uuid-dev libattr1-dev libblkid-dev libselinux-dev libudev-dev libssl-dev python-dev python-setuptools python-cffi python3 python3-dev python3-setuptools python3-cffi
|
|
||||||
# packages for tests
|
|
||||||
sudo apt-get install --yes -qq parted lsscsi ksh attr acl nfs-kernel-server fio
|
|
||||||
sudo apt-get install --yes -qq mandoc cppcheck pax-utils abigail-tools # devscripts - enable then bashisms fixed
|
|
||||||
sudo -E pip --quiet install flake8
|
|
||||||
- name: Prepare
|
|
||||||
run: |
|
|
||||||
sh ./autogen.sh
|
|
||||||
./configure
|
|
||||||
- name: Checkstyle
|
|
||||||
run: |
|
|
||||||
make checkstyle
|
|
||||||
- name: Lint
|
|
||||||
run: |
|
|
||||||
make lint
|
|
||||||
- name: CheckABI
|
|
||||||
run: |
|
|
||||||
make -j$(nproc)
|
|
||||||
make checkabi
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
name: zfs-tests-functional
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests-functional-ubuntu:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [18.04, 20.04]
|
|
||||||
runs-on: ubuntu-${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
|
||||||
git alien fakeroot wget curl bc fio acl \
|
|
||||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
|
||||||
nfs-kernel-server samba rng-tools xz-utils \
|
|
||||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
|
||||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
|
||||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
|
||||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
|
||||||
python3 python3-dev python3-setuptools python3-cffi
|
|
||||||
- name: Autogen.sh
|
|
||||||
run: |
|
|
||||||
sh autogen.sh
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./configure --enable-debug --enable-debuginfo
|
|
||||||
- name: Make
|
|
||||||
run: |
|
|
||||||
make --no-print-directory -s pkg-utils pkg-kmod
|
|
||||||
- name: Install
|
|
||||||
run: |
|
|
||||||
sudo dpkg -i *.deb
|
|
||||||
# Update order of directories to search for modules, otherwise
|
|
||||||
# Ubuntu will load kernel-shipped ones.
|
|
||||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
|
||||||
sudo depmod
|
|
||||||
sudo modprobe zfs
|
|
||||||
- name: Tests
|
|
||||||
run: |
|
|
||||||
/usr/share/zfs/zfs-tests.sh -v -s 3G
|
|
||||||
- name: Prepare artifacts
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
|
||||||
sudo dmesg > $RESULTS_PATH/dmesg
|
|
||||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
|
||||||
sudo chmod +r $RESULTS_PATH/*
|
|
||||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
|
||||||
for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Test logs Ubuntu-${{ matrix.os }}
|
|
||||||
path: /var/tmp/test_results/20*/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
name: zfs-tests-sanity
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
|
||||||
git alien fakeroot wget curl bc fio acl \
|
|
||||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
|
||||||
nfs-kernel-server samba rng-tools xz-utils \
|
|
||||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
|
||||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
|
||||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
|
||||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
|
||||||
python3 python3-dev python3-setuptools python3-cffi
|
|
||||||
- name: Autogen.sh
|
|
||||||
run: |
|
|
||||||
sh autogen.sh
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./configure --enable-debug --enable-debuginfo
|
|
||||||
- name: Make
|
|
||||||
run: |
|
|
||||||
make --no-print-directory -s pkg-utils pkg-kmod
|
|
||||||
- name: Install
|
|
||||||
run: |
|
|
||||||
sudo dpkg -i *.deb
|
|
||||||
# Update order of directories to search for modules, otherwise
|
|
||||||
# Ubuntu will load kernel-shipped ones.
|
|
||||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
|
||||||
sudo depmod
|
|
||||||
sudo modprobe zfs
|
|
||||||
- name: Tests
|
|
||||||
run: |
|
|
||||||
/usr/share/zfs/zfs-tests.sh -v -s 3G -r sanity
|
|
||||||
- name: Prepare artifacts
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
|
||||||
sudo dmesg > $RESULTS_PATH/dmesg
|
|
||||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
|
||||||
sudo chmod +r $RESULTS_PATH/*
|
|
||||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
|
||||||
for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Test logs
|
|
||||||
path: /var/tmp/test_results/20*/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
name: zloop
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
TEST_DIR: /var/tmp/zloop
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb \
|
|
||||||
git alien fakeroot \
|
|
||||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
|
||||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
|
||||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
|
||||||
libpam0g-dev \
|
|
||||||
python-dev python-setuptools python-cffi \
|
|
||||||
python3 python3-dev python3-setuptools python3-cffi
|
|
||||||
- name: Autogen.sh
|
|
||||||
run: |
|
|
||||||
sh autogen.sh
|
|
||||||
- name: Configure
|
|
||||||
run: |
|
|
||||||
./configure --enable-debug --enable-debuginfo
|
|
||||||
- name: Make
|
|
||||||
run: |
|
|
||||||
make --no-print-directory -s pkg-utils pkg-kmod
|
|
||||||
- name: Install
|
|
||||||
run: |
|
|
||||||
sudo dpkg -i *.deb
|
|
||||||
# Update order of directories to search for modules, otherwise
|
|
||||||
# Ubuntu will load kernel-shipped ones.
|
|
||||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
|
||||||
sudo depmod
|
|
||||||
sudo modprobe zfs
|
|
||||||
- name: Tests
|
|
||||||
run: |
|
|
||||||
sudo mkdir -p $TEST_DIR
|
|
||||||
# run for 20 minutes to have a total runner time of 30 minutes
|
|
||||||
sudo /usr/share/zfs/zloop.sh -t 1200 -l -m1
|
|
||||||
- name: Prepare artifacts
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
sudo chmod +r -R $TEST_DIR/
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Logs
|
|
||||||
path: |
|
|
||||||
/var/tmp/zloop/*/
|
|
||||||
!/var/tmp/zloop/*/vdev/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: Pool files
|
|
||||||
path: |
|
|
||||||
/var/tmp/zloop/*/vdev/
|
|
||||||
if-no-files-found: ignore
|
|
||||||
+2
-11
@@ -14,7 +14,6 @@
|
|||||||
# Normal rules
|
# Normal rules
|
||||||
#
|
#
|
||||||
*.[oa]
|
*.[oa]
|
||||||
*.o.ur-safe
|
|
||||||
*.lo
|
*.lo
|
||||||
*.la
|
*.la
|
||||||
*.mod.c
|
*.mod.c
|
||||||
@@ -22,8 +21,6 @@
|
|||||||
*.swp
|
*.swp
|
||||||
*.gcno
|
*.gcno
|
||||||
*.gcda
|
*.gcda
|
||||||
*.pyc
|
|
||||||
*.pyo
|
|
||||||
.deps
|
.deps
|
||||||
.libs
|
.libs
|
||||||
.dirstamp
|
.dirstamp
|
||||||
@@ -36,7 +33,6 @@ Makefile.in
|
|||||||
# Top level generated files specific to this top level dir
|
# Top level generated files specific to this top level dir
|
||||||
#
|
#
|
||||||
/bin
|
/bin
|
||||||
/build
|
|
||||||
/configure
|
/configure
|
||||||
/config.log
|
/config.log
|
||||||
/config.status
|
/config.status
|
||||||
@@ -45,6 +41,8 @@ Makefile.in
|
|||||||
/zfs_config.h.in
|
/zfs_config.h.in
|
||||||
/zfs.release
|
/zfs.release
|
||||||
/stamp-h1
|
/stamp-h1
|
||||||
|
/.script-config
|
||||||
|
/zfs-script-config.sh
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
|
|
||||||
@@ -61,10 +59,3 @@ cscope.*
|
|||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.patch
|
*.patch
|
||||||
*.orig
|
*.orig
|
||||||
*.log
|
|
||||||
*.tmp
|
|
||||||
venv
|
|
||||||
|
|
||||||
*.so
|
|
||||||
*.so.debug
|
|
||||||
*.so.full
|
|
||||||
|
|||||||
@@ -1,308 +1,95 @@
|
|||||||
MAINTAINERS:
|
Brian Behlendorf is the principal developer of the ZFS on Linux port.
|
||||||
|
He works full time as a computer scientist at Lawrence Livermore
|
||||||
|
National Laboratory on the ZFS and Lustre filesystems. However,
|
||||||
|
this port would not have been possible without the help of many
|
||||||
|
others who have contributed their time, effort, and insight.
|
||||||
|
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov>
|
Brian Behlendorf <behlendorf1@llnl.gov>
|
||||||
Tony Hutter <hutter2@llnl.gov>
|
|
||||||
|
|
||||||
PAST MAINTAINERS:
|
First and foremost the hard working ZFS developers at Sun/Oracle.
|
||||||
|
They are responsible for the bulk of the code in this project and
|
||||||
|
without their efforts there never would have been a ZFS filesystem.
|
||||||
|
|
||||||
Ned Bass <bass6@llnl.gov>
|
The ZFS Development Team at Sun/Oracle
|
||||||
|
|
||||||
CONTRIBUTORS:
|
Next all the developers at KQ Infotech who implemented a prototype
|
||||||
|
ZFS Posix Layer (ZPL). Their implementation provided an excellent
|
||||||
|
reference for adding the ZPL functionality.
|
||||||
|
|
||||||
Aaron Fineman <abyxcos@gmail.com>
|
Anand Mitra <mitra@kqinfotech.com>
|
||||||
Adam Leventhal <ahl@delphix.com>
|
Anurag Agarwal <anurag@kqinfotech.com>
|
||||||
Adam Stevko <adam.stevko@gmail.com>
|
Neependra Khare <neependra@kqinfotech.com>
|
||||||
Ahmed G <ahmedg@delphix.com>
|
Prasad Joshi <prasad@kqinfotech.com>
|
||||||
Akash Ayare <aayare@delphix.com>
|
Rohan Puri <rohan@kqinfotech.com>
|
||||||
Alan Somers <asomers@gmail.com>
|
Sandip Divekar <sandipd@kqinfotech.com>
|
||||||
Alar Aun <spamtoaun@gmail.com>
|
Shoaib <shoaib@kqinfotech.com>
|
||||||
Albert Lee <trisk@nexenta.com>
|
Shrirang <shrirang@kqinfotech.com>
|
||||||
Alec Salazar <alec.j.salazar@gmail.com>
|
|
||||||
Alejandro R. Sedeño <asedeno@mit.edu>
|
Additionally the following individuals have all made contributions
|
||||||
Alek Pinchuk <alek@nexenta.com>
|
to the project and deserve to be acknowledged.
|
||||||
Alex Braunegg <alex.braunegg@gmail.com>
|
|
||||||
Alex McWhirter <alexmcwhirter@triadic.us>
|
Albert Lee <trisk@nexenta.com>
|
||||||
Alex Reece <alex@delphix.com>
|
Alejandro R. Sedeño <asedeno@mit.edu>
|
||||||
Alex Wilson <alex.wilson@joyent.com>
|
Alex Zhuravlev <bzzz@whamcloud.com>
|
||||||
Alex Zhuravlev <alexey.zhuravlev@intel.com>
|
Alexander Eremin <a.eremin@nexenta.com>
|
||||||
Alexander Eremin <a.eremin@nexenta.com>
|
Alexander Stetsenko <ams@nexenta.com>
|
||||||
Alexander Motin <mav@freebsd.org>
|
Alexey Shvetsov <alexxy@gentoo.org>
|
||||||
Alexander Pyhalov <apyhalov@gmail.com>
|
Andreas Dilger <adilger@whamcloud.com>
|
||||||
Alexander Stetsenko <ams@nexenta.com>
|
Andrew Reid <ColdCanuck@nailedtotheperch.com>
|
||||||
Alexey Shvetsov <alexxy@gentoo.org>
|
Andrew Stormont <andrew.stormont@nexenta.com>
|
||||||
Alexey Smirnoff <fling@member.fsf.org>
|
Andrew Tselischev <andrewtselischev@gmail.com>
|
||||||
Allan Jude <allanjude@freebsd.org>
|
Andriy Gapon <avg@FreeBSD.org>
|
||||||
AndCycle <andcycle@andcycle.idv.tw>
|
Aniruddha Shankar <k@191a.net>
|
||||||
Andreas Buschmann <andreas.buschmann@tech.net.de>
|
Bill Pijewski <wdp@joyent.com>
|
||||||
Andreas Dilger <adilger@intel.com>
|
Chris Dunlap <cdunlap@llnl.gov>
|
||||||
Andrew Barnes <barnes333@gmail.com>
|
Chris Dunlop <chris@onthe.net.au>
|
||||||
Andrew Hamilton <ahamilto@tjhsst.edu>
|
Chris Siden <chris.siden@delphix.com>
|
||||||
Andrew Reid <ColdCanuck@nailedtotheperch.com>
|
Chris Wedgwood <cw@f00f.org>
|
||||||
Andrew Stormont <andrew.stormont@nexenta.com>
|
Christian Kohlschütter <christian@kohlschutter.com>
|
||||||
Andrew Tselischev <andrewtselischev@gmail.com>
|
Christopher Siden <chris.siden@delphix.com>
|
||||||
Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
|
Craig Sanders <github@taz.net.au>
|
||||||
Andriy Gapon <avg@freebsd.org>
|
Cyril Plisko <cyril.plisko@mountall.com>
|
||||||
Andy Bakun <github@thwartedefforts.org>
|
Dan McDonald <danmcd@nexenta.com>
|
||||||
Aniruddha Shankar <k@191a.net>
|
Daniel Verite <daniel@verite.pro>
|
||||||
Antonio Russo <antonio.e.russo@gmail.com>
|
Darik Horn <dajhorn@vanadac.com>
|
||||||
Arkadiusz Bubała <arkadiusz.bubala@open-e.com>
|
Eric Schrock <Eric.Schrock@delphix.com>
|
||||||
Arne Jansen <arne@die-jansens.de>
|
Etienne Dechamps <etienne.dechamps@ovh.net>
|
||||||
Aron Xu <happyaron.xu@gmail.com>
|
Fajar A. Nugraha <github@fajar.net>
|
||||||
Bart Coddens <bart.coddens@gmail.com>
|
Frederik Wessels <wessels147@gmail.com>
|
||||||
Basil Crow <basil.crow@delphix.com>
|
Garrett D'Amore <garrett@nexenta.com>
|
||||||
Huang Liu <liu.huang@zte.com.cn>
|
George Wilson <george.wilson@delphix.com>
|
||||||
Ben Allen <bsallen@alcf.anl.gov>
|
Gordon Ross <gwr@nexenta.com>
|
||||||
Ben Rubson <ben.rubson@gmail.com>
|
Gregor Kopka <mailfrom-github.com@kopka.net>
|
||||||
Benjamin Albrecht <git@albrecht.io>
|
Gunnar Beutner <gunnar@beutner.name>
|
||||||
Bill McGonigle <bill-github.com-public1@bfccomputing.com>
|
James H <james@kagisoft.co.uk>
|
||||||
Bill Pijewski <wdp@joyent.com>
|
Javen Wu <wu.javen@gmail.com>
|
||||||
Boris Protopopov <boris.protopopov@nexenta.com>
|
Jeremy Gill <jgill@parallax-innovations.com>
|
||||||
Brad Lewis <brad.lewis@delphix.com>
|
Jorgen Lundman <lundman@lundman.net>
|
||||||
Brian Behlendorf <behlendorf1@llnl.gov>
|
KORN Andras <korn@elan.rulez.org>
|
||||||
Brian J. Murrell <brian@sun.com>
|
Kyle Fuller <inbox@kylefuller.co.uk>
|
||||||
Caleb James DeLisle <calebdelisle@lavabit.com>
|
Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
|
||||||
Cao Xuewen <cao.xuewen@zte.com.cn>
|
Martin Matuska <mm@FreeBSD.org>
|
||||||
Carlo Landmeter <clandmeter@gmail.com>
|
Massimo Maggi <massimo@mmmm.it>
|
||||||
Carlos Alberto Lopez Perez <clopez@igalia.com>
|
Matthew Ahrens <mahrens@delphix.com>
|
||||||
Chaoyu Zhang <zhang.chaoyu@zte.com.cn>
|
Michael Martin <mgmartin.mgm@gmail.com>
|
||||||
Chen Can <chen.can2@zte.com.cn>
|
Mike Harsch <mike@harschsystems.com>
|
||||||
Chen Haiquan <oc@yunify.com>
|
Ned Bass <bass6@llnl.gov>
|
||||||
Chip Parker <aparker@enthought.com>
|
Oleg Stepura <oleg@stepura.com>
|
||||||
Chris Burroughs <chris.burroughs@gmail.com>
|
P.SCH <p88@yahoo.com>
|
||||||
Chris Dunlap <cdunlap@llnl.gov>
|
Pawel Jakub Dawidek <pawel@dawidek.net>
|
||||||
Chris Dunlop <chris@onthe.net.au>
|
Prakash Surya <surya1@llnl.gov>
|
||||||
Chris Siden <chris.siden@delphix.com>
|
Prasad Joshi <pjoshi@stec-inc.com>
|
||||||
Chris Wedgwood <cw@f00f.org>
|
Ricardo M. Correia <Ricardo.M.Correia@Sun.COM>
|
||||||
Chris Williamson <chris.williamson@delphix.com>
|
Richard Laager <rlaager@wiktel.com>
|
||||||
Chris Zubrzycki <github@mid-earth.net>
|
Richard Lowe <richlowe@richlowe.net>
|
||||||
Christ Schlacta <aarcane@aarcane.info>
|
Richard Yao <ryao@cs.stonybrook.edu>
|
||||||
Christer Ekholm <che@chrekh.se>
|
Rohan Puri <rohan.puri15@gmail.com>
|
||||||
Christian Kohlschütter <christian@kohlschutter.com>
|
Shampavman <sham.pavman@nexenta.com>
|
||||||
Christian Neukirchen <chneukirchen@gmail.com>
|
Simon Klinkert <klinkert@webgods.de>
|
||||||
Christian Schwarz <me@cschwarz.com>
|
Suman Chakravartula <suman@gogrid.com>
|
||||||
Christopher Voltz <cjunk@voltz.ws>
|
Tim Haley <Tim.Haley@Sun.COM>
|
||||||
Chunwei Chen <david.chen@nutanix.com>
|
Turbo Fredriksson <turbo@bayour.com>
|
||||||
Clemens Fruhwirth <clemens@endorphin.org>
|
Xin Li <delphij@FreeBSD.org>
|
||||||
Coleman Kane <ckane@colemankane.org>
|
Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
Colin Ian King <colin.king@canonical.com>
|
Zachary Bedell <zac@thebedells.org>
|
||||||
Craig Loomis <cloomis@astro.princeton.edu>
|
nordaux <nordaux@gmail.com>
|
||||||
Craig Sanders <github@taz.net.au>
|
|
||||||
Cyril Plisko <cyril.plisko@infinidat.com>
|
|
||||||
DHE <git@dehacked.net>
|
|
||||||
Damian Wojsław <damian@wojslaw.pl>
|
|
||||||
Dan Kimmel <dan.kimmel@delphix.com>
|
|
||||||
Dan McDonald <danmcd@nexenta.com>
|
|
||||||
Dan Swartzendruber <dswartz@druber.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>
|
|
||||||
Dave Eddy <dave@daveeddy.com>
|
|
||||||
David Lamparter <equinox@diac24.net>
|
|
||||||
David Qian <david.qian@intel.com>
|
|
||||||
David Quigley <david.quigley@intel.com>
|
|
||||||
Debabrata Banerjee <dbanerje@akamai.com>
|
|
||||||
Denys Rtveliashvili <denys@rtveliashvili.name>
|
|
||||||
Derek Dai <daiderek@gmail.com>
|
|
||||||
Dimitri John Ledkov <xnox@ubuntu.com>
|
|
||||||
Dmitry Khasanov <pik4ez@gmail.com>
|
|
||||||
Dominik Hassler <hadfl@omniosce.org>
|
|
||||||
Dominik Honnef <dominikh@fork-bomb.org>
|
|
||||||
Don Brady <don.brady@delphix.com>
|
|
||||||
Dr. András Korn <korn-github.com@elan.rulez.org>
|
|
||||||
Eli Rosenthal <eli.rosenthal@delphix.com>
|
|
||||||
Eric Desrochers <eric.desrochers@canonical.com>
|
|
||||||
Eric Dillmann <eric@jave.fr>
|
|
||||||
Eric Schrock <Eric.Schrock@delphix.com>
|
|
||||||
Etienne Dechamps <etienne@edechamps.fr>
|
|
||||||
Evan Susarret <evansus@gmail.com>
|
|
||||||
Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
|
||||||
Fajar A. Nugraha <github@fajar.net>
|
|
||||||
Fan Yong <fan.yong@intel.com>
|
|
||||||
Feng Sun <loyou85@gmail.com>
|
|
||||||
Frederik Wessels <wessels147@gmail.com>
|
|
||||||
Frédéric Vanniere <f.vanniere@planet-work.com>
|
|
||||||
Garrett D'Amore <garrett@nexenta.com>
|
|
||||||
Garrison Jensen <garrison.jensen@gmail.com>
|
|
||||||
Gary Mills <gary_mills@fastmail.fm>
|
|
||||||
Gaurav Kumar <gauravk.18@gmail.com>
|
|
||||||
GeLiXin <ge.lixin@zte.com.cn>
|
|
||||||
George Amanakis <g_amanakis@yahoo.com>
|
|
||||||
George Melikov <mail@gmelikov.ru>
|
|
||||||
George Wilson <gwilson@delphix.com>
|
|
||||||
Georgy Yakovlev <ya@sysdump.net>
|
|
||||||
Giuseppe Di Natale <guss80@gmail.com>
|
|
||||||
Gordan Bobic <gordan@redsleeve.org>
|
|
||||||
Gordon Ross <gwr@nexenta.com>
|
|
||||||
Gregor Kopka <gregor@kopka.net>
|
|
||||||
Grischa Zengel <github.zfsonlinux@zengel.info>
|
|
||||||
Gunnar Beutner <gunnar@beutner.name>
|
|
||||||
Gvozden Neskovic <neskovic@gmail.com>
|
|
||||||
Hajo Möller <dasjoe@gmail.com>
|
|
||||||
Hans Rosenfeld <hans.rosenfeld@nexenta.com>
|
|
||||||
Håkan Johansson <f96hajo@chalmers.se>
|
|
||||||
Igor Kozhukhov <ikozhukhov@gmail.com>
|
|
||||||
Igor Lvovsky <ilvovsky@gmail.com>
|
|
||||||
Isaac Huang <he.huang@intel.com>
|
|
||||||
JK Dingwall <james@dingwall.me.uk>
|
|
||||||
Jacek Fefliński <feflik@gmail.com>
|
|
||||||
James Cowgill <james.cowgill@mips.com>
|
|
||||||
James Lee <jlee@thestaticvoid.com>
|
|
||||||
James Pan <jiaming.pan@yahoo.com>
|
|
||||||
Jan Engelhardt <jengelh@inai.de>
|
|
||||||
Jan Kryl <jan.kryl@nexenta.com>
|
|
||||||
Jan Sanislo <oystr@cs.washington.edu>
|
|
||||||
Jason King <jason.brian.king@gmail.com>
|
|
||||||
Jason Zaman <jasonzaman@gmail.com>
|
|
||||||
Javen Wu <wu.javen@gmail.com>
|
|
||||||
Jeremy Gill <jgill@parallax-innovations.com>
|
|
||||||
Jeremy Jones <jeremy@delphix.com>
|
|
||||||
Jerry Jelinek <jerry.jelinek@joyent.com>
|
|
||||||
Jinshan Xiong <jinshan.xiong@intel.com>
|
|
||||||
Joe Stein <joe.stein@delphix.com>
|
|
||||||
John Albietz <inthecloud247@gmail.com>
|
|
||||||
John Eismeier <john.eismeier@gmail.com>
|
|
||||||
John L. Hammond <john.hammond@intel.com>
|
|
||||||
John Layman <jlayman@sagecloud.com>
|
|
||||||
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
|
|
||||||
John Wren Kennedy <john.kennedy@delphix.com>
|
|
||||||
Johnny Stenback <github@jstenback.com>
|
|
||||||
Jorgen Lundman <lundman@lundman.net>
|
|
||||||
Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
|
|
||||||
Joshua M. Clulow <josh@sysmgr.org>
|
|
||||||
Justin Bedő <cu@cua0.org>
|
|
||||||
Justin Lecher <jlec@gentoo.org>
|
|
||||||
Justin T. Gibbs <gibbs@FreeBSD.org>
|
|
||||||
Jörg Thalheim <joerg@higgsboson.tk>
|
|
||||||
KORN Andras <korn@elan.rulez.org>
|
|
||||||
Kamil Domański <kamil@domanski.co>
|
|
||||||
Karsten Kretschmer <kkretschmer@gmail.com>
|
|
||||||
Kash Pande <kash@tripleback.net>
|
|
||||||
Keith M Wesolowski <wesolows@foobazco.org>
|
|
||||||
Kevin Tanguy <kevin.tanguy@ovh.net>
|
|
||||||
KireinaHoro <i@jsteward.moe>
|
|
||||||
Kjeld Schouten-Lebbing <kjeld@schouten-lebbing.nl>
|
|
||||||
Kohsuke Kawaguchi <kk@kohsuke.org>
|
|
||||||
Kyle Blatter <kyleblatter@llnl.gov>
|
|
||||||
Kyle Fuller <inbox@kylefuller.co.uk>
|
|
||||||
Loli <ezomori.nozomu@gmail.com>
|
|
||||||
Lars Johannsen <laj@it.dk>
|
|
||||||
Li Dongyang <dongyang.li@anu.edu.au>
|
|
||||||
Li Wei <W.Li@Sun.COM>
|
|
||||||
Lukas Wunner <lukas@wunner.de>
|
|
||||||
Madhav Suresh <madhav.suresh@delphix.com>
|
|
||||||
Manoj Joseph <manoj.joseph@delphix.com>
|
|
||||||
Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
|
|
||||||
Marcel Huber <marcelhuberfoo@gmail.com>
|
|
||||||
Marcel Telka <marcel.telka@nexenta.com>
|
|
||||||
Marcel Wysocki <maci.stgn@gmail.com>
|
|
||||||
Mark Shellenbaum <Mark.Shellenbaum@Oracle.COM>
|
|
||||||
Mark Wright <markwright@internode.on.net>
|
|
||||||
Martin Matuska <mm@FreeBSD.org>
|
|
||||||
Massimo Maggi <me@massimo-maggi.eu>
|
|
||||||
Matt Johnston <matt@fugro-fsi.com.au>
|
|
||||||
Matt Kemp <matt@mattikus.com>
|
|
||||||
Matthew Ahrens <matt@delphix.com>
|
|
||||||
Matthew Thode <mthode@mthode.org>
|
|
||||||
Matus Kral <matuskral@me.com>
|
|
||||||
Max Grossman <max.grossman@delphix.com>
|
|
||||||
Maximilian Mehnert <maximilian.mehnert@gmx.de>
|
|
||||||
Michael Gebetsroither <michael@mgeb.org>
|
|
||||||
Michael Kjorling <michael@kjorling.se>
|
|
||||||
Michael Martin <mgmartin.mgm@gmail.com>
|
|
||||||
Michael Niewöhner <foss@mniewoehner.de>
|
|
||||||
Mike Gerdts <mike.gerdts@joyent.com>
|
|
||||||
Mike Harsch <mike@harschsystems.com>
|
|
||||||
Mike Leddy <mike.leddy@gmail.com>
|
|
||||||
Mike Swanson <mikeonthecomputer@gmail.com>
|
|
||||||
Milan Jurik <milan.jurik@xylab.cz>
|
|
||||||
Morgan Jones <mjones@rice.edu>
|
|
||||||
Moritz Maxeiner <moritz@ucworks.org>
|
|
||||||
Nathaniel Clark <Nathaniel.Clark@misrule.us>
|
|
||||||
Nathaniel Wesley Filardo <nwf@cs.jhu.edu>
|
|
||||||
Nav Ravindranath <nav@delphix.com>
|
|
||||||
Neal Gompa (ニール・ゴンパ) <ngompa13@gmail.com>
|
|
||||||
Ned Bass <bass6@llnl.gov>
|
|
||||||
Neependra Khare <neependra@kqinfotech.com>
|
|
||||||
Neil Stockbridge <neil@dist.ro>
|
|
||||||
Nick Garvey <garvey.nick@gmail.com>
|
|
||||||
Nikolay Borisov <n.borisov.lkml@gmail.com>
|
|
||||||
Olaf Faaland <faaland1@llnl.gov>
|
|
||||||
Oleg Drokin <green@linuxhacker.ru>
|
|
||||||
Oleg Stepura <oleg@stepura.com>
|
|
||||||
Patrik Greco <sikevux@sikevux.se>
|
|
||||||
Paul B. Henson <henson@acm.org>
|
|
||||||
Paul Dagnelie <pcd@delphix.com>
|
|
||||||
Paul Zuchowski <pzuchowski@datto.com>
|
|
||||||
Pavel Boldin <boldin.pavel@gmail.com>
|
|
||||||
Pavel Zakharov <pavel.zakharov@delphix.com>
|
|
||||||
Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
|
||||||
Pedro Giffuni <pfg@freebsd.org>
|
|
||||||
Peng <peng.hse@xtaotech.com>
|
|
||||||
Peter Ashford <ashford@accs.com>
|
|
||||||
Prakash Surya <prakash.surya@delphix.com>
|
|
||||||
Prasad Joshi <prasadjoshi124@gmail.com>
|
|
||||||
Ralf Ertzinger <ralf@skytale.net>
|
|
||||||
Randall Mason <ClashTheBunny@gmail.com>
|
|
||||||
Remy Blank <remy.blank@pobox.com>
|
|
||||||
Ricardo M. Correia <ricardo.correia@oracle.com>
|
|
||||||
Rich Ercolani <rincebrain@gmail.com>
|
|
||||||
Richard Elling <Richard.Elling@RichardElling.com>
|
|
||||||
Richard Laager <rlaager@wiktel.com>
|
|
||||||
Richard Lowe <richlowe@richlowe.net>
|
|
||||||
Richard Sharpe <rsharpe@samba.org>
|
|
||||||
Richard Yao <ryao@gentoo.org>
|
|
||||||
Rohan Puri <rohan.puri15@gmail.com>
|
|
||||||
Romain Dolbeau <romain.dolbeau@atos.net>
|
|
||||||
Roman Strashkin <roman.strashkin@nexenta.com>
|
|
||||||
Ruben Kerkhof <ruben@rubenkerkhof.com>
|
|
||||||
Saso Kiselkov <saso.kiselkov@nexenta.com>
|
|
||||||
Scot W. Stevenson <scot.stevenson@gmail.com>
|
|
||||||
Sean Eric Fagan <sef@ixsystems.com>
|
|
||||||
Sebastian Gottschall <s.gottschall@dd-wrt.com>
|
|
||||||
Sen Haerens <sen@senhaerens.be>
|
|
||||||
Serapheim Dimitropoulos <serapheim@delphix.com>
|
|
||||||
Seth Forshee <seth.forshee@canonical.com>
|
|
||||||
Shampavman <sham.pavman@nexenta.com>
|
|
||||||
Shen Yan <shenyanxxxy@qq.com>
|
|
||||||
Simon Guest <simon.guest@tesujimath.org>
|
|
||||||
Simon Klinkert <simon.klinkert@gmail.com>
|
|
||||||
Sowrabha Gopal <sowrabha.gopal@delphix.com>
|
|
||||||
Stanislav Seletskiy <s.seletskiy@gmail.com>
|
|
||||||
Steffen Müthing <steffen.muething@iwr.uni-heidelberg.de>
|
|
||||||
Stephen Blinick <stephen.blinick@delphix.com>
|
|
||||||
Steve Dougherty <sdougherty@barracuda.com>
|
|
||||||
Steven Burgess <sburgess@dattobackup.com>
|
|
||||||
Steven Hartland <smh@freebsd.org>
|
|
||||||
Steven Johnson <sjohnson@sakuraindustries.com>
|
|
||||||
Stian Ellingsen <stian@plaimi.net>
|
|
||||||
Suman Chakravartula <schakrava@gmail.com>
|
|
||||||
Sydney Vanda <sydney.m.vanda@intel.com>
|
|
||||||
Sören Tempel <soeren+git@soeren-tempel.net>
|
|
||||||
Thijs Cramer <thijs.cramer@gmail.com>
|
|
||||||
Tim Chase <tim@chase2k.com>
|
|
||||||
Tim Connors <tconnors@rather.puzzling.org>
|
|
||||||
Tim Crawford <tcrawford@datto.com>
|
|
||||||
Tim Haley <Tim.Haley@Sun.COM>
|
|
||||||
Tobin Harding <me@tobin.cc>
|
|
||||||
Tom Caputi <tcaputi@datto.com>
|
|
||||||
Tom Matthews <tom@axiom-partners.com>
|
|
||||||
Tom Prince <tom.prince@ualberta.net>
|
|
||||||
Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
|
|
||||||
Tony Hutter <hutter2@llnl.gov>
|
|
||||||
Toomas Soome <tsoome@me.com>
|
|
||||||
Trey Dockendorf <treydock@gmail.com>
|
|
||||||
Turbo Fredriksson <turbo@bayour.com>
|
|
||||||
Tyler J. Stachecki <stachecki.tyler@gmail.com>
|
|
||||||
Vitaut Bajaryn <vitaut.bayaryn@gmail.com>
|
|
||||||
Weigang Li <weigang.li@intel.com>
|
|
||||||
Will Andrews <will@freebsd.org>
|
|
||||||
Will Rouesnel <w.rouesnel@gmail.com>
|
|
||||||
Wolfgang Bumiller <w.bumiller@proxmox.com>
|
|
||||||
Xin Li <delphij@FreeBSD.org>
|
|
||||||
Ying Zhu <casualfisher@gmail.com>
|
|
||||||
YunQiang Su <syq@debian.org>
|
|
||||||
Yuri Pankov <yuri.pankov@gmail.com>
|
|
||||||
Yuxuan Shui <yshuiv7@gmail.com>
|
|
||||||
Zachary Bedell <zac@thebedells.org>
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
The [OpenZFS Code of Conduct](http://www.open-zfs.org/wiki/Code_of_Conduct)
|
|
||||||
applies to spaces associated with the OpenZFS project, including GitHub.
|
|
||||||
@@ -1,31 +1,33 @@
|
|||||||
Refer to the git commit log for authoritative copyright attribution.
|
The majority of the code in the ZFS on Linux port comes from OpenSolaris
|
||||||
|
which has been released under the terms of the CDDL open source license.
|
||||||
|
This includes the core ZFS code, libavl, libnvpair, libefi, libunicode,
|
||||||
|
and libutil. The original OpenSolaris source can be downloaded from:
|
||||||
|
|
||||||
The original ZFS source code was obtained from Open Solaris which was
|
http://dlc.sun.com/osol/on/downloads/b121/on-src.tar.bz2
|
||||||
released under the terms of the CDDL open source license. Additional
|
|
||||||
changes have been included from OpenZFS and the Illumos project which
|
|
||||||
are similarly licensed. These projects can be found on Github at:
|
|
||||||
|
|
||||||
* https://github.com/illumos/illumos-gate
|
Files which do not originate from OpenSolaris are noted in the file header
|
||||||
* https://github.com/openzfs/openzfs
|
and attributed properly. These exceptions include, but are not limited
|
||||||
|
to, the vdev_disk.c and zvol.c implementation which are licensed under
|
||||||
|
the CDDL.
|
||||||
|
|
||||||
|
The zpios test code is originally derived from the Lustre pios test code
|
||||||
|
which is licensed under the GPLv2. As such the heavily modified zpios
|
||||||
|
kernel test code also remains licensed under the GPLv2.
|
||||||
|
|
||||||
|
The latest stable and development versions of this port can be downloaded
|
||||||
|
from the official ZFS on Linux site located at:
|
||||||
|
|
||||||
|
http://zfsonlinux.org/
|
||||||
|
|
||||||
|
This ZFS on Linux port was produced at the Lawrence Livermore National
|
||||||
|
Laboratory (LLNL) under Contract No. DE-AC52-07NA27344 (Contract 44)
|
||||||
|
between the U.S. Department of Energy (DOE) and Lawrence Livermore
|
||||||
|
National Security, LLC (LLNS) for the operation of LLNL. It has been
|
||||||
|
approved for release under LLNL-CODE-403049.
|
||||||
|
|
||||||
Unless otherwise noted, all files in this distribution are released
|
Unless otherwise noted, all files in this distribution are released
|
||||||
under the Common Development and Distribution License (CDDL).
|
under the Common Development and Distribution License (CDDL).
|
||||||
|
Exceptions are noted within the associated source files. See the file
|
||||||
|
OPENSOLARIS.LICENSE for more information.
|
||||||
|
|
||||||
Exceptions are noted within the associated source files headers and
|
Refer to the git commit log for authoritative copyright attribution.
|
||||||
by including a THIRDPARTYLICENSE file with the license terms. A few
|
|
||||||
notable exceptions and their respective licenses include:
|
|
||||||
|
|
||||||
* Skein Checksum Implementation: module/icp/algs/skein/THIRDPARTYLICENSE
|
|
||||||
* AES Implementation: module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman
|
|
||||||
* AES Implementation: module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
|
|
||||||
* PBKDF2 Implementation: lib/libzfs/THIRDPARTYLICENSE.openssl
|
|
||||||
* SPL Implementation: module/os/linux/spl/THIRDPARTYLICENSE.gplv2
|
|
||||||
* GCM Implementation: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams
|
|
||||||
* GCM Implementation: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl
|
|
||||||
* GHASH Implementation: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams
|
|
||||||
* GHASH Implementation: module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl
|
|
||||||
|
|
||||||
This product includes software developed by the OpenSSL Project for use
|
|
||||||
in the OpenSSL Toolkit (http://www.openssl.org/)
|
|
||||||
|
|
||||||
See the LICENSE and NOTICE for more information.
|
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
This work was produced at the Lawrence Livermore National Laboratory
|
||||||
|
(LLNL) under Contract No. DE-AC52-07NA27344 (Contract 44) between
|
||||||
|
the U.S. Department of Energy (DOE) and Lawrence Livermore National
|
||||||
|
Security, LLC (LLNS) for the operation of LLNL.
|
||||||
|
|
||||||
|
This work was prepared as an account of work sponsored by an agency of
|
||||||
|
the United States Government. Neither the United States Government nor
|
||||||
|
Lawrence Livermore National Security, LLC nor any of their employees,
|
||||||
|
makes any warranty, express or implied, or assumes any liability or
|
||||||
|
responsibility for the accuracy, completeness, or usefulness of any
|
||||||
|
information, apparatus, product, or process disclosed, or represents
|
||||||
|
that its use would not infringe privately-owned rights.
|
||||||
|
|
||||||
|
Reference herein to any specific commercial products, process, or
|
||||||
|
services by trade name, trademark, manufacturer or otherwise does
|
||||||
|
not necessarily constitute or imply its endorsement, recommendation,
|
||||||
|
or favoring by the United States Government or Lawrence Livermore
|
||||||
|
National Security, LLC. The views and opinions of authors expressed
|
||||||
|
herein do not necessarily state or reflect those of the United States
|
||||||
|
Government or Lawrence Livermore National Security, LLC, and shall
|
||||||
|
not be used for advertising or product endorsement purposes.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution, and
|
||||||
|
modification are specified in the file OPENSOLARIS.LICENSE.
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
Meta: 1
|
Meta: 1
|
||||||
Name: zfs
|
Name: zfs
|
||||||
Branch: 1.0
|
Branch: 1.0
|
||||||
Version: 2.0.4
|
Version: 0.7.13
|
||||||
Release: 1
|
Release: 1
|
||||||
Release-Tags: relext
|
Release-Tags: relext
|
||||||
License: CDDL
|
License: CDDL
|
||||||
Author: OpenZFS
|
Author: OpenZFS on Linux
|
||||||
Linux-Maximum: 5.11
|
|
||||||
Linux-Minimum: 3.10
|
|
||||||
|
|||||||
+26
-191
@@ -1,68 +1,32 @@
|
|||||||
ACLOCAL_AMFLAGS = -I config
|
ACLOCAL_AMFLAGS = -I config
|
||||||
|
|
||||||
SUBDIRS = include
|
include config/rpm.am
|
||||||
if BUILD_LINUX
|
include config/deb.am
|
||||||
SUBDIRS += rpm
|
include config/tgz.am
|
||||||
endif
|
|
||||||
|
|
||||||
|
SUBDIRS = include rpm
|
||||||
if CONFIG_USER
|
if CONFIG_USER
|
||||||
SUBDIRS += etc man scripts lib tests cmd contrib
|
SUBDIRS += udev etc man scripts lib tests cmd contrib
|
||||||
if BUILD_LINUX
|
|
||||||
SUBDIRS += udev
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
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)
|
||||||
kerneldir = $(prefix)/src/zfs-$(VERSION)/$(LINUX_VERSION)
|
|
||||||
nodist_kernel_HEADERS = zfs.release zfs_config.h module/$(LINUX_SYMBOLS)
|
nodist_kernel_HEADERS = zfs.release zfs_config.h module/$(LINUX_SYMBOLS)
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign
|
AUTOMAKE_OPTIONS = foreign
|
||||||
EXTRA_DIST = autogen.sh copy-builtin
|
EXTRA_DIST = autogen.sh copy-builtin
|
||||||
EXTRA_DIST += cppcheck-suppressions.txt
|
|
||||||
EXTRA_DIST += config/config.awk config/rpm.am config/deb.am config/tgz.am
|
EXTRA_DIST += config/config.awk config/rpm.am config/deb.am config/tgz.am
|
||||||
EXTRA_DIST += META AUTHORS COPYRIGHT LICENSE NEWS NOTICE README.md
|
EXTRA_DIST += META DISCLAIMER COPYRIGHT README.markdown OPENSOLARIS.LICENSE
|
||||||
EXTRA_DIST += CODE_OF_CONDUCT.md
|
|
||||||
EXTRA_DIST += module/lua/README.zfs module/os/linux/spl/README.md
|
|
||||||
|
|
||||||
# Include all the extra licensing information for modules
|
|
||||||
EXTRA_DIST += module/icp/algs/skein/THIRDPARTYLICENSE
|
|
||||||
EXTRA_DIST += module/icp/algs/skein/THIRDPARTYLICENSE.descrip
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman.descrip
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl.descrip
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.cryptogams.descrip
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl
|
|
||||||
EXTRA_DIST += module/icp/asm-x86_64/modes/THIRDPARTYLICENSE.openssl.descrip
|
|
||||||
EXTRA_DIST += module/os/linux/spl/THIRDPARTYLICENSE.gplv2
|
|
||||||
EXTRA_DIST += module/os/linux/spl/THIRDPARTYLICENSE.gplv2.descrip
|
|
||||||
EXTRA_DIST += module/zfs/THIRDPARTYLICENSE.cityhash
|
|
||||||
EXTRA_DIST += module/zfs/THIRDPARTYLICENSE.cityhash.descrip
|
|
||||||
|
|
||||||
@CODE_COVERAGE_RULES@
|
@CODE_COVERAGE_RULES@
|
||||||
|
|
||||||
GITREV = include/zfs_gitrev.h
|
|
||||||
|
|
||||||
PHONY = gitrev
|
|
||||||
gitrev:
|
|
||||||
$(AM_V_GEN)$(top_srcdir)/scripts/make_gitrev.sh $(GITREV)
|
|
||||||
|
|
||||||
all: gitrev
|
|
||||||
|
|
||||||
# Double-colon rules are allowed; there are multiple independent definitions.
|
|
||||||
maintainer-clean-local::
|
|
||||||
-$(RM) $(GITREV)
|
|
||||||
|
|
||||||
distclean-local::
|
distclean-local::
|
||||||
-$(RM) -R autom4te*.cache build
|
-$(RM) -R autom4te*.cache
|
||||||
-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 \
|
||||||
\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
|
\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
|
||||||
@@ -73,192 +37,63 @@ distclean-local::
|
|||||||
-o -name '*.gcno' \) \
|
-o -name '*.gcno' \) \
|
||||||
-type f -print | xargs $(RM)
|
-type f -print | xargs $(RM)
|
||||||
|
|
||||||
all-local:
|
|
||||||
-[ -x ${top_builddir}/scripts/zfs-tests.sh ] && \
|
|
||||||
${top_builddir}/scripts/zfs-tests.sh -c
|
|
||||||
|
|
||||||
dist-hook:
|
dist-hook:
|
||||||
$(AM_V_GEN)$(top_srcdir)/scripts/make_gitrev.sh -D $(distdir) $(GITREV)
|
sed -i 's/Release:[[:print:]]*/Release: $(RELEASE)/' \
|
||||||
$(SED) ${ac_inplace} -e 's/Release:[[:print:]]*/Release: $(RELEASE)/' \
|
|
||||||
$(distdir)/META
|
$(distdir)/META
|
||||||
|
|
||||||
if BUILD_LINUX
|
checkstyle: cstyle shellcheck flake8 commitcheck
|
||||||
# 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
|
|
||||||
|
|
||||||
PHONY += codecheck
|
|
||||||
codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck
|
|
||||||
|
|
||||||
PHONY += checkstyle
|
|
||||||
checkstyle: codecheck commitcheck
|
|
||||||
|
|
||||||
PHONY += commitcheck
|
|
||||||
commitcheck:
|
commitcheck:
|
||||||
@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; \
|
scripts/commitcheck.sh; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PHONY += cstyle
|
|
||||||
cstyle:
|
cstyle:
|
||||||
@find ${top_srcdir} -name build -prune \
|
@find ${top_srcdir} -name '*.[hc]' ! -name 'zfs_config.*' \
|
||||||
-o -type f -name '*.[hc]' \
|
! -name '*.mod.c' -type f -exec scripts/cstyle.pl -cpP {} \+
|
||||||
! -name 'zfs_config.*' ! -name '*.mod.c' \
|
|
||||||
! -name 'opt_global.h' ! -name '*_if*.h' \
|
|
||||||
! -path './module/zstd/lib/*' \
|
|
||||||
-exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
|
|
||||||
|
|
||||||
filter_executable = -exec test -x '{}' \; -print
|
|
||||||
|
|
||||||
PHONY += shellcheck
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
@if type shellcheck > /dev/null 2>&1; then \
|
@if type shellcheck > /dev/null 2>&1; then \
|
||||||
shellcheck --exclude=SC1090 --exclude=SC1117 --format=gcc \
|
shellcheck --exclude=SC1090 --format=gcc scripts/paxcheck.sh \
|
||||||
$$(find ${top_srcdir}/scripts/*.sh -type f) \
|
scripts/zloop.sh \
|
||||||
$$(find ${top_srcdir}/cmd/zed/zed.d/*.sh -type f) \
|
scripts/zfs-tests.sh \
|
||||||
$$(find ${top_srcdir}/cmd/zpool/zpool.d/* \
|
scripts/zfs.sh \
|
||||||
-type f ${filter_executable}); \
|
scripts/commitcheck.sh \
|
||||||
else \
|
$$(find cmd/zed/zed.d/*.sh -type f) \
|
||||||
echo "skipping shellcheck because shellcheck is not installed"; \
|
$$(find cmd/zpool/zpool.d/* -executable); \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PHONY += checkabi storeabi
|
|
||||||
checkabi: lib
|
|
||||||
$(MAKE) -C lib checkabi
|
|
||||||
|
|
||||||
storeabi: lib
|
|
||||||
$(MAKE) -C lib storeabi
|
|
||||||
|
|
||||||
PHONY += checkbashisms
|
|
||||||
checkbashisms:
|
|
||||||
@if type checkbashisms > /dev/null 2>&1; then \
|
|
||||||
checkbashisms -n -p -x \
|
|
||||||
$$(find ${top_srcdir} \
|
|
||||||
-name '.git' -prune \
|
|
||||||
-o -name 'build' -prune \
|
|
||||||
-o -name 'tests' -prune \
|
|
||||||
-o -name 'config' -prune \
|
|
||||||
-o -name 'zed-functions.sh*' -prune \
|
|
||||||
-o -name 'zfs-import*' -prune \
|
|
||||||
-o -name 'zfs-mount*' -prune \
|
|
||||||
-o -name 'zfs-zed*' -prune \
|
|
||||||
-o -name 'smart' -prune \
|
|
||||||
-o -name 'paxcheck.sh' -prune \
|
|
||||||
-o -name 'make_gitrev.sh' -prune \
|
|
||||||
-o -name '90zfs' -prune \
|
|
||||||
-o -type f ! -name 'config*' \
|
|
||||||
! -name 'libtool' \
|
|
||||||
-exec sh -c 'awk "NR==1 && /\#\!.*bin\/sh.*/ {print FILENAME;}" "{}"' \;); \
|
|
||||||
else \
|
|
||||||
echo "skipping checkbashisms because checkbashisms is not installed"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
PHONY += mancheck
|
|
||||||
mancheck:
|
|
||||||
@if type mandoc > /dev/null 2>&1; then \
|
|
||||||
find ${top_srcdir}/man/man8 -type f -name 'zfs.8' \
|
|
||||||
-o -name 'zpool.8' -o -name 'zdb.8' \
|
|
||||||
-o -name 'zgenhostid.8' | \
|
|
||||||
xargs mandoc -Tlint -Werror; \
|
|
||||||
else \
|
|
||||||
echo "skipping mancheck because mandoc is not installed"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
if BUILD_LINUX
|
|
||||||
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:
|
|
||||||
@if git rev-parse --git-dir > /dev/null 2>&1; then \
|
|
||||||
git ls-files . --exclude-standard --others | \
|
|
||||||
awk '{c++; print} END {if(c>0) exit 1}' ; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
PHONY += lint
|
|
||||||
lint: cppcheck paxcheck
|
lint: cppcheck paxcheck
|
||||||
|
|
||||||
PHONY += cppcheck
|
|
||||||
cppcheck:
|
cppcheck:
|
||||||
@if type cppcheck > /dev/null 2>&1; then \
|
@if type cppcheck > /dev/null 2>&1; then \
|
||||||
cppcheck --quiet --force --error-exitcode=2 --inline-suppr \
|
cppcheck --quiet --force --error-exitcode=2 --inline-suppr \
|
||||||
--suppressions-list=${top_srcdir}/cppcheck-suppressions.txt \
|
--suppressions-list=.github/suppressions.txt \
|
||||||
-UHAVE_SSE2 -UHAVE_AVX512F -UHAVE_UIO_ZEROCOPY \
|
-UHAVE_SSE2 -UHAVE_AVX512F -UHAVE_UIO_ZEROCOPY \
|
||||||
${top_srcdir}; \
|
-UHAVE_DNLC ${top_srcdir}; \
|
||||||
else \
|
|
||||||
echo "skipping cppcheck because cppcheck is not installed"; \
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PHONY += paxcheck
|
|
||||||
paxcheck:
|
paxcheck:
|
||||||
@if type scanelf > /dev/null 2>&1; then \
|
@if type scanelf > /dev/null 2>&1; then \
|
||||||
${top_srcdir}/scripts/paxcheck.sh ${top_builddir}; \
|
scripts/paxcheck.sh ${top_srcdir}; \
|
||||||
else \
|
|
||||||
echo "skipping paxcheck because scanelf is not installed"; \
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PHONY += flake8
|
|
||||||
flake8:
|
flake8:
|
||||||
@if type flake8 > /dev/null 2>&1; then \
|
@if type flake8 > /dev/null 2>&1; then \
|
||||||
flake8 ${top_srcdir}; \
|
flake8 ${top_srcdir}; \
|
||||||
else \
|
|
||||||
echo "skipping flake8 because flake8 is not installed"; \
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PHONY += ctags
|
|
||||||
ctags:
|
ctags:
|
||||||
$(RM) tags
|
$(RM) tags
|
||||||
find $(top_srcdir) -name '.?*' -prune \
|
find $(top_srcdir) -name .git -prune -o -name '*.[hc]' | xargs ctags
|
||||||
-o -type f -name '*.[hcS]' -print | xargs ctags -a
|
|
||||||
|
|
||||||
PHONY += etags
|
|
||||||
etags:
|
etags:
|
||||||
$(RM) TAGS
|
$(RM) TAGS
|
||||||
find $(top_srcdir) -name '.?*' -prune \
|
find $(top_srcdir) -name .pc -prune -o -name '*.[hc]' | xargs etags -a
|
||||||
-o -type f -name '*.[hcS]' -print | xargs etags -a
|
|
||||||
|
|
||||||
PHONY += cscopelist
|
|
||||||
cscopelist:
|
|
||||||
find $(top_srcdir) -name '.?*' -prune \
|
|
||||||
-o -type f -name '*.[hc]' -print >cscope.files
|
|
||||||
|
|
||||||
PHONY += tags
|
|
||||||
tags: ctags etags
|
tags: ctags etags
|
||||||
|
|
||||||
PHONY += pkg pkg-dkms pkg-kmod pkg-utils
|
|
||||||
pkg: @DEFAULT_PACKAGE@
|
pkg: @DEFAULT_PACKAGE@
|
||||||
pkg-dkms: @DEFAULT_PACKAGE@-dkms
|
pkg-dkms: @DEFAULT_PACKAGE@-dkms
|
||||||
pkg-kmod: @DEFAULT_PACKAGE@-kmod
|
pkg-kmod: @DEFAULT_PACKAGE@-kmod
|
||||||
pkg-utils: @DEFAULT_PACKAGE@-utils
|
pkg-utils: @DEFAULT_PACKAGE@-utils
|
||||||
|
|
||||||
include config/rpm.am
|
|
||||||
include config/deb.am
|
|
||||||
include config/tgz.am
|
|
||||||
|
|
||||||
.PHONY: $(PHONY)
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
Descriptions of all releases can be found on github:
|
|
||||||
|
|
||||||
https://github.com/openzfs/zfs/releases
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
This work was produced under the auspices of the U.S. Department of Energy by
|
|
||||||
Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344.
|
|
||||||
|
|
||||||
This work was prepared as an account of work sponsored by an agency of the
|
|
||||||
United States Government. Neither the United States Government nor Lawrence
|
|
||||||
Livermore National Security, LLC, nor any of their employees makes any warranty,
|
|
||||||
expressed or implied, or assumes any legal liability or responsibility for the
|
|
||||||
accuracy, completeness, or usefulness of any information, apparatus, product, or
|
|
||||||
process disclosed, or represents that its use would not infringe privately owned
|
|
||||||
rights. Reference herein to any specific commercial product, process, or service
|
|
||||||
by trade name, trademark, manufacturer, or otherwise does not necessarily
|
|
||||||
constitute or imply its endorsement, recommendation, or favoring by the United
|
|
||||||
States Government or Lawrence Livermore National Security, LLC. The views and
|
|
||||||
opinions of authors expressed herein do not necessarily state or reflect those
|
|
||||||
of the United States Government or Lawrence Livermore National Security, LLC,
|
|
||||||
and shall not be used for advertising or product endorsement purposes.
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|

|
||||||
|
|
||||||
|
ZFS on Linux is an advanced file system and volume manager which was originally
|
||||||
|
developed for Solaris and is now maintained by the OpenZFS community.
|
||||||
|
|
||||||
|
[](https://codecov.io/gh/zfsonlinux/zfs)
|
||||||
|
|
||||||
|
# Official Resources
|
||||||
|
* [Site](http://zfsonlinux.org)
|
||||||
|
* [Wiki](https://github.com/zfsonlinux/zfs/wiki)
|
||||||
|
* [Mailing lists](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists)
|
||||||
|
* [OpenZFS site](http://open-zfs.org/)
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
Full documentation for installing ZoL on your favorite Linux distribution can
|
||||||
|
be found at [our site](http://zfsonlinux.org/).
|
||||||
|
|
||||||
|
# Contribute & Develop
|
||||||
|
We have a separate document with [contribution guidelines](./.github/CONTRIBUTING.md).
|
||||||
@@ -1,35 +0,0 @@
|
|||||||

|
|
||||||
|
|
||||||
OpenZFS is an advanced file system and volume manager which was originally
|
|
||||||
developed for Solaris and is now maintained by the OpenZFS community.
|
|
||||||
This repository contains the code for running OpenZFS on Linux and FreeBSD.
|
|
||||||
|
|
||||||
[](https://codecov.io/gh/openzfs/zfs)
|
|
||||||
[](https://scan.coverity.com/projects/openzfs-zfs)
|
|
||||||
|
|
||||||
# Official Resources
|
|
||||||
|
|
||||||
* [Documentation](https://openzfs.github.io/openzfs-docs/) - for using and developing this repo
|
|
||||||
* [ZoL Site](https://zfsonlinux.org) - Linux release info & links
|
|
||||||
* [Mailing lists](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html)
|
|
||||||
* [OpenZFS site](http://open-zfs.org/) - for conference videos and info on other platforms (illumos, OSX, Windows, etc)
|
|
||||||
|
|
||||||
# Installation
|
|
||||||
|
|
||||||
Full documentation for installing OpenZFS on your favorite operating system can
|
|
||||||
be found at the [Getting Started Page](https://openzfs.github.io/openzfs-docs/Getting%20Started/index.html).
|
|
||||||
|
|
||||||
# Contribute & Develop
|
|
||||||
|
|
||||||
We have a separate document with [contribution guidelines](./.github/CONTRIBUTING.md).
|
|
||||||
|
|
||||||
We have a [Code of Conduct](./CODE_OF_CONDUCT.md).
|
|
||||||
|
|
||||||
# Release
|
|
||||||
|
|
||||||
OpenZFS is released under a CDDL license.
|
|
||||||
For more details see the NOTICE, LICENSE and COPYRIGHT files; `UCRL-CODE-235197`
|
|
||||||
|
|
||||||
# Supported Kernels
|
|
||||||
* The `META` file contains the officially recognized supported Linux kernel versions.
|
|
||||||
* Supported FreeBSD versions are 12-STABLE and 13-CURRENT.
|
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
### prepare
|
### prepare
|
||||||
#TEST_PREPARE_WATCHDOG="yes"
|
#TEST_PREPARE_WATCHDOG="no"
|
||||||
#TEST_PREPARE_SHARES="yes"
|
|
||||||
|
### SPLAT
|
||||||
|
#TEST_SPLAT_SKIP="yes"
|
||||||
|
#TEST_SPLAT_OPTIONS="-acvx"
|
||||||
|
|
||||||
### ztest
|
### ztest
|
||||||
#TEST_ZTEST_SKIP="yes"
|
#TEST_ZTEST_SKIP="yes"
|
||||||
#TEST_ZTEST_TIMEOUT=1800
|
#TEST_ZTEST_TIMEOUT=1800
|
||||||
#TEST_ZTEST_DIR="/var/tmp/"
|
#TEST_ZTEST_DIR="/var/tmp/"
|
||||||
#TEST_ZTEST_OPTIONS="-V"
|
#TEST_ZTEST_OPTIONS="-V"
|
||||||
#TEST_ZTEST_CORE_DIR="/mnt/zloop"
|
|
||||||
|
|
||||||
### zimport
|
### zimport
|
||||||
#TEST_ZIMPORT_SKIP="yes"
|
#TEST_ZIMPORT_SKIP="yes"
|
||||||
@@ -29,13 +31,9 @@
|
|||||||
|
|
||||||
### zfs-tests.sh
|
### zfs-tests.sh
|
||||||
#TEST_ZFSTESTS_SKIP="yes"
|
#TEST_ZFSTESTS_SKIP="yes"
|
||||||
#TEST_ZFSTESTS_DIR="/mnt/"
|
|
||||||
#TEST_ZFSTESTS_DISKS="vdb vdc vdd"
|
#TEST_ZFSTESTS_DISKS="vdb vdc vdd"
|
||||||
#TEST_ZFSTESTS_DISKSIZE="8G"
|
#TEST_ZFSTESTS_DISKSIZE="8G"
|
||||||
#TEST_ZFSTESTS_ITERS="1"
|
|
||||||
#TEST_ZFSTESTS_OPTIONS="-vx"
|
|
||||||
#TEST_ZFSTESTS_RUNFILE="linux.run"
|
#TEST_ZFSTESTS_RUNFILE="linux.run"
|
||||||
#TEST_ZFSTESTS_TAGS="functional"
|
|
||||||
|
|
||||||
### zfsstress
|
### zfsstress
|
||||||
#TEST_ZFSSTRESS_SKIP="yes"
|
#TEST_ZFSSTRESS_SKIP="yes"
|
||||||
@@ -44,7 +42,53 @@
|
|||||||
#TEST_ZFSSTRESS_RUNTIME=300
|
#TEST_ZFSSTRESS_RUNTIME=300
|
||||||
#TEST_ZFSSTRESS_POOL="tank"
|
#TEST_ZFSSTRESS_POOL="tank"
|
||||||
#TEST_ZFSSTRESS_FS="fish"
|
#TEST_ZFSSTRESS_FS="fish"
|
||||||
#TEST_ZFSSTRESS_FSOPT="-o overlay=on"
|
|
||||||
#TEST_ZFSSTRESS_VDEV="/var/tmp/vdev"
|
#TEST_ZFSSTRESS_VDEV="/var/tmp/vdev"
|
||||||
#TEST_ZFSSTRESS_DIR="/$TEST_ZFSSTRESS_POOL/$TEST_ZFSSTRESS_FS"
|
#TEST_ZFSSTRESS_DIR="/$TEST_ZFSSTRESS_POOL/$TEST_ZFSSTRESS_FS"
|
||||||
#TEST_ZFSSTRESS_OPTIONS=""
|
#TEST_ZFSSTRESS_OPTIONS=""
|
||||||
|
|
||||||
|
### per-builder customization
|
||||||
|
#
|
||||||
|
# BB_NAME=builder-name <distribution-version-architecture-type>
|
||||||
|
# - distribution=Amazon,Debian,Fedora,RHEL,SUSE,Ubuntu
|
||||||
|
# - version=x.y
|
||||||
|
# - architecture=x86_64,i686,arm,aarch64
|
||||||
|
# - type=build,test
|
||||||
|
#
|
||||||
|
case "$BB_NAME" in
|
||||||
|
Amazon*)
|
||||||
|
# ZFS enabled xfstests fails to build
|
||||||
|
TEST_XFSTESTS_SKIP="yes"
|
||||||
|
;;
|
||||||
|
CentOS-7*)
|
||||||
|
# ZFS enabled xfstests fails to build
|
||||||
|
TEST_XFSTESTS_SKIP="yes"
|
||||||
|
;;
|
||||||
|
CentOS-6*)
|
||||||
|
;;
|
||||||
|
Debian*)
|
||||||
|
;;
|
||||||
|
Fedora*)
|
||||||
|
;;
|
||||||
|
RHEL*)
|
||||||
|
;;
|
||||||
|
SUSE*)
|
||||||
|
;;
|
||||||
|
Ubuntu-16.04*)
|
||||||
|
# ZFS enabled xfstests fails to build
|
||||||
|
TEST_XFSTESTS_SKIP="yes"
|
||||||
|
;;
|
||||||
|
Ubuntu*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
###
|
||||||
|
#
|
||||||
|
# Disable the following test suites on 32-bit systems.
|
||||||
|
#
|
||||||
|
if [ $(getconf LONG_BIT) = "32" ]; then
|
||||||
|
TEST_ZTEST_SKIP="yes"
|
||||||
|
TEST_XFSTESTS_SKIP="yes"
|
||||||
|
TEST_ZFSSTRESS_SKIP="yes"
|
||||||
|
fi
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
autoreconf -fiv || exit 1
|
autoreconf -fiv
|
||||||
rm -Rf autom4te.cache
|
rm -Rf autom4te.cache
|
||||||
|
|||||||
+3
-10
@@ -1,10 +1,3 @@
|
|||||||
SUBDIRS = zfs zpool zdb zhack zinject zstream zstreamdump ztest
|
SUBDIRS = zfs zpool zdb zhack zinject zstreamdump ztest zpios
|
||||||
SUBDIRS += fsck_zfs vdev_id raidz_test zfs_ids_to_path
|
SUBDIRS += mount_zfs fsck_zfs zvol_id vdev_id arcstat dbufstat zed
|
||||||
|
SUBDIRS += arc_summary raidz_test zgenhostid
|
||||||
if USING_PYTHON
|
|
||||||
SUBDIRS += arcstat arc_summary dbufstat
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_LINUX
|
|
||||||
SUBDIRS += mount_zfs zed zgenhostid zvol_id zvol_wait
|
|
||||||
endif
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
arc_summary
|
|
||||||
@@ -1,13 +1 @@
|
|||||||
bin_SCRIPTS = arc_summary
|
dist_bin_SCRIPTS = arc_summary.py
|
||||||
|
|
||||||
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 $< $@
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# $Id: arc_summary.pl,v 388:e27800740aa2 2011-07-08 02:53:29Z jhell $
|
# $Id: arc_summary.pl,v 388:e27800740aa2 2011-07-08 02:53:29Z jhell $
|
||||||
#
|
#
|
||||||
@@ -35,14 +35,12 @@
|
|||||||
# Note some of this code uses older code (eg getopt instead of argparse,
|
# Note some of this code uses older code (eg getopt instead of argparse,
|
||||||
# subprocess.Popen() instead of subprocess.run()) because we need to support
|
# subprocess.Popen() instead of subprocess.run()) because we need to support
|
||||||
# some very old versions of Python.
|
# some very old versions of Python.
|
||||||
#
|
|
||||||
|
|
||||||
"""Print statistics on the ZFS Adjustable Replacement Cache (ARC)
|
"""Print statistics on the ZFS Adjustable Replacement Cache (ARC)
|
||||||
|
|
||||||
Provides basic information on the ARC, its efficiency, the L2ARC (if present),
|
Provides basic information on the ARC, its efficiency, the L2ARC (if present),
|
||||||
the Data Management Unit (DMU), Virtual Devices (VDEVs), and tunables. See the
|
the Data Management Unit (DMU), Virtual Devices (VDEVs), and tunables. See the
|
||||||
in-source documentation and code at
|
in-source documentation and code at
|
||||||
https://github.com/openzfs/zfs/blob/master/module/zfs/arc.c for details.
|
https://github.com/zfsonlinux/zfs/blob/master/module/zfs/arc.c for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import getopt
|
import getopt
|
||||||
@@ -54,50 +52,6 @@ import errno
|
|||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from decimal import Decimal as D
|
from decimal import Decimal as D
|
||||||
|
|
||||||
|
|
||||||
if sys.platform.startswith('freebsd'):
|
|
||||||
# Requires py27-sysctl on FreeBSD
|
|
||||||
import sysctl
|
|
||||||
|
|
||||||
def is_value(ctl):
|
|
||||||
return ctl.type != sysctl.CTLTYPE_NODE
|
|
||||||
|
|
||||||
def load_kstats(namespace):
|
|
||||||
"""Collect information on a specific subsystem of the ARC"""
|
|
||||||
|
|
||||||
base = 'kstat.zfs.misc.%s.' % namespace
|
|
||||||
fmt = lambda kstat: (kstat.name, D(kstat.value))
|
|
||||||
kstats = sysctl.filter(base)
|
|
||||||
return [fmt(kstat) for kstat in kstats if is_value(kstat)]
|
|
||||||
|
|
||||||
def load_tunables():
|
|
||||||
ctls = sysctl.filter('vfs.zfs')
|
|
||||||
return dict((ctl.name, ctl.value) for ctl in ctls if is_value(ctl))
|
|
||||||
|
|
||||||
elif sys.platform.startswith('linux'):
|
|
||||||
|
|
||||||
def load_kstats(namespace):
|
|
||||||
"""Collect information on a specific subsystem of the ARC"""
|
|
||||||
|
|
||||||
kstat = 'kstat.zfs.misc.%s.%%s' % namespace
|
|
||||||
path = '/proc/spl/kstat/zfs/%s' % namespace
|
|
||||||
with open(path) as f:
|
|
||||||
entries = [line.strip().split() for line in f][2:] # Skip header
|
|
||||||
return [(kstat % name, D(value)) for name, _, value in entries]
|
|
||||||
|
|
||||||
def load_tunables():
|
|
||||||
basepath = '/sys/module/zfs/parameters'
|
|
||||||
tunables = {}
|
|
||||||
for name in os.listdir(basepath):
|
|
||||||
if not name:
|
|
||||||
continue
|
|
||||||
path = '%s/%s' % (basepath, name)
|
|
||||||
with open(path) as f:
|
|
||||||
value = f.read()
|
|
||||||
tunables[name] = value.strip()
|
|
||||||
return tunables
|
|
||||||
|
|
||||||
|
|
||||||
show_tunable_descriptions = False
|
show_tunable_descriptions = False
|
||||||
alternate_tunable_layout = False
|
alternate_tunable_layout = False
|
||||||
|
|
||||||
@@ -120,10 +74,24 @@ def get_Kstat():
|
|||||||
of the same name.
|
of the same name.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def load_proc_kstats(fn, namespace):
|
||||||
|
"""Collect information on a specific subsystem of the ARC"""
|
||||||
|
|
||||||
|
kstats = [line.strip() for line in open(fn)]
|
||||||
|
del kstats[0:2]
|
||||||
|
for kstat in kstats:
|
||||||
|
kstat = kstat.strip()
|
||||||
|
name, _, value = kstat.split()
|
||||||
|
Kstat[namespace + name] = D(value)
|
||||||
|
|
||||||
Kstat = {}
|
Kstat = {}
|
||||||
Kstat.update(load_kstats('arcstats'))
|
load_proc_kstats('/proc/spl/kstat/zfs/arcstats',
|
||||||
Kstat.update(load_kstats('zfetchstats'))
|
'kstat.zfs.misc.arcstats.')
|
||||||
Kstat.update(load_kstats('vdev_cache_stats'))
|
load_proc_kstats('/proc/spl/kstat/zfs/zfetchstats',
|
||||||
|
'kstat.zfs.misc.zfetchstats.')
|
||||||
|
load_proc_kstats('/proc/spl/kstat/zfs/vdev_cache_stats',
|
||||||
|
'kstat.zfs.misc.vdev_cache_stats.')
|
||||||
|
|
||||||
return Kstat
|
return Kstat
|
||||||
|
|
||||||
|
|
||||||
@@ -236,10 +204,6 @@ def get_arc_summary(Kstat):
|
|||||||
arc_size = Kstat["kstat.zfs.misc.arcstats.size"]
|
arc_size = Kstat["kstat.zfs.misc.arcstats.size"]
|
||||||
mru_size = Kstat["kstat.zfs.misc.arcstats.mru_size"]
|
mru_size = Kstat["kstat.zfs.misc.arcstats.mru_size"]
|
||||||
mfu_size = Kstat["kstat.zfs.misc.arcstats.mfu_size"]
|
mfu_size = Kstat["kstat.zfs.misc.arcstats.mfu_size"]
|
||||||
meta_limit = Kstat["kstat.zfs.misc.arcstats.arc_meta_limit"]
|
|
||||||
meta_size = Kstat["kstat.zfs.misc.arcstats.arc_meta_used"]
|
|
||||||
dnode_limit = Kstat["kstat.zfs.misc.arcstats.arc_dnode_limit"]
|
|
||||||
dnode_size = Kstat["kstat.zfs.misc.arcstats.dnode_size"]
|
|
||||||
target_max_size = Kstat["kstat.zfs.misc.arcstats.c_max"]
|
target_max_size = Kstat["kstat.zfs.misc.arcstats.c_max"]
|
||||||
target_min_size = Kstat["kstat.zfs.misc.arcstats.c_min"]
|
target_min_size = Kstat["kstat.zfs.misc.arcstats.c_min"]
|
||||||
target_size = Kstat["kstat.zfs.misc.arcstats.c"]
|
target_size = Kstat["kstat.zfs.misc.arcstats.c"]
|
||||||
@@ -264,22 +228,6 @@ def get_arc_summary(Kstat):
|
|||||||
'per': fPerc(target_size, target_max_size),
|
'per': fPerc(target_size, target_max_size),
|
||||||
'num': fBytes(target_size),
|
'num': fBytes(target_size),
|
||||||
}
|
}
|
||||||
output['arc_sizing']['meta_limit'] = {
|
|
||||||
'per': fPerc(meta_limit, target_max_size),
|
|
||||||
'num': fBytes(meta_limit),
|
|
||||||
}
|
|
||||||
output['arc_sizing']['meta_size'] = {
|
|
||||||
'per': fPerc(meta_size, meta_limit),
|
|
||||||
'num': fBytes(meta_size),
|
|
||||||
}
|
|
||||||
output['arc_sizing']['dnode_limit'] = {
|
|
||||||
'per': fPerc(dnode_limit, meta_limit),
|
|
||||||
'num': fBytes(dnode_limit),
|
|
||||||
}
|
|
||||||
output['arc_sizing']['dnode_size'] = {
|
|
||||||
'per': fPerc(dnode_size, dnode_limit),
|
|
||||||
'num': fBytes(dnode_size),
|
|
||||||
}
|
|
||||||
|
|
||||||
# ARC Hash Breakdown
|
# ARC Hash Breakdown
|
||||||
output['arc_hash_break'] = {}
|
output['arc_hash_break'] = {}
|
||||||
@@ -385,26 +333,6 @@ def _arc_summary(Kstat):
|
|||||||
arc['arc_size_break']['frequently_used_cache_size']['num'],
|
arc['arc_size_break']['frequently_used_cache_size']['num'],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
sys.stdout.write("\tMetadata Size (Hard Limit):\t%s\t%s\n" % (
|
|
||||||
arc['arc_sizing']['meta_limit']['per'],
|
|
||||||
arc['arc_sizing']['meta_limit']['num'],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tMetadata Size:\t\t\t%s\t%s\n" % (
|
|
||||||
arc['arc_sizing']['meta_size']['per'],
|
|
||||||
arc['arc_sizing']['meta_size']['num'],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tDnode Size (Hard Limit):\t%s\t%s\n" % (
|
|
||||||
arc['arc_sizing']['dnode_limit']['per'],
|
|
||||||
arc['arc_sizing']['dnode_limit']['num'],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
sys.stdout.write("\tDnode Size:\t\t\t%s\t%s\n" % (
|
|
||||||
arc['arc_sizing']['dnode_size']['per'],
|
|
||||||
arc['arc_sizing']['dnode_size']['num'],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
@@ -951,7 +879,14 @@ def _tunable_summary(Kstat):
|
|||||||
global show_tunable_descriptions
|
global show_tunable_descriptions
|
||||||
global alternate_tunable_layout
|
global alternate_tunable_layout
|
||||||
|
|
||||||
tunables = load_tunables()
|
names = os.listdir("/sys/module/zfs/parameters/")
|
||||||
|
|
||||||
|
values = {}
|
||||||
|
for name in names:
|
||||||
|
with open("/sys/module/zfs/parameters/" + name) as f:
|
||||||
|
value = f.read()
|
||||||
|
values[name] = value.strip()
|
||||||
|
|
||||||
descriptions = {}
|
descriptions = {}
|
||||||
|
|
||||||
if show_tunable_descriptions:
|
if show_tunable_descriptions:
|
||||||
@@ -989,17 +924,22 @@ def _tunable_summary(Kstat):
|
|||||||
sys.stderr.write("Tunable descriptions will be disabled.\n")
|
sys.stderr.write("Tunable descriptions will be disabled.\n")
|
||||||
|
|
||||||
sys.stdout.write("ZFS Tunables:\n")
|
sys.stdout.write("ZFS Tunables:\n")
|
||||||
|
names.sort()
|
||||||
|
|
||||||
if alternate_tunable_layout:
|
if alternate_tunable_layout:
|
||||||
fmt = "\t%s=%s\n"
|
fmt = "\t%s=%s\n"
|
||||||
else:
|
else:
|
||||||
fmt = "\t%-50s%s\n"
|
fmt = "\t%-50s%s\n"
|
||||||
|
|
||||||
for name in sorted(tunables.keys()):
|
for name in names:
|
||||||
|
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
|
||||||
if show_tunable_descriptions and name in descriptions:
|
if show_tunable_descriptions and name in descriptions:
|
||||||
sys.stdout.write("\t# %s\n" % descriptions[name])
|
sys.stdout.write("\t# %s\n" % descriptions[name])
|
||||||
|
|
||||||
sys.stdout.write(fmt % (name, tunables[name]))
|
sys.stdout.write(fmt % (name, values[name]))
|
||||||
|
|
||||||
|
|
||||||
unSub = [
|
unSub = [
|
||||||
@@ -1025,7 +965,7 @@ def zfs_header():
|
|||||||
def usage():
|
def usage():
|
||||||
"""Print usage information"""
|
"""Print usage information"""
|
||||||
|
|
||||||
sys.stdout.write("Usage: arc_summary [-h] [-a] [-d] [-p PAGE]\n\n")
|
sys.stdout.write("Usage: arc_summary.py [-h] [-a] [-d] [-p PAGE]\n\n")
|
||||||
sys.stdout.write("\t -h, --help : "
|
sys.stdout.write("\t -h, --help : "
|
||||||
"Print this help message and exit\n")
|
"Print this help message and exit\n")
|
||||||
sys.stdout.write("\t -a, --alternate : "
|
sys.stdout.write("\t -a, --alternate : "
|
||||||
@@ -1038,10 +978,10 @@ def usage():
|
|||||||
"should be an integer between 1 and " +
|
"should be an integer between 1 and " +
|
||||||
str(len(unSub)) + "\n\n")
|
str(len(unSub)) + "\n\n")
|
||||||
sys.stdout.write("Examples:\n")
|
sys.stdout.write("Examples:\n")
|
||||||
sys.stdout.write("\tarc_summary -a\n")
|
sys.stdout.write("\tarc_summary.py -a\n")
|
||||||
sys.stdout.write("\tarc_summary -p 4\n")
|
sys.stdout.write("\tarc_summary.py -p 4\n")
|
||||||
sys.stdout.write("\tarc_summary -ad\n")
|
sys.stdout.write("\tarc_summary.py -ad\n")
|
||||||
sys.stdout.write("\tarc_summary --page=2\n")
|
sys.stdout.write("\tarc_summary.py --page=2\n")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -1,938 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Ben Rockwood <benr@cuddletech.com>,
|
|
||||||
# Copyright (c) 2010 Martin Matuska <mm@FreeBSD.org>,
|
|
||||||
# Copyright (c) 2010-2011 Jason J. Hellenthal <jhell@DataIX.net>,
|
|
||||||
# Copyright (c) 2017 Scot W. Stevenson <scot.stevenson@gmail.com>
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
|
||||||
# modification, are permitted provided that the following conditions
|
|
||||||
# are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer.
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
# notice, this list of conditions and the following disclaimer in the
|
|
||||||
# documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
# SUCH DAMAGE.
|
|
||||||
"""Print statistics on the ZFS ARC Cache and other information
|
|
||||||
|
|
||||||
Provides basic information on the ARC, its efficiency, the L2ARC (if present),
|
|
||||||
the Data Management Unit (DMU), Virtual Devices (VDEVs), and tunables. See
|
|
||||||
the in-source documentation and code at
|
|
||||||
https://github.com/openzfs/zfs/blob/master/module/zfs/arc.c for details.
|
|
||||||
The original introduction to arc_summary can be found at
|
|
||||||
http://cuddletech.com/?p=454
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
DESCRIPTION = 'Print ARC and other statistics for OpenZFS'
|
|
||||||
INDENT = ' '*8
|
|
||||||
LINE_LENGTH = 72
|
|
||||||
DATE_FORMAT = '%a %b %d %H:%M:%S %Y'
|
|
||||||
TITLE = 'ZFS Subsystem Report'
|
|
||||||
|
|
||||||
SECTIONS = 'arc archits dmu l2arc spl tunables vdev zil'.split()
|
|
||||||
SECTION_HELP = 'print info from one section ('+' '.join(SECTIONS)+')'
|
|
||||||
|
|
||||||
# Tunables and SPL are handled separately because they come from
|
|
||||||
# different sources
|
|
||||||
SECTION_PATHS = {'arc': 'arcstats',
|
|
||||||
'dmu': 'dmu_tx',
|
|
||||||
'l2arc': 'arcstats', # L2ARC stuff lives in arcstats
|
|
||||||
'vdev': 'vdev_cache_stats',
|
|
||||||
'xuio': 'xuio_stats',
|
|
||||||
'zfetch': 'zfetchstats',
|
|
||||||
'zil': 'zil'}
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description=DESCRIPTION)
|
|
||||||
parser.add_argument('-a', '--alternate', action='store_true', default=False,
|
|
||||||
help='use alternate formatting for tunables and SPL',
|
|
||||||
dest='alt')
|
|
||||||
parser.add_argument('-d', '--description', action='store_true', default=False,
|
|
||||||
help='print descriptions with tunables and SPL',
|
|
||||||
dest='desc')
|
|
||||||
parser.add_argument('-g', '--graph', action='store_true', default=False,
|
|
||||||
help='print graph on ARC use and exit', dest='graph')
|
|
||||||
parser.add_argument('-p', '--page', type=int, dest='page',
|
|
||||||
help='print page by number (DEPRECATED, use "-s")')
|
|
||||||
parser.add_argument('-r', '--raw', action='store_true', default=False,
|
|
||||||
help='dump all available data with minimal formatting',
|
|
||||||
dest='raw')
|
|
||||||
parser.add_argument('-s', '--section', dest='section', help=SECTION_HELP)
|
|
||||||
ARGS = parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
if sys.platform.startswith('freebsd'):
|
|
||||||
# Requires py36-sysctl on FreeBSD
|
|
||||||
import sysctl
|
|
||||||
|
|
||||||
VDEV_CACHE_SIZE = 'vdev.cache_size'
|
|
||||||
|
|
||||||
def is_value(ctl):
|
|
||||||
return ctl.type != sysctl.CTLTYPE_NODE
|
|
||||||
|
|
||||||
def namefmt(ctl, base='vfs.zfs.'):
|
|
||||||
# base is removed from the name
|
|
||||||
cut = len(base)
|
|
||||||
return ctl.name[cut:]
|
|
||||||
|
|
||||||
def load_kstats(section):
|
|
||||||
base = 'kstat.zfs.misc.{section}.'.format(section=section)
|
|
||||||
fmt = lambda kstat: '{name} : {value}'.format(name=namefmt(kstat, base),
|
|
||||||
value=kstat.value)
|
|
||||||
kstats = sysctl.filter(base)
|
|
||||||
return [fmt(kstat) for kstat in kstats if is_value(kstat)]
|
|
||||||
|
|
||||||
def get_params(base):
|
|
||||||
ctls = sysctl.filter(base)
|
|
||||||
return {namefmt(ctl): str(ctl.value) for ctl in ctls if is_value(ctl)}
|
|
||||||
|
|
||||||
def get_tunable_params():
|
|
||||||
return get_params('vfs.zfs')
|
|
||||||
|
|
||||||
def get_vdev_params():
|
|
||||||
return get_params('vfs.zfs.vdev')
|
|
||||||
|
|
||||||
def get_version_impl(request):
|
|
||||||
# FreeBSD reports versions for zpl and spa instead of zfs and spl.
|
|
||||||
name = {'zfs': 'zpl',
|
|
||||||
'spl': 'spa'}[request]
|
|
||||||
mib = 'vfs.zfs.version.{}'.format(name)
|
|
||||||
version = sysctl.filter(mib)[0].value
|
|
||||||
return '{} version {}'.format(name, version)
|
|
||||||
|
|
||||||
def get_descriptions(_request):
|
|
||||||
ctls = sysctl.filter('vfs.zfs')
|
|
||||||
return {namefmt(ctl): ctl.description for ctl in ctls if is_value(ctl)}
|
|
||||||
|
|
||||||
|
|
||||||
elif sys.platform.startswith('linux'):
|
|
||||||
KSTAT_PATH = '/proc/spl/kstat/zfs'
|
|
||||||
SPL_PATH = '/sys/module/spl/parameters'
|
|
||||||
TUNABLES_PATH = '/sys/module/zfs/parameters'
|
|
||||||
|
|
||||||
VDEV_CACHE_SIZE = 'zfs_vdev_cache_size'
|
|
||||||
|
|
||||||
def load_kstats(section):
|
|
||||||
path = os.path.join(KSTAT_PATH, section)
|
|
||||||
with open(path) as f:
|
|
||||||
return list(f)[2:] # Get rid of header
|
|
||||||
|
|
||||||
def get_params(basepath):
|
|
||||||
"""Collect information on the Solaris Porting Layer (SPL) or the
|
|
||||||
tunables, depending on the PATH given. Does not check if PATH is
|
|
||||||
legal.
|
|
||||||
"""
|
|
||||||
result = {}
|
|
||||||
for name in os.listdir(basepath):
|
|
||||||
path = os.path.join(basepath, name)
|
|
||||||
with open(path) as f:
|
|
||||||
value = f.read()
|
|
||||||
result[name] = value.strip()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def get_spl_params():
|
|
||||||
return get_params(SPL_PATH)
|
|
||||||
|
|
||||||
def get_tunable_params():
|
|
||||||
return get_params(TUNABLES_PATH)
|
|
||||||
|
|
||||||
def get_vdev_params():
|
|
||||||
return get_params(TUNABLES_PATH)
|
|
||||||
|
|
||||||
def get_version_impl(request):
|
|
||||||
# The original arc_summary called /sbin/modinfo/{spl,zfs} to get
|
|
||||||
# the version information. We switch to /sys/module/{spl,zfs}/version
|
|
||||||
# to make sure we get what is really loaded in the kernel
|
|
||||||
command = ["cat", "/sys/module/{0}/version".format(request)]
|
|
||||||
req = request.upper()
|
|
||||||
|
|
||||||
# The recommended way to do this is with subprocess.run(). However,
|
|
||||||
# some installed versions of Python are < 3.5, so we offer them
|
|
||||||
# the option of doing it the old way (for now)
|
|
||||||
if 'run' in dir(subprocess):
|
|
||||||
info = subprocess.run(command, stdout=subprocess.PIPE,
|
|
||||||
universal_newlines=True)
|
|
||||||
version = info.stdout.strip()
|
|
||||||
else:
|
|
||||||
info = subprocess.check_output(command, universal_newlines=True)
|
|
||||||
version = info.strip()
|
|
||||||
|
|
||||||
return version
|
|
||||||
|
|
||||||
def get_descriptions(request):
|
|
||||||
"""Get the descriptions of the Solaris Porting Layer (SPL) or the
|
|
||||||
tunables, return with minimal formatting.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if request not in ('spl', 'zfs'):
|
|
||||||
print('ERROR: description of "{0}" requested)'.format(request))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
descs = {}
|
|
||||||
target_prefix = 'parm:'
|
|
||||||
|
|
||||||
# We would prefer to do this with /sys/modules -- see the discussion at
|
|
||||||
# get_version() -- but there isn't a way to get the descriptions from
|
|
||||||
# there, so we fall back on modinfo
|
|
||||||
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 = ''
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
if 'run' in dir(subprocess):
|
|
||||||
info = subprocess.run(command, stdout=subprocess.PIPE,
|
|
||||||
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:
|
|
||||||
print("Error: Descriptions not available",
|
|
||||||
"(can't access kernel module)")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
for line in raw_output:
|
|
||||||
|
|
||||||
if not line.startswith(target_prefix):
|
|
||||||
continue
|
|
||||||
|
|
||||||
line = line[len(target_prefix):].strip()
|
|
||||||
name, raw_desc = line.split(':', 1)
|
|
||||||
desc = raw_desc.rsplit('(', 1)[0]
|
|
||||||
|
|
||||||
if desc == '':
|
|
||||||
desc = '(No description found)'
|
|
||||||
|
|
||||||
descs[name.strip()] = desc.strip()
|
|
||||||
|
|
||||||
return descs
|
|
||||||
|
|
||||||
|
|
||||||
def cleanup_line(single_line):
|
|
||||||
"""Format a raw line of data from /proc and isolate the name value
|
|
||||||
part, returning a tuple with each. Currently, this gets rid of the
|
|
||||||
middle '4'. For example "arc_no_grow 4 0" returns the tuple
|
|
||||||
("arc_no_grow", "0").
|
|
||||||
"""
|
|
||||||
name, _, value = single_line.split()
|
|
||||||
|
|
||||||
return name, value
|
|
||||||
|
|
||||||
|
|
||||||
def draw_graph(kstats_dict):
|
|
||||||
"""Draw a primitive graph representing the basic information on the
|
|
||||||
ARC -- its size and the proportion used by MFU and MRU -- and quit.
|
|
||||||
We use max size of the ARC to calculate how full it is. This is a
|
|
||||||
very rough representation.
|
|
||||||
"""
|
|
||||||
|
|
||||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
|
||||||
|
|
||||||
GRAPH_INDENT = ' '*4
|
|
||||||
GRAPH_WIDTH = 60
|
|
||||||
arc_size = f_bytes(arc_stats['size'])
|
|
||||||
arc_perc = f_perc(arc_stats['size'], arc_stats['c_max'])
|
|
||||||
mfu_size = f_bytes(arc_stats['mfu_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'])
|
|
||||||
|
|
||||||
info_form = ('ARC: {0} ({1}) MFU: {2} MRU: {3} META: {4} ({5}) '
|
|
||||||
'DNODE {6} ({7})')
|
|
||||||
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_line = GRAPH_INDENT+info_spc+info_line
|
|
||||||
|
|
||||||
graph_line = GRAPH_INDENT+'+'+('-'*(GRAPH_WIDTH-2))+'+'
|
|
||||||
|
|
||||||
mfu_perc = float(int(arc_stats['mfu_size'])/int(arc_stats['c_max']))
|
|
||||||
mru_perc = float(int(arc_stats['mru_size'])/int(arc_stats['c_max']))
|
|
||||||
arc_perc = float(int(arc_stats['size'])/int(arc_stats['c_max']))
|
|
||||||
total_ticks = float(arc_perc)*GRAPH_WIDTH
|
|
||||||
mfu_ticks = mfu_perc*GRAPH_WIDTH
|
|
||||||
mru_ticks = mru_perc*GRAPH_WIDTH
|
|
||||||
other_ticks = total_ticks-(mfu_ticks+mru_ticks)
|
|
||||||
|
|
||||||
core_form = 'F'*int(mfu_ticks)+'R'*int(mru_ticks)+'O'*int(other_ticks)
|
|
||||||
core_spc = ' '*(GRAPH_WIDTH-(2+len(core_form)))
|
|
||||||
core_line = GRAPH_INDENT+'|'+core_form+core_spc+'|'
|
|
||||||
|
|
||||||
for line in ('', info_line, graph_line, core_line, graph_line, ''):
|
|
||||||
print(line)
|
|
||||||
|
|
||||||
|
|
||||||
def f_bytes(byte_string):
|
|
||||||
"""Return human-readable representation of a byte value in
|
|
||||||
powers of 2 (eg "KiB" for "kibibytes", etc) to two decimal
|
|
||||||
points. Values smaller than one KiB are returned without
|
|
||||||
decimal points. Note "bytes" is a reserved keyword.
|
|
||||||
"""
|
|
||||||
|
|
||||||
prefixes = ([2**80, "YiB"], # yobibytes (yotta)
|
|
||||||
[2**70, "ZiB"], # zebibytes (zetta)
|
|
||||||
[2**60, "EiB"], # exbibytes (exa)
|
|
||||||
[2**50, "PiB"], # pebibytes (peta)
|
|
||||||
[2**40, "TiB"], # tebibytes (tera)
|
|
||||||
[2**30, "GiB"], # gibibytes (giga)
|
|
||||||
[2**20, "MiB"], # mebibytes (mega)
|
|
||||||
[2**10, "KiB"]) # kibibytes (kilo)
|
|
||||||
|
|
||||||
bites = int(byte_string)
|
|
||||||
|
|
||||||
if bites >= 2**10:
|
|
||||||
for limit, unit in prefixes:
|
|
||||||
|
|
||||||
if bites >= limit:
|
|
||||||
value = bites / limit
|
|
||||||
break
|
|
||||||
|
|
||||||
result = '{0:.1f} {1}'.format(value, unit)
|
|
||||||
else:
|
|
||||||
result = '{0} Bytes'.format(bites)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def f_hits(hits_string):
|
|
||||||
"""Create a human-readable representation of the number of hits.
|
|
||||||
The single-letter symbols used are SI to avoid the confusion caused
|
|
||||||
by the different "short scale" and "long scale" representations in
|
|
||||||
English, which use the same words for different values. See
|
|
||||||
https://en.wikipedia.org/wiki/Names_of_large_numbers and:
|
|
||||||
https://physics.nist.gov/cuu/Units/prefixes.html
|
|
||||||
"""
|
|
||||||
|
|
||||||
numbers = ([10**24, 'Y'], # yotta (septillion)
|
|
||||||
[10**21, 'Z'], # zetta (sextillion)
|
|
||||||
[10**18, 'E'], # exa (quintrillion)
|
|
||||||
[10**15, 'P'], # peta (quadrillion)
|
|
||||||
[10**12, 'T'], # tera (trillion)
|
|
||||||
[10**9, 'G'], # giga (billion)
|
|
||||||
[10**6, 'M'], # mega (million)
|
|
||||||
[10**3, 'k']) # kilo (thousand)
|
|
||||||
|
|
||||||
hits = int(hits_string)
|
|
||||||
|
|
||||||
if hits >= 1000:
|
|
||||||
for limit, symbol in numbers:
|
|
||||||
|
|
||||||
if hits >= limit:
|
|
||||||
value = hits/limit
|
|
||||||
break
|
|
||||||
|
|
||||||
result = "%0.1f%s" % (value, symbol)
|
|
||||||
else:
|
|
||||||
result = "%d" % hits
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def f_perc(value1, value2):
|
|
||||||
"""Calculate percentage and return in human-readable form. If
|
|
||||||
rounding produces the result '0.0' though the first number is
|
|
||||||
not zero, include a 'less-than' symbol to avoid confusion.
|
|
||||||
Division by zero is handled by returning 'n/a'; no error
|
|
||||||
is called.
|
|
||||||
"""
|
|
||||||
|
|
||||||
v1 = float(value1)
|
|
||||||
v2 = float(value2)
|
|
||||||
|
|
||||||
try:
|
|
||||||
perc = 100 * v1/v2
|
|
||||||
except ZeroDivisionError:
|
|
||||||
result = 'n/a'
|
|
||||||
else:
|
|
||||||
result = '{0:0.1f} %'.format(perc)
|
|
||||||
|
|
||||||
if result == '0.0 %' and v1 > 0:
|
|
||||||
result = '< 0.1 %'
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def format_raw_line(name, value):
|
|
||||||
"""For the --raw option for the tunable and SPL outputs, decide on the
|
|
||||||
correct formatting based on the --alternate flag.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if ARGS.alt:
|
|
||||||
result = '{0}{1}={2}'.format(INDENT, name, value)
|
|
||||||
else:
|
|
||||||
# Right-align the value within the line length if it fits,
|
|
||||||
# otherwise just separate it from the name by a single space.
|
|
||||||
fit = LINE_LENGTH - len(INDENT) - len(name)
|
|
||||||
overflow = len(value) + 1
|
|
||||||
w = max(fit, overflow)
|
|
||||||
result = '{0}{1}{2:>{w}}'.format(INDENT, name, value, w=w)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def get_kstats():
|
|
||||||
"""Collect information on the ZFS subsystem. The step does not perform any
|
|
||||||
further processing, giving us the option to only work on what is actually
|
|
||||||
needed. The name "kstat" is a holdover from the Solaris utility of the same
|
|
||||||
name.
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = {}
|
|
||||||
|
|
||||||
for section in SECTION_PATHS.values():
|
|
||||||
if section not in result:
|
|
||||||
result[section] = load_kstats(section)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def get_version(request):
|
|
||||||
"""Get the version number of ZFS or SPL on this machine for header.
|
|
||||||
Returns an error string, but does not raise an error, if we can't
|
|
||||||
get the ZFS/SPL version.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if request not in ('spl', 'zfs'):
|
|
||||||
error_msg = '(ERROR: "{0}" requested)'.format(request)
|
|
||||||
return error_msg
|
|
||||||
|
|
||||||
return get_version_impl(request)
|
|
||||||
|
|
||||||
|
|
||||||
def print_header():
|
|
||||||
"""Print the initial heading with date and time as well as info on the
|
|
||||||
kernel and ZFS versions. This is not called for the graph.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# datetime is now recommended over time but we keep the exact formatting
|
|
||||||
# from the older version of arc_summary in case there are scripts
|
|
||||||
# that expect it in this way
|
|
||||||
daydate = time.strftime(DATE_FORMAT)
|
|
||||||
spc_date = LINE_LENGTH-len(daydate)
|
|
||||||
sys_version = os.uname()
|
|
||||||
|
|
||||||
sys_msg = sys_version.sysname+' '+sys_version.release
|
|
||||||
zfs = get_version('zfs')
|
|
||||||
spc_zfs = LINE_LENGTH-len(zfs)
|
|
||||||
|
|
||||||
machine_msg = 'Machine: '+sys_version.nodename+' ('+sys_version.machine+')'
|
|
||||||
spl = get_version('spl')
|
|
||||||
spc_spl = LINE_LENGTH-len(spl)
|
|
||||||
|
|
||||||
print('\n'+('-'*LINE_LENGTH))
|
|
||||||
print('{0:<{spc}}{1}'.format(TITLE, daydate, spc=spc_date))
|
|
||||||
print('{0:<{spc}}{1}'.format(sys_msg, zfs, spc=spc_zfs))
|
|
||||||
print('{0:<{spc}}{1}\n'.format(machine_msg, spl, spc=spc_spl))
|
|
||||||
|
|
||||||
|
|
||||||
def print_raw(kstats_dict):
|
|
||||||
"""Print all available data from the system in a minimally sorted format.
|
|
||||||
This can be used as a source to be piped through 'grep'.
|
|
||||||
"""
|
|
||||||
|
|
||||||
sections = sorted(kstats_dict.keys())
|
|
||||||
|
|
||||||
for section in sections:
|
|
||||||
|
|
||||||
print('\n{0}:'.format(section.upper()))
|
|
||||||
lines = sorted(kstats_dict[section])
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
name, value = cleanup_line(line)
|
|
||||||
print(format_raw_line(name, value))
|
|
||||||
|
|
||||||
# Tunables and SPL must be handled separately because they come from a
|
|
||||||
# different source and have descriptions the user might request
|
|
||||||
print()
|
|
||||||
section_spl()
|
|
||||||
section_tunables()
|
|
||||||
|
|
||||||
|
|
||||||
def isolate_section(section_name, kstats_dict):
|
|
||||||
"""From the complete information on all sections, retrieve only those
|
|
||||||
for one section.
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
section_data = kstats_dict[section_name]
|
|
||||||
except KeyError:
|
|
||||||
print('ERROR: Data on {0} not available'.format(section_data))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
section_dict = dict(cleanup_line(l) for l in section_data)
|
|
||||||
|
|
||||||
return section_dict
|
|
||||||
|
|
||||||
|
|
||||||
# Formatted output helper functions
|
|
||||||
|
|
||||||
|
|
||||||
def prt_1(text, value):
|
|
||||||
"""Print text and one value, no indent"""
|
|
||||||
spc = ' '*(LINE_LENGTH-(len(text)+len(value)))
|
|
||||||
print('{0}{spc}{1}'.format(text, value, spc=spc))
|
|
||||||
|
|
||||||
|
|
||||||
def prt_i1(text, value):
|
|
||||||
"""Print text and one value, with indent"""
|
|
||||||
spc = ' '*(LINE_LENGTH-(len(INDENT)+len(text)+len(value)))
|
|
||||||
print(INDENT+'{0}{spc}{1}'.format(text, value, spc=spc))
|
|
||||||
|
|
||||||
|
|
||||||
def prt_2(text, value1, value2):
|
|
||||||
"""Print text and two values, no indent"""
|
|
||||||
values = '{0:>9} {1:>9}'.format(value1, value2)
|
|
||||||
spc = ' '*(LINE_LENGTH-(len(text)+len(values)+2))
|
|
||||||
print('{0}{spc} {1}'.format(text, values, spc=spc))
|
|
||||||
|
|
||||||
|
|
||||||
def prt_i2(text, value1, value2):
|
|
||||||
"""Print text and two values, with indent"""
|
|
||||||
values = '{0:>9} {1:>9}'.format(value1, value2)
|
|
||||||
spc = ' '*(LINE_LENGTH-(len(INDENT)+len(text)+len(values)+2))
|
|
||||||
print(INDENT+'{0}{spc} {1}'.format(text, values, spc=spc))
|
|
||||||
|
|
||||||
|
|
||||||
# The section output concentrates on important parameters instead of
|
|
||||||
# being exhaustive (that is what the --raw parameter is for)
|
|
||||||
|
|
||||||
|
|
||||||
def section_arc(kstats_dict):
|
|
||||||
"""Give basic information on the ARC, MRU and MFU. This is the first
|
|
||||||
and most used section.
|
|
||||||
"""
|
|
||||||
|
|
||||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
|
||||||
|
|
||||||
throttle = arc_stats['memory_throttle_count']
|
|
||||||
|
|
||||||
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_target_size = arc_stats['c']
|
|
||||||
arc_max = arc_stats['c_max']
|
|
||||||
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_size = arc_stats['dnode_size']
|
|
||||||
target_size_ratio = '{0}:1'.format(int(arc_max) // int(arc_min))
|
|
||||||
|
|
||||||
prt_2('ARC size (current):',
|
|
||||||
f_perc(arc_size, arc_max), f_bytes(arc_size))
|
|
||||||
prt_i2('Target size (adaptive):',
|
|
||||||
f_perc(arc_target_size, arc_max), f_bytes(arc_target_size))
|
|
||||||
prt_i2('Min size (hard limit):',
|
|
||||||
f_perc(arc_min, arc_max), f_bytes(arc_min))
|
|
||||||
prt_i2('Max size (high water):',
|
|
||||||
target_size_ratio, f_bytes(arc_max))
|
|
||||||
caches_size = int(mfu_size)+int(mru_size)
|
|
||||||
prt_i2('Most Frequently Used (MFU) cache size:',
|
|
||||||
f_perc(mfu_size, caches_size), f_bytes(mfu_size))
|
|
||||||
prt_i2('Most Recently Used (MRU) cache size:',
|
|
||||||
f_perc(mru_size, caches_size), f_bytes(mru_size))
|
|
||||||
prt_i2('Metadata cache size (hard limit):',
|
|
||||||
f_perc(meta_limit, arc_max), f_bytes(meta_limit))
|
|
||||||
prt_i2('Metadata cache size (current):',
|
|
||||||
f_perc(meta_size, meta_limit), f_bytes(meta_size))
|
|
||||||
prt_i2('Dnode cache size (hard limit):',
|
|
||||||
f_perc(dnode_limit, meta_limit), f_bytes(dnode_limit))
|
|
||||||
prt_i2('Dnode cache size (current):',
|
|
||||||
f_perc(dnode_size, dnode_limit), f_bytes(dnode_size))
|
|
||||||
print()
|
|
||||||
|
|
||||||
print('ARC hash breakdown:')
|
|
||||||
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('Chain max:', f_hits(arc_stats['hash_chain_max']))
|
|
||||||
prt_i1('Chains:', f_hits(arc_stats['hash_chains']))
|
|
||||||
print()
|
|
||||||
|
|
||||||
print('ARC misc:')
|
|
||||||
prt_i1('Deleted:', f_hits(arc_stats['deleted']))
|
|
||||||
prt_i1('Mutex misses:', f_hits(arc_stats['mutex_miss']))
|
|
||||||
prt_i1('Eviction skips:', f_hits(arc_stats['evict_skip']))
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def section_archits(kstats_dict):
|
|
||||||
"""Print information on how the caches are accessed ("arc hits").
|
|
||||||
"""
|
|
||||||
|
|
||||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
|
||||||
all_accesses = int(arc_stats['hits'])+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))
|
|
||||||
|
|
||||||
for title, value in ta_todo:
|
|
||||||
prt_i2(title, f_perc(value, all_accesses), f_hits(value))
|
|
||||||
|
|
||||||
dd_total = int(arc_stats['demand_data_hits']) +\
|
|
||||||
int(arc_stats['demand_data_misses'])
|
|
||||||
prt_i2('Data demand efficiency:',
|
|
||||||
f_perc(arc_stats['demand_data_hits'], dd_total),
|
|
||||||
f_hits(dd_total))
|
|
||||||
|
|
||||||
dp_total = int(arc_stats['prefetch_data_hits']) +\
|
|
||||||
int(arc_stats['prefetch_data_misses'])
|
|
||||||
prt_i2('Data prefetch efficiency:',
|
|
||||||
f_perc(arc_stats['prefetch_data_hits'], dp_total),
|
|
||||||
f_hits(dp_total))
|
|
||||||
|
|
||||||
known_hits = int(arc_stats['mfu_hits']) +\
|
|
||||||
int(arc_stats['mru_hits']) +\
|
|
||||||
int(arc_stats['mfu_ghost_hits']) +\
|
|
||||||
int(arc_stats['mru_ghost_hits'])
|
|
||||||
|
|
||||||
anon_hits = int(arc_stats['hits'])-known_hits
|
|
||||||
|
|
||||||
print()
|
|
||||||
print('Cache hits by cache type:')
|
|
||||||
cl_todo = (('Most frequently used (MFU):', arc_stats['mfu_hits']),
|
|
||||||
('Most recently used (MRU):', arc_stats['mru_hits']),
|
|
||||||
('Most frequently used (MFU) ghost:',
|
|
||||||
arc_stats['mfu_ghost_hits']),
|
|
||||||
('Most recently used (MRU) ghost:',
|
|
||||||
arc_stats['mru_ghost_hits']))
|
|
||||||
|
|
||||||
for title, value in cl_todo:
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
||||||
def section_dmu(kstats_dict):
|
|
||||||
"""Collect information on the DMU"""
|
|
||||||
|
|
||||||
zfetch_stats = isolate_section('zfetchstats', kstats_dict)
|
|
||||||
|
|
||||||
zfetch_access_total = int(zfetch_stats['hits'])+int(zfetch_stats['misses'])
|
|
||||||
|
|
||||||
prt_1('DMU prefetch efficiency:', f_hits(zfetch_access_total))
|
|
||||||
prt_i2('Hit ratio:', f_perc(zfetch_stats['hits'], zfetch_access_total),
|
|
||||||
f_hits(zfetch_stats['hits']))
|
|
||||||
prt_i2('Miss ratio:', f_perc(zfetch_stats['misses'], zfetch_access_total),
|
|
||||||
f_hits(zfetch_stats['misses']))
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def section_l2arc(kstats_dict):
|
|
||||||
"""Collect information on L2ARC device if present. If not, tell user
|
|
||||||
that we're skipping the section.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# The L2ARC statistics live in the same section as the normal ARC stuff
|
|
||||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
|
||||||
|
|
||||||
if arc_stats['l2_size'] == '0':
|
|
||||||
print('L2ARC not detected, skipping section\n')
|
|
||||||
return
|
|
||||||
|
|
||||||
l2_errors = int(arc_stats['l2_writes_error']) +\
|
|
||||||
int(arc_stats['l2_cksum_bad']) +\
|
|
||||||
int(arc_stats['l2_io_error'])
|
|
||||||
|
|
||||||
l2_access_total = int(arc_stats['l2_hits'])+int(arc_stats['l2_misses'])
|
|
||||||
health = 'HEALTHY'
|
|
||||||
|
|
||||||
if l2_errors > 0:
|
|
||||||
health = 'DEGRADED'
|
|
||||||
|
|
||||||
prt_1('L2ARC status:', health)
|
|
||||||
|
|
||||||
l2_todo = (('Low memory aborts:', 'l2_abort_lowmem'),
|
|
||||||
('Free on write:', 'l2_free_on_write'),
|
|
||||||
('R/W clashes:', 'l2_rw_clash'),
|
|
||||||
('Bad checksums:', 'l2_cksum_bad'),
|
|
||||||
('I/O errors:', 'l2_io_error'))
|
|
||||||
|
|
||||||
for title, value in l2_todo:
|
|
||||||
prt_i1(title, f_hits(arc_stats[value]))
|
|
||||||
|
|
||||||
print()
|
|
||||||
prt_1('L2ARC size (adaptive):', f_bytes(arc_stats['l2_size']))
|
|
||||||
prt_i2('Compressed:', f_perc(arc_stats['l2_asize'], arc_stats['l2_size']),
|
|
||||||
f_bytes(arc_stats['l2_asize']))
|
|
||||||
prt_i2('Header size:',
|
|
||||||
f_perc(arc_stats['l2_hdr_size'], arc_stats['l2_size']),
|
|
||||||
f_bytes(arc_stats['l2_hdr_size']))
|
|
||||||
|
|
||||||
print()
|
|
||||||
prt_1('L2ARC breakdown:', f_hits(l2_access_total))
|
|
||||||
prt_i2('Hit ratio:',
|
|
||||||
f_perc(arc_stats['l2_hits'], l2_access_total),
|
|
||||||
f_hits(arc_stats['l2_hits']))
|
|
||||||
prt_i2('Miss ratio:',
|
|
||||||
f_perc(arc_stats['l2_misses'], l2_access_total),
|
|
||||||
f_hits(arc_stats['l2_misses']))
|
|
||||||
prt_i1('Feeds:', f_hits(arc_stats['l2_feeds']))
|
|
||||||
|
|
||||||
print()
|
|
||||||
print('L2ARC writes:')
|
|
||||||
|
|
||||||
if arc_stats['l2_writes_done'] != arc_stats['l2_writes_sent']:
|
|
||||||
prt_i2('Writes sent:', 'FAULTED', f_hits(arc_stats['l2_writes_sent']))
|
|
||||||
prt_i2('Done ratio:',
|
|
||||||
f_perc(arc_stats['l2_writes_done'],
|
|
||||||
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('L2ARC evicts:')
|
|
||||||
prt_i1('Lock retries:', f_hits(arc_stats['l2_evict_lock_retry']))
|
|
||||||
prt_i1('Upon reading:', f_hits(arc_stats['l2_evict_reading']))
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def section_spl(*_):
|
|
||||||
"""Print the SPL parameters, if requested with alternative format
|
|
||||||
and/or descriptions. This does not use kstats.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if sys.platform.startswith('freebsd'):
|
|
||||||
# No SPL support in FreeBSD
|
|
||||||
return
|
|
||||||
|
|
||||||
spls = get_spl_params()
|
|
||||||
keylist = sorted(spls.keys())
|
|
||||||
print('Solaris Porting Layer (SPL):')
|
|
||||||
|
|
||||||
if ARGS.desc:
|
|
||||||
descriptions = get_descriptions('spl')
|
|
||||||
|
|
||||||
for key in keylist:
|
|
||||||
value = spls[key]
|
|
||||||
|
|
||||||
if ARGS.desc:
|
|
||||||
try:
|
|
||||||
print(INDENT+'#', descriptions[key])
|
|
||||||
except KeyError:
|
|
||||||
print(INDENT+'# (No description found)') # paranoid
|
|
||||||
|
|
||||||
print(format_raw_line(key, value))
|
|
||||||
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def section_tunables(*_):
|
|
||||||
"""Print the tunables, if requested with alternative format and/or
|
|
||||||
descriptions. This does not use kstasts.
|
|
||||||
"""
|
|
||||||
|
|
||||||
tunables = get_tunable_params()
|
|
||||||
keylist = sorted(tunables.keys())
|
|
||||||
print('Tunables:')
|
|
||||||
|
|
||||||
if ARGS.desc:
|
|
||||||
descriptions = get_descriptions('zfs')
|
|
||||||
|
|
||||||
for key in keylist:
|
|
||||||
value = tunables[key]
|
|
||||||
|
|
||||||
if ARGS.desc:
|
|
||||||
try:
|
|
||||||
print(INDENT+'#', descriptions[key])
|
|
||||||
except KeyError:
|
|
||||||
print(INDENT+'# (No description found)') # paranoid
|
|
||||||
|
|
||||||
print(format_raw_line(key, value))
|
|
||||||
|
|
||||||
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):
|
|
||||||
"""Collect information on the ZFS Intent Log. Some of the information
|
|
||||||
taken from https://github.com/openzfs/zfs/blob/master/include/sys/zil.h
|
|
||||||
"""
|
|
||||||
|
|
||||||
zil_stats = isolate_section('zil', kstats_dict)
|
|
||||||
|
|
||||||
prt_1('ZIL committed transactions:',
|
|
||||||
f_hits(zil_stats['zil_itx_count']))
|
|
||||||
prt_i1('Commit requests:', f_hits(zil_stats['zil_commit_count']))
|
|
||||||
prt_i1('Flushes to stable storage:',
|
|
||||||
f_hits(zil_stats['zil_commit_writer_count']))
|
|
||||||
prt_i2('Transactions to SLOG storage pool:',
|
|
||||||
f_bytes(zil_stats['zil_itx_metaslab_slog_bytes']),
|
|
||||||
f_hits(zil_stats['zil_itx_metaslab_slog_count']))
|
|
||||||
prt_i2('Transactions to non-SLOG storage pool:',
|
|
||||||
f_bytes(zil_stats['zil_itx_metaslab_normal_bytes']),
|
|
||||||
f_hits(zil_stats['zil_itx_metaslab_normal_count']))
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
section_calls = {'arc': section_arc,
|
|
||||||
'archits': section_archits,
|
|
||||||
'dmu': section_dmu,
|
|
||||||
'l2arc': section_l2arc,
|
|
||||||
'spl': section_spl,
|
|
||||||
'tunables': section_tunables,
|
|
||||||
'vdev': section_vdev,
|
|
||||||
'zil': section_zil}
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Run program. The options to draw a graph and to print all data raw are
|
|
||||||
treated separately because they come with their own call.
|
|
||||||
"""
|
|
||||||
|
|
||||||
kstats = get_kstats()
|
|
||||||
|
|
||||||
if ARGS.graph:
|
|
||||||
draw_graph(kstats)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
print_header()
|
|
||||||
|
|
||||||
if ARGS.raw:
|
|
||||||
print_raw(kstats)
|
|
||||||
|
|
||||||
elif ARGS.section:
|
|
||||||
|
|
||||||
try:
|
|
||||||
section_calls[ARGS.section](kstats)
|
|
||||||
except KeyError:
|
|
||||||
print('Error: Section "{0}" unknown'.format(ARGS.section))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
elif ARGS.page:
|
|
||||||
print('WARNING: Pages are deprecated, please use "--section"\n')
|
|
||||||
|
|
||||||
pages_to_calls = {1: 'arc',
|
|
||||||
2: 'archits',
|
|
||||||
3: 'l2arc',
|
|
||||||
4: 'dmu',
|
|
||||||
5: 'vdev',
|
|
||||||
6: 'tunables'}
|
|
||||||
|
|
||||||
try:
|
|
||||||
call = pages_to_calls[ARGS.page]
|
|
||||||
except KeyError:
|
|
||||||
print('Error: Page "{0}" not supported'.format(ARGS.page))
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
section_calls[call](kstats)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# If no parameters were given, we print all sections. We might want to
|
|
||||||
# change the sequence by hand
|
|
||||||
calls = sorted(section_calls.keys())
|
|
||||||
|
|
||||||
for section in calls:
|
|
||||||
section_calls[section](kstats)
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
arcstat
|
|
||||||
@@ -1,5 +1 @@
|
|||||||
include $(top_srcdir)/config/Substfiles.am
|
dist_bin_SCRIPTS = arcstat.py
|
||||||
|
|
||||||
bin_SCRIPTS = arcstat
|
|
||||||
|
|
||||||
SUBSTFILES += $(bin_SCRIPTS)
|
|
||||||
|
|||||||
@@ -1,25 +1,20 @@
|
|||||||
#!/usr/bin/env @PYTHON_SHEBANG@
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Print out ZFS ARC Statistics exported via kstat(1)
|
# Print out ZFS ARC Statistics exported via kstat(1)
|
||||||
# For a definition of fields, or usage, use arcstat -v
|
# For a definition of fields, or usage, use arctstat.pl -v
|
||||||
#
|
#
|
||||||
# This script was originally a fork of the original arcstat.pl (0.1)
|
# This script is a fork of the original arcstat.pl (0.1) by
|
||||||
# by Neelakanth Nadgir, originally published on his Sun blog on
|
# Neelakanth Nadgir, originally published on his Sun blog on
|
||||||
# 09/18/2007
|
# 09/18/2007
|
||||||
# http://blogs.sun.com/realneel/entry/zfs_arc_statistics
|
# http://blogs.sun.com/realneel/entry/zfs_arc_statistics
|
||||||
#
|
#
|
||||||
# A new version aimed to improve upon the original by adding features
|
# This version aims to improve upon the original by adding features
|
||||||
# and fixing bugs as needed. This version was maintained by Mike
|
# and fixing bugs as needed. This version is maintained by
|
||||||
# Harsch and was hosted in a public open source repository:
|
# Mike Harsch and is hosted in a public open source repository:
|
||||||
# http://github.com/mharsch/arcstat
|
# http://github.com/mharsch/arcstat
|
||||||
#
|
#
|
||||||
# but has since moved to the illumos-gate repository.
|
# Comments, Questions, or Suggestions are always welcome.
|
||||||
#
|
# Contact the maintainer at ( mike at harschsystems dot com )
|
||||||
# This Python port was written by John Hixson for FreeNAS, introduced
|
|
||||||
# in commit e2c29f:
|
|
||||||
# https://github.com/freenas/freenas
|
|
||||||
#
|
|
||||||
# and has been improved by many people since.
|
|
||||||
#
|
#
|
||||||
# CDDL HEADER START
|
# CDDL HEADER START
|
||||||
#
|
#
|
||||||
@@ -47,8 +42,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 2.6+ and Python 3.4+.
|
|
||||||
#
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
@@ -56,16 +50,16 @@ import getopt
|
|||||||
import re
|
import re
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
from signal import signal, SIGINT, SIGWINCH, SIG_DFL
|
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 reads per second"],
|
"hits": [4, 1000, "ARC reads 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"],
|
||||||
"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"],
|
||||||
"dmis": [4, 1000, "Demand misses per second"],
|
"dmis": [4, 1000, "Demand misses per second"],
|
||||||
@@ -77,16 +71,15 @@ cols = {
|
|||||||
"pm%": [3, 100, "Prefetch miss percentage"],
|
"pm%": [3, 100, "Prefetch miss percentage"],
|
||||||
"mhit": [4, 1000, "Metadata hits per second"],
|
"mhit": [4, 1000, "Metadata 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": [4, 1000, "Metadata accesses per second"],
|
||||||
"mh%": [3, 100, "Metadata hit percentage"],
|
"mh%": [3, 100, "Metadata 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": [4, 1024, "ARC size"],
|
"c": [4, 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"],
|
|
||||||
"eskip": [5, 1000, "evict_skip per second"],
|
"eskip": [5, 1000, "evict_skip 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"],
|
||||||
@@ -98,17 +91,12 @@ cols = {
|
|||||||
"l2miss%": [7, 100, "L2ARC access miss percentage"],
|
"l2miss%": [7, 100, "L2ARC access miss percentage"],
|
||||||
"l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"],
|
"l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"],
|
||||||
"l2size": [6, 1024, "Size of the L2ARC"],
|
"l2size": [6, 1024, "Size of the L2ARC"],
|
||||||
"l2bytes": [7, 1024, "Bytes read per second from the L2ARC"],
|
"l2bytes": [7, 1024, "bytes read per second from the L2ARC"],
|
||||||
"grow": [4, 1000, "ARC grow disabled"],
|
|
||||||
"need": [4, 1024, "ARC reclaim need"],
|
|
||||||
"free": [4, 1024, "ARC free memory"],
|
|
||||||
"avail": [5, 1024, "ARC available memory"],
|
|
||||||
"waste": [5, 1024, "Wasted memory due to round up to pagesize"],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v = {}
|
v = {}
|
||||||
hdr = ["time", "read", "miss", "miss%", "dmis", "dm%", "pmis", "pm%", "mmis",
|
hdr = ["time", "read", "miss", "miss%", "dmis", "dm%", "pmis", "pm%", "mmis",
|
||||||
"mm%", "size", "c", "avail"]
|
"mm%", "arcsz", "c"]
|
||||||
xhdr = ["time", "mfu", "mru", "mfug", "mrug", "eskip", "mtxmis", "dread",
|
xhdr = ["time", "mfu", "mru", "mfug", "mrug", "eskip", "mtxmis", "dread",
|
||||||
"pread", "read"]
|
"pread", "read"]
|
||||||
sint = 1 # Default interval is 1 second
|
sint = 1 # Default interval is 1 second
|
||||||
@@ -118,56 +106,12 @@ opfile = None
|
|||||||
sep = " " # Default separator is 2 spaces
|
sep = " " # Default separator is 2 spaces
|
||||||
version = "0.4"
|
version = "0.4"
|
||||||
l2exist = False
|
l2exist = False
|
||||||
cmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval "
|
cmd = ("Usage: arcstat.py [-hvx] [-f fields] [-o file] [-s string] [interval "
|
||||||
"[count]]\n")
|
"[count]]\n")
|
||||||
cur = {}
|
cur = {}
|
||||||
d = {}
|
d = {}
|
||||||
out = None
|
out = None
|
||||||
kstat = None
|
kstat = None
|
||||||
pretty_print = True
|
|
||||||
|
|
||||||
|
|
||||||
if sys.platform.startswith('freebsd'):
|
|
||||||
# Requires py-sysctl on FreeBSD
|
|
||||||
import sysctl
|
|
||||||
|
|
||||||
def kstat_update():
|
|
||||||
global kstat
|
|
||||||
|
|
||||||
k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats')
|
|
||||||
if ctl.type != sysctl.CTLTYPE_NODE]
|
|
||||||
|
|
||||||
if not k:
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
kstat = {}
|
|
||||||
|
|
||||||
for s in k:
|
|
||||||
if not s:
|
|
||||||
continue
|
|
||||||
|
|
||||||
name, value = s.name, s.value
|
|
||||||
# Trims 'kstat.zfs.misc.arcstats' from the name
|
|
||||||
kstat[name[24:]] = int(value)
|
|
||||||
|
|
||||||
elif sys.platform.startswith('linux'):
|
|
||||||
def kstat_update():
|
|
||||||
global kstat
|
|
||||||
|
|
||||||
k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
|
|
||||||
|
|
||||||
if not k:
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
del k[0:2]
|
|
||||||
kstat = {}
|
|
||||||
|
|
||||||
for s in k:
|
|
||||||
if not s:
|
|
||||||
continue
|
|
||||||
|
|
||||||
name, unused, value = s.split()
|
|
||||||
kstat[name] = int(value)
|
|
||||||
|
|
||||||
|
|
||||||
def detailed_usage():
|
def detailed_usage():
|
||||||
@@ -183,7 +127,6 @@ def detailed_usage():
|
|||||||
def usage():
|
def usage():
|
||||||
sys.stderr.write("%s\n" % cmd)
|
sys.stderr.write("%s\n" % cmd)
|
||||||
sys.stderr.write("\t -h : Print this help message\n")
|
sys.stderr.write("\t -h : Print this help message\n")
|
||||||
sys.stderr.write("\t -a : Print all possible stats\n")
|
|
||||||
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")
|
||||||
@@ -191,17 +134,35 @@ def usage():
|
|||||||
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 "
|
||||||
"character or string\n")
|
"character or string\n")
|
||||||
sys.stderr.write("\t -p : Disable auto-scaling of numerical fields\n")
|
|
||||||
sys.stderr.write("\nExamples:\n")
|
sys.stderr.write("\nExamples:\n")
|
||||||
sys.stderr.write("\tarcstat -o /tmp/a.log 2 10\n")
|
sys.stderr.write("\tarcstat.py -o /tmp/a.log 2 10\n")
|
||||||
sys.stderr.write("\tarcstat -s \",\" -o /tmp/a.log 2 10\n")
|
sys.stderr.write("\tarcstat.py -s \",\" -o /tmp/a.log 2 10\n")
|
||||||
sys.stderr.write("\tarcstat -v\n")
|
sys.stderr.write("\tarcstat.py -v\n")
|
||||||
sys.stderr.write("\tarcstat -f time,hit%,dh%,ph%,mh% 1\n")
|
sys.stderr.write("\tarcstat.py -f time,hit%,dh%,ph%,mh% 1\n")
|
||||||
sys.stderr.write("\n")
|
sys.stderr.write("\n")
|
||||||
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def kstat_update():
|
||||||
|
global kstat
|
||||||
|
|
||||||
|
k = [line.strip() for line in open('/proc/spl/kstat/zfs/arcstats')]
|
||||||
|
|
||||||
|
if not k:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
del k[0:2]
|
||||||
|
kstat = {}
|
||||||
|
|
||||||
|
for s in k:
|
||||||
|
if not s:
|
||||||
|
continue
|
||||||
|
|
||||||
|
name, unused, value = s.split()
|
||||||
|
kstat[name] = Decimal(value)
|
||||||
|
|
||||||
|
|
||||||
def snap_stats():
|
def snap_stats():
|
||||||
global cur
|
global cur
|
||||||
global kstat
|
global kstat
|
||||||
@@ -232,7 +193,7 @@ def prettynum(sz, scale, num=0):
|
|||||||
elif 0 < num < 1:
|
elif 0 < num < 1:
|
||||||
num = 0
|
num = 0
|
||||||
|
|
||||||
while abs(num) > scale and index < 5:
|
while num > scale and index < 5:
|
||||||
save = num
|
save = num
|
||||||
num = num / scale
|
num = num / scale
|
||||||
index += 1
|
index += 1
|
||||||
@@ -240,7 +201,7 @@ def prettynum(sz, scale, num=0):
|
|||||||
if index == 0:
|
if index == 0:
|
||||||
return "%*d" % (sz, num)
|
return "%*d" % (sz, num)
|
||||||
|
|
||||||
if abs(save / scale) < 10:
|
if (save / scale) < 10:
|
||||||
return "%*.1f%s" % (sz - 1, num, suffix[index])
|
return "%*.1f%s" % (sz - 1, num, suffix[index])
|
||||||
else:
|
else:
|
||||||
return "%*d%s" % (sz - 1, num, suffix[index])
|
return "%*d%s" % (sz - 1, num, suffix[index])
|
||||||
@@ -250,14 +211,12 @@ def print_values():
|
|||||||
global hdr
|
global hdr
|
||||||
global sep
|
global sep
|
||||||
global v
|
global v
|
||||||
global pretty_print
|
|
||||||
|
|
||||||
if pretty_print:
|
for col in hdr:
|
||||||
fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col])
|
sys.stdout.write("%s%s" % (
|
||||||
else:
|
prettynum(cols[col][0], cols[col][1], v[col]),
|
||||||
fmt = lambda col: v[col]
|
sep
|
||||||
|
))
|
||||||
sys.stdout.write(sep.join(fmt(col) for col in hdr))
|
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
@@ -265,14 +224,9 @@ def print_values():
|
|||||||
def print_header():
|
def print_header():
|
||||||
global hdr
|
global hdr
|
||||||
global sep
|
global sep
|
||||||
global pretty_print
|
|
||||||
|
|
||||||
if pretty_print:
|
for col in hdr:
|
||||||
fmt = lambda col: "%*s" % (cols[col][0], col)
|
sys.stdout.write("%*s%s" % (cols[col][0], col, sep))
|
||||||
else:
|
|
||||||
fmt = lambda col: col
|
|
||||||
|
|
||||||
sys.stdout.write(sep.join(fmt(col) for col in hdr))
|
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
|
|
||||||
@@ -309,10 +263,8 @@ def init():
|
|||||||
global sep
|
global sep
|
||||||
global out
|
global out
|
||||||
global l2exist
|
global l2exist
|
||||||
global pretty_print
|
|
||||||
|
|
||||||
desired_cols = None
|
desired_cols = None
|
||||||
aflag = False
|
|
||||||
xflag = False
|
xflag = False
|
||||||
hflag = False
|
hflag = False
|
||||||
vflag = False
|
vflag = False
|
||||||
@@ -321,16 +273,14 @@ def init():
|
|||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(
|
opts, args = getopt.getopt(
|
||||||
sys.argv[1:],
|
sys.argv[1:],
|
||||||
"axo:hvs:f:p",
|
"xo:hvs:f:",
|
||||||
[
|
[
|
||||||
"all",
|
|
||||||
"extended",
|
"extended",
|
||||||
"outfile",
|
"outfile",
|
||||||
"help",
|
"help",
|
||||||
"verbose",
|
"verbose",
|
||||||
"separator",
|
"separator",
|
||||||
"columns",
|
"columns"
|
||||||
"parsable"
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
except getopt.error as msg:
|
except getopt.error as msg:
|
||||||
@@ -339,8 +289,6 @@ def init():
|
|||||||
opts = None
|
opts = None
|
||||||
|
|
||||||
for opt, arg in opts:
|
for opt, arg in opts:
|
||||||
if opt in ('-a', '--all'):
|
|
||||||
aflag = True
|
|
||||||
if opt in ('-x', '--extended'):
|
if opt in ('-x', '--extended'):
|
||||||
xflag = True
|
xflag = True
|
||||||
if opt in ('-o', '--outfile'):
|
if opt in ('-o', '--outfile'):
|
||||||
@@ -356,13 +304,19 @@ def init():
|
|||||||
if opt in ('-f', '--columns'):
|
if opt in ('-f', '--columns'):
|
||||||
desired_cols = arg
|
desired_cols = arg
|
||||||
i += 1
|
i += 1
|
||||||
if opt in ('-p', '--parsable'):
|
|
||||||
pretty_print = False
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
argv = sys.argv[i:]
|
argv = sys.argv[i:]
|
||||||
sint = int(argv[0]) if argv else sint
|
sint = Decimal(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 count
|
||||||
|
|
||||||
|
if len(argv) > 1:
|
||||||
|
sint = Decimal(argv[0])
|
||||||
|
count = int(argv[1])
|
||||||
|
|
||||||
|
elif len(argv) > 0:
|
||||||
|
sint = Decimal(argv[0])
|
||||||
|
count = 0
|
||||||
|
|
||||||
if hflag or (xflag and desired_cols):
|
if hflag or (xflag and desired_cols):
|
||||||
usage()
|
usage()
|
||||||
@@ -402,12 +356,6 @@ def init():
|
|||||||
incompat)
|
incompat)
|
||||||
usage()
|
usage()
|
||||||
|
|
||||||
if aflag:
|
|
||||||
if l2exist:
|
|
||||||
hdr = cols.keys()
|
|
||||||
else:
|
|
||||||
hdr = [col for col in cols.keys() if not col.startswith("l2")]
|
|
||||||
|
|
||||||
if opfile:
|
if opfile:
|
||||||
try:
|
try:
|
||||||
out = open(opfile, "w")
|
out = open(opfile, "w")
|
||||||
@@ -456,7 +404,6 @@ def calculate():
|
|||||||
v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0
|
v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0
|
||||||
|
|
||||||
v["arcsz"] = cur["size"]
|
v["arcsz"] = cur["size"]
|
||||||
v["size"] = cur["size"]
|
|
||||||
v["c"] = cur["c"]
|
v["c"] = cur["c"]
|
||||||
v["mfu"] = d["mfu_hits"] / sint
|
v["mfu"] = d["mfu_hits"] / sint
|
||||||
v["mru"] = d["mru_hits"] / sint
|
v["mru"] = d["mru_hits"] / sint
|
||||||
@@ -476,12 +423,6 @@ def calculate():
|
|||||||
v["l2size"] = cur["l2_size"]
|
v["l2size"] = cur["l2_size"]
|
||||||
v["l2bytes"] = d["l2_read_bytes"] / sint
|
v["l2bytes"] = d["l2_read_bytes"] / sint
|
||||||
|
|
||||||
v["grow"] = 0 if cur["arc_no_grow"] else 1
|
|
||||||
v["need"] = cur["arc_need_free"]
|
|
||||||
v["free"] = cur["memory_free_bytes"]
|
|
||||||
v["avail"] = cur["memory_available_bytes"]
|
|
||||||
v["waste"] = cur["abd_chunk_waste_size"]
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global sint
|
global sint
|
||||||
@@ -1 +0,0 @@
|
|||||||
dbufstat
|
|
||||||
@@ -1,5 +1 @@
|
|||||||
include $(top_srcdir)/config/Substfiles.am
|
dist_bin_SCRIPTS = dbufstat.py
|
||||||
|
|
||||||
bin_SCRIPTS = dbufstat
|
|
||||||
|
|
||||||
SUBSTFILES += $(bin_SCRIPTS)
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env @PYTHON_SHEBANG@
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Print out statistics for all cached dmu buffers. This information
|
# Print out statistics for all cached dmu buffers. This information
|
||||||
# is available through the dbufs kstat and may be post-processed as
|
# is available through the dbufs kstat and may be post-processed as
|
||||||
@@ -27,17 +27,14 @@
|
|||||||
# 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 Python 2.6+ and Python 3.4+.
|
|
||||||
#
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import getopt
|
import getopt
|
||||||
import errno
|
import errno
|
||||||
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",
|
||||||
"meta", "state", "dbholds", "dbc", "list", "atype", "flags",
|
"meta", "state", "dbholds", "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"]
|
||||||
@@ -48,7 +45,7 @@ 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", "meta", "state", "dbholds",
|
dincompat = ["level", "blkid", "offset", "dbsize", "meta", "state", "dbholds",
|
||||||
"dbc", "list", "atype", "flags", "count", "asize", "access",
|
"list", "atype", "flags", "count", "asize", "access",
|
||||||
"mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
|
"mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
|
||||||
"l2_comp", "aholds"]
|
"l2_comp", "aholds"]
|
||||||
|
|
||||||
@@ -56,7 +53,7 @@ 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", "meta", "state",
|
tincompat = ["object", "level", "blkid", "offset", "dbsize", "meta", "state",
|
||||||
"dbc", "dbholds", "list", "atype", "flags", "count", "asize",
|
"dbholds", "list", "atype", "flags", "count", "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"]
|
||||||
@@ -73,10 +70,9 @@ cols = {
|
|||||||
"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"],
|
||||||
"dbc": [3, -1, "in dbuf cache"],
|
|
||||||
"list": [4, -1, "which ARC list contains this buffer"],
|
"list": [4, -1, "which ARC list contains this buffer"],
|
||||||
"atype": [7, -1, "ARC header type (data or metadata)"],
|
"atype": [7, -1, "ARC header type (data or metadata)"],
|
||||||
"flags": [9, -1, "ARC read flags"],
|
"flags": [8, -1, "ARC read flags"],
|
||||||
"count": [5, -1, "ARC data count"],
|
"count": [5, -1, "ARC data count"],
|
||||||
"asize": [7, 1024, "size of this ARC buffer"],
|
"asize": [7, 1024, "size of this ARC buffer"],
|
||||||
"access": [10, -1, "time this ARC buffer was last accessed"],
|
"access": [10, -1, "time this ARC buffer was last accessed"],
|
||||||
@@ -108,30 +104,15 @@ cols = {
|
|||||||
hdr = None
|
hdr = None
|
||||||
xhdr = None
|
xhdr = None
|
||||||
sep = " " # Default separator is 2 spaces
|
sep = " " # Default separator is 2 spaces
|
||||||
cmd = ("Usage: dbufstat [-bdhnrtvx] [-i file] [-f fields] [-o file] "
|
cmd = ("Usage: dbufstat.py [-bdhrtvx] [-i file] [-f fields] [-o file] "
|
||||||
"[-s string] [-F filter]\n")
|
"[-s string]\n")
|
||||||
raw = 0
|
raw = 0
|
||||||
|
|
||||||
|
|
||||||
if sys.platform.startswith("freebsd"):
|
|
||||||
import io
|
|
||||||
# Requires py-sysctl on FreeBSD
|
|
||||||
import sysctl
|
|
||||||
|
|
||||||
def default_ifile():
|
|
||||||
dbufs = sysctl.filter("kstat.zfs.misc.dbufs")[0].value
|
|
||||||
sys.stdin = io.StringIO(dbufs)
|
|
||||||
return "-"
|
|
||||||
|
|
||||||
elif sys.platform.startswith("linux"):
|
|
||||||
def default_ifile():
|
|
||||||
return "/proc/spl/kstat/zfs/dbufs"
|
|
||||||
|
|
||||||
|
|
||||||
def print_incompat_helper(incompat):
|
def print_incompat_helper(incompat):
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for key in sorted(incompat):
|
for key in sorted(incompat):
|
||||||
if cnt == 0:
|
if cnt is 0:
|
||||||
sys.stderr.write("\t")
|
sys.stderr.write("\t")
|
||||||
elif cnt > 8:
|
elif cnt > 8:
|
||||||
sys.stderr.write(",\n\t")
|
sys.stderr.write(",\n\t")
|
||||||
@@ -170,7 +151,6 @@ def usage():
|
|||||||
sys.stderr.write("\t -b : Print table of information for each dbuf\n")
|
sys.stderr.write("\t -b : Print table of information for each dbuf\n")
|
||||||
sys.stderr.write("\t -d : Print table of information for each dnode\n")
|
sys.stderr.write("\t -d : Print table of information for each dnode\n")
|
||||||
sys.stderr.write("\t -h : Print this help message\n")
|
sys.stderr.write("\t -h : Print this help message\n")
|
||||||
sys.stderr.write("\t -n : Exclude header from output\n")
|
|
||||||
sys.stderr.write("\t -r : Print raw values\n")
|
sys.stderr.write("\t -r : Print raw values\n")
|
||||||
sys.stderr.write("\t -t : Print table of information for each dnode type"
|
sys.stderr.write("\t -t : Print table of information for each dnode type"
|
||||||
"\n")
|
"\n")
|
||||||
@@ -182,13 +162,11 @@ def usage():
|
|||||||
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 "
|
||||||
"character or string\n")
|
"character or string\n")
|
||||||
sys.stderr.write("\t -F : Filter output by value or regex\n")
|
|
||||||
sys.stderr.write("\nExamples:\n")
|
sys.stderr.write("\nExamples:\n")
|
||||||
sys.stderr.write("\tdbufstat -d -o /tmp/d.log\n")
|
sys.stderr.write("\tdbufstat.py -d -o /tmp/d.log\n")
|
||||||
sys.stderr.write("\tdbufstat -t -s \",\" -o /tmp/t.log\n")
|
sys.stderr.write("\tdbufstat.py -t -s \",\" -o /tmp/t.log\n")
|
||||||
sys.stderr.write("\tdbufstat -v\n")
|
sys.stderr.write("\tdbufstat.py -v\n")
|
||||||
sys.stderr.write("\tdbufstat -d -f pool,object,objset,dsize,cached\n")
|
sys.stderr.write("\tdbufstat.py -d -f pool,object,objset,dsize,cached\n")
|
||||||
sys.stderr.write("\tdbufstat -bx -F dbc=1,objset=54,pool=testpool\n")
|
|
||||||
sys.stderr.write("\n")
|
sys.stderr.write("\n")
|
||||||
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -250,8 +228,7 @@ def print_header():
|
|||||||
|
|
||||||
|
|
||||||
def get_typestring(t):
|
def get_typestring(t):
|
||||||
ot_strings = [
|
type_strings = ["DMU_OT_NONE",
|
||||||
"DMU_OT_NONE",
|
|
||||||
# general:
|
# general:
|
||||||
"DMU_OT_OBJECT_DIRECTORY",
|
"DMU_OT_OBJECT_DIRECTORY",
|
||||||
"DMU_OT_OBJECT_ARRAY",
|
"DMU_OT_OBJECT_ARRAY",
|
||||||
@@ -314,39 +291,15 @@ def get_typestring(t):
|
|||||||
"DMU_OT_DEADLIST_HDR",
|
"DMU_OT_DEADLIST_HDR",
|
||||||
"DMU_OT_DSL_CLONES",
|
"DMU_OT_DSL_CLONES",
|
||||||
"DMU_OT_BPOBJ_SUBOBJ"]
|
"DMU_OT_BPOBJ_SUBOBJ"]
|
||||||
otn_strings = {
|
|
||||||
0x80: "DMU_OTN_UINT8_DATA",
|
|
||||||
0xc0: "DMU_OTN_UINT8_METADATA",
|
|
||||||
0x81: "DMU_OTN_UINT16_DATA",
|
|
||||||
0xc1: "DMU_OTN_UINT16_METADATA",
|
|
||||||
0x82: "DMU_OTN_UINT32_DATA",
|
|
||||||
0xc2: "DMU_OTN_UINT32_METADATA",
|
|
||||||
0x83: "DMU_OTN_UINT64_DATA",
|
|
||||||
0xc3: "DMU_OTN_UINT64_METADATA",
|
|
||||||
0x84: "DMU_OTN_ZAP_DATA",
|
|
||||||
0xc4: "DMU_OTN_ZAP_METADATA",
|
|
||||||
0xa0: "DMU_OTN_UINT8_ENC_DATA",
|
|
||||||
0xe0: "DMU_OTN_UINT8_ENC_METADATA",
|
|
||||||
0xa1: "DMU_OTN_UINT16_ENC_DATA",
|
|
||||||
0xe1: "DMU_OTN_UINT16_ENC_METADATA",
|
|
||||||
0xa2: "DMU_OTN_UINT32_ENC_DATA",
|
|
||||||
0xe2: "DMU_OTN_UINT32_ENC_METADATA",
|
|
||||||
0xa3: "DMU_OTN_UINT64_ENC_DATA",
|
|
||||||
0xe3: "DMU_OTN_UINT64_ENC_METADATA",
|
|
||||||
0xa4: "DMU_OTN_ZAP_ENC_DATA",
|
|
||||||
0xe4: "DMU_OTN_ZAP_ENC_METADATA"}
|
|
||||||
|
|
||||||
# If "-rr" option is used, don't convert to string representation
|
# If "-rr" option is used, don't convert to string representation
|
||||||
if raw > 1:
|
if raw > 1:
|
||||||
return "%i" % t
|
return "%i" % t
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if t < len(ot_strings):
|
return type_strings[t]
|
||||||
return ot_strings[t]
|
except IndexError:
|
||||||
else:
|
return "%i" % t
|
||||||
return otn_strings[t]
|
|
||||||
except (IndexError, KeyError):
|
|
||||||
return "(UNKNOWN)"
|
|
||||||
|
|
||||||
|
|
||||||
def get_compstring(c):
|
def get_compstring(c):
|
||||||
@@ -358,7 +311,7 @@ def get_compstring(c):
|
|||||||
"ZIO_COMPRESS_GZIP_6", "ZIO_COMPRESS_GZIP_7",
|
"ZIO_COMPRESS_GZIP_6", "ZIO_COMPRESS_GZIP_7",
|
||||||
"ZIO_COMPRESS_GZIP_8", "ZIO_COMPRESS_GZIP_9",
|
"ZIO_COMPRESS_GZIP_8", "ZIO_COMPRESS_GZIP_9",
|
||||||
"ZIO_COMPRESS_ZLE", "ZIO_COMPRESS_LZ4",
|
"ZIO_COMPRESS_ZLE", "ZIO_COMPRESS_LZ4",
|
||||||
"ZIO_COMPRESS_ZSTD", "ZIO_COMPRESS_FUNCTION"]
|
"ZIO_COMPRESS_FUNCTION"]
|
||||||
|
|
||||||
# If "-rr" option is used, don't convert to string representation
|
# If "-rr" option is used, don't convert to string representation
|
||||||
if raw > 1:
|
if raw > 1:
|
||||||
@@ -431,32 +384,12 @@ def update_dict(d, k, line, labels):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def skip_line(vals, filters):
|
def print_dict(d):
|
||||||
'''
|
print_header()
|
||||||
Determines if a line should be skipped during printing
|
|
||||||
based on a set of filters
|
|
||||||
'''
|
|
||||||
if len(filters) == 0:
|
|
||||||
return False
|
|
||||||
|
|
||||||
for key in vals:
|
|
||||||
if key in filters:
|
|
||||||
val = prettynum(cols[key][0], cols[key][1], vals[key]).strip()
|
|
||||||
# we want a full match here
|
|
||||||
if re.match("(?:" + filters[key] + r")\Z", val) is None:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def print_dict(d, filters, noheader):
|
|
||||||
if not noheader:
|
|
||||||
print_header()
|
|
||||||
for pool in list(d.keys()):
|
for pool in list(d.keys()):
|
||||||
for objset in list(d[pool].keys()):
|
for objset in list(d[pool].keys()):
|
||||||
for v in list(d[pool][objset].values()):
|
for v in list(d[pool][objset].values()):
|
||||||
if not skip_line(v, filters):
|
print_values(v)
|
||||||
print_values(v)
|
|
||||||
|
|
||||||
|
|
||||||
def dnodes_build_dict(filehandle):
|
def dnodes_build_dict(filehandle):
|
||||||
@@ -497,7 +430,7 @@ def types_build_dict(filehandle):
|
|||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
def buffers_print_all(filehandle, filters, noheader):
|
def buffers_print_all(filehandle):
|
||||||
labels = dict()
|
labels = dict()
|
||||||
|
|
||||||
# First 3 lines are header information, skip the first two
|
# First 3 lines are header information, skip the first two
|
||||||
@@ -508,14 +441,11 @@ def buffers_print_all(filehandle, filters, noheader):
|
|||||||
for i, v in enumerate(next(filehandle).split()):
|
for i, v in enumerate(next(filehandle).split()):
|
||||||
labels[v] = i
|
labels[v] = i
|
||||||
|
|
||||||
if not noheader:
|
print_header()
|
||||||
print_header()
|
|
||||||
|
|
||||||
# The rest of the file is buffer information
|
# The rest of the file is buffer information
|
||||||
for line in filehandle:
|
for line in filehandle:
|
||||||
vals = parse_line(line.split(), labels)
|
print_values(parse_line(line.split(), labels))
|
||||||
if not skip_line(vals, filters):
|
|
||||||
print_values(vals)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -532,13 +462,11 @@ def main():
|
|||||||
tflag = False
|
tflag = False
|
||||||
vflag = False
|
vflag = False
|
||||||
xflag = False
|
xflag = False
|
||||||
nflag = False
|
|
||||||
filters = dict()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(
|
opts, args = getopt.getopt(
|
||||||
sys.argv[1:],
|
sys.argv[1:],
|
||||||
"bdf:hi:o:rs:tvxF:n",
|
"bdf:hi:o:rs:tvx",
|
||||||
[
|
[
|
||||||
"buffers",
|
"buffers",
|
||||||
"dnodes",
|
"dnodes",
|
||||||
@@ -549,8 +477,7 @@ def main():
|
|||||||
"separator",
|
"separator",
|
||||||
"types",
|
"types",
|
||||||
"verbose",
|
"verbose",
|
||||||
"extended",
|
"extended"
|
||||||
"filter"
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
except getopt.error:
|
except getopt.error:
|
||||||
@@ -580,35 +507,6 @@ def main():
|
|||||||
vflag = True
|
vflag = True
|
||||||
if opt in ('-x', '--extended'):
|
if opt in ('-x', '--extended'):
|
||||||
xflag = True
|
xflag = True
|
||||||
if opt in ('-n', '--noheader'):
|
|
||||||
nflag = True
|
|
||||||
if opt in ('-F', '--filter'):
|
|
||||||
fils = [x.strip() for x in arg.split(",")]
|
|
||||||
|
|
||||||
for fil in fils:
|
|
||||||
f = [x.strip() for x in fil.split("=")]
|
|
||||||
|
|
||||||
if len(f) != 2:
|
|
||||||
sys.stderr.write("Invalid filter '%s'.\n" % fil)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if f[0] not in cols:
|
|
||||||
sys.stderr.write("Invalid field '%s' in filter.\n" % f[0])
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if f[0] in filters:
|
|
||||||
sys.stderr.write("Field '%s' specified multiple times in "
|
|
||||||
"filter.\n" % f[0])
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
re.compile("(?:" + f[1] + r")\Z")
|
|
||||||
except re.error:
|
|
||||||
sys.stderr.write("Invalid regex for field '%s' in "
|
|
||||||
"filter.\n" % f[0])
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
filters[f[0]] = f[1]
|
|
||||||
|
|
||||||
if hflag or (xflag and desired_cols):
|
if hflag or (xflag and desired_cols):
|
||||||
usage()
|
usage()
|
||||||
@@ -660,9 +558,9 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not ifile:
|
if not ifile:
|
||||||
ifile = default_ifile()
|
ifile = '/proc/spl/kstat/zfs/dbufs'
|
||||||
|
|
||||||
if ifile != "-":
|
if ifile is not "-":
|
||||||
try:
|
try:
|
||||||
tmp = open(ifile, "r")
|
tmp = open(ifile, "r")
|
||||||
sys.stdin = tmp
|
sys.stdin = tmp
|
||||||
@@ -671,13 +569,13 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if bflag:
|
if bflag:
|
||||||
buffers_print_all(sys.stdin, filters, nflag)
|
buffers_print_all(sys.stdin)
|
||||||
|
|
||||||
if dflag:
|
if dflag:
|
||||||
print_dict(dnodes_build_dict(sys.stdin), filters, nflag)
|
print_dict(dnodes_build_dict(sys.stdin))
|
||||||
|
|
||||||
if tflag:
|
if tflag:
|
||||||
print_dict(types_build_dict(sys.stdin), filters, nflag)
|
print_dict(types_build_dict(sys.stdin))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# fsck.zfs: A fsck helper to accommodate distributions that expect
|
# fsck.zfs: A fsck helper to accomidate distributions that expect
|
||||||
# to be able to execute a fsck on all filesystem types. Currently
|
# to be able to execute a fsck on all filesystem types. Currently
|
||||||
# this script does nothing but it could be extended to act as a
|
# this script does nothing but it could be extended to act as a
|
||||||
# compatibility wrapper for 'zpool scrub'.
|
# compatibility wrapper for 'zpool scrub'.
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
|
DEFAULT_INCLUDES += \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_srcdir)/lib/libspl/include
|
||||||
|
|
||||||
#
|
#
|
||||||
# Ignore the prefix for the mount helper. It must be installed in /sbin/
|
# 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.
|
# because this path is hardcoded in the mount(8) for security reasons.
|
||||||
@@ -13,8 +17,8 @@ mount_zfs_SOURCES = \
|
|||||||
mount_zfs.c
|
mount_zfs.c
|
||||||
|
|
||||||
mount_zfs_LDADD = \
|
mount_zfs_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||||
|
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||||
mount_zfs_LDADD += $(LTLIBINTL)
|
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||||
|
|||||||
+295
-44
@@ -31,57 +31,256 @@
|
|||||||
#include <sys/mntent.h>
|
#include <sys/mntent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
#include <libzutil.h>
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define ZS_COMMENT 0x00000000 /* comment */
|
#define ZS_COMMENT 0x00000000 /* comment */
|
||||||
#define ZS_ZFSUTIL 0x00000001 /* caller is zfs(8) */
|
#define ZS_ZFSUTIL 0x00000001 /* caller is zfs(8) */
|
||||||
|
|
||||||
libzfs_handle_t *g_zfs;
|
libzfs_handle_t *g_zfs;
|
||||||
|
|
||||||
|
typedef struct option_map {
|
||||||
|
const char *name;
|
||||||
|
unsigned long mntmask;
|
||||||
|
unsigned long zfsmask;
|
||||||
|
} option_map_t;
|
||||||
|
|
||||||
|
static const option_map_t option_map[] = {
|
||||||
|
/* Canonicalized filesystem independent options from mount(8) */
|
||||||
|
{ MNTOPT_NOAUTO, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_DEFAULTS, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_NODEVICES, MS_NODEV, ZS_COMMENT },
|
||||||
|
{ MNTOPT_DIRSYNC, MS_DIRSYNC, ZS_COMMENT },
|
||||||
|
{ MNTOPT_NOEXEC, MS_NOEXEC, ZS_COMMENT },
|
||||||
|
{ MNTOPT_GROUP, MS_GROUP, ZS_COMMENT },
|
||||||
|
{ MNTOPT_NETDEV, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_NOFAIL, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_NOSUID, MS_NOSUID, ZS_COMMENT },
|
||||||
|
{ MNTOPT_OWNER, MS_OWNER, ZS_COMMENT },
|
||||||
|
{ MNTOPT_REMOUNT, MS_REMOUNT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_RO, MS_RDONLY, ZS_COMMENT },
|
||||||
|
{ MNTOPT_RW, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_SYNC, MS_SYNCHRONOUS, ZS_COMMENT },
|
||||||
|
{ MNTOPT_USER, MS_USERS, ZS_COMMENT },
|
||||||
|
{ MNTOPT_USERS, MS_USERS, ZS_COMMENT },
|
||||||
|
/* acl flags passed with util-linux-2.24 mount command */
|
||||||
|
{ MNTOPT_ACL, MS_POSIXACL, ZS_COMMENT },
|
||||||
|
{ MNTOPT_NOACL, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_POSIXACL, MS_POSIXACL, ZS_COMMENT },
|
||||||
|
#ifdef MS_NOATIME
|
||||||
|
{ MNTOPT_NOATIME, MS_NOATIME, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
#ifdef MS_NODIRATIME
|
||||||
|
{ MNTOPT_NODIRATIME, MS_NODIRATIME, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
#ifdef MS_RELATIME
|
||||||
|
{ MNTOPT_RELATIME, MS_RELATIME, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
#ifdef MS_STRICTATIME
|
||||||
|
{ MNTOPT_STRICTATIME, MS_STRICTATIME, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
#ifdef MS_LAZYTIME
|
||||||
|
{ MNTOPT_LAZYTIME, MS_LAZYTIME, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
{ MNTOPT_CONTEXT, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_FSCONTEXT, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_DEFCONTEXT, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_ROOTCONTEXT, MS_COMMENT, ZS_COMMENT },
|
||||||
|
#ifdef MS_I_VERSION
|
||||||
|
{ MNTOPT_IVERSION, MS_I_VERSION, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
#ifdef MS_MANDLOCK
|
||||||
|
{ MNTOPT_NBMAND, MS_MANDLOCK, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
/* Valid options not found in mount(8) */
|
||||||
|
{ MNTOPT_BIND, MS_BIND, ZS_COMMENT },
|
||||||
|
#ifdef MS_REC
|
||||||
|
{ MNTOPT_RBIND, MS_BIND|MS_REC, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
{ MNTOPT_COMMENT, MS_COMMENT, ZS_COMMENT },
|
||||||
|
#ifdef MS_NOSUB
|
||||||
|
{ MNTOPT_NOSUB, MS_NOSUB, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
#ifdef MS_SILENT
|
||||||
|
{ MNTOPT_QUIET, MS_SILENT, ZS_COMMENT },
|
||||||
|
#endif
|
||||||
|
/* Custom zfs options */
|
||||||
|
{ MNTOPT_XATTR, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_NOXATTR, MS_COMMENT, ZS_COMMENT },
|
||||||
|
{ MNTOPT_ZFSUTIL, MS_COMMENT, ZS_ZFSUTIL },
|
||||||
|
{ NULL, 0, 0 } };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opportunistically convert a target string into a pool name. If the
|
* Break the mount option in to a name/value pair. The name is
|
||||||
* string does not represent a block device with a valid zfs label
|
* validated against the option map and mount flags set accordingly.
|
||||||
* then it is passed through without modification.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
parse_dataset(const char *target, char **dataset)
|
parse_option(char *mntopt, unsigned long *mntflags,
|
||||||
|
unsigned long *zfsflags, int sloppy)
|
||||||
{
|
{
|
||||||
|
const option_map_t *opt;
|
||||||
|
char *ptr, *name, *value = NULL;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
name = strdup(mntopt);
|
||||||
|
if (name == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
for (ptr = name; ptr && *ptr; ptr++) {
|
||||||
|
if (*ptr == '=') {
|
||||||
|
*ptr = '\0';
|
||||||
|
value = ptr+1;
|
||||||
|
VERIFY3P(value, !=, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (opt = option_map; opt->name != NULL; opt++) {
|
||||||
|
if (strncmp(name, opt->name, strlen(name)) == 0) {
|
||||||
|
*mntflags |= opt->mntmask;
|
||||||
|
*zfsflags |= opt->zfsmask;
|
||||||
|
error = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sloppy)
|
||||||
|
error = ENOENT;
|
||||||
|
out:
|
||||||
|
/* If required further process on the value may be done here */
|
||||||
|
free(name);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Translate the mount option string in to MS_* mount flags for the
|
||||||
|
* kernel vfs. When sloppy is non-zero unknown options will be ignored
|
||||||
|
* otherwise they are considered fatal are copied in to badopt.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_options(char *mntopts, unsigned long *mntflags, unsigned long *zfsflags,
|
||||||
|
int sloppy, char *badopt, char *mtabopt)
|
||||||
|
{
|
||||||
|
int error = 0, quote = 0, flag = 0, count = 0;
|
||||||
|
char *ptr, *opt, *opts;
|
||||||
|
|
||||||
|
opts = strdup(mntopts);
|
||||||
|
if (opts == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
*mntflags = 0;
|
||||||
|
opt = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prior to util-linux 2.36.2, if a file or directory in the
|
* Scan through all mount options which must be comma delimited.
|
||||||
* current working directory was named 'dataset' then mount(8)
|
* We must be careful to notice regions which are double quoted
|
||||||
* would prepend the current working directory to the dataset.
|
* and skip commas in these regions. Each option is then checked
|
||||||
* Check for it and strip the prepended path when it is added.
|
* to determine if it is a known option.
|
||||||
*/
|
*/
|
||||||
|
for (ptr = opts; ptr && !flag; ptr++) {
|
||||||
|
if (opt == NULL)
|
||||||
|
opt = ptr;
|
||||||
|
|
||||||
|
if (*ptr == '"')
|
||||||
|
quote = !quote;
|
||||||
|
|
||||||
|
if (quote)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (*ptr == '\0')
|
||||||
|
flag = 1;
|
||||||
|
|
||||||
|
if ((*ptr == ',') || (*ptr == '\0')) {
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
error = parse_option(opt, mntflags, zfsflags, sloppy);
|
||||||
|
if (error) {
|
||||||
|
strcpy(badopt, opt);
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(*mntflags & MS_REMOUNT) &&
|
||||||
|
!(*zfsflags & ZS_ZFSUTIL)) {
|
||||||
|
if (count > 0)
|
||||||
|
strlcat(mtabopt, ",", MNT_LINE_MAX);
|
||||||
|
|
||||||
|
strlcat(mtabopt, opt, MNT_LINE_MAX);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
opt = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(opts);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the pool/dataset to mount given the name passed to mount. This
|
||||||
|
* is expected to be of the form pool/dataset, however may also refer to
|
||||||
|
* a block device if that device contains a valid zfs label.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
parse_dataset(char *dataset)
|
||||||
|
{
|
||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
if (getcwd(cwd, PATH_MAX) == NULL) {
|
struct stat64 statbuf;
|
||||||
perror("getcwd");
|
int error;
|
||||||
return;
|
int len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We expect a pool/dataset to be provided, however if we're
|
||||||
|
* given a device which is a member of a zpool we attempt to
|
||||||
|
* extract the pool name stored in the label. Given the pool
|
||||||
|
* name we can mount the root dataset.
|
||||||
|
*/
|
||||||
|
error = stat64(dataset, &statbuf);
|
||||||
|
if (error == 0) {
|
||||||
|
nvlist_t *config;
|
||||||
|
char *name;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(dataset, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
error = zpool_read_label(fd, &config, NULL);
|
||||||
|
(void) close(fd);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
error = nvlist_lookup_string(config,
|
||||||
|
ZPOOL_CONFIG_POOL_NAME, &name);
|
||||||
|
if (error) {
|
||||||
|
nvlist_free(config);
|
||||||
|
} else {
|
||||||
|
dataset = strdup(name);
|
||||||
|
nvlist_free(config);
|
||||||
|
return (dataset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int len = strlen(cwd);
|
out:
|
||||||
if (strncmp(cwd, target, len) == 0)
|
/*
|
||||||
target += len;
|
* If a file or directory in your current working directory is
|
||||||
|
* named 'dataset' then mount(8) will prepend your current working
|
||||||
|
* directory to the dataset. There is no way to prevent this
|
||||||
|
* behavior so we simply check for it and strip the prepended
|
||||||
|
* patch when it is added.
|
||||||
|
*/
|
||||||
|
if (getcwd(cwd, PATH_MAX) == NULL)
|
||||||
|
return (dataset);
|
||||||
|
|
||||||
/* Assume pool/dataset is more likely */
|
len = strlen(cwd);
|
||||||
strlcpy(*dataset, target, PATH_MAX);
|
|
||||||
|
|
||||||
int fd = open(target, O_RDONLY | O_CLOEXEC);
|
/* Do not add one when cwd already ends in a trailing '/' */
|
||||||
if (fd < 0)
|
if (strncmp(cwd, dataset, len) == 0)
|
||||||
return;
|
return (dataset + len + (cwd[len-1] != '/'));
|
||||||
|
|
||||||
nvlist_t *cfg = NULL;
|
return (dataset);
|
||||||
if (zpool_read_label(fd, &cfg, NULL) == 0) {
|
|
||||||
char *nm = NULL;
|
|
||||||
if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm))
|
|
||||||
strlcpy(*dataset, nm, PATH_MAX);
|
|
||||||
nvlist_free(cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (close(fd))
|
|
||||||
perror("close");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -125,8 +324,8 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
|||||||
if (!fp) {
|
if (!fp) {
|
||||||
(void) fprintf(stderr, gettext(
|
(void) fprintf(stderr, gettext(
|
||||||
"filesystem '%s' was mounted, but /etc/mtab "
|
"filesystem '%s' was mounted, but /etc/mtab "
|
||||||
"could not be opened due to error: %s\n"),
|
"could not be opened due to error %d\n"),
|
||||||
dataset, strerror(errno));
|
dataset, errno);
|
||||||
return (MOUNT_FILEIO);
|
return (MOUNT_FILEIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,8 +333,8 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
|||||||
if (error) {
|
if (error) {
|
||||||
(void) fprintf(stderr, gettext(
|
(void) fprintf(stderr, gettext(
|
||||||
"filesystem '%s' was mounted, but /etc/mtab "
|
"filesystem '%s' was mounted, but /etc/mtab "
|
||||||
"could not be updated due to error: %s\n"),
|
"could not be updated due to error %d\n"),
|
||||||
dataset, strerror(errno));
|
dataset, errno);
|
||||||
return (MOUNT_FILEIO);
|
return (MOUNT_FILEIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +343,34 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
|||||||
return (MOUNT_SUCCESS);
|
return (MOUNT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_mntopt(const char *name, const char *val, char *mntopts,
|
||||||
|
char *mtabopt, boolean_t quote)
|
||||||
|
{
|
||||||
|
char tmp[MNT_LINE_MAX];
|
||||||
|
|
||||||
|
snprintf(tmp, MNT_LINE_MAX, quote ? ",%s=\"%s\"" : ",%s=%s", name, val);
|
||||||
|
|
||||||
|
if (mntopts)
|
||||||
|
strlcat(mntopts, tmp, MNT_LINE_MAX);
|
||||||
|
|
||||||
|
if (mtabopt)
|
||||||
|
strlcat(mtabopt, tmp, MNT_LINE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
zfs_selinux_setcontext(zfs_handle_t *zhp, zfs_prop_t zpt, const char *name,
|
||||||
|
char *mntopts, char *mtabopt)
|
||||||
|
{
|
||||||
|
char context[ZFS_MAXPROPLEN];
|
||||||
|
|
||||||
|
if (zfs_prop_get(zhp, zpt, context, sizeof (context),
|
||||||
|
NULL, NULL, 0, B_FALSE) == 0) {
|
||||||
|
if (strcmp(context, "none") != 0)
|
||||||
|
append_mntopt(name, context, mntopts, mtabopt, B_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -154,13 +381,12 @@ main(int argc, char **argv)
|
|||||||
char badopt[MNT_LINE_MAX] = { '\0' };
|
char badopt[MNT_LINE_MAX] = { '\0' };
|
||||||
char mtabopt[MNT_LINE_MAX] = { '\0' };
|
char mtabopt[MNT_LINE_MAX] = { '\0' };
|
||||||
char mntpoint[PATH_MAX];
|
char mntpoint[PATH_MAX];
|
||||||
char dataset[PATH_MAX], *pdataset = dataset;
|
char *dataset;
|
||||||
unsigned long mntflags = 0, zfsflags = 0, remount = 0;
|
unsigned long mntflags = 0, zfsflags = 0, remount = 0;
|
||||||
int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
|
int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
|
||||||
int error, c;
|
int error, c;
|
||||||
|
|
||||||
(void) setlocale(LC_ALL, "");
|
(void) setlocale(LC_ALL, "");
|
||||||
(void) setlocale(LC_NUMERIC, "C");
|
|
||||||
(void) textdomain(TEXT_DOMAIN);
|
(void) textdomain(TEXT_DOMAIN);
|
||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
@@ -210,18 +436,18 @@ main(int argc, char **argv)
|
|||||||
return (MOUNT_USAGE);
|
return (MOUNT_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_dataset(argv[0], &pdataset);
|
dataset = parse_dataset(argv[0]);
|
||||||
|
|
||||||
/* canonicalize the mount point */
|
/* canonicalize the mount point */
|
||||||
if (realpath(argv[1], mntpoint) == NULL) {
|
if (realpath(argv[1], mntpoint) == NULL) {
|
||||||
(void) fprintf(stderr, gettext("filesystem '%s' cannot be "
|
(void) fprintf(stderr, gettext("filesystem '%s' cannot be "
|
||||||
"mounted at '%s' due to canonicalization error: %s\n"),
|
"mounted at '%s' due to canonicalization error %d.\n"),
|
||||||
dataset, argv[1], strerror(errno));
|
dataset, argv[1], errno);
|
||||||
return (MOUNT_SYSERR);
|
return (MOUNT_SYSERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validate mount options and set mntflags */
|
/* validate mount options and set mntflags */
|
||||||
error = zfs_parse_mount_options(mntopts, &mntflags, &zfsflags, sloppy,
|
error = parse_options(mntopts, &mntflags, &zfsflags, sloppy,
|
||||||
badopt, mtabopt);
|
badopt, mtabopt);
|
||||||
if (error) {
|
if (error) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
@@ -261,7 +487,7 @@ main(int argc, char **argv)
|
|||||||
zfsutil = 1;
|
zfsutil = 1;
|
||||||
|
|
||||||
if ((g_zfs = libzfs_init()) == NULL) {
|
if ((g_zfs = libzfs_init()) == NULL) {
|
||||||
(void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
|
(void) fprintf(stderr, "%s", libzfs_error_init(errno));
|
||||||
return (MOUNT_SYSERR);
|
return (MOUNT_SYSERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +500,32 @@ main(int argc, char **argv)
|
|||||||
return (MOUNT_USAGE);
|
return (MOUNT_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
zfs_adjust_mount_options(zhp, mntpoint, mntopts, mtabopt);
|
/*
|
||||||
|
* Checks to see if the ZFS_PROP_SELINUX_CONTEXT exists
|
||||||
|
* if it does, create a tmp variable in case it's needed
|
||||||
|
* checks to see if the selinux context is set to the default
|
||||||
|
* if it is, allow the setting of the other context properties
|
||||||
|
* this is needed because the 'context' property overrides others
|
||||||
|
* if it is not the default, set the 'context' property
|
||||||
|
*/
|
||||||
|
if (zfs_prop_get(zhp, ZFS_PROP_SELINUX_CONTEXT, prop, sizeof (prop),
|
||||||
|
NULL, NULL, 0, B_FALSE) == 0) {
|
||||||
|
if (strcmp(prop, "none") == 0) {
|
||||||
|
zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_FSCONTEXT,
|
||||||
|
MNTOPT_FSCONTEXT, mntopts, mtabopt);
|
||||||
|
zfs_selinux_setcontext(zhp, ZFS_PROP_SELINUX_DEFCONTEXT,
|
||||||
|
MNTOPT_DEFCONTEXT, mntopts, mtabopt);
|
||||||
|
zfs_selinux_setcontext(zhp,
|
||||||
|
ZFS_PROP_SELINUX_ROOTCONTEXT, MNTOPT_ROOTCONTEXT,
|
||||||
|
mntopts, mtabopt);
|
||||||
|
} else {
|
||||||
|
append_mntopt(MNTOPT_CONTEXT, prop,
|
||||||
|
mntopts, mtabopt, B_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A hint used to determine an auto-mounted snapshot mount point */
|
||||||
|
append_mntopt(MNTOPT_MNTPOINT, mntpoint, mntopts, NULL, B_FALSE);
|
||||||
|
|
||||||
/* treat all snapshots as legacy mount points */
|
/* treat all snapshots as legacy mount points */
|
||||||
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT)
|
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT)
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
# Includes kernel code, generate warnings for large stack frames
|
AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN)
|
||||||
AM_CFLAGS += $(FRAME_LARGER_THAN)
|
AM_CPPFLAGS += -DDEBUG
|
||||||
|
|
||||||
# Unconditionally enable ASSERTs
|
DEFAULT_INCLUDES += \
|
||||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_srcdir)/lib/libspl/include
|
||||||
|
|
||||||
bin_PROGRAMS = raidz_test
|
bin_PROGRAMS = raidz_test
|
||||||
|
|
||||||
@@ -14,7 +15,8 @@ raidz_test_SOURCES = \
|
|||||||
raidz_bench.c
|
raidz_bench.c
|
||||||
|
|
||||||
raidz_test_LDADD = \
|
raidz_test_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la
|
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||||
|
$(top_builddir)/lib/libzpool/libzpool.la
|
||||||
|
|
||||||
raidz_test_LDADD += -lm
|
raidz_test_LDADD += -lm -ldl
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ run_gen_bench_impl(const char *impl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
run_gen_bench(void)
|
run_gen_bench(void)
|
||||||
{
|
{
|
||||||
char **impl_name;
|
char **impl_name;
|
||||||
@@ -197,7 +197,7 @@ run_rec_bench_impl(const char *impl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
run_rec_bench(void)
|
run_rec_bench(void)
|
||||||
{
|
{
|
||||||
char **impl_name;
|
char **impl_name;
|
||||||
|
|||||||
@@ -702,8 +702,10 @@ run_sweep(void)
|
|||||||
opts->rto_dsize = size_v[s];
|
opts->rto_dsize = size_v[s];
|
||||||
opts->rto_v = 0; /* be quiet */
|
opts->rto_v = 0; /* be quiet */
|
||||||
|
|
||||||
VERIFY3P(thread_create(NULL, 0, sweep_thread, (void *) opts,
|
VERIFY3P(zk_thread_create(NULL, 0,
|
||||||
0, NULL, TS_RUN, defclsyspri), !=, NULL);
|
(thread_func_t)sweep_thread,
|
||||||
|
(void *) opts, 0, NULL, TS_RUN, 0,
|
||||||
|
PTHREAD_CREATE_JOINABLE), !=, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -757,7 +759,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
process_options(argc, argv);
|
process_options(argc, argv);
|
||||||
|
|
||||||
kernel_init(SPA_MODE_READ);
|
kernel_init(FREAD);
|
||||||
|
|
||||||
/* setup random data because rand() is not reentrant */
|
/* setup random data because rand() is not reentrant */
|
||||||
rand_data = (int *)umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
|
rand_data = (int *)umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ static const char *raidz_impl_names[] = {
|
|||||||
"avx512bw",
|
"avx512bw",
|
||||||
"aarch64_neon",
|
"aarch64_neon",
|
||||||
"aarch64_neonx2",
|
"aarch64_neonx2",
|
||||||
"powerpc_altivec",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -102,7 +102,7 @@ Usage: vdev_id [-h]
|
|||||||
vdev_id <-d device> [-c config_file] [-p phys_per_port]
|
vdev_id <-d device> [-c config_file] [-p phys_per_port]
|
||||||
[-g sas_direct|sas_switch|scsi] [-m]
|
[-g sas_direct|sas_switch|scsi] [-m]
|
||||||
|
|
||||||
-c specify name of an alternative config file [default=$CONFIG]
|
-c specify name of alernate config file [default=$CONFIG]
|
||||||
-d specify basename of device (i.e. sda)
|
-d specify basename of device (i.e. sda)
|
||||||
-e Create enclose device symlinks only (/dev/by-enclosure)
|
-e Create enclose device symlinks only (/dev/by-enclosure)
|
||||||
-g Storage network topology [default="$TOPOLOGY"]
|
-g Storage network topology [default="$TOPOLOGY"]
|
||||||
@@ -114,8 +114,9 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
map_slot() {
|
map_slot() {
|
||||||
LINUX_SLOT=$1
|
local LINUX_SLOT=$1
|
||||||
CHANNEL=$2
|
local CHANNEL=$2
|
||||||
|
local MAPPED_SLOT=
|
||||||
|
|
||||||
MAPPED_SLOT=`awk "\\$1 == \"slot\" && \\$2 == ${LINUX_SLOT} && \
|
MAPPED_SLOT=`awk "\\$1 == \"slot\" && \\$2 == ${LINUX_SLOT} && \
|
||||||
\\$4 ~ /^${CHANNEL}$|^$/ { print \\$3; exit }" $CONFIG`
|
\\$4 ~ /^${CHANNEL}$|^$/ { print \\$3; exit }" $CONFIG`
|
||||||
@@ -126,9 +127,9 @@ map_slot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
map_channel() {
|
map_channel() {
|
||||||
MAPPED_CHAN=
|
local MAPPED_CHAN=
|
||||||
PCI_ID=$1
|
local PCI_ID=$1
|
||||||
PORT=$2
|
local PORT=$2
|
||||||
|
|
||||||
case $TOPOLOGY in
|
case $TOPOLOGY in
|
||||||
"sas_switch")
|
"sas_switch")
|
||||||
@@ -486,7 +487,7 @@ alias_handler () {
|
|||||||
# digits as partitions, causing alias creation to fail. This
|
# digits as partitions, causing alias creation to fail. This
|
||||||
# ambiguity seems unavoidable, so devices using this facility
|
# ambiguity seems unavoidable, so devices using this facility
|
||||||
# must not use such names.
|
# must not use such names.
|
||||||
DM_PART=
|
local DM_PART=
|
||||||
if echo $DM_NAME | grep -q -E 'p[0-9][0-9]*$' ; then
|
if echo $DM_NAME | grep -q -E 'p[0-9][0-9]*$' ; then
|
||||||
if [ "$DEVTYPE" != "partition" ] ; then
|
if [ "$DEVTYPE" != "partition" ] ; then
|
||||||
DM_PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'`
|
DM_PART=`echo $DM_NAME | awk -Fp '/p/{print "-part"$2}'`
|
||||||
@@ -545,11 +546,10 @@ while getopts 'c:d:eg:mp:h' OPTION; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [ ! -r $CONFIG ] ; then
|
if [ ! -r $CONFIG ] ; then
|
||||||
echo "Error: Config file \"$CONFIG\" not found"
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$DEV" ] && [ -z "$ENCLOSURE_MODE" ] ; then
|
if [ -z "$DEV" -a -z "$ENCLOSURE_MODE" ] ; then
|
||||||
echo "Error: missing required option -d"
|
echo "Error: missing required option -d"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -565,7 +565,7 @@ fi
|
|||||||
TOPOLOGY=${TOPOLOGY:-sas_direct}
|
TOPOLOGY=${TOPOLOGY:-sas_direct}
|
||||||
|
|
||||||
# Should we create /dev/by-enclosure symlinks?
|
# Should we create /dev/by-enclosure symlinks?
|
||||||
if [ "$ENCLOSURE_MODE" = "yes" ] && [ "$TOPOLOGY" = "sas_direct" ] ; then
|
if [ "$ENCLOSURE_MODE" = "yes" -a "$TOPOLOGY" = "sas_direct" ] ; then
|
||||||
ID_ENCLOSURE=$(enclosure_handler)
|
ID_ENCLOSURE=$(enclosure_handler)
|
||||||
if [ -z "$ID_ENCLOSURE" ] ; then
|
if [ -z "$ID_ENCLOSURE" ] ; then
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
+11
-7
@@ -1,16 +1,20 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
# Unconditionally enable debugging for zdb
|
AM_CPPFLAGS += -DDEBUG
|
||||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
|
||||||
|
DEFAULT_INCLUDES += \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_srcdir)/lib/libspl/include
|
||||||
|
|
||||||
sbin_PROGRAMS = zdb
|
sbin_PROGRAMS = zdb
|
||||||
|
|
||||||
zdb_SOURCES = \
|
zdb_SOURCES = \
|
||||||
zdb.c \
|
zdb.c \
|
||||||
zdb_il.c \
|
zdb_il.c
|
||||||
zdb.h
|
|
||||||
|
|
||||||
zdb_LDADD = \
|
zdb_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||||
|
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||||
|
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||||
|
|||||||
+560
-4655
File diff suppressed because it is too large
Load Diff
+70
-97
@@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017 by Delphix. All rights reserved.
|
* Copyright (c) 2013, 2016 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -42,14 +42,11 @@
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/zil.h>
|
#include <sys/zil.h>
|
||||||
#include <sys/zil_impl.h>
|
#include <sys/zil_impl.h>
|
||||||
#include <sys/spa_impl.h>
|
|
||||||
#include <sys/abd.h>
|
#include <sys/abd.h>
|
||||||
|
|
||||||
#include "zdb.h"
|
|
||||||
|
|
||||||
extern uint8_t dump_opt[256];
|
extern uint8_t dump_opt[256];
|
||||||
|
|
||||||
static char tab_prefix[4] = "\t\t\t";
|
static char prefix[4] = "\t\t\t";
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_log_bp(const blkptr_t *bp, const char *prefix)
|
print_log_bp(const blkptr_t *bp, const char *prefix)
|
||||||
@@ -62,9 +59,8 @@ print_log_bp(const blkptr_t *bp, const char *prefix)
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* 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, lr_create_t *lr)
|
||||||
{
|
{
|
||||||
const lr_create_t *lr = arg;
|
|
||||||
time_t crtime = lr->lr_crtime[0];
|
time_t crtime = lr->lr_crtime[0];
|
||||||
char *name, *link;
|
char *name, *link;
|
||||||
lr_attr_t *lrattr;
|
lr_attr_t *lrattr;
|
||||||
@@ -79,55 +75,49 @@ zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
|
|
||||||
if (txtype == TX_SYMLINK) {
|
if (txtype == TX_SYMLINK) {
|
||||||
link = name + strlen(name) + 1;
|
link = name + strlen(name) + 1;
|
||||||
(void) printf("%s%s -> %s\n", tab_prefix, name, link);
|
(void) printf("%s%s -> %s\n", 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", prefix, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) printf("%s%s", tab_prefix, ctime(&crtime));
|
(void) printf("%s%s", prefix, ctime(&crtime));
|
||||||
(void) printf("%sdoid %llu, foid %llu, slots %llu, mode %llo\n",
|
(void) printf("%sdoid %llu, foid %llu, slots %llu, mode %llo\n", prefix,
|
||||||
tab_prefix, (u_longlong_t)lr->lr_doid,
|
(u_longlong_t)lr->lr_doid,
|
||||||
(u_longlong_t)LR_FOID_GET_OBJ(lr->lr_foid),
|
(u_longlong_t)LR_FOID_GET_OBJ(lr->lr_foid),
|
||||||
(u_longlong_t)LR_FOID_GET_SLOTS(lr->lr_foid),
|
(u_longlong_t)LR_FOID_GET_SLOTS(lr->lr_foid),
|
||||||
(longlong_t)lr->lr_mode);
|
(longlong_t)lr->lr_mode);
|
||||||
(void) printf("%suid %llu, gid %llu, gen %llu, rdev 0x%llx\n",
|
(void) printf("%suid %llu, gid %llu, gen %llu, rdev 0x%llx\n", prefix,
|
||||||
tab_prefix,
|
|
||||||
(u_longlong_t)lr->lr_uid, (u_longlong_t)lr->lr_gid,
|
(u_longlong_t)lr->lr_uid, (u_longlong_t)lr->lr_gid,
|
||||||
(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 */
|
/* 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, lr_remove_t *lr)
|
||||||
{
|
{
|
||||||
const lr_remove_t *lr = arg;
|
(void) printf("%sdoid %llu, name %s\n", prefix,
|
||||||
|
|
||||||
(void) printf("%sdoid %llu, name %s\n", tab_prefix,
|
|
||||||
(u_longlong_t)lr->lr_doid, (char *)(lr + 1));
|
(u_longlong_t)lr->lr_doid, (char *)(lr + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* 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, lr_link_t *lr)
|
||||||
{
|
{
|
||||||
const lr_link_t *lr = arg;
|
(void) printf("%sdoid %llu, link_obj %llu, name %s\n", 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,
|
||||||
(char *)(lr + 1));
|
(char *)(lr + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* 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, lr_rename_t *lr)
|
||||||
{
|
{
|
||||||
const lr_rename_t *lr = arg;
|
|
||||||
char *snm = (char *)(lr + 1);
|
char *snm = (char *)(lr + 1);
|
||||||
char *tnm = snm + strlen(snm) + 1;
|
char *tnm = snm + strlen(snm) + 1;
|
||||||
|
|
||||||
(void) printf("%ssdoid %llu, tdoid %llu\n", tab_prefix,
|
(void) printf("%ssdoid %llu, tdoid %llu\n", 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", prefix, snm, tnm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
@@ -135,8 +125,9 @@ 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)
|
||||||
{
|
{
|
||||||
char *cdata = data;
|
char *cdata = data;
|
||||||
|
int i;
|
||||||
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (isprint(*cdata))
|
if (isprint(*cdata))
|
||||||
(void) printf("%c ", *cdata);
|
(void) printf("%c ", *cdata);
|
||||||
else
|
else
|
||||||
@@ -148,16 +139,15 @@ zil_prt_rec_write_cb(void *data, size_t len, void *unused)
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* 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, lr_write_t *lr)
|
||||||
{
|
{
|
||||||
const lr_write_t *lr = arg;
|
|
||||||
abd_t *data;
|
abd_t *data;
|
||||||
const blkptr_t *bp = &lr->lr_blkptr;
|
blkptr_t *bp = &lr->lr_blkptr;
|
||||||
zbookmark_phys_t zb;
|
zbookmark_phys_t zb;
|
||||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
(void) printf("%sfoid %llu, offset %llx, length %llx\n", tab_prefix,
|
(void) printf("%sfoid %llu, offset %llx, length %llx\n", prefix,
|
||||||
(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);
|
||||||
|
|
||||||
@@ -165,21 +155,20 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
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", prefix,
|
||||||
!BP_IS_HOLE(bp) &&
|
!BP_IS_HOLE(bp) &&
|
||||||
bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa) ?
|
bp->blk_birth >= spa_first_txg(zilog->zl_spa) ?
|
||||||
"will claim" : "won't claim");
|
"will claim" : "won't claim");
|
||||||
print_log_bp(bp, tab_prefix);
|
print_log_bp(bp, prefix);
|
||||||
|
|
||||||
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", prefix);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (bp->blk_birth < 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", prefix);
|
||||||
tab_prefix);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +188,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
abd_copy_from_buf(data, lr + 1, lr->lr_length);
|
abd_copy_from_buf(data, lr + 1, lr->lr_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) printf("%s", tab_prefix);
|
(void) printf("%s", prefix);
|
||||||
(void) abd_iterate_func(data,
|
(void) abd_iterate_func(data,
|
||||||
0, MIN(lr->lr_length, (verbose < 6 ? 20 : SPA_MAXBLOCKSIZE)),
|
0, MIN(lr->lr_length, (verbose < 6 ? 20 : SPA_MAXBLOCKSIZE)),
|
||||||
zil_prt_rec_write_cb, NULL);
|
zil_prt_rec_write_cb, NULL);
|
||||||
@@ -211,55 +200,52 @@ out:
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
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, lr_truncate_t *lr)
|
||||||
{
|
{
|
||||||
const lr_truncate_t *lr = arg;
|
(void) printf("%sfoid %llu, offset 0x%llx, length 0x%llx\n", prefix,
|
||||||
|
|
||||||
(void) printf("%sfoid %llu, offset 0x%llx, length 0x%llx\n", tab_prefix,
|
|
||||||
(u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset,
|
(u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset,
|
||||||
(u_longlong_t)lr->lr_length);
|
(u_longlong_t)lr->lr_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* 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, lr_setattr_t *lr)
|
||||||
{
|
{
|
||||||
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];
|
||||||
|
|
||||||
(void) printf("%sfoid %llu, mask 0x%llx\n", tab_prefix,
|
(void) printf("%sfoid %llu, mask 0x%llx\n", prefix,
|
||||||
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_mask);
|
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_mask);
|
||||||
|
|
||||||
if (lr->lr_mask & AT_MODE) {
|
if (lr->lr_mask & AT_MODE) {
|
||||||
(void) printf("%sAT_MODE %llo\n", tab_prefix,
|
(void) printf("%sAT_MODE %llo\n", prefix,
|
||||||
(longlong_t)lr->lr_mode);
|
(longlong_t)lr->lr_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lr->lr_mask & AT_UID) {
|
if (lr->lr_mask & AT_UID) {
|
||||||
(void) printf("%sAT_UID %llu\n", tab_prefix,
|
(void) printf("%sAT_UID %llu\n", prefix,
|
||||||
(u_longlong_t)lr->lr_uid);
|
(u_longlong_t)lr->lr_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lr->lr_mask & AT_GID) {
|
if (lr->lr_mask & AT_GID) {
|
||||||
(void) printf("%sAT_GID %llu\n", tab_prefix,
|
(void) printf("%sAT_GID %llu\n", prefix,
|
||||||
(u_longlong_t)lr->lr_gid);
|
(u_longlong_t)lr->lr_gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lr->lr_mask & AT_SIZE) {
|
if (lr->lr_mask & AT_SIZE) {
|
||||||
(void) printf("%sAT_SIZE %llu\n", tab_prefix,
|
(void) printf("%sAT_SIZE %llu\n", prefix,
|
||||||
(u_longlong_t)lr->lr_size);
|
(u_longlong_t)lr->lr_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lr->lr_mask & AT_ATIME) {
|
if (lr->lr_mask & AT_ATIME) {
|
||||||
(void) printf("%sAT_ATIME %llu.%09llu %s", tab_prefix,
|
(void) printf("%sAT_ATIME %llu.%09llu %s", prefix,
|
||||||
(u_longlong_t)lr->lr_atime[0],
|
(u_longlong_t)lr->lr_atime[0],
|
||||||
(u_longlong_t)lr->lr_atime[1],
|
(u_longlong_t)lr->lr_atime[1],
|
||||||
ctime(&atime));
|
ctime(&atime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lr->lr_mask & AT_MTIME) {
|
if (lr->lr_mask & AT_MTIME) {
|
||||||
(void) printf("%sAT_MTIME %llu.%09llu %s", tab_prefix,
|
(void) printf("%sAT_MTIME %llu.%09llu %s", prefix,
|
||||||
(u_longlong_t)lr->lr_mtime[0],
|
(u_longlong_t)lr->lr_mtime[0],
|
||||||
(u_longlong_t)lr->lr_mtime[1],
|
(u_longlong_t)lr->lr_mtime[1],
|
||||||
ctime(&mtime));
|
ctime(&mtime));
|
||||||
@@ -268,48 +254,46 @@ zil_prt_rec_setattr(zilog_t *zilog, int txtype, const void *arg)
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
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, lr_acl_t *lr)
|
||||||
{
|
{
|
||||||
const lr_acl_t *lr = arg;
|
(void) printf("%sfoid %llu, aclcnt %llu\n", 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*zil_prt_rec_func_t)(zilog_t *, int, const void *);
|
typedef void (*zil_prt_rec_func_t)(zilog_t *, int, 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;
|
||||||
const char *zri_name;
|
char *zri_name;
|
||||||
uint64_t zri_count;
|
uint64_t zri_count;
|
||||||
} zil_rec_info_t;
|
} zil_rec_info_t;
|
||||||
|
|
||||||
static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
||||||
{.zri_print = NULL, .zri_name = "Total "},
|
{ NULL, "Total " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKXATTR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKXATTR " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_SYMLINK "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_SYMLINK " },
|
||||||
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_REMOVE "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_remove, "TX_REMOVE " },
|
||||||
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_RMDIR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_remove, "TX_RMDIR " },
|
||||||
{.zri_print = zil_prt_rec_link, .zri_name = "TX_LINK "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_link, "TX_LINK " },
|
||||||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_rename, "TX_RENAME " },
|
||||||
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_write, "TX_WRITE " },
|
||||||
{.zri_print = zil_prt_rec_truncate, .zri_name = "TX_TRUNCATE "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_truncate, "TX_TRUNCATE " },
|
||||||
{.zri_print = zil_prt_rec_setattr, .zri_name = "TX_SETATTR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_setattr, "TX_SETATTR " },
|
||||||
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_V0 "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_acl, "TX_ACL_V0 " },
|
||||||
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_ACL "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_acl, "TX_ACL_ACL " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE_ACL "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE_ACL " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE_ATTR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE_ATTR " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE_ACL_ATTR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE_ACL_ATTR " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ACL "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR_ACL " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ATTR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR_ATTR " },
|
||||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ACL_ATTR "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR_ACL_ATTR " },
|
||||||
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE2 "},
|
{ (zil_prt_rec_func_t)zil_prt_rec_write, "TX_WRITE2 " },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* 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, lr_t *lr, void *arg, uint64_t claim_txg)
|
||||||
{
|
{
|
||||||
int txtype;
|
int txtype;
|
||||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||||
@@ -327,13 +311,8 @@ print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
|||||||
(u_longlong_t)lr->lrc_txg,
|
(u_longlong_t)lr->lrc_txg,
|
||||||
(u_longlong_t)lr->lrc_seq);
|
(u_longlong_t)lr->lrc_seq);
|
||||||
|
|
||||||
if (txtype && verbose >= 3) {
|
if (txtype && verbose >= 3)
|
||||||
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 {
|
|
||||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zil_rec_info[txtype].zri_count++;
|
zil_rec_info[txtype].zri_count++;
|
||||||
zil_rec_info[0].zri_count++;
|
zil_rec_info[0].zri_count++;
|
||||||
@@ -343,12 +322,11 @@ print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
|
print_log_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
|
||||||
uint64_t claim_txg)
|
|
||||||
{
|
{
|
||||||
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;
|
char *claim;
|
||||||
|
|
||||||
if (verbose <= 3)
|
if (verbose <= 3)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -363,7 +341,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->blk_birth >= spa_min_claim_txg(zilog->zl_spa))
|
else if (bp->blk_birth >= spa_first_txg(zilog->zl_spa))
|
||||||
claim = "will claim";
|
claim = "will claim";
|
||||||
else
|
else
|
||||||
claim = "won't claim";
|
claim = "won't claim";
|
||||||
@@ -377,7 +355,7 @@ print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
|
|||||||
static void
|
static void
|
||||||
print_log_stats(int verbose)
|
print_log_stats(int verbose)
|
||||||
{
|
{
|
||||||
unsigned i, w, p10;
|
int i, w, p10;
|
||||||
|
|
||||||
if (verbose > 3)
|
if (verbose > 3)
|
||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
@@ -418,15 +396,10 @@ dump_intent_log(zilog_t *zilog)
|
|||||||
for (i = 0; i < TX_MAX_TYPE; i++)
|
for (i = 0; i < TX_MAX_TYPE; i++)
|
||||||
zil_rec_info[i].zri_count = 0;
|
zil_rec_info[i].zri_count = 0;
|
||||||
|
|
||||||
/* see comment in zil_claim() or zil_check_log_chain() */
|
|
||||||
if (zilog->zl_spa->spa_uberblock.ub_checkpoint_txg != 0 &&
|
|
||||||
zh->zh_claim_txg == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (verbose >= 2) {
|
if (verbose >= 2) {
|
||||||
(void) printf("\n");
|
(void) printf("\n");
|
||||||
(void) zil_parse(zilog, print_log_block, print_log_record, NULL,
|
(void) zil_parse(zilog, print_log_block, print_log_record, NULL,
|
||||||
zh->zh_claim_txg, B_FALSE);
|
zh->zh_claim_txg);
|
||||||
print_log_stats(verbose);
|
print_log_stats(verbose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-9
@@ -1,8 +1,10 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
AM_CFLAGS += $(LIBUDEV_CFLAGS) $(LIBUUID_CFLAGS)
|
DEFAULT_INCLUDES += \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_srcdir)/lib/libspl/include
|
||||||
|
|
||||||
SUBDIRS = zed.d
|
EXTRA_DIST = zed.d/README
|
||||||
|
|
||||||
sbin_PROGRAMS = zed
|
sbin_PROGRAMS = zed
|
||||||
|
|
||||||
@@ -38,12 +40,55 @@ FMA_SRC = \
|
|||||||
zed_SOURCES = $(ZED_SRC) $(FMA_SRC)
|
zed_SOURCES = $(ZED_SRC) $(FMA_SRC)
|
||||||
|
|
||||||
zed_LDADD = \
|
zed_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
$(top_builddir)/lib/libavl/libavl.la \
|
||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
|
$(top_builddir)/lib/libspl/libspl.la \
|
||||||
$(abs_top_builddir)/lib/libuutil/libuutil.la
|
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||||
|
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||||
|
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||||
|
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||||
|
|
||||||
zed_LDADD += -lrt $(LIBUDEV_LIBS) $(LIBUUID_LIBS)
|
zed_LDFLAGS = -lrt -pthread
|
||||||
zed_LDFLAGS = -pthread
|
|
||||||
|
|
||||||
EXTRA_DIST = agents/README.md
|
zedconfdir = $(sysconfdir)/zfs/zed.d
|
||||||
|
|
||||||
|
dist_zedconf_DATA = \
|
||||||
|
zed.d/zed-functions.sh \
|
||||||
|
zed.d/zed.rc
|
||||||
|
|
||||||
|
zedexecdir = $(libexecdir)/zfs/zed.d
|
||||||
|
|
||||||
|
dist_zedexec_SCRIPTS = \
|
||||||
|
zed.d/all-debug.sh \
|
||||||
|
zed.d/all-syslog.sh \
|
||||||
|
zed.d/data-notify.sh \
|
||||||
|
zed.d/generic-notify.sh \
|
||||||
|
zed.d/resilver_finish-notify.sh \
|
||||||
|
zed.d/scrub_finish-notify.sh \
|
||||||
|
zed.d/statechange-led.sh \
|
||||||
|
zed.d/statechange-notify.sh \
|
||||||
|
zed.d/vdev_clear-led.sh \
|
||||||
|
zed.d/vdev_attach-led.sh \
|
||||||
|
zed.d/pool_import-led.sh \
|
||||||
|
zed.d/resilver_finish-start-scrub.sh
|
||||||
|
|
||||||
|
zedconfdefaults = \
|
||||||
|
all-syslog.sh \
|
||||||
|
data-notify.sh \
|
||||||
|
resilver_finish-notify.sh \
|
||||||
|
scrub_finish-notify.sh \
|
||||||
|
statechange-led.sh \
|
||||||
|
statechange-notify.sh \
|
||||||
|
vdev_clear-led.sh \
|
||||||
|
vdev_attach-led.sh \
|
||||||
|
pool_import-led.sh \
|
||||||
|
resilver_finish-start-scrub.sh
|
||||||
|
|
||||||
|
install-data-hook:
|
||||||
|
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
||||||
|
for f in $(zedconfdefaults); do \
|
||||||
|
test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \
|
||||||
|
-L "$(DESTDIR)$(zedconfdir)/$${f}" || \
|
||||||
|
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
||||||
|
done
|
||||||
|
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file implements the minimal FMD module API required to support the
|
* This file imlements the minimal FMD module API required to support the
|
||||||
* fault logic modules in ZED. This support includes module registration,
|
* fault logic modules in ZED. This support includes module registration,
|
||||||
* memory allocation, module property accessors, basic case management,
|
* memory allocation, module property accessors, basic case management,
|
||||||
* one-shot timers and SERD engines.
|
* one-shot timers and SERD engines.
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ fmd_serd_eng_empty(fmd_serd_eng_t *sgp)
|
|||||||
void
|
void
|
||||||
fmd_serd_eng_reset(fmd_serd_eng_t *sgp)
|
fmd_serd_eng_reset(fmd_serd_eng_t *sgp)
|
||||||
{
|
{
|
||||||
serd_log_msg(" SERD Engine: resetting %s", sgp->sg_name);
|
serd_log_msg(" SERD Engine: reseting %s", sgp->sg_name);
|
||||||
|
|
||||||
while (sgp->sg_count != 0)
|
while (sgp->sg_count != 0)
|
||||||
fmd_serd_eng_discard(sgp, list_head(&sgp->sg_list));
|
fmd_serd_eng_discard(sgp, list_head(&sgp->sg_list));
|
||||||
|
|||||||
+41
-97
@@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Intel Corporation.
|
* Copyright (c) 2016, Intel Corporation.
|
||||||
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libnvpair.h>
|
#include <libnvpair.h>
|
||||||
@@ -54,25 +53,13 @@ pthread_t g_agents_tid;
|
|||||||
libzfs_handle_t *g_zfs_hdl;
|
libzfs_handle_t *g_zfs_hdl;
|
||||||
|
|
||||||
/* guid search data */
|
/* guid search data */
|
||||||
typedef enum device_type {
|
|
||||||
DEVICE_TYPE_L2ARC, /* l2arc device */
|
|
||||||
DEVICE_TYPE_SPARE, /* spare device */
|
|
||||||
DEVICE_TYPE_PRIMARY /* any primary pool storage device */
|
|
||||||
} device_type_t;
|
|
||||||
|
|
||||||
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;
|
||||||
char *gs_devid;
|
char *gs_devid;
|
||||||
device_type_t gs_vdev_type;
|
|
||||||
uint64_t gs_vdev_expandtime; /* vdev expansion time */
|
|
||||||
} guid_search_t;
|
} guid_search_t;
|
||||||
|
|
||||||
/*
|
static void
|
||||||
* Walks the vdev tree recursively looking for a matching devid.
|
|
||||||
* Returns B_TRUE as soon as a matching device is found, B_FALSE otherwise.
|
|
||||||
*/
|
|
||||||
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;
|
||||||
@@ -85,48 +72,19 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
|||||||
*/
|
*/
|
||||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
|
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
|
||||||
&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)) {
|
zfs_agent_iter_vdev(zhp, child[c], gsp);
|
||||||
gsp->gs_vdev_type = DEVICE_TYPE_PRIMARY;
|
return;
|
||||||
return (B_TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Iterate over any spares and cache devices
|
* On a devid match, grab the vdev guid
|
||||||
*/
|
*/
|
||||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_SPARES,
|
if ((gsp->gs_vdev_guid == 0) &&
|
||||||
&child, &children) == 0) {
|
|
||||||
for (c = 0; c < children; c++) {
|
|
||||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
|
||||||
gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
|
|
||||||
return (B_TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_L2CACHE,
|
|
||||||
&child, &children) == 0) {
|
|
||||||
for (c = 0; c < children; c++) {
|
|
||||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
|
||||||
gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
|
|
||||||
return (B_TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* On a devid match, grab the vdev guid and expansion time, if any.
|
|
||||||
*/
|
|
||||||
if (gsp->gs_devid != NULL &&
|
|
||||||
(nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID, &path) == 0) &&
|
(nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID, &path) == 0) &&
|
||||||
(strcmp(gsp->gs_devid, path) == 0)) {
|
(strcmp(gsp->gs_devid, path) == 0)) {
|
||||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
|
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
|
||||||
&gsp->gs_vdev_guid);
|
&gsp->gs_vdev_guid);
|
||||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
|
|
||||||
&gsp->gs_vdev_expandtime);
|
|
||||||
return (B_TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (B_FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -141,7 +99,7 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
|
|||||||
if ((config = zpool_get_config(zhp, NULL)) != NULL) {
|
if ((config = zpool_get_config(zhp, NULL)) != NULL) {
|
||||||
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||||
&nvl) == 0) {
|
&nvl) == 0) {
|
||||||
(void) zfs_agent_iter_vdev(zhp, nvl, gsp);
|
zfs_agent_iter_vdev(zhp, nvl, gsp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -177,12 +135,10 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On Linux, we don't get the expected FM_RESOURCE_REMOVED ereport
|
* On ZFS on Linux, we don't get the expected FM_RESOURCE_REMOVED
|
||||||
* from the vdev_disk layer after a hot unplug. Fortunately we do
|
* ereport from vdev_disk layer after a hot unplug. Fortunately we
|
||||||
* get an EC_DEV_REMOVE from our disk monitor and it is a suitable
|
* get a EC_DEV_REMOVE from our disk monitor and it is a suitable
|
||||||
* proxy so we remap it here for the benefit of the diagnosis engine.
|
* proxy so we remap it here for the benefit of the diagnosis engine.
|
||||||
* Starting in OpenZFS 2.0, we do get FM_RESOURCE_REMOVED from the spa
|
|
||||||
* layer. Processing multiple FM_RESOURCE_REMOVED events is not harmful.
|
|
||||||
*/
|
*/
|
||||||
if ((strcmp(class, EC_DEV_REMOVE) == 0) &&
|
if ((strcmp(class, EC_DEV_REMOVE) == 0) &&
|
||||||
(strcmp(subclass, ESC_DISK) == 0) &&
|
(strcmp(subclass, ESC_DISK) == 0) &&
|
||||||
@@ -192,8 +148,6 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int64_t tod[2];
|
int64_t tod[2];
|
||||||
uint64_t pool_guid = 0, vdev_guid = 0;
|
uint64_t pool_guid = 0, vdev_guid = 0;
|
||||||
guid_search_t search = { 0 };
|
|
||||||
device_type_t devtype = DEVICE_TYPE_PRIMARY;
|
|
||||||
|
|
||||||
class = "resource.fs.zfs.removed";
|
class = "resource.fs.zfs.removed";
|
||||||
subclass = "";
|
subclass = "";
|
||||||
@@ -202,55 +156,30 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
(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);
|
||||||
|
|
||||||
(void) gettimeofday(&tv, NULL);
|
|
||||||
tod[0] = tv.tv_sec;
|
|
||||||
tod[1] = tv.tv_usec;
|
|
||||||
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
|
* For multipath, ZFS_EV_VDEV_GUID is missing so find it.
|
||||||
* ZFS_EV_POOL_GUID may be missing so find them.
|
|
||||||
*/
|
*/
|
||||||
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
if (vdev_guid == 0) {
|
||||||
&search.gs_devid);
|
guid_search_t search = { 0 };
|
||||||
(void) zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
|
|
||||||
pool_guid = search.gs_pool_guid;
|
|
||||||
vdev_guid = search.gs_vdev_guid;
|
|
||||||
devtype = search.gs_vdev_type;
|
|
||||||
|
|
||||||
/*
|
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
||||||
* We want to avoid reporting "remove" events coming from
|
&search.gs_devid);
|
||||||
* libudev for VDEVs which were expanded recently (10s) and
|
|
||||||
* avoid activating spares in response to partitions being
|
(void) zpool_iter(g_zfs_hdl, zfs_agent_iter_pool,
|
||||||
* deleted and created in rapid succession.
|
&search);
|
||||||
*/
|
pool_guid = search.gs_pool_guid;
|
||||||
if (search.gs_vdev_expandtime != 0 &&
|
vdev_guid = search.gs_vdev_guid;
|
||||||
search.gs_vdev_expandtime + 10 > tv.tv_sec) {
|
|
||||||
zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' "
|
|
||||||
"for recently expanded device '%s'", EC_DEV_REMOVE,
|
|
||||||
search.gs_devid);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) nvlist_add_uint64(payload,
|
(void) nvlist_add_uint64(payload,
|
||||||
FM_EREPORT_PAYLOAD_ZFS_POOL_GUID, pool_guid);
|
FM_EREPORT_PAYLOAD_ZFS_POOL_GUID, pool_guid);
|
||||||
(void) nvlist_add_uint64(payload,
|
(void) nvlist_add_uint64(payload,
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, vdev_guid);
|
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, vdev_guid);
|
||||||
switch (devtype) {
|
|
||||||
case DEVICE_TYPE_L2ARC:
|
(void) gettimeofday(&tv, NULL);
|
||||||
(void) nvlist_add_string(payload,
|
tod[0] = tv.tv_sec;
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
|
tod[1] = tv.tv_usec;
|
||||||
VDEV_TYPE_L2CACHE);
|
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
|
||||||
break;
|
|
||||||
case DEVICE_TYPE_SPARE:
|
|
||||||
(void) nvlist_add_string(payload,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE, VDEV_TYPE_SPARE);
|
|
||||||
break;
|
|
||||||
case DEVICE_TYPE_PRIMARY:
|
|
||||||
(void) nvlist_add_string(payload,
|
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE, VDEV_TYPE_DISK);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO, "agent post event: mapping '%s' to '%s'",
|
zed_log_msg(LOG_INFO, "agent post event: mapping '%s' to '%s'",
|
||||||
EC_DEV_REMOVE, class);
|
EC_DEV_REMOVE, class);
|
||||||
@@ -264,7 +193,6 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
|||||||
list_insert_tail(&agent_events, event);
|
list_insert_tail(&agent_events, event);
|
||||||
(void) pthread_mutex_unlock(&agent_lock);
|
(void) pthread_mutex_unlock(&agent_lock);
|
||||||
|
|
||||||
out:
|
|
||||||
(void) pthread_cond_signal(&agent_cond);
|
(void) pthread_cond_signal(&agent_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,3 +350,19 @@ zfs_agent_fini(void)
|
|||||||
|
|
||||||
g_zfs_hdl = NULL;
|
g_zfs_hdl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In ZED context, all the FMA agents run in the same thread
|
||||||
|
* and do not require a unique libzfs instance. Modules should
|
||||||
|
* use these stubs.
|
||||||
|
*/
|
||||||
|
libzfs_handle_t *
|
||||||
|
__libzfs_init(void)
|
||||||
|
{
|
||||||
|
return (g_zfs_hdl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__libzfs_fini(libzfs_handle_t *hdl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ extern int zfs_slm_init(void);
|
|||||||
extern void zfs_slm_fini(void);
|
extern void zfs_slm_fini(void);
|
||||||
extern void zfs_slm_event(const char *, const char *, nvlist_t *);
|
extern void zfs_slm_event(const char *, const char *, nvlist_t *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In ZED context, all the FMA agents run in the same thread
|
||||||
|
* and do not require a unique libzfs instance.
|
||||||
|
*/
|
||||||
|
extern libzfs_handle_t *__libzfs_init(void);
|
||||||
|
extern void __libzfs_fini(libzfs_handle_t *);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <libuutil.h>
|
#include <libuutil.h>
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
@@ -168,12 +167,14 @@ zfs_case_unserialize(fmd_hdl_t *hdl, fmd_case_t *cp)
|
|||||||
static void
|
static void
|
||||||
zfs_mark_vdev(uint64_t pool_guid, nvlist_t *vd, er_timeval_t *loaded)
|
zfs_mark_vdev(uint64_t pool_guid, nvlist_t *vd, er_timeval_t *loaded)
|
||||||
{
|
{
|
||||||
uint64_t vdev_guid = 0;
|
uint64_t vdev_guid;
|
||||||
uint_t c, children;
|
uint_t c, children;
|
||||||
nvlist_t **child;
|
nvlist_t **child;
|
||||||
zfs_case_t *zcp;
|
zfs_case_t *zcp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
(void) nvlist_lookup_uint64(vd, ZPOOL_CONFIG_GUID, &vdev_guid);
|
ret = nvlist_lookup_uint64(vd, ZPOOL_CONFIG_GUID, &vdev_guid);
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark any cases associated with this (pool, vdev) pair.
|
* Mark any cases associated with this (pool, vdev) pair.
|
||||||
@@ -252,10 +253,7 @@ zfs_mark_pool(zpool_handle_t *zhp, void *unused)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &vd);
|
ret = nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &vd);
|
||||||
if (ret) {
|
assert(ret == 0);
|
||||||
zpool_close(zhp);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
zfs_mark_vdev(pool_guid, vd, &loaded);
|
zfs_mark_vdev(pool_guid, vd, &loaded);
|
||||||
|
|
||||||
@@ -379,6 +377,11 @@ zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname,
|
|||||||
nvlist_t *detector, *fault;
|
nvlist_t *detector, *fault;
|
||||||
boolean_t serialize;
|
boolean_t serialize;
|
||||||
nvlist_t *fru = NULL;
|
nvlist_t *fru = NULL;
|
||||||
|
#ifdef HAVE_LIBTOPO
|
||||||
|
nvlist_t *fmri;
|
||||||
|
topo_hdl_t *thp;
|
||||||
|
int err;
|
||||||
|
#endif
|
||||||
fmd_hdl_debug(hdl, "solving fault '%s'", faultname);
|
fmd_hdl_debug(hdl, "solving fault '%s'", faultname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -397,6 +400,64 @@ zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname,
|
|||||||
zcp->zc_data.zc_vdev_guid);
|
zcp->zc_data.zc_vdev_guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTOPO
|
||||||
|
/*
|
||||||
|
* We also want to make sure that the detector (pool or vdev) properly
|
||||||
|
* reflects the diagnosed state, when the fault corresponds to internal
|
||||||
|
* ZFS state (i.e. not checksum or I/O error-induced). Otherwise, a
|
||||||
|
* device which was unavailable early in boot (because the driver/file
|
||||||
|
* wasn't available) and is now healthy will be mis-diagnosed.
|
||||||
|
*/
|
||||||
|
if (!fmd_nvl_fmri_present(hdl, detector) ||
|
||||||
|
(checkunusable && !fmd_nvl_fmri_unusable(hdl, detector))) {
|
||||||
|
fmd_case_close(hdl, zcp->zc_case);
|
||||||
|
nvlist_free(detector);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fru = NULL;
|
||||||
|
if (zcp->zc_fru != NULL &&
|
||||||
|
(thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) != NULL) {
|
||||||
|
/*
|
||||||
|
* If the vdev had an associated FRU, then get the FRU nvlist
|
||||||
|
* from the topo handle and use that in the suspect list. We
|
||||||
|
* explicitly lookup the FRU because the fmri reported from the
|
||||||
|
* kernel may not have up to date details about the disk itself
|
||||||
|
* (serial, part, etc).
|
||||||
|
*/
|
||||||
|
if (topo_fmri_str2nvl(thp, zcp->zc_fru, &fmri, &err) == 0) {
|
||||||
|
libzfs_handle_t *zhdl = fmd_hdl_getspecific(hdl);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the disk is part of the system chassis, but the
|
||||||
|
* FRU indicates a different chassis ID than our
|
||||||
|
* current system, then ignore the error. This
|
||||||
|
* indicates that the device was part of another
|
||||||
|
* cluster head, and for obvious reasons cannot be
|
||||||
|
* imported on this system.
|
||||||
|
*/
|
||||||
|
if (libzfs_fru_notself(zhdl, zcp->zc_fru)) {
|
||||||
|
fmd_case_close(hdl, zcp->zc_case);
|
||||||
|
nvlist_free(fmri);
|
||||||
|
fmd_hdl_topo_rele(hdl, thp);
|
||||||
|
nvlist_free(detector);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the device is no longer present on the system, or
|
||||||
|
* topo_fmri_fru() fails for other reasons, then fall
|
||||||
|
* back to the fmri specified in the vdev.
|
||||||
|
*/
|
||||||
|
if (topo_fmri_fru(thp, fmri, &fru, &err) != 0)
|
||||||
|
fru = fmd_nvl_dup(hdl, fmri, FMD_SLEEP);
|
||||||
|
nvlist_free(fmri);
|
||||||
|
}
|
||||||
|
|
||||||
|
fmd_hdl_topo_rele(hdl, thp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
fault = fmd_nvl_create_fault(hdl, faultname, 100, detector,
|
fault = fmd_nvl_create_fault(hdl, faultname, 100, detector,
|
||||||
fru, detector);
|
fru, detector);
|
||||||
fmd_case_add_suspect(hdl, zcp->zc_case, fault);
|
fmd_case_add_suspect(hdl, zcp->zc_case, fault);
|
||||||
@@ -921,27 +982,27 @@ _zfs_diagnosis_init(fmd_hdl_t *hdl)
|
|||||||
{
|
{
|
||||||
libzfs_handle_t *zhdl;
|
libzfs_handle_t *zhdl;
|
||||||
|
|
||||||
if ((zhdl = libzfs_init()) == NULL)
|
if ((zhdl = __libzfs_init()) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((zfs_case_pool = uu_list_pool_create("zfs_case_pool",
|
if ((zfs_case_pool = uu_list_pool_create("zfs_case_pool",
|
||||||
sizeof (zfs_case_t), offsetof(zfs_case_t, zc_node),
|
sizeof (zfs_case_t), offsetof(zfs_case_t, zc_node),
|
||||||
NULL, UU_LIST_POOL_DEBUG)) == NULL) {
|
NULL, UU_LIST_POOL_DEBUG)) == NULL) {
|
||||||
libzfs_fini(zhdl);
|
__libzfs_fini(zhdl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((zfs_cases = uu_list_create(zfs_case_pool, NULL,
|
if ((zfs_cases = uu_list_create(zfs_case_pool, NULL,
|
||||||
UU_LIST_DEBUG)) == NULL) {
|
UU_LIST_DEBUG)) == NULL) {
|
||||||
uu_list_pool_destroy(zfs_case_pool);
|
uu_list_pool_destroy(zfs_case_pool);
|
||||||
libzfs_fini(zhdl);
|
__libzfs_fini(zhdl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) {
|
if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) {
|
||||||
uu_list_destroy(zfs_cases);
|
uu_list_destroy(zfs_cases);
|
||||||
uu_list_pool_destroy(zfs_case_pool);
|
uu_list_pool_destroy(zfs_case_pool);
|
||||||
libzfs_fini(zhdl);
|
__libzfs_fini(zhdl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,5 +1038,5 @@ _zfs_diagnosis_fini(fmd_hdl_t *hdl)
|
|||||||
uu_list_pool_destroy(zfs_case_pool);
|
uu_list_pool_destroy(zfs_case_pool);
|
||||||
|
|
||||||
zhdl = fmd_hdl_getspecific(hdl);
|
zhdl = fmd_hdl_getspecific(hdl);
|
||||||
libzfs_fini(zhdl);
|
__libzfs_fini(zhdl);
|
||||||
}
|
}
|
||||||
|
|||||||
+72
-108
@@ -23,7 +23,6 @@
|
|||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -63,14 +62,17 @@
|
|||||||
* If the device could not be replaced, then the second online attempt will
|
* If the device could not be replaced, then the second online attempt will
|
||||||
* trigger the FMA fault that we skipped earlier.
|
* trigger the FMA fault that we skipped earlier.
|
||||||
*
|
*
|
||||||
* On Linux udev provides a disk insert for both the disk and the partition.
|
* ZFS on Linux porting notes:
|
||||||
|
* In lieu of a thread pool, just spawn a thread on demmand.
|
||||||
|
* Linux udev provides a disk insert for both the disk and the partition
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <devid.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <libnvpair.h>
|
#include <libnvpair.h>
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
#include <libzutil.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -80,10 +82,8 @@
|
|||||||
#include <sys/sunddi.h>
|
#include <sys/sunddi.h>
|
||||||
#include <sys/sysevent/eventdefs.h>
|
#include <sys/sysevent/eventdefs.h>
|
||||||
#include <sys/sysevent/dev.h>
|
#include <sys/sysevent/dev.h>
|
||||||
#include <thread_pool.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include "zfs_agents.h"
|
#include "zfs_agents.h"
|
||||||
#include "../zed_log.h"
|
#include "../zed_log.h"
|
||||||
|
|
||||||
@@ -96,12 +96,12 @@ typedef void (*zfs_process_func_t)(zpool_handle_t *, nvlist_t *, boolean_t);
|
|||||||
libzfs_handle_t *g_zfshdl;
|
libzfs_handle_t *g_zfshdl;
|
||||||
list_t g_pool_list; /* list of unavailable pools at initialization */
|
list_t g_pool_list; /* list of unavailable pools at initialization */
|
||||||
list_t g_device_list; /* list of disks with asynchronous label request */
|
list_t g_device_list; /* list of disks with asynchronous label request */
|
||||||
tpool_t *g_tpool;
|
|
||||||
boolean_t g_enumeration_done;
|
boolean_t g_enumeration_done;
|
||||||
pthread_t g_zfs_tid; /* zfs_enum_pools() thread */
|
pthread_t g_zfs_tid;
|
||||||
|
|
||||||
typedef struct unavailpool {
|
typedef struct unavailpool {
|
||||||
zpool_handle_t *uap_zhp;
|
zpool_handle_t *uap_zhp;
|
||||||
|
pthread_t uap_enable_tid; /* dataset enable thread if activated */
|
||||||
list_node_t uap_node;
|
list_node_t uap_node;
|
||||||
} unavailpool_t;
|
} unavailpool_t;
|
||||||
|
|
||||||
@@ -134,6 +134,7 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
|
|||||||
unavailpool_t *uap;
|
unavailpool_t *uap;
|
||||||
uap = malloc(sizeof (unavailpool_t));
|
uap = malloc(sizeof (unavailpool_t));
|
||||||
uap->uap_zhp = zhp;
|
uap->uap_zhp = zhp;
|
||||||
|
uap->uap_enable_tid = 0;
|
||||||
list_insert_tail((list_t *)data, uap);
|
list_insert_tail((list_t *)data, uap);
|
||||||
} else {
|
} else {
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
@@ -154,7 +155,7 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
|
|||||||
* 1. physical match with no fs, no partition
|
* 1. physical match with no fs, no partition
|
||||||
* tag it top, partition disk
|
* tag it top, partition disk
|
||||||
*
|
*
|
||||||
* 2. physical match again, see partition and tag
|
* 2. physical match again, see partion and tag
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -189,8 +190,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
char rawpath[PATH_MAX], fullpath[PATH_MAX];
|
char rawpath[PATH_MAX], fullpath[PATH_MAX];
|
||||||
char devpath[PATH_MAX];
|
char devpath[PATH_MAX];
|
||||||
int ret;
|
int ret;
|
||||||
boolean_t is_dm = B_FALSE;
|
int is_dm = 0;
|
||||||
boolean_t is_sd = B_FALSE;
|
int is_sd = 0;
|
||||||
uint_t c;
|
uint_t c;
|
||||||
vdev_stat_t *vs;
|
vdev_stat_t *vs;
|
||||||
|
|
||||||
@@ -218,8 +219,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
|
|
||||||
is_dm = zfs_dev_is_dm(path);
|
is_dm = zfs_dev_is_dm(path);
|
||||||
zed_log_msg(LOG_INFO, "zfs_process_add: pool '%s' vdev '%s', phys '%s'"
|
zed_log_msg(LOG_INFO, "zfs_process_add: pool '%s' vdev '%s', phys '%s'"
|
||||||
" wholedisk %d, %s dm (guid %llu)", zpool_get_name(zhp), path,
|
" wholedisk %d, dm %d (%llu)", zpool_get_name(zhp), path,
|
||||||
physpath ? physpath : "NULL", wholedisk, is_dm ? "is" : "not",
|
physpath ? physpath : "NULL", wholedisk, is_dm,
|
||||||
(long long unsigned int)guid);
|
(long long unsigned int)guid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -264,7 +265,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
* testing)
|
* testing)
|
||||||
*/
|
*/
|
||||||
if (physpath != NULL && strcmp("scsidebug", physpath) == 0)
|
if (physpath != NULL && strcmp("scsidebug", physpath) == 0)
|
||||||
is_sd = B_TRUE;
|
is_sd = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the pool doesn't have the autoreplace property set, then use
|
* If the pool doesn't have the autoreplace property set, then use
|
||||||
@@ -425,17 +426,9 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
|||||||
nvlist_free(newvd);
|
nvlist_free(newvd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for udev to verify the links exist, then auto-replace
|
* auto replace a leaf disk at same physical location
|
||||||
* the leaf disk at same physical location.
|
|
||||||
*/
|
*/
|
||||||
if (zpool_label_disk_wait(path, 3000) != 0) {
|
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE);
|
||||||
zed_log_msg(LOG_WARNING, "zfs_mod: expected replacement "
|
|
||||||
"disk %s is missing", path);
|
|
||||||
nvlist_free(nvroot);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE, B_FALSE);
|
|
||||||
|
|
||||||
zed_log_msg(LOG_INFO, " zpool_vdev_replace: %s with %s (%s)",
|
zed_log_msg(LOG_INFO, " zpool_vdev_replace: %s with %s (%s)",
|
||||||
fullpath, path, (ret == 0) ? "no errors" :
|
fullpath, path, (ret == 0) ? "no errors" :
|
||||||
@@ -473,20 +466,7 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
|||||||
&child, &children) == 0) {
|
&child, &children) == 0) {
|
||||||
for (c = 0; c < children; c++)
|
for (c = 0; c < children; c++)
|
||||||
zfs_iter_vdev(zhp, child[c], data);
|
zfs_iter_vdev(zhp, child[c], data);
|
||||||
}
|
return;
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterate over any spares and cache devices
|
|
||||||
*/
|
|
||||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_SPARES,
|
|
||||||
&child, &children) == 0) {
|
|
||||||
for (c = 0; c < children; c++)
|
|
||||||
zfs_iter_vdev(zhp, child[c], data);
|
|
||||||
}
|
|
||||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_L2CACHE,
|
|
||||||
&child, &children) == 0) {
|
|
||||||
for (c = 0; c < children; c++)
|
|
||||||
zfs_iter_vdev(zhp, child[c], 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 */
|
||||||
@@ -531,14 +511,19 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
|||||||
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
|
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void *
|
||||||
zfs_enable_ds(void *arg)
|
zfs_enable_ds(void *arg)
|
||||||
{
|
{
|
||||||
unavailpool_t *pool = (unavailpool_t *)arg;
|
unavailpool_t *pool = (unavailpool_t *)arg;
|
||||||
|
|
||||||
|
assert(pool->uap_enable_tid = pthread_self());
|
||||||
|
|
||||||
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0);
|
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0);
|
||||||
zpool_close(pool->uap_zhp);
|
zpool_close(pool->uap_zhp);
|
||||||
free(pool);
|
pool->uap_zhp = NULL;
|
||||||
|
|
||||||
|
/* Note: zfs_slm_fini() will cleanup this pool entry on exit */
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -573,13 +558,15 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
|
|||||||
for (pool = list_head(&g_pool_list); pool != NULL;
|
for (pool = list_head(&g_pool_list); pool != NULL;
|
||||||
pool = list_next(&g_pool_list, pool)) {
|
pool = list_next(&g_pool_list, pool)) {
|
||||||
|
|
||||||
|
if (pool->uap_enable_tid != 0)
|
||||||
|
continue; /* entry already processed */
|
||||||
if (strcmp(zpool_get_name(zhp),
|
if (strcmp(zpool_get_name(zhp),
|
||||||
zpool_get_name(pool->uap_zhp)))
|
zpool_get_name(pool->uap_zhp)))
|
||||||
continue;
|
continue;
|
||||||
if (zfs_toplevel_state(zhp) >= VDEV_STATE_DEGRADED) {
|
if (zfs_toplevel_state(zhp) >= VDEV_STATE_DEGRADED) {
|
||||||
list_remove(&g_pool_list, pool);
|
/* send to a background thread; keep on list */
|
||||||
(void) tpool_dispatch(g_tpool, zfs_enable_ds,
|
(void) pthread_create(&pool->uap_enable_tid,
|
||||||
pool);
|
NULL, zfs_enable_ds, pool);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -671,7 +658,7 @@ zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
|
|||||||
devid, devpath ? devpath : "NULL", is_slice);
|
devid, devpath ? devpath : "NULL", is_slice);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over all vdevs looking for a match in the following order:
|
* Iterate over all vdevs looking for a match in the folllowing order:
|
||||||
* 1. ZPOOL_CONFIG_DEVID (identifies the unique disk)
|
* 1. ZPOOL_CONFIG_DEVID (identifies the unique disk)
|
||||||
* 2. ZPOOL_CONFIG_PHYS_PATH (identifies disk physical location).
|
* 2. ZPOOL_CONFIG_PHYS_PATH (identifies disk physical location).
|
||||||
*
|
*
|
||||||
@@ -716,8 +703,8 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
|||||||
{
|
{
|
||||||
char *devname = data;
|
char *devname = data;
|
||||||
boolean_t avail_spare, l2cache;
|
boolean_t avail_spare, l2cache;
|
||||||
|
vdev_state_t newstate;
|
||||||
nvlist_t *tgt;
|
nvlist_t *tgt;
|
||||||
int error;
|
|
||||||
|
|
||||||
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));
|
||||||
@@ -725,58 +712,40 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
|||||||
if ((tgt = zpool_find_vdev_by_physpath(zhp, devname,
|
if ((tgt = zpool_find_vdev_by_physpath(zhp, devname,
|
||||||
&avail_spare, &l2cache, NULL)) != NULL) {
|
&avail_spare, &l2cache, NULL)) != NULL) {
|
||||||
char *path, fullpath[MAXPATHLEN];
|
char *path, fullpath[MAXPATHLEN];
|
||||||
uint64_t wholedisk;
|
uint64_t wholedisk = 0ULL;
|
||||||
|
|
||||||
error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path);
|
verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH,
|
||||||
if (error) {
|
&path) == 0);
|
||||||
zpool_close(zhp);
|
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
|
||||||
return (0);
|
&wholedisk) == 0);
|
||||||
}
|
|
||||||
|
|
||||||
error = nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
|
|
||||||
&wholedisk);
|
|
||||||
if (error)
|
|
||||||
wholedisk = 0;
|
|
||||||
|
|
||||||
|
(void) strlcpy(fullpath, path, sizeof (fullpath));
|
||||||
if (wholedisk) {
|
if (wholedisk) {
|
||||||
path = strrchr(path, '/');
|
char *spath = zfs_strip_partition(fullpath);
|
||||||
if (path != NULL) {
|
if (!spath) {
|
||||||
path = zfs_strip_partition(path + 1);
|
zed_log_msg(LOG_INFO, "%s: Can't alloc",
|
||||||
if (path == NULL) {
|
__func__);
|
||||||
zpool_close(zhp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
zpool_close(zhp);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) strlcpy(fullpath, path, sizeof (fullpath));
|
(void) strlcpy(fullpath, spath, sizeof (fullpath));
|
||||||
free(path);
|
free(spath);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to reopen the pool associated with this
|
* We need to reopen the pool associated with this
|
||||||
* device so that the kernel can update the size of
|
* device so that the kernel can update the size
|
||||||
* the expanded device. When expanding there is no
|
* of the expanded device.
|
||||||
* need to restart the scrub from the beginning.
|
|
||||||
*/
|
*/
|
||||||
boolean_t scrub_restart = B_FALSE;
|
(void) zpool_reopen(zhp);
|
||||||
(void) zpool_reopen_one(zhp, &scrub_restart);
|
|
||||||
} else {
|
|
||||||
(void) strlcpy(fullpath, path, sizeof (fullpath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) {
|
if (zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) {
|
||||||
vdev_state_t newstate;
|
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: setting "
|
||||||
|
"device '%s' to ONLINE state in pool '%s'",
|
||||||
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
|
fullpath, zpool_get_name(zhp));
|
||||||
error = zpool_vdev_online(zhp, fullpath, 0,
|
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL)
|
||||||
|
(void) zpool_vdev_online(zhp, fullpath, 0,
|
||||||
&newstate);
|
&newstate);
|
||||||
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: "
|
|
||||||
"setting device '%s' to ONLINE state "
|
|
||||||
"in pool '%s': %d", fullpath,
|
|
||||||
zpool_get_name(zhp), error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
return (1);
|
return (1);
|
||||||
@@ -786,32 +755,23 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function handles the ESC_DEV_DLE device change event. Use the
|
* This function handles the ESC_DEV_DLE event.
|
||||||
* provided vdev guid when looking up a disk or partition, when the guid
|
|
||||||
* is not present assume the entire disk is owned by ZFS and append the
|
|
||||||
* expected -part1 partition information then lookup by physical path.
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
zfs_deliver_dle(nvlist_t *nvl)
|
zfs_deliver_dle(nvlist_t *nvl)
|
||||||
{
|
{
|
||||||
char *devname, name[MAXPATHLEN];
|
char *devname;
|
||||||
uint64_t guid;
|
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
|
if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devname) != 0) {
|
||||||
sprintf(name, "%llu", (u_longlong_t)guid);
|
zed_log_msg(LOG_INFO, "zfs_deliver_dle: no physpath");
|
||||||
} else if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devname) == 0) {
|
return (-1);
|
||||||
strlcpy(name, devname, MAXPATHLEN);
|
|
||||||
zfs_append_partition(name, MAXPATHLEN);
|
|
||||||
} else {
|
|
||||||
zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zpool_iter(g_zfshdl, zfsdle_vdev_online, name) != 1) {
|
if (zpool_iter(g_zfshdl, zfsdle_vdev_online, devname) != 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", devname);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -889,12 +849,12 @@ zfs_enum_pools(void *arg)
|
|||||||
*
|
*
|
||||||
* sent messages from zevents or udev monitor
|
* sent messages from zevents or udev monitor
|
||||||
*
|
*
|
||||||
* For now, each agent has its own libzfs instance
|
* For now, each agent has it's own libzfs instance
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
zfs_slm_init()
|
zfs_slm_init()
|
||||||
{
|
{
|
||||||
if ((g_zfshdl = libzfs_init()) == NULL)
|
if ((g_zfshdl = __libzfs_init()) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -906,7 +866,7 @@ zfs_slm_init()
|
|||||||
|
|
||||||
if (pthread_create(&g_zfs_tid, NULL, zfs_enum_pools, NULL) != 0) {
|
if (pthread_create(&g_zfs_tid, NULL, zfs_enum_pools, NULL) != 0) {
|
||||||
list_destroy(&g_pool_list);
|
list_destroy(&g_pool_list);
|
||||||
libzfs_fini(g_zfshdl);
|
__libzfs_fini(g_zfshdl);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -924,15 +884,19 @@ zfs_slm_fini()
|
|||||||
|
|
||||||
/* wait for zfs_enum_pools thread to complete */
|
/* wait for zfs_enum_pools thread to complete */
|
||||||
(void) pthread_join(g_zfs_tid, NULL);
|
(void) pthread_join(g_zfs_tid, NULL);
|
||||||
/* destroy the thread pool */
|
|
||||||
if (g_tpool != NULL) {
|
|
||||||
tpool_wait(g_tpool);
|
|
||||||
tpool_destroy(g_tpool);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((pool = (list_head(&g_pool_list))) != NULL) {
|
while ((pool = (list_head(&g_pool_list))) != NULL) {
|
||||||
|
/*
|
||||||
|
* each pool entry has two possibilities
|
||||||
|
* 1. was made available (so wait for zfs_enable_ds thread)
|
||||||
|
* 2. still unavailable (just close the pool)
|
||||||
|
*/
|
||||||
|
if (pool->uap_enable_tid)
|
||||||
|
(void) pthread_join(pool->uap_enable_tid, NULL);
|
||||||
|
else if (pool->uap_zhp != NULL)
|
||||||
|
zpool_close(pool->uap_zhp);
|
||||||
|
|
||||||
list_remove(&g_pool_list, pool);
|
list_remove(&g_pool_list, pool);
|
||||||
zpool_close(pool->uap_zhp);
|
|
||||||
free(pool);
|
free(pool);
|
||||||
}
|
}
|
||||||
list_destroy(&g_pool_list);
|
list_destroy(&g_pool_list);
|
||||||
@@ -943,7 +907,7 @@ zfs_slm_fini()
|
|||||||
}
|
}
|
||||||
list_destroy(&g_device_list);
|
list_destroy(&g_device_list);
|
||||||
|
|
||||||
libzfs_fini(g_zfshdl);
|
__libzfs_fini(g_zfshdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
+158
-73
@@ -22,7 +22,6 @@
|
|||||||
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016, Intel Corporation.
|
* Copyright (c) 2016, Intel Corporation.
|
||||||
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -72,6 +71,7 @@ zfs_retire_clear_data(fmd_hdl_t *hdl, zfs_retire_data_t *zdp)
|
|||||||
*/
|
*/
|
||||||
typedef struct find_cbdata {
|
typedef struct find_cbdata {
|
||||||
uint64_t cb_guid;
|
uint64_t cb_guid;
|
||||||
|
const char *cb_fru;
|
||||||
zpool_handle_t *cb_zhp;
|
zpool_handle_t *cb_zhp;
|
||||||
nvlist_t *cb_vdev;
|
nvlist_t *cb_vdev;
|
||||||
} find_cbdata_t;
|
} find_cbdata_t;
|
||||||
@@ -95,18 +95,26 @@ find_pool(zpool_handle_t *zhp, void *data)
|
|||||||
* Find a vdev within a tree with a matching GUID.
|
* Find a vdev within a tree with a matching GUID.
|
||||||
*/
|
*/
|
||||||
static nvlist_t *
|
static nvlist_t *
|
||||||
find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, const char *search_fru,
|
||||||
|
uint64_t search_guid)
|
||||||
{
|
{
|
||||||
uint64_t guid;
|
uint64_t guid;
|
||||||
nvlist_t **child;
|
nvlist_t **child;
|
||||||
uint_t c, children;
|
uint_t c, children;
|
||||||
nvlist_t *ret;
|
nvlist_t *ret;
|
||||||
|
char *fru;
|
||||||
|
|
||||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
|
if (search_fru != NULL) {
|
||||||
guid == search_guid) {
|
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_FRU, &fru) == 0 &&
|
||||||
fmd_hdl_debug(fmd_module_hdl("zfs-retire"),
|
libzfs_fru_compare(zhdl, fru, search_fru))
|
||||||
"matched vdev %llu", guid);
|
return (nv);
|
||||||
return (nv);
|
} else {
|
||||||
|
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
|
||||||
|
guid == search_guid) {
|
||||||
|
fmd_hdl_debug(fmd_module_hdl("zfs-retire"),
|
||||||
|
"matched vdev %llu", guid);
|
||||||
|
return (nv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||||
@@ -114,7 +122,8 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++) {
|
||||||
if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL)
|
if ((ret = find_vdev(zhdl, child[c], search_fru,
|
||||||
|
search_guid)) != NULL)
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,16 +132,8 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++) {
|
||||||
if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL)
|
if ((ret = find_vdev(zhdl, child[c], search_fru,
|
||||||
return (ret);
|
search_guid)) != NULL)
|
||||||
}
|
|
||||||
|
|
||||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
|
|
||||||
&child, &children) != 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
for (c = 0; c < children; c++) {
|
|
||||||
if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL)
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +167,8 @@ find_by_guid(libzfs_handle_t *zhdl, uint64_t pool_guid, uint64_t vdev_guid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vdev_guid != 0) {
|
if (vdev_guid != 0) {
|
||||||
if ((*vdevp = find_vdev(zhdl, nvroot, vdev_guid)) == NULL) {
|
if ((*vdevp = find_vdev(zhdl, nvroot, NULL,
|
||||||
|
vdev_guid)) == NULL) {
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@@ -175,37 +177,72 @@ find_by_guid(libzfs_handle_t *zhdl, uint64_t pool_guid, uint64_t vdev_guid,
|
|||||||
return (zhp);
|
return (zhp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTOPO
|
||||||
|
static int
|
||||||
|
search_pool(zpool_handle_t *zhp, void *data)
|
||||||
|
{
|
||||||
|
find_cbdata_t *cbp = data;
|
||||||
|
nvlist_t *config;
|
||||||
|
nvlist_t *nvroot;
|
||||||
|
|
||||||
|
config = zpool_get_config(zhp, NULL);
|
||||||
|
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||||
|
&nvroot) != 0) {
|
||||||
|
zpool_close(zhp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cbp->cb_vdev = find_vdev(zpool_get_handle(zhp), nvroot,
|
||||||
|
cbp->cb_fru, 0)) != NULL) {
|
||||||
|
cbp->cb_zhp = zhp;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
zpool_close(zhp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a FRU FMRI, find the matching pool and vdev.
|
||||||
|
*/
|
||||||
|
static zpool_handle_t *
|
||||||
|
find_by_fru(libzfs_handle_t *zhdl, const char *fru, nvlist_t **vdevp)
|
||||||
|
{
|
||||||
|
find_cbdata_t cb;
|
||||||
|
|
||||||
|
cb.cb_fru = fru;
|
||||||
|
cb.cb_zhp = NULL;
|
||||||
|
if (zpool_iter(zhdl, search_pool, &cb) != 1)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
*vdevp = cb.cb_vdev;
|
||||||
|
return (cb.cb_zhp);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LIBTOPO */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a vdev, attempt to replace it with every known spare until one
|
* Given a vdev, attempt to replace it with every known spare until one
|
||||||
* succeeds or we run out of devices to try.
|
* succeeds.
|
||||||
* Return whether we were successful or not in replacing the device.
|
|
||||||
*/
|
*/
|
||||||
static boolean_t
|
static void
|
||||||
replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
||||||
{
|
{
|
||||||
nvlist_t *config, *nvroot, *replacement;
|
nvlist_t *config, *nvroot, *replacement;
|
||||||
nvlist_t **spares;
|
nvlist_t **spares;
|
||||||
uint_t s, nspares;
|
uint_t s, nspares;
|
||||||
char *dev_name;
|
char *dev_name;
|
||||||
zprop_source_t source;
|
|
||||||
int ashift;
|
|
||||||
|
|
||||||
config = zpool_get_config(zhp, NULL);
|
config = zpool_get_config(zhp, NULL);
|
||||||
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||||
&nvroot) != 0)
|
&nvroot) != 0)
|
||||||
return (B_FALSE);
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find out if there are any hot spares available in the pool.
|
* Find out if there are any hot spares available in the pool.
|
||||||
*/
|
*/
|
||||||
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
||||||
&spares, &nspares) != 0)
|
&spares, &nspares) != 0)
|
||||||
return (B_FALSE);
|
return;
|
||||||
|
|
||||||
/*
|
|
||||||
* lookup "ashift" pool property, we may need it for the replacement
|
|
||||||
*/
|
|
||||||
ashift = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &source);
|
|
||||||
|
|
||||||
replacement = fmd_nvl_alloc(hdl, FMD_SLEEP);
|
replacement = fmd_nvl_alloc(hdl, FMD_SLEEP);
|
||||||
|
|
||||||
@@ -225,11 +262,6 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
|||||||
&spare_name) != 0)
|
&spare_name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* if set, add the "ashift" pool property to the spare nvlist */
|
|
||||||
if (source != ZPROP_SRC_DEFAULT)
|
|
||||||
(void) nvlist_add_uint64(spares[s],
|
|
||||||
ZPOOL_CONFIG_ASHIFT, ashift);
|
|
||||||
|
|
||||||
(void) nvlist_add_nvlist_array(replacement,
|
(void) nvlist_add_nvlist_array(replacement,
|
||||||
ZPOOL_CONFIG_CHILDREN, &spares[s], 1);
|
ZPOOL_CONFIG_CHILDREN, &spares[s], 1);
|
||||||
|
|
||||||
@@ -237,17 +269,12 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
|||||||
dev_name, basename(spare_name));
|
dev_name, basename(spare_name));
|
||||||
|
|
||||||
if (zpool_vdev_attach(zhp, dev_name, spare_name,
|
if (zpool_vdev_attach(zhp, dev_name, spare_name,
|
||||||
replacement, B_TRUE, B_FALSE) == 0) {
|
replacement, B_TRUE) == 0)
|
||||||
free(dev_name);
|
break;
|
||||||
nvlist_free(replacement);
|
|
||||||
return (B_TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(dev_name);
|
free(dev_name);
|
||||||
nvlist_free(replacement);
|
nvlist_free(replacement);
|
||||||
|
|
||||||
return (B_FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -262,6 +289,10 @@ zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl)
|
|||||||
zfs_retire_data_t *zdp = fmd_hdl_getspecific(hdl);
|
zfs_retire_data_t *zdp = fmd_hdl_getspecific(hdl);
|
||||||
zfs_retire_repaired_t *zrp;
|
zfs_retire_repaired_t *zrp;
|
||||||
uint64_t pool_guid, vdev_guid;
|
uint64_t pool_guid, vdev_guid;
|
||||||
|
#ifdef HAVE_LIBTOPO
|
||||||
|
nvlist_t *asru;
|
||||||
|
#endif
|
||||||
|
|
||||||
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 || nvlist_lookup_uint64(nvl,
|
&pool_guid) != 0 || nvlist_lookup_uint64(nvl,
|
||||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
||||||
@@ -284,6 +315,47 @@ zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBTOPO
|
||||||
|
asru = fmd_nvl_alloc(hdl, FMD_SLEEP);
|
||||||
|
|
||||||
|
(void) nvlist_add_uint8(asru, FM_VERSION, ZFS_SCHEME_VERSION0);
|
||||||
|
(void) nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_ZFS);
|
||||||
|
(void) nvlist_add_uint64(asru, FM_FMRI_ZFS_POOL, pool_guid);
|
||||||
|
(void) nvlist_add_uint64(asru, FM_FMRI_ZFS_VDEV, vdev_guid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We explicitly check for the unusable state here to make sure we
|
||||||
|
* aren't responding to a transient state change. As part of opening a
|
||||||
|
* vdev, it's possible to see the 'statechange' event, only to be
|
||||||
|
* followed by a vdev failure later. If we don't check the current
|
||||||
|
* state of the vdev (or pool) before marking it repaired, then we risk
|
||||||
|
* generating spurious repair events followed immediately by the same
|
||||||
|
* diagnosis.
|
||||||
|
*
|
||||||
|
* This assumes that the ZFS scheme code associated unusable (i.e.
|
||||||
|
* isolated) with its own definition of faulty state. In the case of a
|
||||||
|
* DEGRADED leaf vdev (due to checksum errors), this is not the case.
|
||||||
|
* This works, however, because the transient state change is not
|
||||||
|
* posted in this case. This could be made more explicit by not
|
||||||
|
* relying on the scheme's unusable callback and instead directly
|
||||||
|
* checking the vdev state, where we could correctly account for
|
||||||
|
* DEGRADED state.
|
||||||
|
*/
|
||||||
|
if (!fmd_nvl_fmri_unusable(hdl, asru) && fmd_nvl_fmri_has_fault(hdl,
|
||||||
|
asru, FMD_HAS_FAULT_ASRU, NULL)) {
|
||||||
|
topo_hdl_t *thp;
|
||||||
|
char *fmri = NULL;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
|
||||||
|
if (topo_fmri_nvl2str(thp, asru, &fmri, &err) == 0)
|
||||||
|
(void) fmd_repair_asru(hdl, fmri);
|
||||||
|
fmd_hdl_topo_rele(hdl, thp);
|
||||||
|
|
||||||
|
topo_hdl_strfree(thp, fmri);
|
||||||
|
}
|
||||||
|
nvlist_free(asru);
|
||||||
|
#endif
|
||||||
zrp = fmd_hdl_alloc(hdl, sizeof (zfs_retire_repaired_t), FMD_SLEEP);
|
zrp = fmd_hdl_alloc(hdl, sizeof (zfs_retire_repaired_t), FMD_SLEEP);
|
||||||
zrp->zrr_next = zdp->zrd_repaired;
|
zrp->zrr_next = zdp->zrd_repaired;
|
||||||
zrp->zrr_pool = pool_guid;
|
zrp->zrr_pool = pool_guid;
|
||||||
@@ -319,19 +391,11 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
|
|
||||||
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
|
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
|
||||||
|
|
||||||
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_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
|
||||||
* check for an available spare and continue unless the device is a
|
* check for an available spare and continue.
|
||||||
* l2arc vdev, in which case we just offline it.
|
|
||||||
*/
|
*/
|
||||||
if (strcmp(class, "resource.fs.zfs.removed") == 0 ||
|
if (strcmp(class, "resource.fs.zfs.removed") == 0) {
|
||||||
(strcmp(class, "resource.fs.zfs.statechange") == 0 &&
|
|
||||||
state == VDEV_STATE_REMOVED)) {
|
|
||||||
char *devtype;
|
|
||||||
char *devname;
|
|
||||||
|
|
||||||
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,
|
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID,
|
||||||
@@ -342,20 +406,8 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
&vdev)) == NULL)
|
&vdev)) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE);
|
if (fmd_prop_get_int32(hdl, "spare_on_remove"))
|
||||||
|
replace_with_spare(hdl, zhp, vdev);
|
||||||
/* Can't replace l2arc with a spare: offline the device */
|
|
||||||
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);
|
|
||||||
zpool_vdev_offline(zhp, devname, B_TRUE);
|
|
||||||
} else if (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
|
|
||||||
replace_with_spare(hdl, zhp, vdev) == B_FALSE) {
|
|
||||||
/* Could not handle with spare */
|
|
||||||
fmd_hdl_debug(hdl, "no spare for '%s'", devname);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(devname);
|
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -364,11 +416,12 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: on Linux statechange events are more than just
|
* Note: on zfsonlinux statechange events are more than just
|
||||||
* healthy ones so we need to confirm the actual state value.
|
* healthy ones so we need to confirm the actual state value.
|
||||||
*/
|
*/
|
||||||
if (strcmp(class, "resource.fs.zfs.statechange") == 0 &&
|
if (strcmp(class, "resource.fs.zfs.statechange") == 0 &&
|
||||||
state == VDEV_STATE_HEALTHY) {
|
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE,
|
||||||
|
&state) == 0 && state == VDEV_STATE_HEALTHY) {
|
||||||
zfs_vdev_repair(hdl, nvl);
|
zfs_vdev_repair(hdl, nvl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -424,7 +477,39 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_disk) {
|
if (is_disk) {
|
||||||
|
#ifdef HAVE_LIBTOPO
|
||||||
|
/*
|
||||||
|
* This is a disk fault. Lookup the FRU, convert it to
|
||||||
|
* an FMRI string, and attempt to find a matching vdev.
|
||||||
|
*/
|
||||||
|
if (nvlist_lookup_nvlist(fault, FM_FAULT_FRU,
|
||||||
|
&fru) != 0 ||
|
||||||
|
nvlist_lookup_string(fru, FM_FMRI_SCHEME,
|
||||||
|
&scheme) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(scheme, FM_FMRI_SCHEME_HC) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
|
||||||
|
if (topo_fmri_nvl2str(thp, fru, &fmri, &err) != 0) {
|
||||||
|
fmd_hdl_topo_rele(hdl, thp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
zhp = find_by_fru(zhdl, fmri, &vdev);
|
||||||
|
topo_hdl_strfree(thp, fmri);
|
||||||
|
fmd_hdl_topo_rele(hdl, thp);
|
||||||
|
|
||||||
|
if (zhp == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
(void) nvlist_lookup_uint64(vdev,
|
||||||
|
ZPOOL_CONFIG_GUID, &vdev_guid);
|
||||||
|
aux = VDEV_AUX_EXTERNAL;
|
||||||
|
#else
|
||||||
continue;
|
continue;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* This is a ZFS fault. Lookup the resource, and
|
* This is a ZFS fault. Lookup the resource, and
|
||||||
@@ -498,7 +583,7 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
|||||||
/*
|
/*
|
||||||
* Attempt to substitute a hot spare.
|
* Attempt to substitute a hot spare.
|
||||||
*/
|
*/
|
||||||
(void) replace_with_spare(hdl, zhp, vdev);
|
replace_with_spare(hdl, zhp, vdev);
|
||||||
zpool_close(zhp);
|
zpool_close(zhp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +615,7 @@ _zfs_retire_init(fmd_hdl_t *hdl)
|
|||||||
zfs_retire_data_t *zdp;
|
zfs_retire_data_t *zdp;
|
||||||
libzfs_handle_t *zhdl;
|
libzfs_handle_t *zhdl;
|
||||||
|
|
||||||
if ((zhdl = libzfs_init()) == NULL)
|
if ((zhdl = __libzfs_init()) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) {
|
if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) {
|
||||||
@@ -551,7 +636,7 @@ _zfs_retire_fini(fmd_hdl_t *hdl)
|
|||||||
|
|
||||||
if (zdp != NULL) {
|
if (zdp != NULL) {
|
||||||
zfs_retire_clear_data(hdl, zdp);
|
zfs_retire_clear_data(hdl, zdp);
|
||||||
libzfs_fini(zdp->zrd_hdl);
|
__libzfs_fini(zdp->zrd_hdl);
|
||||||
fmd_hdl_free(hdl, zdp, sizeof (zfs_retire_data_t));
|
fmd_hdl_free(hdl, zdp, sizeof (zfs_retire_data_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-29
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -263,43 +263,18 @@ main(int argc, char *argv[])
|
|||||||
if (zed_conf_read_state(zcp, &saved_eid, saved_etime) < 0)
|
if (zed_conf_read_state(zcp, &saved_eid, saved_etime) < 0)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
idle:
|
zed_event_init(zcp);
|
||||||
/*
|
|
||||||
* If -I is specified, attempt to open /dev/zfs repeatedly until
|
|
||||||
* successful.
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
if (!zed_event_init(zcp))
|
|
||||||
break;
|
|
||||||
/* Wait for some time and try again. tunable? */
|
|
||||||
sleep(30);
|
|
||||||
} while (!_got_exit && zcp->do_idle);
|
|
||||||
|
|
||||||
if (_got_exit)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
zed_event_seek(zcp, saved_eid, saved_etime);
|
zed_event_seek(zcp, saved_eid, saved_etime);
|
||||||
|
|
||||||
while (!_got_exit) {
|
while (!_got_exit) {
|
||||||
int rv;
|
|
||||||
if (_got_hup) {
|
if (_got_hup) {
|
||||||
_got_hup = 0;
|
_got_hup = 0;
|
||||||
(void) zed_conf_scan_dir(zcp);
|
(void) zed_conf_scan_dir(zcp);
|
||||||
}
|
}
|
||||||
rv = zed_event_service(zcp);
|
zed_event_service(zcp);
|
||||||
|
|
||||||
/* ENODEV: When kernel module is unloaded (osx) */
|
|
||||||
if (rv == ENODEV)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zed_log_msg(LOG_NOTICE, "Exiting");
|
zed_log_msg(LOG_NOTICE, "Exiting");
|
||||||
zed_event_fini(zcp);
|
zed_event_fini(zcp);
|
||||||
|
|
||||||
if (zcp->do_idle && !_got_exit)
|
|
||||||
goto idle;
|
|
||||||
|
|
||||||
out:
|
|
||||||
zed_conf_destroy(zcp);
|
zed_conf_destroy(zcp);
|
||||||
zed_log_fini();
|
zed_log_fini();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
history_event-zfs-list-cacher.sh
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
|
||||||
include $(top_srcdir)/config/Substfiles.am
|
|
||||||
|
|
||||||
EXTRA_DIST += README
|
|
||||||
|
|
||||||
zedconfdir = $(sysconfdir)/zfs/zed.d
|
|
||||||
|
|
||||||
dist_zedconf_DATA = \
|
|
||||||
zed-functions.sh \
|
|
||||||
zed.rc
|
|
||||||
|
|
||||||
zedexecdir = $(zfsexecdir)/zed.d
|
|
||||||
|
|
||||||
dist_zedexec_SCRIPTS = \
|
|
||||||
all-debug.sh \
|
|
||||||
all-syslog.sh \
|
|
||||||
data-notify.sh \
|
|
||||||
generic-notify.sh \
|
|
||||||
resilver_finish-notify.sh \
|
|
||||||
scrub_finish-notify.sh \
|
|
||||||
statechange-led.sh \
|
|
||||||
statechange-notify.sh \
|
|
||||||
vdev_clear-led.sh \
|
|
||||||
vdev_attach-led.sh \
|
|
||||||
pool_import-led.sh \
|
|
||||||
resilver_finish-start-scrub.sh \
|
|
||||||
trim_finish-notify.sh
|
|
||||||
|
|
||||||
nodist_zedexec_SCRIPTS = history_event-zfs-list-cacher.sh
|
|
||||||
|
|
||||||
SUBSTFILES += $(nodist_zedexec_SCRIPTS)
|
|
||||||
|
|
||||||
zedconfdefaults = \
|
|
||||||
all-syslog.sh \
|
|
||||||
data-notify.sh \
|
|
||||||
history_event-zfs-list-cacher.sh \
|
|
||||||
resilver_finish-notify.sh \
|
|
||||||
scrub_finish-notify.sh \
|
|
||||||
statechange-led.sh \
|
|
||||||
statechange-notify.sh \
|
|
||||||
vdev_clear-led.sh \
|
|
||||||
vdev_attach-led.sh \
|
|
||||||
pool_import-led.sh \
|
|
||||||
resilver_finish-start-scrub.sh
|
|
||||||
|
|
||||||
install-data-hook:
|
|
||||||
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
|
||||||
for f in $(zedconfdefaults); do \
|
|
||||||
test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \
|
|
||||||
-L "$(DESTDIR)$(zedconfdir)/$${f}" || \
|
|
||||||
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
|
||||||
done
|
|
||||||
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
|
|
||||||
@@ -1,50 +1,14 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
|
||||||
# Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
|
||||||
# Copyright (c) 2020 by Delphix. All rights reserved.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Log the zevent via syslog.
|
# Log the zevent via syslog.
|
||||||
#
|
|
||||||
|
|
||||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
||||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
||||||
|
|
||||||
zed_exit_if_ignoring_this_event
|
zed_exit_if_ignoring_this_event
|
||||||
|
|
||||||
# build a string of name=value pairs for this event
|
zed_log_msg "eid=${ZEVENT_EID}" "class=${ZEVENT_SUBCLASS}" \
|
||||||
msg="eid=${ZEVENT_EID} class=${ZEVENT_SUBCLASS}"
|
"${ZEVENT_POOL_GUID:+"pool_guid=${ZEVENT_POOL_GUID}"}" \
|
||||||
|
"${ZEVENT_VDEV_PATH:+"vdev_path=${ZEVENT_VDEV_PATH}"}" \
|
||||||
if [ "${ZED_SYSLOG_DISPLAY_GUIDS}" = "1" ]; then
|
"${ZEVENT_VDEV_STATE_STR:+"vdev_state=${ZEVENT_VDEV_STATE_STR}"}"
|
||||||
[ -n "${ZEVENT_POOL_GUID}" ] && msg="${msg} pool_guid=${ZEVENT_POOL_GUID}"
|
|
||||||
[ -n "${ZEVENT_VDEV_GUID}" ] && msg="${msg} vdev_guid=${ZEVENT_VDEV_GUID}"
|
|
||||||
else
|
|
||||||
[ -n "${ZEVENT_POOL}" ] && msg="${msg} pool='${ZEVENT_POOL}'"
|
|
||||||
[ -n "${ZEVENT_VDEV_PATH}" ] && msg="${msg} vdev=$(basename "${ZEVENT_VDEV_PATH}")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# log pool state if state is anything other than 'ACTIVE'
|
|
||||||
[ -n "${ZEVENT_POOL_STATE_STR}" ] && [ "$ZEVENT_POOL_STATE" -ne 0 ] && \
|
|
||||||
msg="${msg} pool_state=${ZEVENT_POOL_STATE_STR}"
|
|
||||||
|
|
||||||
# Log the following payload nvpairs if they are present
|
|
||||||
[ -n "${ZEVENT_VDEV_STATE_STR}" ] && msg="${msg} vdev_state=${ZEVENT_VDEV_STATE_STR}"
|
|
||||||
[ -n "${ZEVENT_CKSUM_ALGORITHM}" ] && msg="${msg} algorithm=${ZEVENT_CKSUM_ALGORITHM}"
|
|
||||||
[ -n "${ZEVENT_ZIO_SIZE}" ] && msg="${msg} size=${ZEVENT_ZIO_SIZE}"
|
|
||||||
[ -n "${ZEVENT_ZIO_OFFSET}" ] && msg="${msg} offset=${ZEVENT_ZIO_OFFSET}"
|
|
||||||
[ -n "${ZEVENT_ZIO_PRIORITY}" ] && msg="${msg} priority=${ZEVENT_ZIO_PRIORITY}"
|
|
||||||
[ -n "${ZEVENT_ZIO_ERR}" ] && msg="${msg} err=${ZEVENT_ZIO_ERR}"
|
|
||||||
[ -n "${ZEVENT_ZIO_FLAGS}" ] && msg="${msg} flags=$(printf '0x%x' "${ZEVENT_ZIO_FLAGS}")"
|
|
||||||
|
|
||||||
# log delays that are >= 10 milisec
|
|
||||||
[ -n "${ZEVENT_ZIO_DELAY}" ] && [ "$ZEVENT_ZIO_DELAY" -gt 10000000 ] && \
|
|
||||||
msg="${msg} delay=$((ZEVENT_ZIO_DELAY / 1000000))ms"
|
|
||||||
|
|
||||||
# list the bookmark data together
|
|
||||||
[ -n "${ZEVENT_ZIO_OBJSET}" ] && \
|
|
||||||
msg="${msg} bookmark=${ZEVENT_ZIO_OBJSET}:${ZEVENT_ZIO_OBJECT}:${ZEVENT_ZIO_LEVEL}:${ZEVENT_ZIO_BLKID}"
|
|
||||||
|
|
||||||
zed_log_msg "${msg}"
|
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# Track changes to enumerated pools for use in early-boot
|
|
||||||
set -ef
|
|
||||||
|
|
||||||
FSLIST_DIR="@sysconfdir@/zfs/zfs-list.cache"
|
|
||||||
FSLIST_TMP="@runstatedir@/zfs-list.cache.new"
|
|
||||||
FSLIST="${FSLIST_DIR}/${ZEVENT_POOL}"
|
|
||||||
|
|
||||||
# If the pool specific cache file is not writeable, abort
|
|
||||||
[ -w "${FSLIST}" ] || exit 0
|
|
||||||
|
|
||||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
|
||||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
|
||||||
|
|
||||||
[ "$ZEVENT_SUBCLASS" != "history_event" ] && exit 0
|
|
||||||
zed_check_cmd "${ZFS}" sort diff grep
|
|
||||||
|
|
||||||
# If we are acting on a snapshot, we have nothing to do
|
|
||||||
printf '%s' "${ZEVENT_HISTORY_DSNAME}" | grep '@' && exit 0
|
|
||||||
|
|
||||||
# We obtain a lock on zfs-list to avoid any simultaneous writes.
|
|
||||||
# If we run into trouble, log and drop the lock
|
|
||||||
abort_alter() {
|
|
||||||
zed_log_msg "Error updating zfs-list.cache!"
|
|
||||||
zed_unlock zfs-list
|
|
||||||
}
|
|
||||||
|
|
||||||
finished() {
|
|
||||||
zed_unlock zfs-list
|
|
||||||
trap - EXIT
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
case "${ZEVENT_HISTORY_INTERNAL_NAME}" in
|
|
||||||
create|"finish receiving"|import|destroy|rename)
|
|
||||||
;;
|
|
||||||
|
|
||||||
export)
|
|
||||||
zed_lock zfs-list
|
|
||||||
trap abort_alter EXIT
|
|
||||||
echo > "${FSLIST}"
|
|
||||||
finished
|
|
||||||
;;
|
|
||||||
|
|
||||||
set|inherit)
|
|
||||||
# Only act if one of the tracked properties is altered.
|
|
||||||
case "${ZEVENT_HISTORY_INTERNAL_STR%%=*}" in
|
|
||||||
canmount|mountpoint|atime|relatime|devices|exec|readonly| \
|
|
||||||
setuid|nbmand|encroot|keylocation|org.openzfs.systemd:requires| \
|
|
||||||
org.openzfs.systemd:requires-mounts-for| \
|
|
||||||
org.openzfs.systemd:before|org.openzfs.systemd:after| \
|
|
||||||
org.openzfs.systemd:wanted-by|org.openzfs.systemd:required-by| \
|
|
||||||
org.openzfs.systemd:nofail|org.openzfs.systemd:ignore \
|
|
||||||
) ;;
|
|
||||||
*) exit 0 ;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
# Ignore all other events.
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
zed_lock zfs-list
|
|
||||||
trap abort_alter EXIT
|
|
||||||
|
|
||||||
PROPS="name,mountpoint,canmount,atime,relatime,devices,exec\
|
|
||||||
,readonly,setuid,nbmand,encroot,keylocation\
|
|
||||||
,org.openzfs.systemd:requires,org.openzfs.systemd:requires-mounts-for\
|
|
||||||
,org.openzfs.systemd:before,org.openzfs.systemd:after\
|
|
||||||
,org.openzfs.systemd:wanted-by,org.openzfs.systemd:required-by\
|
|
||||||
,org.openzfs.systemd:nofail,org.openzfs.systemd:ignore"
|
|
||||||
|
|
||||||
"${ZFS}" list -H -t filesystem -o $PROPS -r "${ZEVENT_POOL}" > "${FSLIST_TMP}"
|
|
||||||
|
|
||||||
# Sort the output so that it is stable
|
|
||||||
sort "${FSLIST_TMP}" -o "${FSLIST_TMP}"
|
|
||||||
|
|
||||||
# Don't modify the file if it hasn't changed
|
|
||||||
diff -q "${FSLIST_TMP}" "${FSLIST}" || mv "${FSLIST_TMP}" "${FSLIST}"
|
|
||||||
rm -f "${FSLIST_TMP}"
|
|
||||||
|
|
||||||
finished
|
|
||||||
@@ -5,12 +5,10 @@
|
|||||||
# Exit codes:
|
# Exit codes:
|
||||||
# 1: Internal error
|
# 1: Internal error
|
||||||
# 2: Script wasn't enabled in zed.rc
|
# 2: Script wasn't enabled in zed.rc
|
||||||
# 3: Scrubs are automatically started for sequential resilvers
|
|
||||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
||||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
||||||
|
|
||||||
[ "${ZED_SCRUB_AFTER_RESILVER}" = "1" ] || exit 2
|
[ "${ZED_SCRUB_AFTER_RESILVER}" = "1" ] || exit 2
|
||||||
[ "${ZEVENT_RESILVER_TYPE}" != "sequential" ] || exit 3
|
|
||||||
[ -n "${ZEVENT_POOL}" ] || exit 1
|
[ -n "${ZEVENT_POOL}" ] || exit 1
|
||||||
[ -n "${ZEVENT_SUBCLASS}" ] || exit 1
|
[ -n "${ZEVENT_SUBCLASS}" ] || exit 1
|
||||||
zed_check_cmd "${ZPOOL}" || exit 1
|
zed_check_cmd "${ZPOOL}" || exit 1
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# Exit codes:
|
# Exit codes:
|
||||||
# 0: enclosure led successfully set
|
# 0: enclosure led successfully set
|
||||||
# 1: enclosure leds not available
|
# 1: enclosure leds not not available
|
||||||
# 2: enclosure leds administratively disabled
|
# 2: enclosure leds administratively disabled
|
||||||
# 3: The led sysfs path passed from ZFS does not exist
|
# 3: The led sysfs path passed from ZFS does not exist
|
||||||
# 4: $ZPOOL not set
|
# 4: $ZPOOL not set
|
||||||
@@ -68,7 +68,7 @@ check_and_set_led()
|
|||||||
# timeout.
|
# timeout.
|
||||||
for _ in $(seq 1 5); do
|
for _ in $(seq 1 5); do
|
||||||
# We want to check the current state first, since writing to the
|
# We want to check the current state first, since writing to the
|
||||||
# 'fault' entry always causes a SES command, even if the
|
# 'fault' entry always always causes a SES command, even if the
|
||||||
# current state is already what you want.
|
# current state is already what you want.
|
||||||
current=$(cat "${file}")
|
current=$(cat "${file}")
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ process_pool()
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -n "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ -n "$ZEVENT_VDEV_STATE_STR" ] ; then
|
if [ ! -z "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ ! -z "$ZEVENT_VDEV_STATE_STR" ] ; then
|
||||||
# Got a statechange for an individual VDEV
|
# Got a statechange for an individual VDEV
|
||||||
val=$(state_to_val "$ZEVENT_VDEV_STATE_STR")
|
val=$(state_to_val "$ZEVENT_VDEV_STATE_STR")
|
||||||
vdev=$(basename "$ZEVENT_VDEV_PATH")
|
vdev=$(basename "$ZEVENT_VDEV_PATH")
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# Send notification in response to a TRIM_FINISH. The event
|
|
||||||
# will be received for each vdev in the pool which was trimmed.
|
|
||||||
#
|
|
||||||
# Exit codes:
|
|
||||||
# 0: notification sent
|
|
||||||
# 1: notification failed
|
|
||||||
# 2: notification not configured
|
|
||||||
# 9: internal error
|
|
||||||
|
|
||||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
|
||||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
|
||||||
|
|
||||||
[ -n "${ZEVENT_POOL}" ] || exit 9
|
|
||||||
[ -n "${ZEVENT_SUBCLASS}" ] || exit 9
|
|
||||||
|
|
||||||
zed_check_cmd "${ZPOOL}" || exit 9
|
|
||||||
|
|
||||||
umask 077
|
|
||||||
note_subject="ZFS ${ZEVENT_SUBCLASS} event for ${ZEVENT_POOL} on $(hostname)"
|
|
||||||
note_pathname="${TMPDIR:="/tmp"}/$(basename -- "$0").${ZEVENT_EID}.$$"
|
|
||||||
{
|
|
||||||
echo "ZFS has finished a trim:"
|
|
||||||
echo
|
|
||||||
echo " eid: ${ZEVENT_EID}"
|
|
||||||
echo " class: ${ZEVENT_SUBCLASS}"
|
|
||||||
echo " host: $(hostname)"
|
|
||||||
echo " time: ${ZEVENT_TIME_STRING}"
|
|
||||||
|
|
||||||
"${ZPOOL}" status -t "${ZEVENT_POOL}"
|
|
||||||
|
|
||||||
} > "${note_pathname}"
|
|
||||||
|
|
||||||
zed_notify "${note_subject}" "${note_pathname}"; rv=$?
|
|
||||||
rm -f "${note_pathname}"
|
|
||||||
exit "${rv}"
|
|
||||||
@@ -202,10 +202,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_slack_webhook "${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
|
||||||
@@ -363,80 +359,6 @@ zed_notify_pushbullet()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# zed_notify_slack_webhook (subject, pathname)
|
|
||||||
#
|
|
||||||
# Notification via Slack Webhook <https://api.slack.com/incoming-webhooks>.
|
|
||||||
# The Webhook URL (ZED_SLACK_WEBHOOK_URL) identifies this client to the
|
|
||||||
# Slack channel.
|
|
||||||
#
|
|
||||||
# Requires awk, curl, and sed executables to be installed in the standard PATH.
|
|
||||||
#
|
|
||||||
# References
|
|
||||||
# https://api.slack.com/incoming-webhooks
|
|
||||||
#
|
|
||||||
# Arguments
|
|
||||||
# subject: notification subject
|
|
||||||
# pathname: pathname containing the notification message (OPTIONAL)
|
|
||||||
#
|
|
||||||
# Globals
|
|
||||||
# ZED_SLACK_WEBHOOK_URL
|
|
||||||
#
|
|
||||||
# Return
|
|
||||||
# 0: notification sent
|
|
||||||
# 1: notification failed
|
|
||||||
# 2: not configured
|
|
||||||
#
|
|
||||||
zed_notify_slack_webhook()
|
|
||||||
{
|
|
||||||
[ -n "${ZED_SLACK_WEBHOOK_URL}" ] || return 2
|
|
||||||
|
|
||||||
local subject="$1"
|
|
||||||
local pathname="${2:-"/dev/null"}"
|
|
||||||
local msg_body
|
|
||||||
local msg_tag
|
|
||||||
local msg_json
|
|
||||||
local msg_out
|
|
||||||
local msg_err
|
|
||||||
local url="${ZED_SLACK_WEBHOOK_URL}"
|
|
||||||
|
|
||||||
[ -n "${subject}" ] || return 1
|
|
||||||
if [ ! -r "${pathname}" ]; then
|
|
||||||
zed_log_err "slack webhook cannot read \"${pathname}\""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
zed_check_cmd "awk" "curl" "sed" || return 1
|
|
||||||
|
|
||||||
# Escape the following characters in the message body for JSON:
|
|
||||||
# newline, backslash, double quote, horizontal tab, vertical tab,
|
|
||||||
# and carriage return.
|
|
||||||
#
|
|
||||||
msg_body="$(awk '{ ORS="\\n" } { gsub(/\\/, "\\\\"); gsub(/"/, "\\\"");
|
|
||||||
gsub(/\t/, "\\t"); gsub(/\f/, "\\f"); gsub(/\r/, "\\r"); print }' \
|
|
||||||
"${pathname}")"
|
|
||||||
|
|
||||||
# Construct the JSON message for posting.
|
|
||||||
#
|
|
||||||
msg_json="$(printf '{"text": "*%s*\n%s"}' "${subject}" "${msg_body}" )"
|
|
||||||
|
|
||||||
# Send the POST request and check for errors.
|
|
||||||
#
|
|
||||||
msg_out="$(curl -X POST "${url}" \
|
|
||||||
--header "Content-Type: application/json" --data-binary "${msg_json}" \
|
|
||||||
2>/dev/null)"; rv=$?
|
|
||||||
if [ "${rv}" -ne 0 ]; then
|
|
||||||
zed_log_err "curl exit=${rv}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
msg_err="$(echo "${msg_out}" \
|
|
||||||
| sed -n -e 's/.*"error" *:.*"message" *: *"\([^"]*\)".*/\1/p')"
|
|
||||||
if [ -n "${msg_err}" ]; then
|
|
||||||
zed_log_err "slack webhook \"${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
|
||||||
@@ -512,7 +434,7 @@ zed_guid_to_pool()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
guid=$(printf "%llu" "$1")
|
guid=$(printf "%llu" "$1")
|
||||||
if [ -n "$guid" ] ; then
|
if [ ! -z "$guid" ] ; then
|
||||||
$ZPOOL get -H -ovalue,name guid | awk '$1=='"$guid"' {print $2}'
|
$ZPOOL get -H -ovalue,name guid | awk '$1=='"$guid"' {print $2}'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-18
@@ -52,9 +52,9 @@
|
|||||||
|
|
||||||
##
|
##
|
||||||
# Send notifications for 'ereport.fs.zfs.data' events.
|
# Send notifications for 'ereport.fs.zfs.data' events.
|
||||||
# Disabled by default, any non-empty value will enable the feature.
|
# Disabled by default
|
||||||
#
|
#
|
||||||
#ZED_NOTIFY_DATA=
|
#ZED_NOTIFY_DATA=1
|
||||||
|
|
||||||
##
|
##
|
||||||
# Pushbullet access token.
|
# Pushbullet access token.
|
||||||
@@ -74,14 +74,6 @@
|
|||||||
#
|
#
|
||||||
#ZED_PUSHBULLET_CHANNEL_TAG=""
|
#ZED_PUSHBULLET_CHANNEL_TAG=""
|
||||||
|
|
||||||
##
|
|
||||||
# Slack Webhook URL.
|
|
||||||
# This allows posting to the given channel and includes an access token.
|
|
||||||
# <https://api.slack.com/incoming-webhooks>
|
|
||||||
# Disabled by default; uncomment to enable.
|
|
||||||
#
|
|
||||||
#ZED_SLACK_WEBHOOK_URL=""
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Default directory for zed state files.
|
# Default directory for zed state files.
|
||||||
#
|
#
|
||||||
@@ -96,8 +88,7 @@ ZED_USE_ENCLOSURE_LEDS=1
|
|||||||
|
|
||||||
##
|
##
|
||||||
# Run a scrub after every resilver
|
# Run a scrub after every resilver
|
||||||
# Disabled by default, 1 to enable and 0 to disable.
|
#ZED_SCRUB_AFTER_RESILVER=1
|
||||||
#ZED_SCRUB_AFTER_RESILVER=0
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# The syslog priority (e.g., specified as a "facility.level" pair).
|
# The syslog priority (e.g., specified as a "facility.level" pair).
|
||||||
@@ -118,10 +109,5 @@ ZED_USE_ENCLOSURE_LEDS=1
|
|||||||
# Otherwise, if ZED_SYSLOG_SUBCLASS_EXCLUDE is set, the
|
# Otherwise, if ZED_SYSLOG_SUBCLASS_EXCLUDE is set, the
|
||||||
# matching subclasses are excluded from logging.
|
# matching subclasses are excluded from logging.
|
||||||
#ZED_SYSLOG_SUBCLASS_INCLUDE="checksum|scrub_*|vdev.*"
|
#ZED_SYSLOG_SUBCLASS_INCLUDE="checksum|scrub_*|vdev.*"
|
||||||
ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
|
#ZED_SYSLOG_SUBCLASS_EXCLUDE="statechange|config_*|history_event"
|
||||||
|
|
||||||
##
|
|
||||||
# Use GUIDs instead of names when logging pool and vdevs
|
|
||||||
# Disabled by default, 1 to enable and 0 to disable.
|
|
||||||
#ZED_SYSLOG_DISPLAY_GUIDS=1
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
|
|||||||
+3
-8
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -153,8 +153,6 @@ _zed_conf_display_help(const char *prog, int got_err)
|
|||||||
"Force daemon to run.");
|
"Force daemon to run.");
|
||||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-F",
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-F",
|
||||||
"Run daemon in the foreground.");
|
"Run daemon in the foreground.");
|
||||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-I",
|
|
||||||
"Idle daemon until kernel module is (re)loaded.");
|
|
||||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-M",
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-M",
|
||||||
"Lock all pages in memory.");
|
"Lock all pages in memory.");
|
||||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-P",
|
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-P",
|
||||||
@@ -251,7 +249,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 = ":hLVc:d:p:P:s:vfFMZI";
|
const char * const opts = ":hLVc:d:p:P:s:vfFMZ";
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
if (!zcp || !argv || !argv[0])
|
if (!zcp || !argv || !argv[0])
|
||||||
@@ -276,9 +274,6 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
|||||||
case 'd':
|
case 'd':
|
||||||
_zed_conf_parse_path(&zcp->zedlet_dir, optarg);
|
_zed_conf_parse_path(&zcp->zedlet_dir, optarg);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
|
||||||
zcp->do_idle = 1;
|
|
||||||
break;
|
|
||||||
case 'p':
|
case 'p':
|
||||||
_zed_conf_parse_path(&zcp->pid_file, optarg);
|
_zed_conf_parse_path(&zcp->pid_file, optarg);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -25,7 +25,6 @@ struct zed_conf {
|
|||||||
unsigned do_memlock:1; /* true if locking memory */
|
unsigned do_memlock:1; /* true if locking memory */
|
||||||
unsigned do_verbose:1; /* true if verbosity enabled */
|
unsigned do_verbose:1; /* true if verbosity enabled */
|
||||||
unsigned do_zero:1; /* true if zeroing state */
|
unsigned do_zero:1; /* true if zeroing state */
|
||||||
unsigned do_idle:1; /* true if idle enabled */
|
|
||||||
int syslog_facility; /* syslog facility value */
|
int syslog_facility; /* syslog facility value */
|
||||||
int min_events; /* RESERVED FOR FUTURE USE */
|
int min_events; /* RESERVED FOR FUTURE USE */
|
||||||
int max_events; /* RESERVED FOR FUTURE USE */
|
int max_events; /* RESERVED FOR FUTURE USE */
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include <libnvpair.h>
|
#include <libnvpair.h>
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
#include <libzutil.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -38,7 +37,7 @@
|
|||||||
* A libudev monitor is established to monitor block device actions and pass
|
* A libudev monitor is established to monitor block device actions and pass
|
||||||
* them on to internal ZED logic modules. Initially, zfs_mod.c is the only
|
* them on to internal ZED logic modules. Initially, zfs_mod.c is the only
|
||||||
* consumer and is the Linux equivalent for the illumos syseventd ZFS SLM
|
* consumer and is the Linux equivalent for the illumos syseventd ZFS SLM
|
||||||
* module responsible for handling disk events for ZFS.
|
* module responsible for handeling disk events for ZFS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pthread_t g_mon_tid;
|
pthread_t g_mon_tid;
|
||||||
|
|||||||
+9
-22
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
#include "zed.h"
|
#include "zed.h"
|
||||||
#include "zed_conf.h"
|
#include "zed_conf.h"
|
||||||
#include "zed_disk_event.h"
|
#include "zed_disk_event.h"
|
||||||
#include "zed_event.h"
|
|
||||||
#include "zed_exec.h"
|
#include "zed_exec.h"
|
||||||
#include "zed_file.h"
|
#include "zed_file.h"
|
||||||
#include "zed_log.h"
|
#include "zed_log.h"
|
||||||
@@ -41,36 +40,25 @@
|
|||||||
/*
|
/*
|
||||||
* Open the libzfs interface.
|
* Open the libzfs interface.
|
||||||
*/
|
*/
|
||||||
int
|
void
|
||||||
zed_event_init(struct zed_conf *zcp)
|
zed_event_init(struct zed_conf *zcp)
|
||||||
{
|
{
|
||||||
if (!zcp)
|
if (!zcp)
|
||||||
zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
|
zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
|
||||||
|
|
||||||
zcp->zfs_hdl = libzfs_init();
|
zcp->zfs_hdl = libzfs_init();
|
||||||
if (!zcp->zfs_hdl) {
|
if (!zcp->zfs_hdl)
|
||||||
if (zcp->do_idle)
|
|
||||||
return (-1);
|
|
||||||
zed_log_die("Failed to initialize libzfs");
|
zed_log_die("Failed to initialize libzfs");
|
||||||
}
|
|
||||||
|
|
||||||
zcp->zevent_fd = open(ZFS_DEV, O_RDWR);
|
zcp->zevent_fd = open(ZFS_DEV, O_RDWR);
|
||||||
if (zcp->zevent_fd < 0) {
|
if (zcp->zevent_fd < 0)
|
||||||
if (zcp->do_idle)
|
|
||||||
return (-1);
|
|
||||||
zed_log_die("Failed to open \"%s\": %s",
|
zed_log_die("Failed to open \"%s\": %s",
|
||||||
ZFS_DEV, strerror(errno));
|
ZFS_DEV, strerror(errno));
|
||||||
}
|
|
||||||
|
|
||||||
zfs_agent_init(zcp->zfs_hdl);
|
zfs_agent_init(zcp->zfs_hdl);
|
||||||
|
|
||||||
if (zed_disk_event_init() != 0) {
|
if (zed_disk_event_init() != 0)
|
||||||
if (zcp->do_idle)
|
|
||||||
return (-1);
|
|
||||||
zed_log_die("Failed to initialize disk events");
|
zed_log_die("Failed to initialize disk events");
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -884,7 +872,7 @@ _zed_event_add_time_strings(uint64_t eid, zed_strings_t *zsp, int64_t etime[])
|
|||||||
/*
|
/*
|
||||||
* Service the next zevent, blocking until one is available.
|
* Service the next zevent, blocking until one is available.
|
||||||
*/
|
*/
|
||||||
int
|
void
|
||||||
zed_event_service(struct zed_conf *zcp)
|
zed_event_service(struct zed_conf *zcp)
|
||||||
{
|
{
|
||||||
nvlist_t *nvl;
|
nvlist_t *nvl;
|
||||||
@@ -902,13 +890,13 @@ zed_event_service(struct zed_conf *zcp)
|
|||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
|
zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return (EINVAL);
|
return;
|
||||||
}
|
}
|
||||||
rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
|
rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
|
||||||
zcp->zevent_fd);
|
zcp->zevent_fd);
|
||||||
|
|
||||||
if ((rv != 0) || !nvl)
|
if ((rv != 0) || !nvl)
|
||||||
return (errno);
|
return;
|
||||||
|
|
||||||
if (n_dropped > 0) {
|
if (n_dropped > 0) {
|
||||||
zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
|
zed_log_msg(LOG_WARNING, "Missed %d events", n_dropped);
|
||||||
@@ -961,5 +949,4 @@ zed_event_service(struct zed_conf *zcp)
|
|||||||
zed_strings_destroy(zsp);
|
zed_strings_destroy(zsp);
|
||||||
}
|
}
|
||||||
nvlist_free(nvl);
|
nvlist_free(nvl);
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -17,13 +17,13 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
int zed_event_init(struct zed_conf *zcp);
|
void zed_event_init(struct zed_conf *zcp);
|
||||||
|
|
||||||
void zed_event_fini(struct zed_conf *zcp);
|
void zed_event_fini(struct zed_conf *zcp);
|
||||||
|
|
||||||
int zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid,
|
int zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid,
|
||||||
int64_t saved_etime[]);
|
int64_t saved_etime[]);
|
||||||
|
|
||||||
int zed_event_service(struct zed_conf *zcp);
|
void zed_event_service(struct zed_conf *zcp);
|
||||||
|
|
||||||
#endif /* !ZED_EVENT_H */
|
#endif /* !ZED_EVENT_H */
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "zed_exec.h"
|
|
||||||
#include "zed_file.h"
|
#include "zed_file.h"
|
||||||
#include "zed_log.h"
|
#include "zed_log.h"
|
||||||
#include "zed_strings.h"
|
#include "zed_strings.h"
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
#define ZED_EXEC_H
|
#define ZED_EXEC_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "zed_strings.h"
|
|
||||||
|
|
||||||
int zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
int zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
||||||
const char *dir, zed_strings_t *zedlets, zed_strings_t *envs,
|
const char *dir, zed_strings_t *zedlets, zed_strings_t *envs,
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "zed_file.h"
|
|
||||||
#include "zed_log.h"
|
#include "zed_log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
@@ -108,7 +108,7 @@ _zed_strings_node_destroy(zed_strings_node_t *np)
|
|||||||
* If [key] is specified, it will be used to index the node; otherwise,
|
* If [key] is specified, it will be used to index the node; otherwise,
|
||||||
* the string [val] will be used.
|
* the string [val] will be used.
|
||||||
*/
|
*/
|
||||||
static zed_strings_node_t *
|
zed_strings_node_t *
|
||||||
_zed_strings_node_create(const char *key, const char *val)
|
_zed_strings_node_create(const char *key, const char *val)
|
||||||
{
|
{
|
||||||
zed_strings_node_t *np;
|
zed_strings_node_t *np;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the ZFS Event Daemon (ZED).
|
* This file is part of the ZFS Event Daemon (ZED)
|
||||||
*
|
* for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
|
||||||
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
* Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
|
||||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||||
|
|||||||
+11
-12
@@ -1,23 +1,22 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
|
DEFAULT_INCLUDES += \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_srcdir)/lib/libspl/include
|
||||||
|
|
||||||
sbin_PROGRAMS = zfs
|
sbin_PROGRAMS = zfs
|
||||||
|
|
||||||
zfs_SOURCES = \
|
zfs_SOURCES = \
|
||||||
zfs_iter.c \
|
zfs_iter.c \
|
||||||
zfs_iter.h \
|
zfs_iter.h \
|
||||||
zfs_main.c \
|
zfs_main.c \
|
||||||
zfs_util.h \
|
zfs_util.h
|
||||||
zfs_project.c \
|
|
||||||
zfs_projectutil.h
|
|
||||||
|
|
||||||
zfs_LDADD = \
|
zfs_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
|
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||||
$(abs_top_builddir)/lib/libuutil/libuutil.la
|
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||||
|
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||||
|
|
||||||
zfs_LDADD += $(LTLIBINTL)
|
zfs_LDFLAGS = -pthread
|
||||||
|
|
||||||
if BUILD_FREEBSD
|
|
||||||
zfs_LDADD += -lgeom -ljail
|
|
||||||
endif
|
|
||||||
|
|||||||
+6
-22
@@ -31,7 +31,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
@@ -134,31 +133,16 @@ zfs_callback(zfs_handle_t *zhp, void *data)
|
|||||||
((cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
|
((cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
|
||||||
cb->cb_depth < cb->cb_depth_limit)) {
|
cb->cb_depth < cb->cb_depth_limit)) {
|
||||||
cb->cb_depth++;
|
cb->cb_depth++;
|
||||||
|
if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
|
||||||
/*
|
|
||||||
* If we are not looking for filesystems, we don't need to
|
|
||||||
* recurse into filesystems when we are at our depth limit.
|
|
||||||
*/
|
|
||||||
if ((cb->cb_depth < cb->cb_depth_limit ||
|
|
||||||
(cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
|
|
||||||
(cb->cb_types &
|
|
||||||
(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) &&
|
|
||||||
zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
|
|
||||||
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
|
(void) zfs_iter_filesystems(zhp, 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(zhp,
|
(void) zfs_iter_snapshots(zhp,
|
||||||
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0,
|
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
|
||||||
zfs_callback, data, 0, 0);
|
data);
|
||||||
}
|
|
||||||
|
|
||||||
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(zhp, zfs_callback, data);
|
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
|
||||||
}
|
|
||||||
|
|
||||||
cb->cb_depth--;
|
cb->cb_depth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +224,7 @@ zfs_compare(const void *larg, const void *rarg, void *unused)
|
|||||||
*rat = '\0';
|
*rat = '\0';
|
||||||
|
|
||||||
ret = strcmp(lname, rname);
|
ret = strcmp(lname, rname);
|
||||||
if (ret == 0 && (lat != NULL || rat != NULL)) {
|
if (ret == 0) {
|
||||||
/*
|
/*
|
||||||
* If we're comparing a dataset to one of its snapshots, we
|
* If we're comparing a dataset to one of its snapshots, we
|
||||||
* always make the full dataset first.
|
* always make the full dataset first.
|
||||||
|
|||||||
+307
-1799
File diff suppressed because it is too large
Load Diff
@@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of the
|
|
||||||
* Common Development and Distribution License (the "License").
|
|
||||||
* You may not use this file except in compliance with the License.
|
|
||||||
*
|
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
||||||
* or http://www.opensolaris.org/os/licensing.
|
|
||||||
* See the License for the specific language governing permissions
|
|
||||||
* and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing Covered Code, include this CDDL HEADER in each
|
|
||||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
||||||
* If applicable, add the following below this CDDL HEADER, with the
|
|
||||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
||||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, Intle Corporation. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <libintl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/list.h>
|
|
||||||
#include <sys/zfs_project.h>
|
|
||||||
|
|
||||||
#include "zfs_util.h"
|
|
||||||
#include "zfs_projectutil.h"
|
|
||||||
|
|
||||||
typedef struct zfs_project_item {
|
|
||||||
list_node_t zpi_list;
|
|
||||||
char zpi_name[0];
|
|
||||||
} zfs_project_item_t;
|
|
||||||
|
|
||||||
static void
|
|
||||||
zfs_project_item_alloc(list_t *head, const char *name)
|
|
||||||
{
|
|
||||||
zfs_project_item_t *zpi;
|
|
||||||
|
|
||||||
zpi = safe_malloc(sizeof (zfs_project_item_t) + strlen(name) + 1);
|
|
||||||
strcpy(zpi->zpi_name, name);
|
|
||||||
list_insert_tail(head, zpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_project_sanity_check(const char *name, zfs_project_control_t *zpc,
|
|
||||||
struct stat *st)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = stat(name, st);
|
|
||||||
if (ret) {
|
|
||||||
(void) fprintf(stderr, gettext("failed to stat %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) {
|
|
||||||
(void) fprintf(stderr, gettext("only support project quota on "
|
|
||||||
"regular file or directory\n"));
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISDIR(st->st_mode)) {
|
|
||||||
if (zpc->zpc_dironly) {
|
|
||||||
(void) fprintf(stderr, gettext(
|
|
||||||
"'-d' option on non-dir target %s\n"), name);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zpc->zpc_recursive) {
|
|
||||||
(void) fprintf(stderr, gettext(
|
|
||||||
"'-r' option on non-dir target %s\n"), name);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_project_load_projid(const char *name, zfs_project_control_t *zpc)
|
|
||||||
{
|
|
||||||
zfsxattr_t fsx;
|
|
||||||
int ret, fd;
|
|
||||||
|
|
||||||
fd = open(name, O_RDONLY | O_NOCTTY);
|
|
||||||
if (fd < 0) {
|
|
||||||
(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
return (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ioctl(fd, ZFS_IOC_FSGETXATTR, &fsx);
|
|
||||||
if (ret)
|
|
||||||
(void) fprintf(stderr,
|
|
||||||
gettext("failed to get xattr for %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
else
|
|
||||||
zpc->zpc_expected_projid = fsx.fsx_projid;
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_project_handle_one(const char *name, zfs_project_control_t *zpc)
|
|
||||||
{
|
|
||||||
zfsxattr_t fsx;
|
|
||||||
int ret, fd;
|
|
||||||
|
|
||||||
fd = open(name, O_RDONLY | O_NOCTTY);
|
|
||||||
if (fd < 0) {
|
|
||||||
if (errno == ENOENT && zpc->zpc_ignore_noent)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
return (fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ioctl(fd, ZFS_IOC_FSGETXATTR, &fsx);
|
|
||||||
if (ret) {
|
|
||||||
(void) fprintf(stderr,
|
|
||||||
gettext("failed to get xattr for %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (zpc->zpc_op) {
|
|
||||||
case ZFS_PROJECT_OP_LIST:
|
|
||||||
(void) printf("%5u %c %s\n", fsx.fsx_projid,
|
|
||||||
(fsx.fsx_xflags & ZFS_PROJINHERIT_FL) ? 'P' : '-', name);
|
|
||||||
goto out;
|
|
||||||
case ZFS_PROJECT_OP_CHECK:
|
|
||||||
if (fsx.fsx_projid == zpc->zpc_expected_projid &&
|
|
||||||
fsx.fsx_xflags & ZFS_PROJINHERIT_FL)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (!zpc->zpc_newline) {
|
|
||||||
char c = '\0';
|
|
||||||
|
|
||||||
(void) printf("%s%c", name, c);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsx.fsx_projid != zpc->zpc_expected_projid)
|
|
||||||
(void) printf("%s - project ID is not set properly "
|
|
||||||
"(%u/%u)\n", name, fsx.fsx_projid,
|
|
||||||
(uint32_t)zpc->zpc_expected_projid);
|
|
||||||
|
|
||||||
if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
|
|
||||||
(void) printf("%s - project inherit flag is not set\n",
|
|
||||||
name);
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
case ZFS_PROJECT_OP_CLEAR:
|
|
||||||
if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL) &&
|
|
||||||
(zpc->zpc_keep_projid ||
|
|
||||||
fsx.fsx_projid == ZFS_DEFAULT_PROJID))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
fsx.fsx_xflags &= ~ZFS_PROJINHERIT_FL;
|
|
||||||
if (!zpc->zpc_keep_projid)
|
|
||||||
fsx.fsx_projid = ZFS_DEFAULT_PROJID;
|
|
||||||
break;
|
|
||||||
case ZFS_PROJECT_OP_SET:
|
|
||||||
if (fsx.fsx_projid == zpc->zpc_expected_projid &&
|
|
||||||
(!zpc->zpc_set_flag || fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
fsx.fsx_projid = zpc->zpc_expected_projid;
|
|
||||||
if (zpc->zpc_set_flag)
|
|
||||||
fsx.fsx_xflags |= ZFS_PROJINHERIT_FL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ioctl(fd, ZFS_IOC_FSSETXATTR, &fsx);
|
|
||||||
if (ret)
|
|
||||||
(void) fprintf(stderr,
|
|
||||||
gettext("failed to set xattr for %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
|
|
||||||
out:
|
|
||||||
close(fd);
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
|
|
||||||
list_t *head)
|
|
||||||
{
|
|
||||||
char fullname[PATH_MAX];
|
|
||||||
struct dirent *ent;
|
|
||||||
DIR *dir;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
dir = opendir(name);
|
|
||||||
if (dir == NULL) {
|
|
||||||
if (errno == ENOENT && zpc->zpc_ignore_noent)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
ret = -errno;
|
|
||||||
(void) fprintf(stderr, gettext("failed to opendir %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Non-top item, ignore the case of being removed or renamed by race. */
|
|
||||||
zpc->zpc_ignore_noent = B_TRUE;
|
|
||||||
errno = 0;
|
|
||||||
while (!ret && (ent = readdir(dir)) != NULL) {
|
|
||||||
/* skip "." and ".." */
|
|
||||||
if (strcmp(ent->d_name, ".") == 0 ||
|
|
||||||
strcmp(ent->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strlen(ent->d_name) + strlen(name) >=
|
|
||||||
sizeof (fullname) + 1) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(fullname, "%s/%s", name, ent->d_name);
|
|
||||||
ret = zfs_project_handle_one(fullname, zpc);
|
|
||||||
if (!ret && zpc->zpc_recursive && ent->d_type == DT_DIR)
|
|
||||||
zfs_project_item_alloc(head, fullname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno && !ret) {
|
|
||||||
ret = -errno;
|
|
||||||
(void) fprintf(stderr, gettext("failed to readdir %s: %s\n"),
|
|
||||||
name, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
zfs_project_handle(const char *name, zfs_project_control_t *zpc)
|
|
||||||
{
|
|
||||||
zfs_project_item_t *zpi;
|
|
||||||
struct stat st;
|
|
||||||
list_t head;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = zfs_project_sanity_check(name, zpc, &st);
|
|
||||||
if (ret)
|
|
||||||
return (ret);
|
|
||||||
|
|
||||||
if ((zpc->zpc_op == ZFS_PROJECT_OP_SET ||
|
|
||||||
zpc->zpc_op == ZFS_PROJECT_OP_CHECK) &&
|
|
||||||
zpc->zpc_expected_projid == ZFS_INVALID_PROJID) {
|
|
||||||
ret = zfs_project_load_projid(name, zpc);
|
|
||||||
if (ret)
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
zpc->zpc_ignore_noent = B_FALSE;
|
|
||||||
ret = zfs_project_handle_one(name, zpc);
|
|
||||||
if (ret || !S_ISDIR(st.st_mode) || zpc->zpc_dironly ||
|
|
||||||
(!zpc->zpc_recursive &&
|
|
||||||
zpc->zpc_op != ZFS_PROJECT_OP_LIST &&
|
|
||||||
zpc->zpc_op != ZFS_PROJECT_OP_CHECK))
|
|
||||||
return (ret);
|
|
||||||
|
|
||||||
list_create(&head, sizeof (zfs_project_item_t),
|
|
||||||
offsetof(zfs_project_item_t, zpi_list));
|
|
||||||
zfs_project_item_alloc(&head, name);
|
|
||||||
while ((zpi = list_remove_head(&head)) != NULL) {
|
|
||||||
if (!ret)
|
|
||||||
ret = zfs_project_handle_dir(zpi->zpi_name, zpc, &head);
|
|
||||||
free(zpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of the
|
|
||||||
* Common Development and Distribution License (the "License").
|
|
||||||
* You may not use this file except in compliance with the License.
|
|
||||||
*
|
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
||||||
* or http://www.opensolaris.org/os/licensing.
|
|
||||||
* See the License for the specific language governing permissions
|
|
||||||
* and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing Covered Code, include this CDDL HEADER in each
|
|
||||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
||||||
* If applicable, add the following below this CDDL HEADER, with the
|
|
||||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
||||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2017, Intel Corporation. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ZFS_PROJECTUTIL_H
|
|
||||||
#define _ZFS_PROJECTUTIL_H
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
ZFS_PROJECT_OP_DEFAULT = 0,
|
|
||||||
ZFS_PROJECT_OP_LIST = 1,
|
|
||||||
ZFS_PROJECT_OP_CHECK = 2,
|
|
||||||
ZFS_PROJECT_OP_CLEAR = 3,
|
|
||||||
ZFS_PROJECT_OP_SET = 4,
|
|
||||||
} zfs_project_ops_t;
|
|
||||||
|
|
||||||
typedef struct zfs_project_control {
|
|
||||||
uint64_t zpc_expected_projid;
|
|
||||||
zfs_project_ops_t zpc_op;
|
|
||||||
boolean_t zpc_dironly;
|
|
||||||
boolean_t zpc_ignore_noent;
|
|
||||||
boolean_t zpc_keep_projid;
|
|
||||||
boolean_t zpc_newline;
|
|
||||||
boolean_t zpc_recursive;
|
|
||||||
boolean_t zpc_set_flag;
|
|
||||||
} zfs_project_control_t;
|
|
||||||
|
|
||||||
int zfs_project_handle(const char *name, zfs_project_control_t *zpc);
|
|
||||||
|
|
||||||
#endif /* _ZFS_PROJECTUTIL_H */
|
|
||||||
+1
-1
@@ -33,7 +33,7 @@ extern "C" {
|
|||||||
|
|
||||||
void * safe_malloc(size_t size);
|
void * safe_malloc(size_t size);
|
||||||
void nomem(void);
|
void nomem(void);
|
||||||
extern libzfs_handle_t *g_zfs;
|
libzfs_handle_t *g_zfs;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
zfs_ids_to_path
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
|
||||||
|
|
||||||
sbin_PROGRAMS = zfs_ids_to_path
|
|
||||||
|
|
||||||
zfs_ids_to_path_SOURCES = \
|
|
||||||
zfs_ids_to_path.c
|
|
||||||
|
|
||||||
zfs_ids_to_path_LDADD = \
|
|
||||||
$(abs_top_builddir)/lib/libzfs/libzfs.la
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of the
|
|
||||||
* Common Development and Distribution License (the "License").
|
|
||||||
* You may not use this file except in compliance with the License.
|
|
||||||
*
|
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
||||||
* or http://www.opensolaris.org/os/licensing.
|
|
||||||
* See the License for the specific language governing permissions
|
|
||||||
* and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing Covered Code, include this CDDL HEADER in each
|
|
||||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
||||||
* If applicable, add the following below this CDDL HEADER, with the
|
|
||||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
||||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
#include <libintl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <libzfs.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
libzfs_handle_t *g_zfs;
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(int err)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage: [-v] zfs_ids_to_path <pool> <objset id> "
|
|
||||||
"<object id>\n");
|
|
||||||
exit(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
boolean_t verbose = B_FALSE;
|
|
||||||
int c;
|
|
||||||
while ((c = getopt(argc, argv, "v")) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
case 'v':
|
|
||||||
verbose = B_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (argc != 3) {
|
|
||||||
(void) fprintf(stderr, "Incorrect number of arguments: %d\n",
|
|
||||||
argc);
|
|
||||||
usage(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t objset, object;
|
|
||||||
if (sscanf(argv[1], "%llu", (u_longlong_t *)&objset) != 1) {
|
|
||||||
(void) fprintf(stderr, "Invalid objset id: %s\n", argv[2]);
|
|
||||||
usage(2);
|
|
||||||
}
|
|
||||||
if (sscanf(argv[2], "%llu", (u_longlong_t *)&object) != 1) {
|
|
||||||
(void) fprintf(stderr, "Invalid object id: %s\n", argv[3]);
|
|
||||||
usage(3);
|
|
||||||
}
|
|
||||||
if ((g_zfs = libzfs_init()) == NULL) {
|
|
||||||
(void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
|
|
||||||
return (4);
|
|
||||||
}
|
|
||||||
zpool_handle_t *pool = zpool_open(g_zfs, argv[0]);
|
|
||||||
if (pool == NULL) {
|
|
||||||
fprintf(stderr, "Could not open pool %s\n", argv[1]);
|
|
||||||
libzfs_fini(g_zfs);
|
|
||||||
return (5);
|
|
||||||
}
|
|
||||||
|
|
||||||
char pathname[PATH_MAX * 2];
|
|
||||||
if (verbose) {
|
|
||||||
zpool_obj_to_path_ds(pool, objset, object, pathname,
|
|
||||||
sizeof (pathname));
|
|
||||||
} else {
|
|
||||||
zpool_obj_to_path(pool, objset, object, pathname,
|
|
||||||
sizeof (pathname));
|
|
||||||
}
|
|
||||||
printf("%s\n", pathname);
|
|
||||||
zpool_close(pool);
|
|
||||||
libzfs_fini(g_zfs);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/zgenhostid
|
|
||||||
@@ -1,5 +1 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
dist_bin_SCRIPTS = zgenhostid
|
||||||
|
|
||||||
sbin_PROGRAMS = zgenhostid
|
|
||||||
|
|
||||||
zgenhostid_SOURCES = zgenhostid.c
|
|
||||||
|
|||||||
Executable
+61
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Emulate genhostid(1) available on RHEL/CENTOS, for use on distros
|
||||||
|
# which do not provide that utility.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# zgenhostid
|
||||||
|
# zgenhostid <value>
|
||||||
|
#
|
||||||
|
# If /etc/hostid already exists and is size > 0, the script exits immediately
|
||||||
|
# and changes nothing. Unlike genhostid, this generates an error message.
|
||||||
|
#
|
||||||
|
# The first form generates a random hostid and stores it in /etc/hostid.
|
||||||
|
# The second form checks that the provided value is between 0x1 and 0xFFFFFFFF
|
||||||
|
# and if so, stores it in /etc/hostid. This form is not supported by
|
||||||
|
# genhostid(1).
|
||||||
|
|
||||||
|
hostid_file=/etc/hostid
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
echo "$0 [value]"
|
||||||
|
echo "If $hostid_file is not present, store a hostid in it." >&2
|
||||||
|
echo "The optional value must be an 8-digit hex number between" >&2
|
||||||
|
echo "1 and 2^32-1. If no value is provided, a random one will" >&2
|
||||||
|
echo "be generated. The value must be unique among your systems." >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# hostid(1) ignores contents of /etc/hostid if size < 4 bytes. It would
|
||||||
|
# be better if this checked size >= 4 bytes but it the method must be
|
||||||
|
# widely portable.
|
||||||
|
if [ -s $hostid_file ]; then
|
||||||
|
echo "$hostid_file already exists. No change made." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
host_id=$1
|
||||||
|
else
|
||||||
|
# $RANDOM goes from 0..32k-1
|
||||||
|
number=$((((RANDOM % 4) * 32768 + RANDOM) * 32768 + RANDOM))
|
||||||
|
host_id=$(printf "%08x" $number)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if egrep -o '^0{8}$' <<< $host_id >/dev/null 2>&1; then
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! egrep -o '^[a-fA-F0-9]{8}$' <<< $host_id >/dev/null 2>&1; then
|
||||||
|
usage
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
a=${host_id:6:2}
|
||||||
|
b=${host_id:4:2}
|
||||||
|
c=${host_id:2:2}
|
||||||
|
d=${host_id:0:2}
|
||||||
|
|
||||||
|
echo -ne \\x$a\\x$b\\x$c\\x$d > $hostid_file
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of the
|
|
||||||
* Common Development and Distribution License (the "License").
|
|
||||||
* You may not use this file except in compliance with the License.
|
|
||||||
*
|
|
||||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
||||||
* or http://www.opensolaris.org/os/licensing.
|
|
||||||
* See the License for the specific language governing permissions
|
|
||||||
* and limitations under the License.
|
|
||||||
*
|
|
||||||
* When distributing Covered Code, include this CDDL HEADER in each
|
|
||||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
||||||
* If applicable, add the following below this CDDL HEADER, with the
|
|
||||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
||||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2020, Georgy Yakovlev. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static void usage(void);
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
(void) fprintf(stderr,
|
|
||||||
"usage: zgenhostid [-fh] [-o path] [value]\n\n"
|
|
||||||
" -f\t\t force hostid file write\n"
|
|
||||||
" -h\t\t print this usage and exit\n"
|
|
||||||
" -o <filename>\t write hostid to this file\n\n"
|
|
||||||
"If hostid file is not present, store a hostid in it.\n"
|
|
||||||
"The optional value should be an 8-digit hex number between"
|
|
||||||
" 1 and 2^32-1.\n"
|
|
||||||
"If the value is 0 or no value is provided, a random one"
|
|
||||||
" will be generated.\n"
|
|
||||||
"The value must be unique among your systems.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
/* default file path, can be optionally set by user */
|
|
||||||
char path[PATH_MAX] = "/etc/hostid";
|
|
||||||
/* holds converted user input or lrand48() generated value */
|
|
||||||
unsigned long input_i = 0;
|
|
||||||
|
|
||||||
int opt;
|
|
||||||
int pathlen;
|
|
||||||
int force_fwrite = 0;
|
|
||||||
while ((opt = getopt_long(argc, argv, "fo:h?", 0, 0)) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'f':
|
|
||||||
force_fwrite = 1;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
pathlen = snprintf(path, sizeof (path), "%s", optarg);
|
|
||||||
if (pathlen >= sizeof (path)) {
|
|
||||||
fprintf(stderr, "%s\n", strerror(EOVERFLOW));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else if (pathlen < 1) {
|
|
||||||
fprintf(stderr, "%s\n", strerror(EINVAL));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *in_s = argv[optind];
|
|
||||||
if (in_s != NULL) {
|
|
||||||
/* increment pointer by 2 if string is 0x prefixed */
|
|
||||||
if (strncasecmp("0x", in_s, 2) == 0) {
|
|
||||||
in_s += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* need to be exactly 8 characters */
|
|
||||||
const char *hex = "0123456789abcdefABCDEF";
|
|
||||||
if (strlen(in_s) != 8 || strspn(in_s, hex) != 8) {
|
|
||||||
fprintf(stderr, "%s\n", strerror(ERANGE));
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
input_i = strtoul(in_s, NULL, 16);
|
|
||||||
if (errno != 0) {
|
|
||||||
perror("strtoul");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input_i > UINT32_MAX) {
|
|
||||||
fprintf(stderr, "%s\n", strerror(ERANGE));
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stat fstat;
|
|
||||||
if (force_fwrite == 0 && stat(path, &fstat) == 0 &&
|
|
||||||
S_ISREG(fstat.st_mode)) {
|
|
||||||
fprintf(stderr, "%s: %s\n", path, strerror(EEXIST));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* generate if not provided by user
|
|
||||||
* also handle unlikely zero return from lrand48()
|
|
||||||
*/
|
|
||||||
while (input_i == 0) {
|
|
||||||
srand48(getpid() ^ time(NULL));
|
|
||||||
input_i = lrand48();
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp = fopen(path, "wb");
|
|
||||||
if (!fp) {
|
|
||||||
perror("fopen");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we need just 4 bytes in native endianess
|
|
||||||
* not using sethostid() because it may be missing or just a stub
|
|
||||||
*/
|
|
||||||
uint32_t hostid = input_i;
|
|
||||||
int written = fwrite(&hostid, 1, 4, fp);
|
|
||||||
if (written != 4) {
|
|
||||||
perror("fwrite");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
# Unconditionally enable debugging for zhack
|
DEFAULT_INCLUDES += \
|
||||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_srcdir)/lib/libspl/include
|
||||||
|
|
||||||
sbin_PROGRAMS = zhack
|
sbin_PROGRAMS = zhack
|
||||||
|
|
||||||
@@ -9,6 +10,8 @@ zhack_SOURCES = \
|
|||||||
zhack.c
|
zhack.c
|
||||||
|
|
||||||
zhack_LDADD = \
|
zhack_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||||
|
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||||
|
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||||
|
|||||||
+12
-9
@@ -48,11 +48,12 @@
|
|||||||
#include <sys/zio_compress.h>
|
#include <sys/zio_compress.h>
|
||||||
#include <sys/zfeature.h>
|
#include <sys/zfeature.h>
|
||||||
#include <sys/dmu_tx.h>
|
#include <sys/dmu_tx.h>
|
||||||
#include <libzutil.h>
|
#include <libzfs.h>
|
||||||
|
|
||||||
extern boolean_t zfeature_checks_disable;
|
extern boolean_t zfeature_checks_disable;
|
||||||
|
|
||||||
const char cmdname[] = "zhack";
|
const char cmdname[] = "zhack";
|
||||||
|
libzfs_handle_t *g_zfs;
|
||||||
static importargs_t g_importargs;
|
static importargs_t g_importargs;
|
||||||
static char *g_pool;
|
static char *g_pool;
|
||||||
static boolean_t g_readonly;
|
static boolean_t g_readonly;
|
||||||
@@ -103,8 +104,8 @@ fatal(spa_t *spa, void *tag, const char *fmt, ...)
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
space_delta_cb(dmu_object_type_t bonustype, const void *data,
|
space_delta_cb(dmu_object_type_t bonustype, void *data,
|
||||||
zfs_file_info_t *zoi)
|
uint64_t *userp, uint64_t *groupp)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Is it a valid type of object to track?
|
* Is it a valid type of object to track?
|
||||||
@@ -126,19 +127,21 @@ zhack_import(char *target, boolean_t readonly)
|
|||||||
nvlist_t *props;
|
nvlist_t *props;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
kernel_init(readonly ? SPA_MODE_READ :
|
kernel_init(readonly ? FREAD : (FREAD | FWRITE));
|
||||||
(SPA_MODE_READ | SPA_MODE_WRITE));
|
g_zfs = libzfs_init();
|
||||||
|
ASSERT(g_zfs != NULL);
|
||||||
|
|
||||||
dmu_objset_register_type(DMU_OST_ZFS, space_delta_cb);
|
dmu_objset_register_type(DMU_OST_ZFS, space_delta_cb);
|
||||||
|
|
||||||
g_readonly = readonly;
|
g_readonly = readonly;
|
||||||
|
g_importargs.unique = B_TRUE;
|
||||||
g_importargs.can_be_active = readonly;
|
g_importargs.can_be_active = readonly;
|
||||||
g_pool = strdup(target);
|
g_pool = strdup(target);
|
||||||
|
|
||||||
error = zpool_find_config(NULL, target, &config, &g_importargs,
|
error = zpool_tryimport(g_zfs, target, &config, &g_importargs);
|
||||||
&libzpool_config_ops);
|
|
||||||
if (error)
|
if (error)
|
||||||
fatal(NULL, FTAG, "cannot import '%s'", target);
|
fatal(NULL, FTAG, "cannot import '%s': %s", target,
|
||||||
|
libzfs_error_description(g_zfs));
|
||||||
|
|
||||||
props = NULL;
|
props = NULL;
|
||||||
if (readonly) {
|
if (readonly) {
|
||||||
@@ -150,7 +153,6 @@ zhack_import(char *target, boolean_t readonly)
|
|||||||
zfeature_checks_disable = B_TRUE;
|
zfeature_checks_disable = B_TRUE;
|
||||||
error = spa_import(target, config, props,
|
error = spa_import(target, config, props,
|
||||||
(readonly ? ZFS_IMPORT_SKIP_MMP : ZFS_IMPORT_NORMAL));
|
(readonly ? ZFS_IMPORT_SKIP_MMP : ZFS_IMPORT_NORMAL));
|
||||||
fnvlist_free(config);
|
|
||||||
zfeature_checks_disable = B_FALSE;
|
zfeature_checks_disable = B_FALSE;
|
||||||
if (error == EEXIST)
|
if (error == EEXIST)
|
||||||
error = 0;
|
error = 0;
|
||||||
@@ -527,6 +529,7 @@ main(int argc, char **argv)
|
|||||||
"changes may not be committed to disk\n");
|
"changes may not be committed to disk\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libzfs_fini(g_zfs);
|
||||||
kernel_fini();
|
kernel_fini();
|
||||||
|
|
||||||
return (rv);
|
return (rv);
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
include $(top_srcdir)/config/Rules.am
|
include $(top_srcdir)/config/Rules.am
|
||||||
|
|
||||||
|
DEFAULT_INCLUDES += \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
-I$(top_srcdir)/lib/libspl/include
|
||||||
|
|
||||||
sbin_PROGRAMS = zinject
|
sbin_PROGRAMS = zinject
|
||||||
|
|
||||||
zinject_SOURCES = \
|
zinject_SOURCES = \
|
||||||
@@ -8,6 +12,8 @@ zinject_SOURCES = \
|
|||||||
zinject.h
|
zinject.h
|
||||||
|
|
||||||
zinject_LDADD = \
|
zinject_LDADD = \
|
||||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||||
|
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||||
|
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||||
|
|||||||
+144
-20
@@ -20,11 +20,13 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libzfs.h>
|
#include <libzfs.h>
|
||||||
|
|
||||||
|
#include <sys/zfs_context.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -47,6 +49,9 @@
|
|||||||
|
|
||||||
#include "zinject.h"
|
#include "zinject.h"
|
||||||
|
|
||||||
|
extern void kernel_init(int);
|
||||||
|
extern void kernel_fini(void);
|
||||||
|
|
||||||
static int debug;
|
static int debug;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -85,6 +90,8 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
|
|||||||
struct stat64 *statbuf)
|
struct stat64 *statbuf)
|
||||||
{
|
{
|
||||||
struct extmnttab mp;
|
struct extmnttab mp;
|
||||||
|
FILE *fp;
|
||||||
|
int match;
|
||||||
const char *rel;
|
const char *rel;
|
||||||
char fullpath[MAXPATHLEN];
|
char fullpath[MAXPATHLEN];
|
||||||
|
|
||||||
@@ -97,7 +104,35 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getextmntent(fullpath, &mp, statbuf) != 0) {
|
if (strlen(fullpath) >= MAXPATHLEN) {
|
||||||
|
(void) fprintf(stderr, "invalid object; pathname too long\n");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat64(fullpath, statbuf) != 0) {
|
||||||
|
(void) fprintf(stderr, "cannot open '%s': %s\n",
|
||||||
|
fullpath, strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SETMNTENT
|
||||||
|
if ((fp = setmntent(MNTTAB, "r")) == NULL) {
|
||||||
|
#else
|
||||||
|
if ((fp = fopen(MNTTAB, "r")) == NULL) {
|
||||||
|
#endif
|
||||||
|
(void) fprintf(stderr, "cannot open %s\n", MNTTAB);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
match = 0;
|
||||||
|
while (getextmntent(fp, &mp, sizeof (mp)) == 0) {
|
||||||
|
if (makedev(mp.mnt_major, mp.mnt_minor) == statbuf->st_dev) {
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
(void) fprintf(stderr, "cannot find mountpoint for '%s'\n",
|
(void) fprintf(stderr, "cannot find mountpoint for '%s'\n",
|
||||||
fullpath);
|
fullpath);
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -126,32 +161,51 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert from a dataset to a objset id. Note that
|
* Convert from a (dataset, path) pair into a (objset, object) pair. Note that
|
||||||
* we grab the object number from the inode number.
|
* we grab the object number from the inode number, since looking this up via
|
||||||
|
* libzpool is a real pain.
|
||||||
*/
|
*/
|
||||||
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
object_from_path(const char *dataset, uint64_t object, zinject_record_t *record)
|
object_from_path(const char *dataset, const char *path, struct stat64 *statbuf,
|
||||||
|
zinject_record_t *record)
|
||||||
{
|
{
|
||||||
zfs_handle_t *zhp;
|
objset_t *os;
|
||||||
|
int err;
|
||||||
|
|
||||||
if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
|
/*
|
||||||
|
* Before doing any libzpool operations, call sync() to ensure that the
|
||||||
|
* on-disk state is consistent with the in-core state.
|
||||||
|
*/
|
||||||
|
sync();
|
||||||
|
|
||||||
|
err = dmu_objset_own(dataset, DMU_OST_ZFS, B_TRUE, FTAG, &os);
|
||||||
|
if (err != 0) {
|
||||||
|
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||||
|
dataset, strerror(err));
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
record->zi_objset = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
|
record->zi_objset = dmu_objset_id(os);
|
||||||
record->zi_object = object;
|
record->zi_object = statbuf->st_ino;
|
||||||
|
|
||||||
zfs_close(zhp);
|
dmu_objset_disown(os, FTAG);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the range based on the type, level, and range given.
|
* Calculate the real range based on the type, level, and range given.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
initialize_range(err_type_t type, int level, char *range,
|
calculate_range(const char *dataset, err_type_t type, int level, char *range,
|
||||||
zinject_record_t *record)
|
zinject_record_t *record)
|
||||||
{
|
{
|
||||||
|
objset_t *os = NULL;
|
||||||
|
dnode_t *dn = NULL;
|
||||||
|
int err;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the numeric range from the string.
|
* Determine the numeric range from the string.
|
||||||
*/
|
*/
|
||||||
@@ -179,7 +233,7 @@ initialize_range(err_type_t type, int level, char *range,
|
|||||||
(void) fprintf(stderr, "invalid range '%s': must be "
|
(void) fprintf(stderr, "invalid range '%s': must be "
|
||||||
"a numeric range of the form 'start[,end]'\n",
|
"a numeric range of the form 'start[,end]'\n",
|
||||||
range);
|
range);
|
||||||
return (-1);
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +253,7 @@ initialize_range(err_type_t type, int level, char *range,
|
|||||||
if (range != NULL) {
|
if (range != NULL) {
|
||||||
(void) fprintf(stderr, "range cannot be specified when "
|
(void) fprintf(stderr, "range cannot be specified when "
|
||||||
"type is 'dnode'\n");
|
"type is 'dnode'\n");
|
||||||
return (-1);
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
record->zi_start = record->zi_object * sizeof (dnode_phys_t);
|
record->zi_start = record->zi_object * sizeof (dnode_phys_t);
|
||||||
@@ -208,9 +262,76 @@ initialize_range(err_type_t type, int level, char *range,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
record->zi_level = level;
|
/*
|
||||||
|
* Get the dnode associated with object, so we can calculate the block
|
||||||
|
* size.
|
||||||
|
*/
|
||||||
|
if ((err = dmu_objset_own(dataset, DMU_OST_ANY,
|
||||||
|
B_TRUE, FTAG, &os)) != 0) {
|
||||||
|
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||||
|
dataset, strerror(err));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
return (0);
|
if (record->zi_object == 0) {
|
||||||
|
dn = DMU_META_DNODE(os);
|
||||||
|
} else {
|
||||||
|
err = dnode_hold(os, record->zi_object, FTAG, &dn);
|
||||||
|
if (err != 0) {
|
||||||
|
(void) fprintf(stderr, "failed to hold dnode "
|
||||||
|
"for object %llu\n",
|
||||||
|
(u_longlong_t)record->zi_object);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ziprintf("data shift: %d\n", (int)dn->dn_datablkshift);
|
||||||
|
ziprintf(" ind shift: %d\n", (int)dn->dn_indblkshift);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Translate range into block IDs.
|
||||||
|
*/
|
||||||
|
if (record->zi_start != 0 || record->zi_end != -1ULL) {
|
||||||
|
record->zi_start >>= dn->dn_datablkshift;
|
||||||
|
record->zi_end >>= dn->dn_datablkshift;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check level, and then translate level 0 blkids into ranges
|
||||||
|
* appropriate for level of indirection.
|
||||||
|
*/
|
||||||
|
record->zi_level = level;
|
||||||
|
if (level > 0) {
|
||||||
|
ziprintf("level 0 blkid range: [%llu, %llu]\n",
|
||||||
|
record->zi_start, record->zi_end);
|
||||||
|
|
||||||
|
if (level >= dn->dn_nlevels) {
|
||||||
|
(void) fprintf(stderr, "level %d exceeds max level "
|
||||||
|
"of object (%d)\n", level, dn->dn_nlevels - 1);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record->zi_start != 0 || record->zi_end != 0) {
|
||||||
|
int shift = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
|
||||||
|
|
||||||
|
for (; level > 0; level--) {
|
||||||
|
record->zi_start >>= shift;
|
||||||
|
record->zi_end >>= shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
out:
|
||||||
|
if (dn) {
|
||||||
|
if (dn != DMU_META_DNODE(os))
|
||||||
|
dnode_rele(dn, FTAG);
|
||||||
|
}
|
||||||
|
if (os)
|
||||||
|
dmu_objset_disown(os, FTAG);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -222,6 +343,8 @@ translate_record(err_type_t type, const char *object, const char *range,
|
|||||||
struct stat64 statbuf;
|
struct stat64 statbuf;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
|
kernel_init(FREAD);
|
||||||
|
|
||||||
debug = (getenv("ZINJECT_DEBUG") != NULL);
|
debug = (getenv("ZINJECT_DEBUG") != NULL);
|
||||||
|
|
||||||
ziprintf("translating: %s\n", object);
|
ziprintf("translating: %s\n", object);
|
||||||
@@ -273,16 +396,16 @@ translate_record(err_type_t type, const char *object, const char *range,
|
|||||||
/*
|
/*
|
||||||
* Convert (dataset, file) into (objset, object)
|
* Convert (dataset, file) into (objset, object)
|
||||||
*/
|
*/
|
||||||
if (object_from_path(dataset, statbuf.st_ino, record) != 0)
|
if (object_from_path(dataset, path, &statbuf, record) != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ziprintf("raw objset: %llu\n", record->zi_objset);
|
ziprintf("raw objset: %llu\n", record->zi_objset);
|
||||||
ziprintf("raw object: %llu\n", record->zi_object);
|
ziprintf("raw object: %llu\n", record->zi_object);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the given object, initialize the range in bytes
|
* For the given object, calculate the real (type, level, range)
|
||||||
*/
|
*/
|
||||||
if (initialize_range(type, level, (char *)range, record) != 0)
|
if (calculate_range(dataset, type, level, (char *)range, record) != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ziprintf(" objset: %llu\n", record->zi_objset);
|
ziprintf(" objset: %llu\n", record->zi_objset);
|
||||||
@@ -304,6 +427,7 @@ translate_record(err_type_t type, const char *object, const char *range,
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
kernel_fini();
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +512,7 @@ translate_device(const char *pool, const char *device, err_type_t label_type,
|
|||||||
record->zi_end = record->zi_start + VDEV_PAD_SIZE - 1;
|
record->zi_end = record->zi_start + VDEV_PAD_SIZE - 1;
|
||||||
break;
|
break;
|
||||||
case TYPE_LABEL_PAD2:
|
case TYPE_LABEL_PAD2:
|
||||||
record->zi_start = offsetof(vdev_label_t, vl_be);
|
record->zi_start = offsetof(vdev_label_t, vl_pad2);
|
||||||
record->zi_end = record->zi_start + VDEV_PAD_SIZE - 1;
|
record->zi_end = record->zi_start + VDEV_PAD_SIZE - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user