mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 19:04:45 +03:00
Compare commits
148 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1222e921c9 | |||
| c37fa0d5a8 | |||
| 12a78fbb4f | |||
| 63d8f57fe7 | |||
| 9fa8b5b55b | |||
| e17445d1f7 | |||
| 97d4986214 | |||
| 0ae5f0c8d2 | |||
| 146d7d8846 | |||
| 9f261b1be6 | |||
| 5acba22ec0 | |||
| 38528476bf | |||
| beb21db3c6 | |||
| 13e5e396a3 | |||
| 3cf4ecb03f | |||
| 0e765c4eb8 | |||
| c7a4255f12 | |||
| 931bef81c8 | |||
| ea34735203 | |||
| 95319fc569 | |||
| 33374f21f0 | |||
| 512a50f38d | |||
| 023ab67a64 | |||
| 65469f6e30 | |||
| 569f5d5d05 | |||
| 6d1599c1e1 | |||
| 6c9882d5db | |||
| 8c00159411 | |||
| a8c5bcb5de | |||
| 6c68594675 | |||
| 1f5979d23f | |||
| 4f951b183c | |||
| 65a0b28b42 | |||
| be068aeea8 | |||
| 1c4b0fc745 | |||
| bbbe4b0a98 | |||
| 3c144b9267 | |||
| 428a63cc62 | |||
| 3982d959c5 | |||
| 54561073e7 | |||
| 4c98586daf | |||
| ceb516ac2f | |||
| 2b9f73e5e6 | |||
| 984bfb373f | |||
| 446d08fba4 | |||
| af7a5672c3 | |||
| 73e50a7d5d | |||
| d751b12a9d | |||
| 78831d4290 | |||
| 0a223246e1 | |||
| cf966cb19a | |||
| 6e19cc77cf | |||
| c3a3c5a30f | |||
| ccd8125e45 | |||
| 2ac233c633 | |||
| 1f72a18f59 | |||
| 14a11bf2f6 | |||
| 7a03d7c73c | |||
| 9e09826b33 | |||
| 093bb64461 | |||
| 7d2489cfad | |||
| 04d4df89f4 | |||
| 05006f125c | |||
| bfe5f029cf | |||
| cc7fe8a599 | |||
| 7d64595c25 | |||
| be4a282a8d | |||
| 2d88230d97 | |||
| 95fcb04215 | |||
| d053481523 | |||
| 7a5f4656ce | |||
| 1fd28bd8d4 | |||
| ab24c9cd4c | |||
| 3c2a42fd25 | |||
| 9af524b0ee | |||
| b96ceeead2 | |||
| 01cc94f68d | |||
| fb6f6b47d6 | |||
| 2087b6cf49 | |||
| 5b0327bc57 | |||
| b5e8d14a4b | |||
| ed7b0d357a | |||
| 9e54b9d930 | |||
| b033353b25 | |||
| 6083f40387 | |||
| 592ee2e6dd | |||
| cab7d856ea | |||
| 19cebf0518 | |||
| 77e64c6fff | |||
| 4f809bddc6 | |||
| 516a08ebb4 | |||
| 812c36fc71 | |||
| fe11968bbf | |||
| 4be4dedb9f | |||
| fb52bf9b1d | |||
| a22b00f924 | |||
| c350e62309 | |||
| 6f7bc75825 | |||
| 06900c409b | |||
| 60cbc18136 | |||
| b63ed49c29 | |||
| fafe72712a | |||
| 328c95e391 | |||
| 6ce10fdabb | |||
| e4a11acfac | |||
| 90d8067a77 | |||
| e5a877c5d0 | |||
| 4933b0a25b | |||
| e0cd6c28a3 | |||
| 63b88f7e22 | |||
| 72888812b0 | |||
| 581c77e725 | |||
| ba505f90d8 | |||
| eaa21b2349 | |||
| 8dc8bbde6e | |||
| 9fd95a2f1b | |||
| 35050ef39e | |||
| 5108d27aec | |||
| 02010e9c2c | |||
| a0bf24952d | |||
| d6920fb996 | |||
| 58b2de6420 | |||
| 11ad06d1d8 | |||
| 4f8eef29e0 | |||
| 94866d8309 | |||
| a1eaf0dde0 | |||
| 580256045b | |||
| aaf3b30dcf | |||
| 27b446f799 | |||
| 0c6206e7f1 | |||
| 51de7ccb42 | |||
| 69ae34076f | |||
| b746c397e3 | |||
| 2fb37bcadd | |||
| a727f69e52 | |||
| 8ec352be1f | |||
| df717bb835 | |||
| e0b3689ed5 | |||
| 438275c9a0 | |||
| 8cfa6d4a1c | |||
| ad0157ec91 | |||
| cd75d5f710 | |||
| c6bbacebc8 | |||
| 4d7cb872e8 | |||
| f91e7e6284 | |||
| abe267f677 | |||
| cc434dcf45 | |||
| e2e7b0a2cd |
@@ -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
|
||||
+94
-83
@@ -1,12 +1,10 @@
|
||||
# Contributing to OpenZFS
|
||||
<p align="center">
|
||||
<img alt="OpenZFS Logo"
|
||||
src="https://openzfs.github.io/openzfs-docs/_static/img/logo/480px-Open-ZFS-Secondary-Logo-Colour-halfsize.png"/>
|
||||
</p>
|
||||
# Contributing to ZFS on Linux
|
||||
<p align="center"><img src="http://zfsonlinux.org/images/zfs-linux.png"/></p>
|
||||
|
||||
*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
|
||||
[What should I know before I get
|
||||
@@ -34,17 +32,17 @@ started?](#what-should-i-know-before-i-get-started)
|
||||
|
||||
Helpful resources
|
||||
|
||||
* [OpenZFS Documentation](https://openzfs.github.io/openzfs-docs/)
|
||||
* [OpenZFS Developer Resources](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)
|
||||
* [ZFS on Linux wiki](https://github.com/zfsonlinux/zfs/wiki)
|
||||
* [OpenZFS Documentation](http://open-zfs.org/wiki/Developer_resources)
|
||||
* [Git and GitHub for beginners](https://github.com/zfsonlinux/zfs/wiki/Git-and-GitHub-for-beginners)
|
||||
|
||||
## What should I know before I get started?
|
||||
|
||||
### Get ZFS
|
||||
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
|
||||
repository](https://openzfs.github.io/openzfs-docs/Getting%20Started/index.html).
|
||||
repository](https://github.com/zfsonlinux/zfs/wiki/Getting-Started).
|
||||
|
||||
### Debug ZFS
|
||||
A variety of methods and tools are available to aid ZFS developers.
|
||||
@@ -53,30 +51,29 @@ configure option should be set. This will enable additional correctness
|
||||
checks and all the ASSERTs to help quickly catch potential issues.
|
||||
|
||||
In addition, there are numerous utilities and debugging files which
|
||||
provide visibility into the inner workings of ZFS. The most useful
|
||||
of these tools are discussed in detail on the [Troubleshooting
|
||||
page](https://openzfs.github.io/openzfs-docs/Basic%20Concepts/Troubleshooting.html).
|
||||
provide visibility in to the inner workings of ZFS. The most useful
|
||||
of these tools are discussed in detail on the [debugging ZFS wiki
|
||||
page](https://github.com/zfsonlinux/zfs/wiki/Debugging).
|
||||
|
||||
### Where can I ask for help?
|
||||
The [zfs-discuss mailing
|
||||
list](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html)
|
||||
or IRC are the best places to ask for help. Please do not file
|
||||
support requests on the GitHub issue tracker.
|
||||
[The zfs-discuss mailing list or IRC](http://list.zfsonlinux.org)
|
||||
are the best places to ask for help. Please do not file support requests
|
||||
on the GitHub issue tracker.
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting Bugs
|
||||
*Please* contact us via the [zfs-discuss mailing
|
||||
list](https://openzfs.github.io/openzfs-docs/Project%20and%20Community/Mailing%20Lists.html)
|
||||
or IRC if you aren't certain that you are experiencing a bug.
|
||||
list or IRC](http://list.zfsonlinux.org) if you aren't
|
||||
certain that you are experiencing a bug.
|
||||
|
||||
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
|
||||
found anything similar to your 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:
|
||||
* What distribution (with version) you are using.
|
||||
@@ -108,13 +105,13 @@ information like:
|
||||
* Stack traces which may be logged to `dmesg`.
|
||||
|
||||
### Suggesting Enhancements
|
||||
OpenZFS is a widely deployed production filesystem which is under active
|
||||
development. The team's primary focus is on fixing known issues, improving
|
||||
performance, and adding compelling new features.
|
||||
ZFS on Linux is a widely deployed production filesystem which is under
|
||||
active development. The team's primary focus is on fixing known issues,
|
||||
improving performance, and adding compelling new features.
|
||||
|
||||
You can view the list of proposed features
|
||||
by filtering the issue tracker by the ["Type: Feature"
|
||||
label](https://github.com/openzfs/zfs/issues?q=is%3Aopen+is%3Aissue+label%3A%22Type%3A+Feature%22).
|
||||
by filtering the issue tracker by the ["Feature"
|
||||
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
|
||||
appears then add a +1 to the top most comment, this helps us gauge interest
|
||||
in that feature.
|
||||
@@ -123,11 +120,8 @@ Otherwise, open a new issue and describe your proposed feature. Why is this
|
||||
feature needed? What problem does it solve?
|
||||
|
||||
### Pull Requests
|
||||
|
||||
#### General
|
||||
|
||||
* All pull requests, except backports and releases, must be based on the current master branch
|
||||
and should apply without conflicts.
|
||||
* All pull requests must be based on the current master branch and apply
|
||||
without conflicts.
|
||||
* Please attempt to limit pull requests to a single commit which resolves
|
||||
one specific issue.
|
||||
* Make sure your commit messages are in the correct format. See the
|
||||
@@ -139,28 +133,16 @@ logically independent patches which build on each other. This makes large
|
||||
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
|
||||
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.
|
||||
This includes making sure new features have adequate code coverage.
|
||||
* If your pull request improves performance, please include some benchmarks.
|
||||
* The pull request must pass all required [ZFS
|
||||
Buildbot](http://build.zfsonlinux.org/) builders before
|
||||
being accepted. If you are experiencing intermittent TEST
|
||||
builder failures, you may be experiencing a [test suite
|
||||
issue](https://github.com/openzfs/zfs/issues?q=is%3Aissue+is%3Aopen+label%3A%22Type%3A+Test+Suite%22).
|
||||
There are also various [buildbot options](https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.html)
|
||||
issue](https://github.com/zfsonlinux/zfs/issues?q=is%3Aissue+is%3Aopen+label%3A%22Test+Suite%22).
|
||||
There are also various [buildbot options](https://github.com/zfsonlinux/zfs/wiki/Buildbot-Options)
|
||||
to control how changes are tested.
|
||||
* All proposed changes must be approved by a ZFS on Linux organization member.
|
||||
|
||||
### Testing
|
||||
All help is appreciated! If you're in a position to run the latest code
|
||||
@@ -170,41 +152,16 @@ range of realistic workloads, configurations and architectures we're better
|
||||
able quickly identify and resolve potential issues.
|
||||
|
||||
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.
|
||||
|
||||
## 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
|
||||
We currently use [C Style and Coding Standards for
|
||||
SunOS](http://www.cis.upenn.edu/%7Elee/06cse480/data/cstyle.ms.pdf) as our
|
||||
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
|
||||
#### New Changes
|
||||
Commit messages for new changes must meet the following guidelines:
|
||||
@@ -230,6 +187,70 @@ attempting to solve.
|
||||
Signed-off-by: Contributor <contributor@email.com>
|
||||
```
|
||||
|
||||
#### OpenZFS Patch Ports
|
||||
If you are porting OpenZFS patches, the commit message must meet
|
||||
the following guidelines:
|
||||
* The first line must be the summary line from the most important OpenZFS commit being ported.
|
||||
It must begin with `OpenZFS dddd, dddd - ` where `dddd` are OpenZFS issue numbers.
|
||||
* Provides a `Authored by:` line to attribute each patch for each original author.
|
||||
* Provides the `Reviewed by:` and `Approved by:` lines from each original
|
||||
OpenZFS commit.
|
||||
* Provides a `Ported-by:` line with the developer's name followed by
|
||||
their email for each OpenZFS commit.
|
||||
* Provides a `OpenZFS-issue:` line with link for each original illumos
|
||||
issue.
|
||||
* Provides a `OpenZFS-commit:` line with link for each original OpenZFS commit.
|
||||
* If necessary, provide some porting notes to describe any deviations from
|
||||
the original OpenZFS commits.
|
||||
|
||||
An example OpenZFS patch port commit message for a single patch is provided
|
||||
below.
|
||||
```
|
||||
OpenZFS 1234 - Summary from the original OpenZFS commit
|
||||
|
||||
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>
|
||||
|
||||
Provide some porting notes here if necessary.
|
||||
|
||||
OpenZFS-issue: https://www.illumos.org/issues/1234
|
||||
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/abcd1234
|
||||
```
|
||||
|
||||
If necessary, multiple OpenZFS patches can be combined in a single port.
|
||||
This is useful when you are porting a new patch and its subsequent bug
|
||||
fixes. An example commit message is provided below.
|
||||
```
|
||||
OpenZFS 1234, 5678 - Summary of most important OpenZFS commit
|
||||
|
||||
1234 Summary from original OpenZFS commit for 1234
|
||||
|
||||
Authored by: Original Author <original@email.com>
|
||||
Reviewed by: Reviewer Two <reviewer2@email.com>
|
||||
Approved by: Approver One <approver1@email.com>
|
||||
Ported-by: ZFS Contributor <contributor@email.com>
|
||||
|
||||
Provide some porting notes here for 1234 if necessary.
|
||||
|
||||
OpenZFS-issue: https://www.illumos.org/issues/1234
|
||||
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/abcd1234
|
||||
|
||||
5678 Summary from original OpenZFS commit for 5678
|
||||
|
||||
Authored by: Original Author2 <original2@email.com>
|
||||
Reviewed by: Reviewer One <reviewer1@email.com>
|
||||
Approved by: Approver Two <approver2@email.com>
|
||||
Ported-by: ZFS Contributor <contributor@email.com>
|
||||
|
||||
Provide some porting notes here for 5678 if necessary.
|
||||
|
||||
OpenZFS-issue: https://www.illumos.org/issues/5678
|
||||
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/efgh5678
|
||||
```
|
||||
|
||||
#### Coverity Defect Fixes
|
||||
If you are submitting a fix to a
|
||||
[Coverity defect](https://scan.coverity.com/projects/zfsonlinux-zfs),
|
||||
@@ -269,13 +290,3 @@ 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>`
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
---
|
||||
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.
|
||||
*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.
|
||||
-->
|
||||
@@ -22,17 +18,17 @@ 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 |
|
||||
<!--
|
||||
--- | ---
|
||||
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
|
||||
modinfo spl | grep -iw version
|
||||
-->
|
||||
|
||||
### Describe the problem you're observing
|
||||
@@ -40,9 +36,9 @@ modinfo spl | grep -iw version
|
||||
### 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.
|
||||
<!--
|
||||
*IMPORTANT* - Please mark logs and text output from terminal commands
|
||||
or else Github will not display them correctly.
|
||||
An example is provided below.
|
||||
|
||||
Example:
|
||||
@@ -50,4 +46,3 @@ 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?
|
||||
-->
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<!---
|
||||
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
|
||||
-->
|
||||
|
||||
### Motivation and Context
|
||||
@@ -19,7 +19,6 @@ https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.
|
||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||
<!--- see how your change affects other areas of the code, etc. -->
|
||||
<!--- If your change is a performance enhancement, please provide benchmarks here. -->
|
||||
<!--- Please think about using the draft PR feature if appropriate -->
|
||||
|
||||
### Types of changes
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
@@ -37,5 +36,5 @@ https://openzfs.github.io/openzfs-docs/Developer%20Resources/Buildbot%20Options.
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have read the [**contributing** document](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md).
|
||||
- [ ] I have added [tests](https://github.com/zfsonlinux/zfs/tree/master/tests) to cover my changes.
|
||||
- [ ] I have run the ZFS Test Suite with this change applied.
|
||||
- [ ] 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).
|
||||
|
||||
+1
-4
@@ -4,8 +4,7 @@ codecov:
|
||||
after_n_builds: 2 # user and kernel
|
||||
|
||||
coverage:
|
||||
precision: 0 # 0 decimals of precision
|
||||
round: nearest # Round to nearest precision point
|
||||
precision: 2 # 2 digits of precision
|
||||
range: "50...90" # red -> yellow -> green
|
||||
|
||||
status:
|
||||
@@ -21,5 +20,3 @@ comment:
|
||||
layout: "reach, diff, flags, footer"
|
||||
behavior: once # update if exists; post new; skip if deleted
|
||||
require_changes: yes # only post when coverage changes
|
||||
|
||||
# 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-18.04
|
||||
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,70 +0,0 @@
|
||||
name: zfs-tests-functional
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
tests-functional-ubuntu:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [18.04, 20.04]
|
||||
runs-on: ubuntu-${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
||||
git alien fakeroot wget curl bc fio acl \
|
||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
||||
nfs-kernel-server samba rng-tools xz-utils \
|
||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
||||
python3 python3-dev python3-setuptools python3-cffi
|
||||
- name: Autogen.sh
|
||||
run: |
|
||||
sh autogen.sh
|
||||
- name: Configure
|
||||
run: |
|
||||
./configure --enable-debug --enable-debuginfo
|
||||
- name: Make
|
||||
run: |
|
||||
make --no-print-directory -s pkg-utils pkg-kmod
|
||||
- name: Install
|
||||
run: |
|
||||
sudo dpkg -i *.deb
|
||||
# Update order of directories to search for modules, otherwise
|
||||
# Ubuntu will load kernel-shipped ones.
|
||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
||||
sudo depmod
|
||||
sudo modprobe zfs
|
||||
# Workaround to provide additional free space for testing.
|
||||
# https://github.com/actions/virtual-environments/issues/2840
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf "/usr/local/share/boost"
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
- name: Tests
|
||||
run: |
|
||||
/usr/share/zfs/zfs-tests.sh -v -s 3G
|
||||
- name: Prepare artifacts
|
||||
if: failure()
|
||||
run: |
|
||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
||||
sudo dmesg > $RESULTS_PATH/dmesg
|
||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
||||
sudo chmod +r $RESULTS_PATH/*
|
||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
||||
for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: Test logs Ubuntu-${{ matrix.os }}
|
||||
path: /var/tmp/test_results/20*/
|
||||
if-no-files-found: ignore
|
||||
@@ -1,66 +0,0 @@
|
||||
name: zfs-tests-sanity
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb lcov \
|
||||
git alien fakeroot wget curl bc fio acl \
|
||||
sysstat mdadm lsscsi parted gdebi attr dbench watchdog ksh \
|
||||
nfs-kernel-server samba rng-tools xz-utils \
|
||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
||||
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
|
||||
python3 python3-dev python3-setuptools python3-cffi
|
||||
- name: Autogen.sh
|
||||
run: |
|
||||
sh autogen.sh
|
||||
- name: Configure
|
||||
run: |
|
||||
./configure --enable-debug --enable-debuginfo
|
||||
- name: Make
|
||||
run: |
|
||||
make --no-print-directory -s pkg-utils pkg-kmod
|
||||
- name: Install
|
||||
run: |
|
||||
sudo dpkg -i *.deb
|
||||
# Update order of directories to search for modules, otherwise
|
||||
# Ubuntu will load kernel-shipped ones.
|
||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
||||
sudo depmod
|
||||
sudo modprobe zfs
|
||||
# Workaround to provide additional free space for testing.
|
||||
# https://github.com/actions/virtual-environments/issues/2840
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf "/usr/local/share/boost"
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
- name: Tests
|
||||
run: |
|
||||
/usr/share/zfs/zfs-tests.sh -v -s 3G -r sanity
|
||||
- name: Prepare artifacts
|
||||
if: failure()
|
||||
run: |
|
||||
RESULTS_PATH=$(readlink -f /var/tmp/test_results/current)
|
||||
sudo dmesg > $RESULTS_PATH/dmesg
|
||||
sudo cp /var/log/syslog $RESULTS_PATH/
|
||||
sudo chmod +r $RESULTS_PATH/*
|
||||
# Replace ':' in dir names, actions/upload-artifact doesn't support it
|
||||
for f in $(find $RESULTS_PATH -name '*:*'); do mv "$f" "${f//:/__}"; done
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: Test logs
|
||||
path: /var/tmp/test_results/20*/
|
||||
if-no-files-found: ignore
|
||||
@@ -1,67 +0,0 @@
|
||||
name: zloop
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TEST_DIR: /var/tmp/zloop
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes -qq build-essential autoconf libtool gdb \
|
||||
git alien fakeroot \
|
||||
zlib1g-dev uuid-dev libblkid-dev libselinux-dev \
|
||||
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
|
||||
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
|
||||
libpam0g-dev \
|
||||
python-dev python-setuptools python-cffi \
|
||||
python3 python3-dev python3-setuptools python3-cffi
|
||||
- name: Autogen.sh
|
||||
run: |
|
||||
sh autogen.sh
|
||||
- name: Configure
|
||||
run: |
|
||||
./configure --enable-debug --enable-debuginfo
|
||||
- name: Make
|
||||
run: |
|
||||
make --no-print-directory -s pkg-utils pkg-kmod
|
||||
- name: Install
|
||||
run: |
|
||||
sudo dpkg -i *.deb
|
||||
# Update order of directories to search for modules, otherwise
|
||||
# Ubuntu will load kernel-shipped ones.
|
||||
sudo sed -i.bak 's/updates/extra updates/' /etc/depmod.d/ubuntu.conf
|
||||
sudo depmod
|
||||
sudo modprobe zfs
|
||||
- name: Tests
|
||||
run: |
|
||||
sudo mkdir -p $TEST_DIR
|
||||
# run for 20 minutes to have a total runner time of 30 minutes
|
||||
sudo /usr/share/zfs/zloop.sh -t 1200 -l -m1
|
||||
- name: Prepare artifacts
|
||||
if: failure()
|
||||
run: |
|
||||
sudo chmod +r -R $TEST_DIR/
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: Logs
|
||||
path: |
|
||||
/var/tmp/zloop/*/
|
||||
!/var/tmp/zloop/*/vdev/
|
||||
if-no-files-found: ignore
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: Pool files
|
||||
path: |
|
||||
/var/tmp/zloop/*/vdev/
|
||||
if-no-files-found: ignore
|
||||
+11
-5
@@ -36,7 +36,6 @@ Makefile.in
|
||||
# Top level generated files specific to this top level dir
|
||||
#
|
||||
/bin
|
||||
/build
|
||||
/configure
|
||||
/config.log
|
||||
/config.status
|
||||
@@ -62,9 +61,16 @@ cscope.*
|
||||
*.patch
|
||||
*.orig
|
||||
*.log
|
||||
*.tmp
|
||||
venv
|
||||
|
||||
*.so
|
||||
*.so.debug
|
||||
*.so.full
|
||||
#
|
||||
# Module leftovers
|
||||
#
|
||||
/module/avl/zavl.mod
|
||||
/module/icp/icp.mod
|
||||
/module/lua/zlua.mod
|
||||
/module/nvpair/znvpair.mod
|
||||
/module/spl/spl.mod
|
||||
/module/unicode/zunicode.mod
|
||||
/module/zcommon/zcommon.mod
|
||||
/module/zfs/zfs.mod
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
language: c
|
||||
sudo: required
|
||||
env:
|
||||
global:
|
||||
# Travis limits maximum log size, we have to cut tests output
|
||||
- ZFS_TEST_TRAVIS_LOG_MAX_LENGTH=800
|
||||
matrix:
|
||||
# tags are mainly in ascending order
|
||||
- ZFS_TEST_TAGS='acl,atime,bootfs,cachefile,casenorm,chattr,checksum,clean_mirror,compression,ctime,delegate,devices,events,exec,fault,features,grow_pool,zdb,zfs,zfs_bookmark,zfs_change-key,zfs_clone,zfs_copies,zfs_create,zfs_diff,zfs_get,zfs_inherit,zfs_load-key,zfs_rename'
|
||||
- ZFS_TEST_TAGS='cache,history,hkdf,inuse,zfs_property,zfs_receive,zfs_reservation,zfs_send,zfs_set,zfs_share,zfs_snapshot,zfs_unload-key,zfs_unmount,zfs_unshare,zfs_upgrade,zpool,zpool_add,zpool_attach,zpool_clear,zpool_create,zpool_destroy,zpool_detach'
|
||||
- ZFS_TEST_TAGS='grow_replicas,mv_files,cli_user,zfs_mount,zfs_promote,zfs_rollback,zpool_events,zpool_expand,zpool_export,zpool_get,zpool_history,zpool_import,zpool_labelclear,zpool_offline,zpool_online,zpool_remove,zpool_reopen,zpool_replace,zpool_scrub,zpool_set,zpool_status,zpool_sync,zpool_upgrade'
|
||||
- ZFS_TEST_TAGS='zfs_destroy,large_files,largest_pool,link_count,migration,mmap,mmp,mount,nestedfs,no_space,nopwrite,online_offline,pool_names,poolversion,privilege,quota,raidz,redundancy,rsend'
|
||||
- ZFS_TEST_TAGS='inheritance,refquota,refreserv,rename_dirs,replacement,reservation,rootpool,scrub_mirror,slog,snapshot,snapused,sparse,threadsappend,tmpfile,truncate,upgrade,userquota,vdev_zaps,write_dirs,xattr,zvol,libzfs'
|
||||
before_install:
|
||||
- sudo apt-get -qq 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
|
||||
# packages for tests
|
||||
- sudo apt-get install --yes -qq parted lsscsi ksh attr acl nfs-kernel-server fio
|
||||
install:
|
||||
- git clone --depth=1 https://github.com/zfsonlinux/spl
|
||||
- cd spl
|
||||
- git checkout master
|
||||
- sh autogen.sh
|
||||
- ./configure
|
||||
- make --no-print-directory -s pkg-utils pkg-kmod
|
||||
- sudo dpkg -i *.deb
|
||||
- cd ..
|
||||
- sh autogen.sh
|
||||
- ./configure
|
||||
- make --no-print-directory -s pkg-utils pkg-kmod
|
||||
- sudo dpkg -i *.deb
|
||||
script:
|
||||
- travis_wait 50 /usr/share/zfs/zfs-tests.sh -v -T $ZFS_TEST_TAGS
|
||||
after_failure:
|
||||
- find /var/tmp/test_results/current/log -type f -name '*' -printf "%f\n" -exec cut -c -$ZFS_TEST_TRAVIS_LOG_MAX_LENGTH {} \;
|
||||
after_success:
|
||||
- find /var/tmp/test_results/current/log -type f -name '*' -printf "%f\n" -exec cut -c -$ZFS_TEST_TRAVIS_LOG_MAX_LENGTH {} \;
|
||||
@@ -83,7 +83,6 @@ CONTRIBUTORS:
|
||||
Christopher Voltz <cjunk@voltz.ws>
|
||||
Chunwei Chen <david.chen@nutanix.com>
|
||||
Clemens Fruhwirth <clemens@endorphin.org>
|
||||
Coleman Kane <ckane@colemankane.org>
|
||||
Colin Ian King <colin.king@canonical.com>
|
||||
Craig Loomis <cloomis@astro.princeton.edu>
|
||||
Craig Sanders <github@taz.net.au>
|
||||
@@ -182,7 +181,6 @@ CONTRIBUTORS:
|
||||
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>
|
||||
@@ -211,7 +209,6 @@ CONTRIBUTORS:
|
||||
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>
|
||||
@@ -260,7 +257,6 @@ CONTRIBUTORS:
|
||||
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>
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
The [OpenZFS Code of Conduct](http://www.open-zfs.org/wiki/Code_of_Conduct)
|
||||
applies to spaces associated with the OpenZFS project, including GitHub.
|
||||
applies to spaces associated with the ZFS on Linux project, including GitHub.
|
||||
|
||||
@@ -19,11 +19,7 @@ notable exceptions and their respective licenses include:
|
||||
* 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
|
||||
* SPL Implementation: module/spl/THIRDPARTYLICENSE.gplv2
|
||||
|
||||
This product includes software developed by the OpenSSL Project for use
|
||||
in the OpenSSL Toolkit (http://www.openssl.org/)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Meta: 1
|
||||
Name: zfs
|
||||
Branch: 1.0
|
||||
Version: 2.0.6
|
||||
Version: 0.8.2
|
||||
Release: 1
|
||||
Release-Tags: relext
|
||||
License: CDDL
|
||||
Author: OpenZFS
|
||||
Linux-Maximum: 5.14
|
||||
Linux-Minimum: 3.10
|
||||
Author: OpenZFS on Linux
|
||||
Linux-Maximum: 5.3
|
||||
Linux-Minimum: 2.6.32
|
||||
|
||||
+36
-131
@@ -1,15 +1,12 @@
|
||||
ACLOCAL_AMFLAGS = -I config
|
||||
|
||||
SUBDIRS = include
|
||||
if BUILD_LINUX
|
||||
SUBDIRS += rpm
|
||||
endif
|
||||
include config/rpm.am
|
||||
include config/deb.am
|
||||
include config/tgz.am
|
||||
|
||||
SUBDIRS = include rpm
|
||||
if CONFIG_USER
|
||||
SUBDIRS += etc man scripts lib tests cmd contrib
|
||||
if BUILD_LINUX
|
||||
SUBDIRS += udev
|
||||
endif
|
||||
SUBDIRS += udev etc man scripts lib tests cmd contrib
|
||||
endif
|
||||
if CONFIG_KERNEL
|
||||
SUBDIRS += module
|
||||
@@ -17,51 +14,33 @@ SUBDIRS += module
|
||||
extradir = $(prefix)/src/zfs-$(VERSION)
|
||||
extra_HEADERS = zfs.release.in zfs_config.h.in
|
||||
|
||||
if BUILD_LINUX
|
||||
kerneldir = $(prefix)/src/zfs-$(VERSION)/$(LINUX_VERSION)
|
||||
nodist_kernel_HEADERS = zfs.release zfs_config.h module/$(LINUX_SYMBOLS)
|
||||
endif
|
||||
endif
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
EXTRA_DIST = autogen.sh copy-builtin
|
||||
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 += 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
|
||||
EXTRA_DIST += module/icp/algs/skein/THIRDPARTYLICENSE module/icp/algs/skein/THIRDPARTYLICENSE.descrip
|
||||
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman.descrip
|
||||
EXTRA_DIST += module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl.descrip
|
||||
EXTRA_DIST += module/spl/THIRDPARTYLICENSE.gplv2 module/spl/THIRDPARTYLICENSE.gplv2.descrip
|
||||
EXTRA_DIST += module/zfs/THIRDPARTYLICENSE.cityhash module/zfs/THIRDPARTYLICENSE.cityhash.descrip
|
||||
|
||||
@CODE_COVERAGE_RULES@
|
||||
|
||||
GITREV = include/zfs_gitrev.h
|
||||
|
||||
PHONY = gitrev
|
||||
.PHONY: gitrev
|
||||
gitrev:
|
||||
$(AM_V_GEN)$(top_srcdir)/scripts/make_gitrev.sh $(GITREV)
|
||||
-${top_srcdir}/scripts/make_gitrev.sh
|
||||
|
||||
all: gitrev
|
||||
|
||||
# Double-colon rules are allowed; there are multiple independent definitions.
|
||||
maintainer-clean-local::
|
||||
-$(RM) $(GITREV)
|
||||
BUILT_SOURCES = gitrev
|
||||
|
||||
distclean-local::
|
||||
-$(RM) -R autom4te*.cache build
|
||||
-$(RM) -R autom4te*.cache
|
||||
-find . \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \
|
||||
-o -name .pc -o -name .hg -o -name .git \) -prune -o \
|
||||
\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
|
||||
@@ -76,12 +55,11 @@ all-local:
|
||||
-[ -x ${top_builddir}/scripts/zfs-tests.sh ] && \
|
||||
${top_builddir}/scripts/zfs-tests.sh -c
|
||||
|
||||
dist-hook:
|
||||
$(AM_V_GEN)$(top_srcdir)/scripts/make_gitrev.sh -D $(distdir) $(GITREV)
|
||||
$(SED) ${ac_inplace} -e 's/Release:[[:print:]]*/Release: $(RELEASE)/' \
|
||||
dist-hook: gitrev
|
||||
cp ${top_srcdir}/include/zfs_gitrev.h $(distdir)/include; \
|
||||
sed -i 's/Release:[[:print:]]*/Release: $(RELEASE)/' \
|
||||
$(distdir)/META
|
||||
|
||||
if BUILD_LINUX
|
||||
# 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.
|
||||
@@ -98,75 +76,31 @@ install-data-hook:
|
||||
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
|
||||
codecheck: cstyle shellcheck flake8 mancheck testscheck vcscheck
|
||||
|
||||
PHONY += checkstyle
|
||||
checkstyle: codecheck commitcheck
|
||||
|
||||
PHONY += commitcheck
|
||||
commitcheck:
|
||||
@if git rev-parse --git-dir > /dev/null 2>&1; then \
|
||||
${top_srcdir}/scripts/commitcheck.sh; \
|
||||
fi
|
||||
|
||||
PHONY += cstyle
|
||||
cstyle:
|
||||
@find ${top_srcdir} -name build -prune \
|
||||
-o -type f -name '*.[hc]' \
|
||||
! -name 'zfs_config.*' ! -name '*.mod.c' \
|
||||
! -name 'opt_global.h' ! -name '*_if*.h' \
|
||||
! -path './module/zstd/lib/*' \
|
||||
@find ${top_srcdir} -name '*.[hc]' ! -name 'zfs_config.*' \
|
||||
! -name '*.mod.c' -type f \
|
||||
-exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
|
||||
|
||||
filter_executable = -exec test -x '{}' \; -print
|
||||
|
||||
PHONY += shellcheck
|
||||
shellcheck:
|
||||
@if type shellcheck > /dev/null 2>&1; then \
|
||||
shellcheck --exclude=SC1090 --exclude=SC1117 --format=gcc \
|
||||
shellcheck --exclude=SC1090 --format=gcc \
|
||||
$$(find ${top_srcdir}/scripts/*.sh -type f) \
|
||||
$$(find ${top_srcdir}/cmd/zed/zed.d/*.sh -type f) \
|
||||
$$(find ${top_srcdir}/cmd/zpool/zpool.d/* \
|
||||
-type f ${filter_executable}); \
|
||||
$$(find ${top_srcdir}/cmd/zpool/zpool.d/* -executable); \
|
||||
else \
|
||||
echo "skipping shellcheck because shellcheck is not installed"; \
|
||||
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' \
|
||||
@@ -177,52 +111,40 @@ mancheck:
|
||||
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} | \
|
||||
\( -name '*.ksh' -not -executable \) -o \
|
||||
\( -name '*.kshlib' -executable \) -o \
|
||||
\( -name '*.shlib' -executable \) -o \
|
||||
\( -name '*.cfg' -executable \) | \
|
||||
xargs -r stat -c '%A %n' | \
|
||||
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
|
||||
|
||||
CPPCHECKDIRS = cmd lib module
|
||||
PHONY += cppcheck
|
||||
cppcheck: $(CPPCHECKDIRS)
|
||||
@if test -n "$(CPPCHECK)"; then \
|
||||
set -e ; for dir in $(CPPCHECKDIRS) ; do \
|
||||
$(MAKE) -C $$dir cppcheck ; \
|
||||
done \
|
||||
cppcheck:
|
||||
@if type cppcheck > /dev/null 2>&1; then \
|
||||
cppcheck --quiet --force --error-exitcode=2 --inline-suppr \
|
||||
--suppressions-list=.github/suppressions.txt \
|
||||
-UHAVE_SSE2 -UHAVE_AVX512F -UHAVE_UIO_ZEROCOPY \
|
||||
${top_srcdir}; \
|
||||
else \
|
||||
echo "skipping cppcheck because cppcheck is not installed"; \
|
||||
fi
|
||||
|
||||
PHONY += paxcheck
|
||||
paxcheck:
|
||||
@if type scanelf > /dev/null 2>&1; then \
|
||||
${top_srcdir}/scripts/paxcheck.sh ${top_builddir}; \
|
||||
${top_srcdir}/scripts/paxcheck.sh ${top_srcdir}; \
|
||||
else \
|
||||
echo "skipping paxcheck because scanelf is not installed"; \
|
||||
fi
|
||||
|
||||
PHONY += flake8
|
||||
flake8:
|
||||
@if type flake8 > /dev/null 2>&1; then \
|
||||
flake8 ${top_srcdir}; \
|
||||
@@ -230,34 +152,17 @@ flake8:
|
||||
echo "skipping flake8 because flake8 is not installed"; \
|
||||
fi
|
||||
|
||||
PHONY += ctags
|
||||
ctags:
|
||||
$(RM) tags
|
||||
find $(top_srcdir) -name '.?*' -prune \
|
||||
-o -type f -name '*.[hcS]' -print | xargs ctags -a
|
||||
find $(top_srcdir) -name .git -prune -o -name '*.[hc]' | xargs ctags
|
||||
|
||||
PHONY += etags
|
||||
etags:
|
||||
$(RM) TAGS
|
||||
find $(top_srcdir) -name '.?*' -prune \
|
||||
-o -type f -name '*.[hcS]' -print | xargs etags -a
|
||||
find $(top_srcdir) -name .pc -prune -o -name '*.[hc]' | xargs etags -a
|
||||
|
||||
PHONY += cscopelist
|
||||
cscopelist:
|
||||
find $(top_srcdir) -name '.?*' -prune \
|
||||
-o -type f -name '*.[hc]' -print >cscope.files
|
||||
|
||||
PHONY += tags
|
||||
tags: ctags etags
|
||||
|
||||
PHONY += pkg pkg-dkms pkg-kmod pkg-utils
|
||||
pkg: @DEFAULT_PACKAGE@
|
||||
pkg-dkms: @DEFAULT_PACKAGE@-dkms
|
||||
pkg-kmod: @DEFAULT_PACKAGE@-kmod
|
||||
pkg-utils: @DEFAULT_PACKAGE@-utils
|
||||
|
||||
include config/rpm.am
|
||||
include config/deb.am
|
||||
include config/tgz.am
|
||||
|
||||
.PHONY: $(PHONY)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Descriptions of all releases can be found on github:
|
||||
|
||||
https://github.com/openzfs/zfs/releases
|
||||
https://github.com/zfsonlinux/zfs/releases
|
||||
|
||||
@@ -1,35 +1,31 @@
|
||||

|
||||

|
||||
|
||||
OpenZFS is an advanced file system and volume manager which was originally
|
||||
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.
|
||||
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)
|
||||
[](https://codecov.io/gh/zfsonlinux/zfs)
|
||||
[](https://scan.coverity.com/projects/zfsonlinux-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)
|
||||
* [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 OpenZFS on your favorite operating system can
|
||||
be found at the [Getting Started Page](https://openzfs.github.io/openzfs-docs/Getting%20Started/index.html).
|
||||
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).
|
||||
|
||||
We have a [Code of Conduct](./CODE_OF_CONDUCT.md).
|
||||
|
||||
# Release
|
||||
|
||||
OpenZFS is released under a CDDL license.
|
||||
ZFS on Linux 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.
|
||||
* The `META` file contains the officially recognized supported kernel versions.
|
||||
|
||||
@@ -48,3 +48,64 @@
|
||||
#TEST_ZFSSTRESS_VDEV="/var/tmp/vdev"
|
||||
#TEST_ZFSSTRESS_DIR="/$TEST_ZFSSTRESS_POOL/$TEST_ZFSSTRESS_FS"
|
||||
#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
|
||||
|
||||
###
|
||||
#
|
||||
# Run ztest longer on the "coverage" builders to gain more code coverage
|
||||
# data out of ztest, libzpool, etc.
|
||||
#
|
||||
case "$BB_NAME" in
|
||||
*coverage*)
|
||||
TEST_ZTEST_TIMEOUT=3600
|
||||
;;
|
||||
*)
|
||||
TEST_ZTEST_TIMEOUT=900
|
||||
;;
|
||||
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
|
||||
|
||||
+3
-15
@@ -1,20 +1,8 @@
|
||||
SUBDIRS = zfs zpool zdb zhack zinject zstream zstreamdump ztest
|
||||
SUBDIRS += fsck_zfs vdev_id raidz_test zfs_ids_to_path
|
||||
|
||||
CPPCHECKDIRS = zfs zpool zdb zhack zinject zstream ztest
|
||||
CPPCHECKDIRS += raidz_test zfs_ids_to_path
|
||||
SUBDIRS = zfs zpool zdb zhack zinject zstreamdump ztest
|
||||
SUBDIRS += fsck_zfs vdev_id raidz_test zgenhostid
|
||||
|
||||
if USING_PYTHON
|
||||
SUBDIRS += arcstat arc_summary dbufstat
|
||||
endif
|
||||
|
||||
if BUILD_LINUX
|
||||
SUBDIRS += mount_zfs zed zgenhostid zvol_id zvol_wait
|
||||
CPPCHECKDIRS += mount_zfs zed zgenhostid zvol_id
|
||||
endif
|
||||
|
||||
PHONY = cppcheck
|
||||
cppcheck: $(CPPCHECKDIRS)
|
||||
set -e ; for dir in $(CPPCHECKDIRS) ; do \
|
||||
$(MAKE) -C $$dir cppcheck ; \
|
||||
done
|
||||
SUBDIRS += mount_zfs zed zvol_id zvol_wait
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
arc_summary
|
||||
@@ -1,13 +1,11 @@
|
||||
bin_SCRIPTS = arc_summary
|
||||
|
||||
CLEANFILES = arc_summary
|
||||
EXTRA_DIST = arc_summary2 arc_summary3
|
||||
|
||||
if USING_PYTHON_2
|
||||
SCRIPT = arc_summary2
|
||||
dist_bin_SCRIPTS = arc_summary2
|
||||
install-exec-hook:
|
||||
mv $(DESTDIR)$(bindir)/arc_summary2 $(DESTDIR)$(bindir)/arc_summary
|
||||
else
|
||||
SCRIPT = arc_summary3
|
||||
dist_bin_SCRIPTS = arc_summary3
|
||||
install-exec-hook:
|
||||
mv $(DESTDIR)$(bindir)/arc_summary3 $(DESTDIR)$(bindir)/arc_summary
|
||||
endif
|
||||
|
||||
arc_summary: $(SCRIPT)
|
||||
cp $< $@
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# $Id: arc_summary.pl,v 388:e27800740aa2 2011-07-08 02:53:29Z jhell $
|
||||
#
|
||||
@@ -42,7 +42,7 @@
|
||||
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.
|
||||
https://github.com/zfsonlinux/zfs/blob/master/module/zfs/arc.c for details.
|
||||
"""
|
||||
|
||||
import getopt
|
||||
@@ -54,50 +54,6 @@ import errno
|
||||
from subprocess import Popen, PIPE
|
||||
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
|
||||
alternate_tunable_layout = False
|
||||
|
||||
@@ -120,10 +76,24 @@ def get_Kstat():
|
||||
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.update(load_kstats('arcstats'))
|
||||
Kstat.update(load_kstats('zfetchstats'))
|
||||
Kstat.update(load_kstats('vdev_cache_stats'))
|
||||
load_proc_kstats('/proc/spl/kstat/zfs/arcstats',
|
||||
'kstat.zfs.misc.arcstats.')
|
||||
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
|
||||
|
||||
|
||||
@@ -951,7 +921,14 @@ def _tunable_summary(Kstat):
|
||||
global show_tunable_descriptions
|
||||
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 = {}
|
||||
|
||||
if show_tunable_descriptions:
|
||||
@@ -989,17 +966,22 @@ def _tunable_summary(Kstat):
|
||||
sys.stderr.write("Tunable descriptions will be disabled.\n")
|
||||
|
||||
sys.stdout.write("ZFS Tunables:\n")
|
||||
names.sort()
|
||||
|
||||
if alternate_tunable_layout:
|
||||
fmt = "\t%s=%s\n"
|
||||
else:
|
||||
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:
|
||||
sys.stdout.write("\t# %s\n" % descriptions[name])
|
||||
|
||||
sys.stdout.write(fmt % (name, tunables[name]))
|
||||
sys.stdout.write(fmt % (name, values[name]))
|
||||
|
||||
|
||||
unSub = [
|
||||
|
||||
+129
-192
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright (c) 2008 Ben Rockwood <benr@cuddletech.com>,
|
||||
# Copyright (c) 2010 Martin Matuska <mm@FreeBSD.org>,
|
||||
@@ -32,7 +32,7 @@
|
||||
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.
|
||||
https://github.com/zfsonlinux/zfs/blob/master/module/zfs/arc.c for details.
|
||||
The original introduction to arc_summary can be found at
|
||||
http://cuddletech.com/?p=454
|
||||
"""
|
||||
@@ -43,9 +43,12 @@ import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
DESCRIPTION = 'Print ARC and other statistics for OpenZFS'
|
||||
DECRIPTION = 'Print ARC and other statistics for ZFS on Linux'
|
||||
INDENT = ' '*8
|
||||
LINE_LENGTH = 72
|
||||
PROC_PATH = '/proc/spl/kstat/zfs/'
|
||||
SPL_PATH = '/sys/module/spl/parameters/'
|
||||
TUNABLES_PATH = '/sys/module/zfs/parameters/'
|
||||
DATE_FORMAT = '%a %b %d %H:%M:%S %Y'
|
||||
TITLE = 'ZFS Subsystem Report'
|
||||
|
||||
@@ -62,7 +65,7 @@ SECTION_PATHS = {'arc': 'arcstats',
|
||||
'zfetch': 'zfetchstats',
|
||||
'zil': 'zil'}
|
||||
|
||||
parser = argparse.ArgumentParser(description=DESCRIPTION)
|
||||
parser = argparse.ArgumentParser(description=DECRIPTION)
|
||||
parser.add_argument('-a', '--alternate', action='store_true', default=False,
|
||||
help='use alternate formatting for tunables and SPL',
|
||||
dest='alt')
|
||||
@@ -80,159 +83,6 @@ 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
|
||||
@@ -388,48 +238,139 @@ def format_raw_line(name, value):
|
||||
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)
|
||||
spc = LINE_LENGTH-(len(INDENT)+len(value))
|
||||
result = '{0}{1:<{spc}}{2}'.format(INDENT, name, value, spc=spc)
|
||||
|
||||
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.
|
||||
"""Collect information on the ZFS subsystem from the /proc Linux virtual
|
||||
file system. 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 = {}
|
||||
secs = SECTION_PATHS.values()
|
||||
|
||||
for section in SECTION_PATHS.values():
|
||||
if section not in result:
|
||||
result[section] = load_kstats(section)
|
||||
for section in secs:
|
||||
|
||||
with open(PROC_PATH+section, 'r') as proc_location:
|
||||
lines = [line for line in proc_location]
|
||||
|
||||
del lines[0:2] # Get rid of header
|
||||
result[section] = lines
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_spl_tunables(PATH):
|
||||
"""Collect information on the Solaris Porting Layer (SPL) or the
|
||||
tunables, depending on the PATH given. Does not check if PATH is
|
||||
legal.
|
||||
"""
|
||||
|
||||
result = {}
|
||||
parameters = os.listdir(PATH)
|
||||
|
||||
for name in parameters:
|
||||
|
||||
with open(PATH+name, 'r') as para_file:
|
||||
value = para_file.read()
|
||||
result[name] = value.strip()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_descriptions(request):
|
||||
"""Get the decriptions 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 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.
|
||||
get the ZFS/SPL version via modinfo.
|
||||
"""
|
||||
|
||||
if request not in ('spl', 'zfs'):
|
||||
error_msg = '(ERROR: "{0}" requested)'.format(request)
|
||||
return error_msg
|
||||
|
||||
return 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()
|
||||
version = "(Can't get {0} version)".format(req)
|
||||
|
||||
# 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 = ''
|
||||
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 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.
|
||||
Linux and ZFS versions. This is not called for the graph.
|
||||
"""
|
||||
|
||||
# datetime is now recommended over time but we keep the exact formatting
|
||||
@@ -736,10 +677,10 @@ def section_l2arc(kstats_dict):
|
||||
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']))
|
||||
f_bytes(arc_stats['l2_hits']))
|
||||
prt_i2('Miss ratio:',
|
||||
f_perc(arc_stats['l2_misses'], l2_access_total),
|
||||
f_hits(arc_stats['l2_misses']))
|
||||
f_bytes(arc_stats['l2_misses']))
|
||||
prt_i1('Feeds:', f_hits(arc_stats['l2_feeds']))
|
||||
|
||||
print()
|
||||
@@ -750,13 +691,13 @@ def section_l2arc(kstats_dict):
|
||||
prt_i2('Done ratio:',
|
||||
f_perc(arc_stats['l2_writes_done'],
|
||||
arc_stats['l2_writes_sent']),
|
||||
f_hits(arc_stats['l2_writes_done']))
|
||||
f_bytes(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']))
|
||||
f_bytes(arc_stats['l2_writes_error']))
|
||||
else:
|
||||
prt_i2('Writes sent:', '100 %', f_hits(arc_stats['l2_writes_sent']))
|
||||
prt_i2('Writes sent:', '100 %', f_bytes(arc_stats['l2_writes_sent']))
|
||||
|
||||
print()
|
||||
print('L2ARC evicts:')
|
||||
@@ -767,14 +708,10 @@ def section_l2arc(kstats_dict):
|
||||
|
||||
def section_spl(*_):
|
||||
"""Print the SPL parameters, if requested with alternative format
|
||||
and/or descriptions. This does not use kstats.
|
||||
and/or decriptions. This does not use kstats.
|
||||
"""
|
||||
|
||||
if sys.platform.startswith('freebsd'):
|
||||
# No SPL support in FreeBSD
|
||||
return
|
||||
|
||||
spls = get_spl_params()
|
||||
spls = get_spl_tunables(SPL_PATH)
|
||||
keylist = sorted(spls.keys())
|
||||
print('Solaris Porting Layer (SPL):')
|
||||
|
||||
@@ -788,7 +725,7 @@ def section_spl(*_):
|
||||
try:
|
||||
print(INDENT+'#', descriptions[key])
|
||||
except KeyError:
|
||||
print(INDENT+'# (No description found)') # paranoid
|
||||
print(INDENT+'# (No decription found)') # paranoid
|
||||
|
||||
print(format_raw_line(key, value))
|
||||
|
||||
@@ -797,10 +734,10 @@ def section_spl(*_):
|
||||
|
||||
def section_tunables(*_):
|
||||
"""Print the tunables, if requested with alternative format and/or
|
||||
descriptions. This does not use kstasts.
|
||||
decriptions. This does not use kstasts.
|
||||
"""
|
||||
|
||||
tunables = get_tunable_params()
|
||||
tunables = get_spl_tunables(TUNABLES_PATH)
|
||||
keylist = sorted(tunables.keys())
|
||||
print('Tunables:')
|
||||
|
||||
@@ -814,7 +751,7 @@ def section_tunables(*_):
|
||||
try:
|
||||
print(INDENT+'#', descriptions[key])
|
||||
except KeyError:
|
||||
print(INDENT+'# (No description found)') # paranoid
|
||||
print(INDENT+'# (No decription found)') # paranoid
|
||||
|
||||
print(format_raw_line(key, value))
|
||||
|
||||
@@ -826,11 +763,11 @@ def section_vdev(kstats_dict):
|
||||
|
||||
# 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
|
||||
# https://github.com/zfsonlinux/zfs/blob/master/module/zfs/vdev_cache.c
|
||||
# for details
|
||||
tunables = get_vdev_params()
|
||||
tunables = get_spl_tunables(TUNABLES_PATH)
|
||||
|
||||
if tunables[VDEV_CACHE_SIZE] == '0':
|
||||
if tunables['zfs_vdev_cache_size'] == '0':
|
||||
print('VDEV cache disabled, skipping section\n')
|
||||
return
|
||||
|
||||
@@ -852,7 +789,7 @@ def section_vdev(kstats_dict):
|
||||
|
||||
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
|
||||
taken from https://github.com/zfsonlinux/zfs/blob/master/include/sys/zil.h
|
||||
"""
|
||||
|
||||
zil_stats = isolate_section('zil', kstats_dict)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
arcstat
|
||||
+12
-4
@@ -1,5 +1,13 @@
|
||||
include $(top_srcdir)/config/Substfiles.am
|
||||
dist_bin_SCRIPTS = arcstat
|
||||
|
||||
bin_SCRIPTS = arcstat
|
||||
|
||||
SUBSTFILES += $(bin_SCRIPTS)
|
||||
#
|
||||
# The arcstat script is compatibile with both Python 2.6 and 3.4.
|
||||
# As such the python 3 shebang can be replaced at install time when
|
||||
# targeting a python 2 system. This allows us to maintain a single
|
||||
# version of the source.
|
||||
#
|
||||
if USING_PYTHON_2
|
||||
install-exec-hook:
|
||||
sed --in-place 's|^#!/usr/bin/python3|#!/usr/bin/python2|' \
|
||||
$(DESTDIR)$(bindir)/arcstat
|
||||
endif
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
#!/usr/bin/env @PYTHON_SHEBANG@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# 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)
|
||||
# by Neelakanth Nadgir, originally published on his Sun blog on
|
||||
# This script is a fork of the original arcstat.pl (0.1) by
|
||||
# Neelakanth Nadgir, originally published on his Sun blog on
|
||||
# 09/18/2007
|
||||
# http://blogs.sun.com/realneel/entry/zfs_arc_statistics
|
||||
#
|
||||
# A new version aimed to improve upon the original by adding features
|
||||
# and fixing bugs as needed. This version was maintained by Mike
|
||||
# Harsch and was hosted in a public open source repository:
|
||||
# This version aims to improve upon the original by adding features
|
||||
# and fixing bugs as needed. This version is maintained by
|
||||
# Mike Harsch and is hosted in a public open source repository:
|
||||
# http://github.com/mharsch/arcstat
|
||||
#
|
||||
# but has since moved to the illumos-gate repository.
|
||||
#
|
||||
# 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.
|
||||
# Comments, Questions, or Suggestions are always welcome.
|
||||
# Contact the maintainer at ( mike at harschsystems dot com )
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
@@ -56,16 +51,16 @@ import getopt
|
||||
import re
|
||||
import copy
|
||||
|
||||
from decimal import Decimal
|
||||
from signal import signal, SIGINT, SIGWINCH, SIG_DFL
|
||||
|
||||
|
||||
cols = {
|
||||
# HDR: [Size, Scale, Description]
|
||||
"time": [8, -1, "Time"],
|
||||
"hits": [4, 1000, "ARC reads per second"],
|
||||
"miss": [4, 1000, "ARC misses 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"],
|
||||
"dhit": [4, 1000, "Demand hits per second"],
|
||||
"dmis": [4, 1000, "Demand misses per second"],
|
||||
@@ -80,13 +75,12 @@ cols = {
|
||||
"mread": [5, 1000, "Metadata accesses per second"],
|
||||
"mh%": [3, 100, "Metadata hit percentage"],
|
||||
"mm%": [3, 100, "Metadata miss percentage"],
|
||||
"arcsz": [5, 1024, "ARC size"],
|
||||
"size": [4, 1024, "ARC size"],
|
||||
"c": [4, 1024, "ARC target size"],
|
||||
"mfu": [4, 1000, "MFU list hits per second"],
|
||||
"mru": [4, 1000, "MRU list hits per second"],
|
||||
"mfug": [4, 1000, "MFU ghost list hits per second"],
|
||||
"mrug": [4, 1000, "MRU ghost list hits per second"],
|
||||
"arcsz": [5, 1024, "ARC Size"],
|
||||
"c": [4, 1024, "ARC Target Size"],
|
||||
"mfu": [4, 1000, "MFU List hits per second"],
|
||||
"mru": [4, 1000, "MRU List hits per second"],
|
||||
"mfug": [4, 1000, "MFU Ghost List hits per second"],
|
||||
"mrug": [4, 1000, "MRU Ghost List hits per second"],
|
||||
"eskip": [5, 1000, "evict_skip per second"],
|
||||
"mtxmis": [6, 1000, "mutex_miss per second"],
|
||||
"dread": [5, 1000, "Demand accesses per second"],
|
||||
@@ -98,17 +92,15 @@ cols = {
|
||||
"l2miss%": [7, 100, "L2ARC access miss percentage"],
|
||||
"l2asize": [7, 1024, "Actual (compressed) size of the L2ARC"],
|
||||
"l2size": [6, 1024, "Size of 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"],
|
||||
"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"],
|
||||
}
|
||||
|
||||
v = {}
|
||||
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",
|
||||
"pread", "read"]
|
||||
sint = 1 # Default interval is 1 second
|
||||
@@ -118,56 +110,12 @@ opfile = None
|
||||
sep = " " # Default separator is 2 spaces
|
||||
version = "0.4"
|
||||
l2exist = False
|
||||
cmd = ("Usage: arcstat [-havxp] [-f fields] [-o file] [-s string] [interval "
|
||||
cmd = ("Usage: arcstat [-hvx] [-f fields] [-o file] [-s string] [interval "
|
||||
"[count]]\n")
|
||||
cur = {}
|
||||
d = {}
|
||||
out = 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():
|
||||
@@ -183,7 +131,6 @@ def detailed_usage():
|
||||
def usage():
|
||||
sys.stderr.write("%s\n" % cmd)
|
||||
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"
|
||||
"\n")
|
||||
sys.stderr.write("\t -x : Print extended stats\n")
|
||||
@@ -191,7 +138,6 @@ def usage():
|
||||
sys.stderr.write("\t -o : Redirect output to the specified file\n")
|
||||
sys.stderr.write("\t -s : Override default field separator with custom "
|
||||
"character or string\n")
|
||||
sys.stderr.write("\t -p : Disable auto-scaling of numerical fields\n")
|
||||
sys.stderr.write("\nExamples:\n")
|
||||
sys.stderr.write("\tarcstat -o /tmp/a.log 2 10\n")
|
||||
sys.stderr.write("\tarcstat -s \",\" -o /tmp/a.log 2 10\n")
|
||||
@@ -202,6 +148,25 @@ def usage():
|
||||
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():
|
||||
global cur
|
||||
global kstat
|
||||
@@ -232,7 +197,7 @@ def prettynum(sz, scale, num=0):
|
||||
elif 0 < num < 1:
|
||||
num = 0
|
||||
|
||||
while abs(num) > scale and index < 5:
|
||||
while num > scale and index < 5:
|
||||
save = num
|
||||
num = num / scale
|
||||
index += 1
|
||||
@@ -240,7 +205,7 @@ def prettynum(sz, scale, num=0):
|
||||
if index == 0:
|
||||
return "%*d" % (sz, num)
|
||||
|
||||
if abs(save / scale) < 10:
|
||||
if (save / scale) < 10:
|
||||
return "%*.1f%s" % (sz - 1, num, suffix[index])
|
||||
else:
|
||||
return "%*d%s" % (sz - 1, num, suffix[index])
|
||||
@@ -250,14 +215,12 @@ def print_values():
|
||||
global hdr
|
||||
global sep
|
||||
global v
|
||||
global pretty_print
|
||||
|
||||
if pretty_print:
|
||||
fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col])
|
||||
else:
|
||||
fmt = lambda col: v[col]
|
||||
|
||||
sys.stdout.write(sep.join(fmt(col) for col in hdr))
|
||||
for col in hdr:
|
||||
sys.stdout.write("%s%s" % (
|
||||
prettynum(cols[col][0], cols[col][1], v[col]),
|
||||
sep
|
||||
))
|
||||
sys.stdout.write("\n")
|
||||
sys.stdout.flush()
|
||||
|
||||
@@ -265,14 +228,9 @@ def print_values():
|
||||
def print_header():
|
||||
global hdr
|
||||
global sep
|
||||
global pretty_print
|
||||
|
||||
if pretty_print:
|
||||
fmt = lambda col: "%*s" % (cols[col][0], col)
|
||||
else:
|
||||
fmt = lambda col: col
|
||||
|
||||
sys.stdout.write(sep.join(fmt(col) for col in hdr))
|
||||
for col in hdr:
|
||||
sys.stdout.write("%*s%s" % (cols[col][0], col, sep))
|
||||
sys.stdout.write("\n")
|
||||
|
||||
|
||||
@@ -309,10 +267,8 @@ def init():
|
||||
global sep
|
||||
global out
|
||||
global l2exist
|
||||
global pretty_print
|
||||
|
||||
desired_cols = None
|
||||
aflag = False
|
||||
xflag = False
|
||||
hflag = False
|
||||
vflag = False
|
||||
@@ -321,16 +277,14 @@ def init():
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
sys.argv[1:],
|
||||
"axo:hvs:f:p",
|
||||
"xo:hvs:f:",
|
||||
[
|
||||
"all",
|
||||
"extended",
|
||||
"outfile",
|
||||
"help",
|
||||
"verbose",
|
||||
"separator",
|
||||
"columns",
|
||||
"parsable"
|
||||
"columns"
|
||||
]
|
||||
)
|
||||
except getopt.error as msg:
|
||||
@@ -339,8 +293,6 @@ def init():
|
||||
opts = None
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt in ('-a', '--all'):
|
||||
aflag = True
|
||||
if opt in ('-x', '--extended'):
|
||||
xflag = True
|
||||
if opt in ('-o', '--outfile'):
|
||||
@@ -356,13 +308,19 @@ def init():
|
||||
if opt in ('-f', '--columns'):
|
||||
desired_cols = arg
|
||||
i += 1
|
||||
if opt in ('-p', '--parsable'):
|
||||
pretty_print = False
|
||||
i += 1
|
||||
|
||||
argv = sys.argv[i:]
|
||||
sint = int(argv[0]) if argv else sint
|
||||
count = int(argv[1]) if len(argv) > 1 else (0 if len(argv) > 0 else 1)
|
||||
sint = Decimal(argv[0]) if argv else sint
|
||||
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):
|
||||
usage()
|
||||
@@ -402,12 +360,6 @@ def init():
|
||||
incompat)
|
||||
usage()
|
||||
|
||||
if aflag:
|
||||
if l2exist:
|
||||
hdr = cols.keys()
|
||||
else:
|
||||
hdr = [col for col in cols.keys() if not col.startswith("l2")]
|
||||
|
||||
if opfile:
|
||||
try:
|
||||
out = open(opfile, "w")
|
||||
@@ -456,7 +408,6 @@ def calculate():
|
||||
v["mm%"] = 100 - v["mh%"] if v["mread"] > 0 else 0
|
||||
|
||||
v["arcsz"] = cur["size"]
|
||||
v["size"] = cur["size"]
|
||||
v["c"] = cur["c"]
|
||||
v["mfu"] = d["mfu_hits"] / sint
|
||||
v["mru"] = d["mru_hits"] / sint
|
||||
@@ -478,9 +429,7 @@ def calculate():
|
||||
|
||||
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"]
|
||||
v["free"] = cur["arc_sys_free"]
|
||||
|
||||
|
||||
def main():
|
||||
@@ -1 +0,0 @@
|
||||
dbufstat
|
||||
@@ -1,5 +1,13 @@
|
||||
include $(top_srcdir)/config/Substfiles.am
|
||||
dist_bin_SCRIPTS = dbufstat
|
||||
|
||||
bin_SCRIPTS = dbufstat
|
||||
|
||||
SUBSTFILES += $(bin_SCRIPTS)
|
||||
#
|
||||
# The dbufstat script is compatibile with both Python 2.6 and 3.4.
|
||||
# As such the python 3 shebang can be replaced at install time when
|
||||
# targeting a python 2 system. This allows us to maintain a single
|
||||
# version of the source.
|
||||
#
|
||||
if USING_PYTHON_2
|
||||
install-exec-hook:
|
||||
sed --in-place 's|^#!/usr/bin/python3|#!/usr/bin/python2|' \
|
||||
$(DESTDIR)$(bindir)/dbufstat
|
||||
endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env @PYTHON_SHEBANG@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Print out statistics for all cached dmu buffers. This information
|
||||
# is available through the dbufs kstat and may be post-processed as
|
||||
@@ -113,25 +113,10 @@ cmd = ("Usage: dbufstat [-bdhnrtvx] [-i file] [-f fields] [-o file] "
|
||||
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):
|
||||
cnt = 0
|
||||
for key in sorted(incompat):
|
||||
if cnt == 0:
|
||||
if cnt is 0:
|
||||
sys.stderr.write("\t")
|
||||
elif cnt > 8:
|
||||
sys.stderr.write(",\n\t")
|
||||
@@ -358,7 +343,7 @@ def get_compstring(c):
|
||||
"ZIO_COMPRESS_GZIP_6", "ZIO_COMPRESS_GZIP_7",
|
||||
"ZIO_COMPRESS_GZIP_8", "ZIO_COMPRESS_GZIP_9",
|
||||
"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 raw > 1:
|
||||
@@ -660,9 +645,9 @@ def main():
|
||||
sys.exit(1)
|
||||
|
||||
if not ifile:
|
||||
ifile = default_ifile()
|
||||
ifile = '/proc/spl/kstat/zfs/dbufs'
|
||||
|
||||
if ifile != "-":
|
||||
if ifile is not "-":
|
||||
try:
|
||||
tmp = open(ifile, "r")
|
||||
sys.stdin = tmp
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/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
|
||||
# this script does nothing but it could be extended to act as a
|
||||
# compatibility wrapper for 'zpool scrub'.
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
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/
|
||||
# because this path is hardcoded in the mount(8) for security reasons.
|
||||
@@ -13,10 +17,5 @@ mount_zfs_SOURCES = \
|
||||
mount_zfs.c
|
||||
|
||||
mount_zfs_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
||||
|
||||
mount_zfs_LDADD += $(LTLIBINTL)
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
|
||||
+295
-42
@@ -42,46 +42,247 @@
|
||||
|
||||
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
|
||||
* string does not represent a block device with a valid zfs label
|
||||
* then it is passed through without modification.
|
||||
* Break the mount option in to a name/value pair. The name is
|
||||
* validated against the option map and mount flags set accordingly.
|
||||
*/
|
||||
static void
|
||||
parse_dataset(const char *target, char **dataset)
|
||||
static int
|
||||
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
|
||||
* current working directory was named 'dataset' then mount(8)
|
||||
* would prepend the current working directory to the dataset.
|
||||
* Check for it and strip the prepended path when it is added.
|
||||
* Scan through all mount options which must be comma delimited.
|
||||
* We must be careful to notice regions which are double quoted
|
||||
* and skip commas in these regions. Each option is then checked
|
||||
* 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];
|
||||
if (getcwd(cwd, PATH_MAX) == NULL) {
|
||||
perror("getcwd");
|
||||
return;
|
||||
struct stat64 statbuf;
|
||||
int error;
|
||||
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);
|
||||
if (strncmp(cwd, target, len) == 0)
|
||||
target += len;
|
||||
out:
|
||||
/*
|
||||
* 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 */
|
||||
strlcpy(*dataset, target, PATH_MAX);
|
||||
len = strlen(cwd);
|
||||
|
||||
int fd = open(target, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return;
|
||||
/* Do not add one when cwd already ends in a trailing '/' */
|
||||
if (strncmp(cwd, dataset, len) == 0)
|
||||
return (dataset + len + (cwd[len-1] != '/'));
|
||||
|
||||
nvlist_t *cfg = NULL;
|
||||
if (zpool_read_label(fd, &cfg, NULL) == 0) {
|
||||
char *nm = NULL;
|
||||
if (!nvlist_lookup_string(cfg, ZPOOL_CONFIG_POOL_NAME, &nm))
|
||||
strlcpy(*dataset, nm, PATH_MAX);
|
||||
nvlist_free(cfg);
|
||||
}
|
||||
|
||||
if (close(fd))
|
||||
perror("close");
|
||||
return (dataset);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -125,8 +326,8 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
||||
if (!fp) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"filesystem '%s' was mounted, but /etc/mtab "
|
||||
"could not be opened due to error: %s\n"),
|
||||
dataset, strerror(errno));
|
||||
"could not be opened due to error %d\n"),
|
||||
dataset, errno);
|
||||
return (MOUNT_FILEIO);
|
||||
}
|
||||
|
||||
@@ -134,8 +335,8 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
||||
if (error) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"filesystem '%s' was mounted, but /etc/mtab "
|
||||
"could not be updated due to error: %s\n"),
|
||||
dataset, strerror(errno));
|
||||
"could not be updated due to error %d\n"),
|
||||
dataset, errno);
|
||||
return (MOUNT_FILEIO);
|
||||
}
|
||||
|
||||
@@ -144,6 +345,34 @@ mtab_update(char *dataset, char *mntpoint, char *type, char *mntopts)
|
||||
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
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -154,13 +383,12 @@ main(int argc, char **argv)
|
||||
char badopt[MNT_LINE_MAX] = { '\0' };
|
||||
char mtabopt[MNT_LINE_MAX] = { '\0' };
|
||||
char mntpoint[PATH_MAX];
|
||||
char dataset[PATH_MAX], *pdataset = dataset;
|
||||
char *dataset;
|
||||
unsigned long mntflags = 0, zfsflags = 0, remount = 0;
|
||||
int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
|
||||
int error, c;
|
||||
|
||||
(void) setlocale(LC_ALL, "");
|
||||
(void) setlocale(LC_NUMERIC, "C");
|
||||
(void) textdomain(TEXT_DOMAIN);
|
||||
|
||||
opterr = 0;
|
||||
@@ -210,18 +438,18 @@ main(int argc, char **argv)
|
||||
return (MOUNT_USAGE);
|
||||
}
|
||||
|
||||
parse_dataset(argv[0], &pdataset);
|
||||
dataset = parse_dataset(argv[0]);
|
||||
|
||||
/* canonicalize the mount point */
|
||||
if (realpath(argv[1], mntpoint) == NULL) {
|
||||
(void) fprintf(stderr, gettext("filesystem '%s' cannot be "
|
||||
"mounted at '%s' due to canonicalization error: %s\n"),
|
||||
dataset, argv[1], strerror(errno));
|
||||
"mounted at '%s' due to canonicalization error %d.\n"),
|
||||
dataset, argv[1], errno);
|
||||
return (MOUNT_SYSERR);
|
||||
}
|
||||
|
||||
/* validate mount options and set mntflags */
|
||||
error = zfs_parse_mount_options(mntopts, &mntflags, &zfsflags, sloppy,
|
||||
error = parse_options(mntopts, &mntflags, &zfsflags, sloppy,
|
||||
badopt, mtabopt);
|
||||
if (error) {
|
||||
switch (error) {
|
||||
@@ -261,7 +489,7 @@ main(int argc, char **argv)
|
||||
zfsutil = 1;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -274,7 +502,32 @@ main(int argc, char **argv)
|
||||
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 */
|
||||
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT)
|
||||
|
||||
@@ -4,7 +4,11 @@ include $(top_srcdir)/config/Rules.am
|
||||
AM_CFLAGS += $(FRAME_LARGER_THAN)
|
||||
|
||||
# Unconditionally enable ASSERTs
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
bin_PROGRAMS = raidz_test
|
||||
|
||||
@@ -14,9 +18,6 @@ raidz_test_SOURCES = \
|
||||
raidz_bench.c
|
||||
|
||||
raidz_test_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
$(top_builddir)/lib/libzpool/libzpool.la
|
||||
|
||||
raidz_test_LDADD += -lm
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
raidz_test_LDADD += -lm -ldl
|
||||
|
||||
@@ -113,7 +113,7 @@ run_gen_bench_impl(const char *impl)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
run_gen_bench(void)
|
||||
{
|
||||
char **impl_name;
|
||||
@@ -197,7 +197,7 @@ run_rec_bench_impl(const char *impl)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
run_rec_bench(void)
|
||||
{
|
||||
char **impl_name;
|
||||
|
||||
@@ -757,7 +757,7 @@ main(int argc, char **argv)
|
||||
|
||||
process_options(argc, argv);
|
||||
|
||||
kernel_init(SPA_MODE_READ);
|
||||
kernel_init(FREAD);
|
||||
|
||||
/* setup random data because rand() is not reentrant */
|
||||
rand_data = (int *)umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
|
||||
|
||||
@@ -38,7 +38,6 @@ static const char *raidz_impl_names[] = {
|
||||
"avx512bw",
|
||||
"aarch64_neon",
|
||||
"aarch64_neonx2",
|
||||
"powerpc_altivec",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+10
-10
@@ -102,7 +102,7 @@ Usage: vdev_id [-h]
|
||||
vdev_id <-d device> [-c config_file] [-p phys_per_port]
|
||||
[-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)
|
||||
-e Create enclose device symlinks only (/dev/by-enclosure)
|
||||
-g Storage network topology [default="$TOPOLOGY"]
|
||||
@@ -114,8 +114,9 @@ EOF
|
||||
}
|
||||
|
||||
map_slot() {
|
||||
LINUX_SLOT=$1
|
||||
CHANNEL=$2
|
||||
local LINUX_SLOT=$1
|
||||
local CHANNEL=$2
|
||||
local MAPPED_SLOT=
|
||||
|
||||
MAPPED_SLOT=`awk "\\$1 == \"slot\" && \\$2 == ${LINUX_SLOT} && \
|
||||
\\$4 ~ /^${CHANNEL}$|^$/ { print \\$3; exit }" $CONFIG`
|
||||
@@ -126,9 +127,9 @@ map_slot() {
|
||||
}
|
||||
|
||||
map_channel() {
|
||||
MAPPED_CHAN=
|
||||
PCI_ID=$1
|
||||
PORT=$2
|
||||
local MAPPED_CHAN=
|
||||
local PCI_ID=$1
|
||||
local PORT=$2
|
||||
|
||||
case $TOPOLOGY in
|
||||
"sas_switch")
|
||||
@@ -486,7 +487,7 @@ alias_handler () {
|
||||
# digits as partitions, causing alias creation to fail. This
|
||||
# ambiguity seems unavoidable, so devices using this facility
|
||||
# must not use such names.
|
||||
DM_PART=
|
||||
local DM_PART=
|
||||
if echo $DM_NAME | grep -q -E 'p[0-9][0-9]*$' ; then
|
||||
if [ "$DEVTYPE" != "partition" ] ; then
|
||||
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
|
||||
|
||||
if [ ! -r $CONFIG ] ; then
|
||||
echo "Error: Config file \"$CONFIG\" not found"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "$DEV" ] && [ -z "$ENCLOSURE_MODE" ] ; then
|
||||
if [ -z "$DEV" -a -z "$ENCLOSURE_MODE" ] ; then
|
||||
echo "Error: missing required option -d"
|
||||
exit 1
|
||||
fi
|
||||
@@ -565,7 +565,7 @@ fi
|
||||
TOPOLOGY=${TOPOLOGY:-sas_direct}
|
||||
|
||||
# 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)
|
||||
if [ -z "$ID_ENCLOSURE" ] ; then
|
||||
exit 0
|
||||
|
||||
+7
-6
@@ -1,7 +1,11 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
# Unconditionally enable debugging for zdb
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
sbin_PROGRAMS = zdb
|
||||
|
||||
@@ -11,8 +15,5 @@ zdb_SOURCES = \
|
||||
zdb.h
|
||||
|
||||
zdb_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la
|
||||
|
||||
+318
-2711
File diff suppressed because it is too large
Load Diff
+20
-21
@@ -62,9 +62,9 @@ print_log_bp(const blkptr_t *bp, const char *prefix)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_create(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_create_t *lr = arg;
|
||||
lr_create_t *lr = arg;
|
||||
time_t crtime = lr->lr_crtime[0];
|
||||
char *name, *link;
|
||||
lr_attr_t *lrattr;
|
||||
@@ -98,9 +98,9 @@ zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_remove(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_remove(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_remove_t *lr = arg;
|
||||
lr_remove_t *lr = arg;
|
||||
|
||||
(void) printf("%sdoid %llu, name %s\n", tab_prefix,
|
||||
(u_longlong_t)lr->lr_doid, (char *)(lr + 1));
|
||||
@@ -108,9 +108,9 @@ zil_prt_rec_remove(zilog_t *zilog, int txtype, const void *arg)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_link(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_link(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_link_t *lr = arg;
|
||||
lr_link_t *lr = arg;
|
||||
|
||||
(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,
|
||||
@@ -119,9 +119,9 @@ zil_prt_rec_link(zilog_t *zilog, int txtype, const void *arg)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_rename(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_rename(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_rename_t *lr = arg;
|
||||
lr_rename_t *lr = arg;
|
||||
char *snm = (char *)(lr + 1);
|
||||
char *tnm = snm + strlen(snm) + 1;
|
||||
|
||||
@@ -148,11 +148,11 @@ zil_prt_rec_write_cb(void *data, size_t len, void *unused)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_write(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_write(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_write_t *lr = arg;
|
||||
lr_write_t *lr = arg;
|
||||
abd_t *data;
|
||||
const blkptr_t *bp = &lr->lr_blkptr;
|
||||
blkptr_t *bp = &lr->lr_blkptr;
|
||||
zbookmark_phys_t zb;
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
int error;
|
||||
@@ -211,9 +211,9 @@ out:
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_truncate(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_truncate(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_truncate_t *lr = arg;
|
||||
lr_truncate_t *lr = arg;
|
||||
|
||||
(void) printf("%sfoid %llu, offset 0x%llx, length 0x%llx\n", tab_prefix,
|
||||
(u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset,
|
||||
@@ -222,9 +222,9 @@ zil_prt_rec_truncate(zilog_t *zilog, int txtype, const void *arg)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_setattr(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_setattr(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_setattr_t *lr = arg;
|
||||
lr_setattr_t *lr = arg;
|
||||
time_t atime = (time_t)lr->lr_atime[0];
|
||||
time_t mtime = (time_t)lr->lr_mtime[0];
|
||||
|
||||
@@ -268,15 +268,15 @@ zil_prt_rec_setattr(zilog_t *zilog, int txtype, const void *arg)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_acl(zilog_t *zilog, int txtype, const void *arg)
|
||||
zil_prt_rec_acl(zilog_t *zilog, int txtype, void *arg)
|
||||
{
|
||||
const lr_acl_t *lr = arg;
|
||||
lr_acl_t *lr = arg;
|
||||
|
||||
(void) printf("%sfoid %llu, aclcnt %llu\n", tab_prefix,
|
||||
(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 {
|
||||
zil_prt_rec_func_t zri_print;
|
||||
const char *zri_name;
|
||||
@@ -309,7 +309,7 @@ static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
||||
|
||||
/* ARGSUSED */
|
||||
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 verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
@@ -343,8 +343,7 @@ print_log_record(zilog_t *zilog, const lr_t *lr, void *arg, uint64_t claim_txg)
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
print_log_block(zilog_t *zilog, const blkptr_t *bp, void *arg,
|
||||
uint64_t claim_txg)
|
||||
print_log_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
|
||||
{
|
||||
char blkbuf[BP_SPRINTF_LEN + 10];
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
|
||||
+9
-12
@@ -1,8 +1,10 @@
|
||||
SUBDIRS = zed.d
|
||||
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
AM_CFLAGS += $(LIBUDEV_CFLAGS) $(LIBUUID_CFLAGS)
|
||||
|
||||
SUBDIRS = zed.d
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
sbin_PROGRAMS = zed
|
||||
|
||||
@@ -38,14 +40,9 @@ FMA_SRC = \
|
||||
zed_SOURCES = $(ZED_SRC) $(FMA_SRC)
|
||||
|
||||
zed_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(abs_top_builddir)/lib/libuutil/libuutil.la
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
|
||||
zed_LDADD += -lrt $(LIBUDEV_LIBS) $(LIBUUID_LIBS)
|
||||
zed_LDADD += -lrt
|
||||
zed_LDFLAGS = -pthread
|
||||
|
||||
EXTRA_DIST = agents/README.md
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
|
||||
@@ -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,
|
||||
* memory allocation, module property accessors, basic case management,
|
||||
* one-shot timers and SERD engines.
|
||||
|
||||
@@ -281,7 +281,7 @@ fmd_serd_eng_empty(fmd_serd_eng_t *sgp)
|
||||
void
|
||||
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)
|
||||
fmd_serd_eng_discard(sgp, list_head(&sgp->sg_list));
|
||||
|
||||
@@ -177,12 +177,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
|
||||
* from the vdev_disk layer after a hot unplug. Fortunately we do
|
||||
* get an EC_DEV_REMOVE from our disk monitor and it is a suitable
|
||||
* On ZFS on Linux, we don't get the expected FM_RESOURCE_REMOVED
|
||||
* ereport from vdev_disk layer after a hot unplug. Fortunately we
|
||||
* 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.
|
||||
* 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) &&
|
||||
(strcmp(subclass, ESC_DISK) == 0) &&
|
||||
|
||||
+14
-11
@@ -63,10 +63,13 @@
|
||||
* If the device could not be replaced, then the second online attempt will
|
||||
* 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:
|
||||
* Linux udev provides a disk insert for both the disk and the partition
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <devid.h>
|
||||
#include <fcntl.h>
|
||||
#include <libnvpair.h>
|
||||
#include <libzfs.h>
|
||||
@@ -154,7 +157,7 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
|
||||
* 1. physical match with no fs, no partition
|
||||
* tag it top, partition disk
|
||||
*
|
||||
* 2. physical match again, see partition and tag
|
||||
* 2. physical match again, see partion and tag
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -189,8 +192,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
char rawpath[PATH_MAX], fullpath[PATH_MAX];
|
||||
char devpath[PATH_MAX];
|
||||
int ret;
|
||||
boolean_t is_dm = B_FALSE;
|
||||
boolean_t is_sd = B_FALSE;
|
||||
int is_dm = 0;
|
||||
int is_sd = 0;
|
||||
uint_t c;
|
||||
vdev_stat_t *vs;
|
||||
|
||||
@@ -218,8 +221,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
|
||||
is_dm = zfs_dev_is_dm(path);
|
||||
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,
|
||||
physpath ? physpath : "NULL", wholedisk, is_dm ? "is" : "not",
|
||||
" wholedisk %d, dm %d (%llu)", zpool_get_name(zhp), path,
|
||||
physpath ? physpath : "NULL", wholedisk, is_dm,
|
||||
(long long unsigned int)guid);
|
||||
|
||||
/*
|
||||
@@ -264,7 +267,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
* testing)
|
||||
*/
|
||||
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
|
||||
@@ -435,7 +438,7 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE, B_FALSE);
|
||||
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE);
|
||||
|
||||
zed_log_msg(LOG_INFO, " zpool_vdev_replace: %s with %s (%s)",
|
||||
fullpath, path, (ret == 0) ? "no errors" :
|
||||
@@ -531,7 +534,7 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
zfs_enable_ds(void *arg)
|
||||
{
|
||||
unavailpool_t *pool = (unavailpool_t *)arg;
|
||||
@@ -671,7 +674,7 @@ zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
|
||||
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)
|
||||
* 2. ZPOOL_CONFIG_PHYS_PATH (identifies disk physical location).
|
||||
*
|
||||
@@ -889,7 +892,7 @@ zfs_enum_pools(void *arg)
|
||||
*
|
||||
* 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
|
||||
zfs_slm_init()
|
||||
|
||||
@@ -237,7 +237,7 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
||||
dev_name, basename(spare_name));
|
||||
|
||||
if (zpool_vdev_attach(zhp, dev_name, spare_name,
|
||||
replacement, B_TRUE, B_FALSE) == 0) {
|
||||
replacement, B_TRUE) == 0) {
|
||||
free(dev_name);
|
||||
nvlist_free(replacement);
|
||||
return (B_TRUE);
|
||||
@@ -319,16 +319,12 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
|
||||
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
|
||||
* check for an available spare and continue unless the device is a
|
||||
* l2arc vdev, in which case we just offline it.
|
||||
*/
|
||||
if (strcmp(class, "resource.fs.zfs.removed") == 0 ||
|
||||
(strcmp(class, "resource.fs.zfs.statechange") == 0 &&
|
||||
state == VDEV_STATE_REMOVED)) {
|
||||
if (strcmp(class, "resource.fs.zfs.removed") == 0) {
|
||||
char *devtype;
|
||||
char *devname;
|
||||
|
||||
@@ -351,8 +347,9 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
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);
|
||||
/* Could not handle with spare: offline the device */
|
||||
fmd_hdl_debug(hdl, "zpool_vdev_offline '%s'", devname);
|
||||
zpool_vdev_offline(zhp, devname, B_TRUE);
|
||||
}
|
||||
|
||||
free(devname);
|
||||
@@ -364,11 +361,12 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
+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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
idle:
|
||||
/*
|
||||
* 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_init(zcp);
|
||||
zed_event_seek(zcp, saved_eid, saved_etime);
|
||||
|
||||
while (!_got_exit) {
|
||||
int rv;
|
||||
if (_got_hup) {
|
||||
_got_hup = 0;
|
||||
(void) zed_conf_scan_dir(zcp);
|
||||
}
|
||||
rv = zed_event_service(zcp);
|
||||
|
||||
/* ENODEV: When kernel module is unloaded (osx) */
|
||||
if (rv == ENODEV)
|
||||
break;
|
||||
zed_event_service(zcp);
|
||||
}
|
||||
|
||||
zed_log_msg(LOG_NOTICE, "Exiting");
|
||||
zed_event_fini(zcp);
|
||||
|
||||
if (zcp->do_idle && !_got_exit)
|
||||
goto idle;
|
||||
|
||||
out:
|
||||
zed_conf_destroy(zcp);
|
||||
zed_log_fini();
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
include $(top_srcdir)/config/Substfiles.am
|
||||
|
||||
EXTRA_DIST += README
|
||||
EXTRA_DIST = \
|
||||
README \
|
||||
history_event-zfs-list-cacher.sh.in
|
||||
|
||||
zedconfdir = $(sysconfdir)/zfs/zed.d
|
||||
|
||||
@@ -23,17 +24,20 @@ dist_zedexec_SCRIPTS = \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
resilver_finish-start-scrub.sh \
|
||||
trim_finish-notify.sh
|
||||
resilver_finish-start-scrub.sh
|
||||
|
||||
nodist_zedexec_SCRIPTS = history_event-zfs-list-cacher.sh
|
||||
|
||||
SUBSTFILES += $(nodist_zedexec_SCRIPTS)
|
||||
$(nodist_zedexec_SCRIPTS): %: %.in
|
||||
-$(SED) -e 's,@bindir\@,$(bindir),g' \
|
||||
-e 's,@runstatedir\@,$(runstatedir),g' \
|
||||
-e 's,@sbindir\@,$(sbindir),g' \
|
||||
-e 's,@sysconfdir\@,$(sysconfdir),g' \
|
||||
$< >'$@'
|
||||
|
||||
zedconfdefaults = \
|
||||
all-syslog.sh \
|
||||
data-notify.sh \
|
||||
history_event-zfs-list-cacher.sh \
|
||||
resilver_finish-notify.sh \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
|
||||
@@ -1,50 +1,14 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
# Copyright (c) 2020 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Log the zevent via syslog.
|
||||
#
|
||||
|
||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
||||
|
||||
zed_exit_if_ignoring_this_event
|
||||
|
||||
# build a string of name=value pairs for this event
|
||||
msg="eid=${ZEVENT_EID} class=${ZEVENT_SUBCLASS}"
|
||||
|
||||
if [ "${ZED_SYSLOG_DISPLAY_GUIDS}" = "1" ]; then
|
||||
[ -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}"
|
||||
|
||||
zed_log_msg "eid=${ZEVENT_EID}" "class=${ZEVENT_SUBCLASS}" \
|
||||
"${ZEVENT_POOL_GUID:+"pool_guid=${ZEVENT_POOL_GUID}"}" \
|
||||
"${ZEVENT_VDEV_PATH:+"vdev_path=${ZEVENT_VDEV_PATH}"}" \
|
||||
"${ZEVENT_VDEV_STATE_STR:+"vdev_state=${ZEVENT_VDEV_STATE_STR}"}"
|
||||
exit 0
|
||||
|
||||
@@ -13,7 +13,7 @@ FSLIST="${FSLIST_DIR}/${ZEVENT_POOL}"
|
||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
||||
|
||||
[ "$ZEVENT_SUBCLASS" != "history_event" ] && exit 0
|
||||
zed_exit_if_ignoring_this_event
|
||||
zed_check_cmd "${ZFS}" sort diff grep
|
||||
|
||||
# If we are acting on a snapshot, we have nothing to do
|
||||
@@ -46,13 +46,8 @@ case "${ZEVENT_HISTORY_INTERNAL_NAME}" in
|
||||
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 \
|
||||
) ;;
|
||||
canmount|mountpoint|atime|relatime|devices|exec| \
|
||||
readonly|setuid|nbmand|encroot|keylocation) ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
;;
|
||||
@@ -66,12 +61,8 @@ 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"
|
||||
PROPS="name,mountpoint,canmount,atime,relatime,devices,exec,readonly"
|
||||
PROPS="${PROPS},setuid,nbmand,encroot,keylocation"
|
||||
|
||||
"${ZFS}" list -H -t filesystem -o $PROPS -r "${ZEVENT_POOL}" > "${FSLIST_TMP}"
|
||||
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
# Exit codes:
|
||||
# 1: Internal error
|
||||
# 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"
|
||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
||||
|
||||
[ "${ZED_SCRUB_AFTER_RESILVER}" = "1" ] || exit 2
|
||||
[ "${ZEVENT_RESILVER_TYPE}" != "sequential" ] || exit 3
|
||||
[ -n "${ZEVENT_POOL}" ] || exit 1
|
||||
[ -n "${ZEVENT_SUBCLASS}" ] || exit 1
|
||||
zed_check_cmd "${ZPOOL}" || exit 1
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#
|
||||
# Exit codes:
|
||||
# 0: enclosure led successfully set
|
||||
# 1: enclosure leds not available
|
||||
# 1: enclosure leds not not available
|
||||
# 2: enclosure leds administratively disabled
|
||||
# 3: The led sysfs path passed from ZFS does not exist
|
||||
# 4: $ZPOOL not set
|
||||
@@ -68,7 +68,7 @@ check_and_set_led()
|
||||
# timeout.
|
||||
for _ in $(seq 1 5); do
|
||||
# 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=$(cat "${file}")
|
||||
|
||||
|
||||
@@ -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 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_failure}" -gt 0 ] && return 1
|
||||
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])
|
||||
#
|
||||
# Check whether an event of a given type [tag] has already occurred within the
|
||||
|
||||
+1
-14
@@ -74,14 +74,6 @@
|
||||
#
|
||||
#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.
|
||||
#
|
||||
@@ -118,10 +110,5 @@ ZED_USE_ENCLOSURE_LEDS=1
|
||||
# Otherwise, if ZED_SYSLOG_SUBCLASS_EXCLUDE is set, the
|
||||
# matching subclasses are excluded from logging.
|
||||
#ZED_SYSLOG_SUBCLASS_INCLUDE="checksum|scrub_*|vdev.*"
|
||||
ZED_SYSLOG_SUBCLASS_EXCLUDE="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
|
||||
#ZED_SYSLOG_SUBCLASS_EXCLUDE="statechange|config_*|history_event"
|
||||
|
||||
|
||||
+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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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.");
|
||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-F",
|
||||
"Run daemon in the foreground.");
|
||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-I",
|
||||
"Idle daemon until kernel module is (re)loaded.");
|
||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-M",
|
||||
"Lock all pages in memory.");
|
||||
fprintf(fp, "%*c%*s %s\n", w1, 0x20, -w2, "-P",
|
||||
@@ -251,7 +249,7 @@ _zed_conf_parse_path(char **resultp, const char *path)
|
||||
void
|
||||
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;
|
||||
|
||||
if (!zcp || !argv || !argv[0])
|
||||
@@ -276,9 +274,6 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
||||
case 'd':
|
||||
_zed_conf_parse_path(&zcp->zedlet_dir, optarg);
|
||||
break;
|
||||
case 'I':
|
||||
zcp->do_idle = 1;
|
||||
break;
|
||||
case 'p':
|
||||
_zed_conf_parse_path(&zcp->pid_file, optarg);
|
||||
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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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_verbose:1; /* true if verbosity enabled */
|
||||
unsigned do_zero:1; /* true if zeroing state */
|
||||
unsigned do_idle:1; /* true if idle enabled */
|
||||
int syslog_facility; /* syslog facility value */
|
||||
int min_events; /* RESERVED FOR FUTURE USE */
|
||||
int max_events; /* RESERVED FOR FUTURE USE */
|
||||
|
||||
+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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "zed.h"
|
||||
#include "zed_conf.h"
|
||||
#include "zed_disk_event.h"
|
||||
#include "zed_event.h"
|
||||
#include "zed_exec.h"
|
||||
#include "zed_file.h"
|
||||
#include "zed_log.h"
|
||||
@@ -41,36 +40,25 @@
|
||||
/*
|
||||
* Open the libzfs interface.
|
||||
*/
|
||||
int
|
||||
void
|
||||
zed_event_init(struct zed_conf *zcp)
|
||||
{
|
||||
if (!zcp)
|
||||
zed_log_die("Failed zed_event_init: %s", strerror(EINVAL));
|
||||
|
||||
zcp->zfs_hdl = libzfs_init();
|
||||
if (!zcp->zfs_hdl) {
|
||||
if (zcp->do_idle)
|
||||
return (-1);
|
||||
if (!zcp->zfs_hdl)
|
||||
zed_log_die("Failed to initialize libzfs");
|
||||
}
|
||||
|
||||
zcp->zevent_fd = open(ZFS_DEV, O_RDWR);
|
||||
if (zcp->zevent_fd < 0) {
|
||||
if (zcp->do_idle)
|
||||
return (-1);
|
||||
if (zcp->zevent_fd < 0)
|
||||
zed_log_die("Failed to open \"%s\": %s",
|
||||
ZFS_DEV, strerror(errno));
|
||||
}
|
||||
|
||||
zfs_agent_init(zcp->zfs_hdl);
|
||||
|
||||
if (zed_disk_event_init() != 0) {
|
||||
if (zcp->do_idle)
|
||||
return (-1);
|
||||
if (zed_disk_event_init() != 0)
|
||||
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.
|
||||
*/
|
||||
int
|
||||
void
|
||||
zed_event_service(struct zed_conf *zcp)
|
||||
{
|
||||
nvlist_t *nvl;
|
||||
@@ -902,13 +890,13 @@ zed_event_service(struct zed_conf *zcp)
|
||||
errno = EINVAL;
|
||||
zed_log_msg(LOG_ERR, "Failed to service zevent: %s",
|
||||
strerror(errno));
|
||||
return (EINVAL);
|
||||
return;
|
||||
}
|
||||
rv = zpool_events_next(zcp->zfs_hdl, &nvl, &n_dropped, ZEVENT_NONE,
|
||||
zcp->zevent_fd);
|
||||
|
||||
if ((rv != 0) || !nvl)
|
||||
return (errno);
|
||||
return;
|
||||
|
||||
if (n_dropped > 0) {
|
||||
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);
|
||||
}
|
||||
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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
#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);
|
||||
|
||||
int zed_event_seek(struct zed_conf *zcp, uint64_t saved_eid,
|
||||
int64_t saved_etime[]);
|
||||
|
||||
int zed_event_service(struct zed_conf *zcp);
|
||||
void zed_event_service(struct zed_conf *zcp);
|
||||
|
||||
#endif /* !ZED_EVENT_H */
|
||||
|
||||
+2
-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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "zed_exec.h"
|
||||
#include "zed_file.h"
|
||||
#include "zed_log.h"
|
||||
#include "zed_strings.h"
|
||||
@@ -173,7 +172,6 @@ _zed_exec_fork_child(uint64_t eid, const char *dir, const char *prog,
|
||||
zed_log_msg(LOG_WARNING, "Killing hung \"%s\" pid=%d",
|
||||
prog, pid);
|
||||
(void) kill(pid, SIGKILL);
|
||||
(void) waitpid(pid, &status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||
@@ -16,7 +16,6 @@
|
||||
#define ZED_EXEC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "zed_strings.h"
|
||||
|
||||
int zed_exec_process(uint64_t eid, const char *class, const char *subclass,
|
||||
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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "zed_file.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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* 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,
|
||||
* 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_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).
|
||||
* Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
|
||||
* Refer to the ZoL git commit log for authoritative copyright attribution.
|
||||
|
||||
+8
-12
@@ -1,5 +1,9 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
sbin_PROGRAMS = zfs
|
||||
|
||||
zfs_SOURCES = \
|
||||
@@ -11,15 +15,7 @@ zfs_SOURCES = \
|
||||
zfs_projectutil.h
|
||||
|
||||
zfs_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(abs_top_builddir)/lib/libuutil/libuutil.la
|
||||
|
||||
zfs_LDADD += $(LTLIBINTL)
|
||||
|
||||
if BUILD_FREEBSD
|
||||
zfs_LDADD += -lgeom -ljail
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
+327
-735
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -33,7 +33,7 @@ extern "C" {
|
||||
|
||||
void * safe_malloc(size_t size);
|
||||
void nomem(void);
|
||||
extern libzfs_handle_t *g_zfs;
|
||||
libzfs_handle_t *g_zfs;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
zfs_ids_to_path
|
||||
@@ -1,11 +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
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
@@ -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,7 +1 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
sbin_PROGRAMS = zgenhostid
|
||||
|
||||
zgenhostid_SOURCES = zgenhostid.c
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
dist_bin_SCRIPTS = zgenhostid
|
||||
|
||||
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
|
||||
|
||||
# Unconditionally enable debugging for zhack
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG -DZFS_DEBUG
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
sbin_PROGRAMS = zhack
|
||||
|
||||
@@ -9,8 +10,5 @@ zhack_SOURCES = \
|
||||
zhack.c
|
||||
|
||||
zhack_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la
|
||||
|
||||
+3
-5
@@ -103,8 +103,8 @@ fatal(spa_t *spa, void *tag, const char *fmt, ...)
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
space_delta_cb(dmu_object_type_t bonustype, const void *data,
|
||||
zfs_file_info_t *zoi)
|
||||
space_delta_cb(dmu_object_type_t bonustype, void *data,
|
||||
uint64_t *userp, uint64_t *groupp, uint64_t *projectp)
|
||||
{
|
||||
/*
|
||||
* Is it a valid type of object to track?
|
||||
@@ -126,8 +126,7 @@ zhack_import(char *target, boolean_t readonly)
|
||||
nvlist_t *props;
|
||||
int error;
|
||||
|
||||
kernel_init(readonly ? SPA_MODE_READ :
|
||||
(SPA_MODE_READ | SPA_MODE_WRITE));
|
||||
kernel_init(readonly ? FREAD : (FREAD | FWRITE));
|
||||
|
||||
dmu_objset_register_type(DMU_OST_ZFS, space_delta_cb);
|
||||
|
||||
@@ -150,7 +149,6 @@ zhack_import(char *target, boolean_t readonly)
|
||||
zfeature_checks_disable = B_TRUE;
|
||||
error = spa_import(target, config, props,
|
||||
(readonly ? ZFS_IMPORT_SKIP_MMP : ZFS_IMPORT_NORMAL));
|
||||
fnvlist_free(config);
|
||||
zfeature_checks_disable = B_FALSE;
|
||||
if (error == EEXIST)
|
||||
error = 0;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
sbin_PROGRAMS = zinject
|
||||
|
||||
zinject_SOURCES = \
|
||||
@@ -8,8 +12,5 @@ zinject_SOURCES = \
|
||||
zinject.h
|
||||
|
||||
zinject_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
|
||||
+35
-5
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* 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>
|
||||
@@ -85,6 +85,8 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
|
||||
struct stat64 *statbuf)
|
||||
{
|
||||
struct extmnttab mp;
|
||||
FILE *fp;
|
||||
int match;
|
||||
const char *rel;
|
||||
char fullpath[MAXPATHLEN];
|
||||
|
||||
@@ -97,7 +99,35 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
|
||||
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",
|
||||
fullpath);
|
||||
return (-1);
|
||||
@@ -146,7 +176,7 @@ object_from_path(const char *dataset, uint64_t object, zinject_record_t *record)
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the range based on the type, level, and range given.
|
||||
* Intialize the range based on the type, level, and range given.
|
||||
*/
|
||||
static int
|
||||
initialize_range(err_type_t type, int level, char *range,
|
||||
@@ -280,7 +310,7 @@ translate_record(err_type_t type, const char *object, const char *range,
|
||||
ziprintf("raw object: %llu\n", record->zi_object);
|
||||
|
||||
/*
|
||||
* For the given object, initialize the range in bytes
|
||||
* For the given object, intialize the range in bytes
|
||||
*/
|
||||
if (initialize_range(type, level, (char *)range, record) != 0)
|
||||
goto err;
|
||||
@@ -388,7 +418,7 @@ translate_device(const char *pool, const char *device, err_type_t label_type,
|
||||
record->zi_end = record->zi_start + VDEV_PAD_SIZE - 1;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -159,6 +159,8 @@
|
||||
libzfs_handle_t *g_zfs;
|
||||
int zfs_fd;
|
||||
|
||||
#define ECKSUM EBADE
|
||||
|
||||
static const char *errtable[TYPE_INVAL] = {
|
||||
"data",
|
||||
"dnode",
|
||||
@@ -338,7 +340,7 @@ iter_handlers(int (*func)(int, const char *, zinject_record_t *, void *),
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
int ret;
|
||||
|
||||
while (zfs_ioctl(g_zfs, ZFS_IOC_INJECT_LIST_NEXT, &zc) == 0)
|
||||
while (ioctl(zfs_fd, ZFS_IOC_INJECT_LIST_NEXT, &zc) == 0)
|
||||
if ((ret = func((int)zc.zc_guid, zc.zc_name,
|
||||
&zc.zc_inject_record, data)) != 0)
|
||||
return (ret);
|
||||
@@ -506,7 +508,7 @@ cancel_one_handler(int id, const char *pool, zinject_record_t *record,
|
||||
|
||||
zc.zc_guid = (uint64_t)id;
|
||||
|
||||
if (zfs_ioctl(g_zfs, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to remove handler %d: %s\n",
|
||||
id, strerror(errno));
|
||||
return (1);
|
||||
@@ -539,7 +541,7 @@ cancel_handler(int id)
|
||||
|
||||
zc.zc_guid = (uint64_t)id;
|
||||
|
||||
if (zfs_ioctl(g_zfs, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to remove handler %d: %s\n",
|
||||
id, strerror(errno));
|
||||
return (1);
|
||||
@@ -563,7 +565,7 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
zc.zc_inject_record = *record;
|
||||
zc.zc_guid = flags;
|
||||
|
||||
if (zfs_ioctl(g_zfs, ZFS_IOC_INJECT_FAULT, &zc) != 0) {
|
||||
if (ioctl(zfs_fd, ZFS_IOC_INJECT_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to add handler: %s\n",
|
||||
errno == EDOM ? "block level exceeds max level of object" :
|
||||
strerror(errno));
|
||||
@@ -613,7 +615,7 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
perform_action(const char *pool, zinject_record_t *record, int cmd)
|
||||
{
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
@@ -623,7 +625,7 @@ perform_action(const char *pool, zinject_record_t *record, int cmd)
|
||||
zc.zc_guid = record->zi_guid;
|
||||
zc.zc_cookie = cmd;
|
||||
|
||||
if (zfs_ioctl(g_zfs, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
|
||||
if (ioctl(zfs_fd, ZFS_IOC_VDEV_SET_STATE, &zc) == 0)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
@@ -761,7 +763,7 @@ main(int argc, char **argv)
|
||||
uint32_t dvas = 0;
|
||||
|
||||
if ((g_zfs = libzfs_init()) == NULL) {
|
||||
(void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
|
||||
(void) fprintf(stderr, "%s", libzfs_error_init(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
+9
-25
@@ -1,8 +1,8 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
AM_CFLAGS += $(LIBBLKID_CFLAGS) $(LIBUUID_CFLAGS)
|
||||
|
||||
DEFAULT_INCLUDES += -I$(srcdir)
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
sbin_PROGRAMS = zpool
|
||||
|
||||
@@ -13,28 +13,12 @@ zpool_SOURCES = \
|
||||
zpool_util.h \
|
||||
zpool_vdev.c
|
||||
|
||||
if BUILD_FREEBSD
|
||||
zpool_SOURCES += os/freebsd/zpool_vdev_os.c
|
||||
endif
|
||||
|
||||
if BUILD_LINUX
|
||||
zpool_SOURCES += os/linux/zpool_vdev_os.c
|
||||
endif
|
||||
|
||||
zpool_LDADD = \
|
||||
$(abs_top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(abs_top_builddir)/lib/libuutil/libuutil.la
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
|
||||
zpool_LDADD += $(LTLIBINTL)
|
||||
|
||||
if BUILD_FREEBSD
|
||||
zpool_LDADD += -lgeom
|
||||
endif
|
||||
zpool_LDADD += -lm $(LIBBLKID_LIBS) $(LIBUUID_LIBS)
|
||||
|
||||
include $(top_srcdir)/config/CppCheck.am
|
||||
zpool_LDADD += -lm $(LIBBLKID)
|
||||
|
||||
zpoolconfdir = $(sysconfdir)/zfs/zpool.d
|
||||
zpoolexecdir = $(zfsexecdir)/zpool.d
|
||||
@@ -42,7 +26,6 @@ zpoolexecdir = $(zfsexecdir)/zpool.d
|
||||
EXTRA_DIST = zpool.d/README
|
||||
|
||||
dist_zpoolexec_SCRIPTS = \
|
||||
zpool.d/dm-deps \
|
||||
zpool.d/enc \
|
||||
zpool.d/encdev \
|
||||
zpool.d/fault_led \
|
||||
@@ -57,6 +40,7 @@ dist_zpoolexec_SCRIPTS = \
|
||||
zpool.d/serial \
|
||||
zpool.d/ses \
|
||||
zpool.d/size \
|
||||
zpool.d/slaves \
|
||||
zpool.d/slot \
|
||||
zpool.d/smart \
|
||||
zpool.d/smartx \
|
||||
@@ -86,7 +70,6 @@ dist_zpoolexec_SCRIPTS = \
|
||||
zpool.d/test_ended
|
||||
|
||||
zpoolconfdefaults = \
|
||||
dm-deps \
|
||||
enc \
|
||||
encdev \
|
||||
fault_led \
|
||||
@@ -101,6 +84,7 @@ zpoolconfdefaults = \
|
||||
serial \
|
||||
ses \
|
||||
size \
|
||||
slaves \
|
||||
slot \
|
||||
smart \
|
||||
smartx \
|
||||
|
||||
@@ -1,103 +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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2016, 2017 Intel Corporation.
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Functions to convert between a list of vdevs and an nvlist representing the
|
||||
* configuration. Each entry in the list can be one of:
|
||||
*
|
||||
* Device vdevs
|
||||
* disk=(path=..., devid=...)
|
||||
* file=(path=...)
|
||||
*
|
||||
* Group vdevs
|
||||
* raidz[1|2]=(...)
|
||||
* mirror=(...)
|
||||
*
|
||||
* Hot spares
|
||||
*
|
||||
* While the underlying implementation supports it, group vdevs cannot contain
|
||||
* other group vdevs. All userland verification of devices is contained within
|
||||
* this file. If successful, the nvlist returned can be passed directly to the
|
||||
* kernel; we've done as much verification as possible in userland.
|
||||
*
|
||||
* Hot spares are a special case, and passed down as an array of disk vdevs, at
|
||||
* the same level as the root of the vdev tree.
|
||||
*
|
||||
* The only function exported by this file is 'make_root_vdev'. The
|
||||
* function performs several passes:
|
||||
*
|
||||
* 1. Construct the vdev specification. Performs syntax validation and
|
||||
* makes sure each device is valid.
|
||||
* 2. Check for devices in use. Using libdiskmgt, makes sure that no
|
||||
* devices are also in use. Some can be overridden using the 'force'
|
||||
* flag, others cannot.
|
||||
* 3. Check for replication errors if the 'force' flag is not specified.
|
||||
* validates that the replication level is consistent across the
|
||||
* entire pool.
|
||||
* 4. Call libzfs to label any whole disks with an EFI label.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libintl.h>
|
||||
#include <libnvpair.h>
|
||||
#include <libzutil.h>
|
||||
#include <limits.h>
|
||||
#include <sys/spa.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <paths.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <libgeom.h>
|
||||
|
||||
#include "zpool_util.h"
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
int
|
||||
check_device(const char *name, boolean_t force, boolean_t isspare,
|
||||
boolean_t iswholedisk)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
|
||||
if (strncmp(name, _PATH_DEV, sizeof (_PATH_DEV) - 1) != 0)
|
||||
snprintf(path, sizeof (path), "%s%s", _PATH_DEV, name);
|
||||
else
|
||||
strlcpy(path, name, sizeof (path));
|
||||
|
||||
return (check_file(path, force, isspare));
|
||||
}
|
||||
|
||||
boolean_t
|
||||
check_sector_size_database(char *path, int *sector_size)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
@@ -1,410 +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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2016, 2017 Intel Corporation.
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Functions to convert between a list of vdevs and an nvlist representing the
|
||||
* configuration. Each entry in the list can be one of:
|
||||
*
|
||||
* Device vdevs
|
||||
* disk=(path=..., devid=...)
|
||||
* file=(path=...)
|
||||
*
|
||||
* Group vdevs
|
||||
* raidz[1|2]=(...)
|
||||
* mirror=(...)
|
||||
*
|
||||
* Hot spares
|
||||
*
|
||||
* While the underlying implementation supports it, group vdevs cannot contain
|
||||
* other group vdevs. All userland verification of devices is contained within
|
||||
* this file. If successful, the nvlist returned can be passed directly to the
|
||||
* kernel; we've done as much verification as possible in userland.
|
||||
*
|
||||
* Hot spares are a special case, and passed down as an array of disk vdevs, at
|
||||
* the same level as the root of the vdev tree.
|
||||
*
|
||||
* The only function exported by this file is 'make_root_vdev'. The
|
||||
* function performs several passes:
|
||||
*
|
||||
* 1. Construct the vdev specification. Performs syntax validation and
|
||||
* makes sure each device is valid.
|
||||
* 2. Check for devices in use. Using libblkid to make sure that no
|
||||
* devices are also in use. Some can be overridden using the 'force'
|
||||
* flag, others cannot.
|
||||
* 3. Check for replication errors if the 'force' flag is not specified.
|
||||
* validates that the replication level is consistent across the
|
||||
* entire pool.
|
||||
* 4. Call libzfs to label any whole disks with an EFI label.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libintl.h>
|
||||
#include <libnvpair.h>
|
||||
#include <libzutil.h>
|
||||
#include <limits.h>
|
||||
#include <sys/spa.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "zpool_util.h"
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/sg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/efi_partition.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vtoc.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <blkid/blkid.h>
|
||||
|
||||
typedef struct vdev_disk_db_entry
|
||||
{
|
||||
char id[24];
|
||||
int sector_size;
|
||||
} vdev_disk_db_entry_t;
|
||||
|
||||
/*
|
||||
* Database of block devices that lie about physical sector sizes. The
|
||||
* identification string must be precisely 24 characters to avoid false
|
||||
* negatives
|
||||
*/
|
||||
static vdev_disk_db_entry_t vdev_disk_database[] = {
|
||||
{"ATA ADATA SSD S396 3", 8192},
|
||||
{"ATA APPLE SSD SM128E", 8192},
|
||||
{"ATA APPLE SSD SM256E", 8192},
|
||||
{"ATA APPLE SSD SM512E", 8192},
|
||||
{"ATA APPLE SSD SM768E", 8192},
|
||||
{"ATA C400-MTFDDAC064M", 8192},
|
||||
{"ATA C400-MTFDDAC128M", 8192},
|
||||
{"ATA C400-MTFDDAC256M", 8192},
|
||||
{"ATA C400-MTFDDAC512M", 8192},
|
||||
{"ATA Corsair Force 3 ", 8192},
|
||||
{"ATA Corsair Force GS", 8192},
|
||||
{"ATA INTEL SSDSA2CT04", 8192},
|
||||
{"ATA INTEL SSDSA2BZ10", 8192},
|
||||
{"ATA INTEL SSDSA2BZ20", 8192},
|
||||
{"ATA INTEL SSDSA2BZ30", 8192},
|
||||
{"ATA INTEL SSDSA2CW04", 8192},
|
||||
{"ATA INTEL SSDSA2CW08", 8192},
|
||||
{"ATA INTEL SSDSA2CW12", 8192},
|
||||
{"ATA INTEL SSDSA2CW16", 8192},
|
||||
{"ATA INTEL SSDSA2CW30", 8192},
|
||||
{"ATA INTEL SSDSA2CW60", 8192},
|
||||
{"ATA INTEL SSDSC2CT06", 8192},
|
||||
{"ATA INTEL SSDSC2CT12", 8192},
|
||||
{"ATA INTEL SSDSC2CT18", 8192},
|
||||
{"ATA INTEL SSDSC2CT24", 8192},
|
||||
{"ATA INTEL SSDSC2CW06", 8192},
|
||||
{"ATA INTEL SSDSC2CW12", 8192},
|
||||
{"ATA INTEL SSDSC2CW18", 8192},
|
||||
{"ATA INTEL SSDSC2CW24", 8192},
|
||||
{"ATA INTEL SSDSC2CW48", 8192},
|
||||
{"ATA KINGSTON SH100S3", 8192},
|
||||
{"ATA KINGSTON SH103S3", 8192},
|
||||
{"ATA M4-CT064M4SSD2 ", 8192},
|
||||
{"ATA M4-CT128M4SSD2 ", 8192},
|
||||
{"ATA M4-CT256M4SSD2 ", 8192},
|
||||
{"ATA M4-CT512M4SSD2 ", 8192},
|
||||
{"ATA OCZ-AGILITY2 ", 8192},
|
||||
{"ATA OCZ-AGILITY3 ", 8192},
|
||||
{"ATA OCZ-VERTEX2 3.5 ", 8192},
|
||||
{"ATA OCZ-VERTEX3 ", 8192},
|
||||
{"ATA OCZ-VERTEX3 LT ", 8192},
|
||||
{"ATA OCZ-VERTEX3 MI ", 8192},
|
||||
{"ATA OCZ-VERTEX4 ", 8192},
|
||||
{"ATA SAMSUNG MZ7WD120", 8192},
|
||||
{"ATA SAMSUNG MZ7WD240", 8192},
|
||||
{"ATA SAMSUNG MZ7WD480", 8192},
|
||||
{"ATA SAMSUNG MZ7WD960", 8192},
|
||||
{"ATA SAMSUNG SSD 830 ", 8192},
|
||||
{"ATA Samsung SSD 840 ", 8192},
|
||||
{"ATA SanDisk SSD U100", 8192},
|
||||
{"ATA TOSHIBA THNSNH06", 8192},
|
||||
{"ATA TOSHIBA THNSNH12", 8192},
|
||||
{"ATA TOSHIBA THNSNH25", 8192},
|
||||
{"ATA TOSHIBA THNSNH51", 8192},
|
||||
{"ATA APPLE SSD TS064C", 4096},
|
||||
{"ATA APPLE SSD TS128C", 4096},
|
||||
{"ATA APPLE SSD TS256C", 4096},
|
||||
{"ATA APPLE SSD TS512C", 4096},
|
||||
{"ATA INTEL SSDSA2M040", 4096},
|
||||
{"ATA INTEL SSDSA2M080", 4096},
|
||||
{"ATA INTEL SSDSA2M160", 4096},
|
||||
{"ATA INTEL SSDSC2MH12", 4096},
|
||||
{"ATA INTEL SSDSC2MH25", 4096},
|
||||
{"ATA OCZ CORE_SSD ", 4096},
|
||||
{"ATA OCZ-VERTEX ", 4096},
|
||||
{"ATA SAMSUNG MCCOE32G", 4096},
|
||||
{"ATA SAMSUNG MCCOE64G", 4096},
|
||||
{"ATA SAMSUNG SSD PM80", 4096},
|
||||
/* Flash drives optimized for 4KB IOs on larger pages */
|
||||
{"ATA INTEL SSDSC2BA10", 4096},
|
||||
{"ATA INTEL SSDSC2BA20", 4096},
|
||||
{"ATA INTEL SSDSC2BA40", 4096},
|
||||
{"ATA INTEL SSDSC2BA80", 4096},
|
||||
{"ATA INTEL SSDSC2BB08", 4096},
|
||||
{"ATA INTEL SSDSC2BB12", 4096},
|
||||
{"ATA INTEL SSDSC2BB16", 4096},
|
||||
{"ATA INTEL SSDSC2BB24", 4096},
|
||||
{"ATA INTEL SSDSC2BB30", 4096},
|
||||
{"ATA INTEL SSDSC2BB40", 4096},
|
||||
{"ATA INTEL SSDSC2BB48", 4096},
|
||||
{"ATA INTEL SSDSC2BB60", 4096},
|
||||
{"ATA INTEL SSDSC2BB80", 4096},
|
||||
{"ATA INTEL SSDSC2BW24", 4096},
|
||||
{"ATA INTEL SSDSC2BW48", 4096},
|
||||
{"ATA INTEL SSDSC2BP24", 4096},
|
||||
{"ATA INTEL SSDSC2BP48", 4096},
|
||||
{"NA SmrtStorSDLKAE9W", 4096},
|
||||
{"NVMe Amazon EC2 NVMe ", 4096},
|
||||
/* Imported from Open Solaris */
|
||||
{"ATA MARVELL SD88SA02", 4096},
|
||||
/* Advanced format Hard drives */
|
||||
{"ATA Hitachi HDS5C303", 4096},
|
||||
{"ATA SAMSUNG HD204UI ", 4096},
|
||||
{"ATA ST2000DL004 HD20", 4096},
|
||||
{"ATA WDC WD10EARS-00M", 4096},
|
||||
{"ATA WDC WD10EARS-00S", 4096},
|
||||
{"ATA WDC WD10EARS-00Z", 4096},
|
||||
{"ATA WDC WD15EARS-00M", 4096},
|
||||
{"ATA WDC WD15EARS-00S", 4096},
|
||||
{"ATA WDC WD15EARS-00Z", 4096},
|
||||
{"ATA WDC WD20EARS-00M", 4096},
|
||||
{"ATA WDC WD20EARS-00S", 4096},
|
||||
{"ATA WDC WD20EARS-00Z", 4096},
|
||||
{"ATA WDC WD1600BEVT-0", 4096},
|
||||
{"ATA WDC WD2500BEVT-0", 4096},
|
||||
{"ATA WDC WD3200BEVT-0", 4096},
|
||||
{"ATA WDC WD5000BEVT-0", 4096},
|
||||
};
|
||||
|
||||
|
||||
#define INQ_REPLY_LEN 96
|
||||
#define INQ_CMD_LEN 6
|
||||
|
||||
static const int vdev_disk_database_size =
|
||||
sizeof (vdev_disk_database) / sizeof (vdev_disk_database[0]);
|
||||
|
||||
boolean_t
|
||||
check_sector_size_database(char *path, int *sector_size)
|
||||
{
|
||||
unsigned char inq_buff[INQ_REPLY_LEN];
|
||||
unsigned char sense_buffer[32];
|
||||
unsigned char inq_cmd_blk[INQ_CMD_LEN] =
|
||||
{INQUIRY, 0, 0, 0, INQ_REPLY_LEN, 0};
|
||||
sg_io_hdr_t io_hdr;
|
||||
int error;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
/* Prepare INQUIRY command */
|
||||
memset(&io_hdr, 0, sizeof (sg_io_hdr_t));
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmd_len = sizeof (inq_cmd_blk);
|
||||
io_hdr.mx_sb_len = sizeof (sense_buffer);
|
||||
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
io_hdr.dxfer_len = INQ_REPLY_LEN;
|
||||
io_hdr.dxferp = inq_buff;
|
||||
io_hdr.cmdp = inq_cmd_blk;
|
||||
io_hdr.sbp = sense_buffer;
|
||||
io_hdr.timeout = 10; /* 10 milliseconds is ample time */
|
||||
|
||||
if ((fd = open(path, O_RDONLY|O_DIRECT)) < 0)
|
||||
return (B_FALSE);
|
||||
|
||||
error = ioctl(fd, SG_IO, (unsigned long) &io_hdr);
|
||||
|
||||
(void) close(fd);
|
||||
|
||||
if (error < 0)
|
||||
return (B_FALSE);
|
||||
|
||||
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
|
||||
return (B_FALSE);
|
||||
|
||||
for (i = 0; i < vdev_disk_database_size; i++) {
|
||||
if (memcmp(inq_buff + 8, vdev_disk_database[i].id, 24))
|
||||
continue;
|
||||
|
||||
*sector_size = vdev_disk_database[i].sector_size;
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
static int
|
||||
check_slice(const char *path, blkid_cache cache, int force, boolean_t isspare)
|
||||
{
|
||||
int err;
|
||||
char *value;
|
||||
|
||||
/* No valid type detected device is safe to use */
|
||||
value = blkid_get_tag_value(cache, "TYPE", path);
|
||||
if (value == NULL)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* If libblkid detects a ZFS device, we check the device
|
||||
* using check_file() to see if it's safe. The one safe
|
||||
* case is a spare device shared between multiple pools.
|
||||
*/
|
||||
if (strcmp(value, "zfs_member") == 0) {
|
||||
err = check_file(path, force, isspare);
|
||||
} else {
|
||||
if (force) {
|
||||
err = 0;
|
||||
} else {
|
||||
err = -1;
|
||||
vdev_error(gettext("%s contains a filesystem of "
|
||||
"type '%s'\n"), path, value);
|
||||
}
|
||||
}
|
||||
|
||||
free(value);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that a disk including all partitions are safe to use.
|
||||
*
|
||||
* For EFI labeled disks this can done relatively easily with the libefi
|
||||
* library. The partition numbers are extracted from the label and used
|
||||
* to generate the expected /dev/ paths. Each partition can then be
|
||||
* checked for conflicts.
|
||||
*
|
||||
* For non-EFI labeled disks (MBR/EBR/etc) the same process is possible
|
||||
* but due to the lack of a readily available libraries this scanning is
|
||||
* not implemented. Instead only the device path as given is checked.
|
||||
*/
|
||||
static int
|
||||
check_disk(const char *path, blkid_cache cache, int force,
|
||||
boolean_t isspare, boolean_t iswholedisk)
|
||||
{
|
||||
struct dk_gpt *vtoc;
|
||||
char slice_path[MAXPATHLEN];
|
||||
int err = 0;
|
||||
int fd, i;
|
||||
int flags = O_RDONLY|O_DIRECT;
|
||||
|
||||
if (!iswholedisk)
|
||||
return (check_slice(path, cache, force, isspare));
|
||||
|
||||
/* only spares can be shared, other devices require exclusive access */
|
||||
if (!isspare)
|
||||
flags |= O_EXCL;
|
||||
|
||||
if ((fd = open(path, flags)) < 0) {
|
||||
char *value = blkid_get_tag_value(cache, "TYPE", path);
|
||||
(void) fprintf(stderr, gettext("%s is in use and contains "
|
||||
"a %s filesystem.\n"), path, value ? value : "unknown");
|
||||
free(value);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expected to fail for non-EFI labeled disks. Just check the device
|
||||
* as given and do not attempt to detect and scan partitions.
|
||||
*/
|
||||
err = efi_alloc_and_read(fd, &vtoc);
|
||||
if (err) {
|
||||
(void) close(fd);
|
||||
return (check_slice(path, cache, force, isspare));
|
||||
}
|
||||
|
||||
/*
|
||||
* The primary efi partition label is damaged however the secondary
|
||||
* label at the end of the device is intact. Rather than use this
|
||||
* label we should play it safe and treat this as a non efi device.
|
||||
*/
|
||||
if (vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
|
||||
efi_free(vtoc);
|
||||
(void) close(fd);
|
||||
|
||||
if (force) {
|
||||
/* Partitions will now be created using the backup */
|
||||
return (0);
|
||||
} else {
|
||||
vdev_error(gettext("%s contains a corrupt primary "
|
||||
"EFI label.\n"), path);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < vtoc->efi_nparts; i++) {
|
||||
|
||||
if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED ||
|
||||
uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_guid))
|
||||
continue;
|
||||
|
||||
if (strncmp(path, UDISK_ROOT, strlen(UDISK_ROOT)) == 0)
|
||||
(void) snprintf(slice_path, sizeof (slice_path),
|
||||
"%s%s%d", path, "-part", i+1);
|
||||
else
|
||||
(void) snprintf(slice_path, sizeof (slice_path),
|
||||
"%s%s%d", path, isdigit(path[strlen(path)-1]) ?
|
||||
"p" : "", i+1);
|
||||
|
||||
err = check_slice(slice_path, cache, force, isspare);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
efi_free(vtoc);
|
||||
(void) close(fd);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
check_device(const char *path, boolean_t force,
|
||||
boolean_t isspare, boolean_t iswholedisk)
|
||||
{
|
||||
blkid_cache cache;
|
||||
int error;
|
||||
|
||||
error = blkid_get_cache(&cache, NULL);
|
||||
if (error != 0) {
|
||||
(void) fprintf(stderr, gettext("unable to access the blkid "
|
||||
"cache.\n"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
error = check_disk(path, cache, force, isspare, iswholedisk);
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@@ -17,14 +17,14 @@ fi
|
||||
|
||||
if [ "$script" = "iostat-1s" ] ; then
|
||||
# Do a single one-second sample
|
||||
interval=1
|
||||
extra="1 1"
|
||||
# Don't show summary stats
|
||||
brief="yes"
|
||||
y="-y"
|
||||
elif [ "$script" = "iostat-10s" ] ; then
|
||||
# Do a single ten-second sample
|
||||
interval=10
|
||||
extra="10 1"
|
||||
# Don't show summary stats
|
||||
brief="yes"
|
||||
y="-y"
|
||||
fi
|
||||
|
||||
if [ -f "$VDEV_UPATH" ] ; then
|
||||
@@ -32,19 +32,7 @@ if [ -f "$VDEV_UPATH" ] ; then
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$(uname)" = "FreeBSD" ]; then
|
||||
out=$(iostat -dKx \
|
||||
${interval:+"-w $interval"} \
|
||||
${interval:+"-c 1"} \
|
||||
"$VDEV_UPATH" | tail -n 2)
|
||||
else
|
||||
out=$(iostat -kx \
|
||||
${brief:+"-y"} \
|
||||
${interval:+"$interval"} \
|
||||
${interval:+"1"} \
|
||||
"$VDEV_UPATH" | awk NF | tail -n 2)
|
||||
fi
|
||||
|
||||
out=$(eval "iostat $y -k -x $VDEV_UPATH $extra")
|
||||
|
||||
# Sample output (we want the last two lines):
|
||||
#
|
||||
@@ -58,16 +46,16 @@ fi
|
||||
#
|
||||
|
||||
# Get the column names
|
||||
cols=$(echo "$out" | head -n 1)
|
||||
cols=$(echo "$out" | grep Device)
|
||||
|
||||
# Get the values and tab separate them to make them cut-able.
|
||||
vals=$(echo "$out" | tail -n 1 | sed -r 's/[[:blank:]]+/\t/g')
|
||||
vals="$(echo "$out" | grep -A1 Device | tail -n 1 | sed -r 's/[[:blank:]]+/\t/g')"
|
||||
|
||||
i=0
|
||||
for col in $cols ; do
|
||||
i=$((i+1))
|
||||
# Skip the first column since it's just the device name
|
||||
if [ $i -eq 1 ]; then
|
||||
if [ "$col" = "Device:" ] ; then
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Show device mapper dependent / underlying devices. This is useful for
|
||||
# looking up the /dev/sd* devices associated with a dm or multipath device.
|
||||
# Show device mapper slave devices. This is useful for looking up the
|
||||
# /dev/sd* devices associated with a dm or multipath device. For example:
|
||||
#
|
||||
# $ ls /sys/block/dm-113/slaves/
|
||||
# sddt sdjw
|
||||
#
|
||||
|
||||
if [ "$1" = "-h" ] ; then
|
||||
echo "Show device mapper dependent (underlying) devices."
|
||||
echo "Show device mapper slave devices."
|
||||
exit
|
||||
fi
|
||||
|
||||
@@ -26,4 +29,4 @@ if [ -d "/sys/class/block/$dev/slaves" ] ; then
|
||||
val=$(echo "$val" | sed -r 's/[[:blank:]]+/ /g')
|
||||
fi
|
||||
|
||||
echo "dm-deps=$val"
|
||||
echo "slaves=$val"
|
||||
@@ -71,12 +71,11 @@ fi
|
||||
|
||||
smartctl_path=$(command -v smartctl)
|
||||
|
||||
# shellcheck disable=SC2015
|
||||
if [ -b "$VDEV_UPATH" ] && [ -x "$smartctl_path" ] || [ -n "$samples" ] ; then
|
||||
if [ -n "$samples" ] ; then
|
||||
# cat a smartctl output text file instead of running smartctl
|
||||
# on a vdev (only used for developer testing).
|
||||
file=$(get_filename_from_dir "$samples")
|
||||
file=$(get_filename_from_dir $samples)
|
||||
echo "file=$file"
|
||||
raw_out=$(cat "$samples/$file")
|
||||
else
|
||||
|
||||
+7
-13
@@ -56,7 +56,6 @@ typedef struct zpool_node {
|
||||
|
||||
struct zpool_list {
|
||||
boolean_t zl_findall;
|
||||
boolean_t zl_literal;
|
||||
uu_avl_t *zl_avl;
|
||||
uu_avl_pool_t *zl_pool;
|
||||
zprop_list_t **zl_proplist;
|
||||
@@ -89,9 +88,7 @@ add_pool(zpool_handle_t *zhp, void *data)
|
||||
uu_avl_node_init(node, &node->zn_avlnode, zlp->zl_pool);
|
||||
if (uu_avl_find(zlp->zl_avl, node, NULL, &idx) == NULL) {
|
||||
if (zlp->zl_proplist &&
|
||||
zpool_expand_proplist(zhp, zlp->zl_proplist,
|
||||
zlp->zl_literal)
|
||||
!= 0) {
|
||||
zpool_expand_proplist(zhp, zlp->zl_proplist) != 0) {
|
||||
zpool_close(zhp);
|
||||
free(node);
|
||||
return (-1);
|
||||
@@ -113,8 +110,7 @@ add_pool(zpool_handle_t *zhp, void *data)
|
||||
* line.
|
||||
*/
|
||||
zpool_list_t *
|
||||
pool_list_get(int argc, char **argv, zprop_list_t **proplist,
|
||||
boolean_t literal, int *err)
|
||||
pool_list_get(int argc, char **argv, zprop_list_t **proplist, int *err)
|
||||
{
|
||||
zpool_list_t *zlp;
|
||||
|
||||
@@ -132,8 +128,6 @@ pool_list_get(int argc, char **argv, zprop_list_t **proplist,
|
||||
|
||||
zlp->zl_proplist = proplist;
|
||||
|
||||
zlp->zl_literal = literal;
|
||||
|
||||
if (argc == 0) {
|
||||
(void) zpool_iter(g_zfs, add_pool, zlp);
|
||||
zlp->zl_findall = B_TRUE;
|
||||
@@ -248,12 +242,12 @@ pool_list_count(zpool_list_t *zlp)
|
||||
*/
|
||||
int
|
||||
for_each_pool(int argc, char **argv, boolean_t unavail,
|
||||
zprop_list_t **proplist, boolean_t literal, zpool_iter_f func, void *data)
|
||||
zprop_list_t **proplist, zpool_iter_f func, void *data)
|
||||
{
|
||||
zpool_list_t *list;
|
||||
int ret = 0;
|
||||
|
||||
if ((list = pool_list_get(argc, argv, proplist, literal, &ret)) == NULL)
|
||||
if ((list = pool_list_get(argc, argv, proplist, &ret)) == NULL)
|
||||
return (1);
|
||||
|
||||
if (pool_list_iter(list, unavail, func, data) != 0)
|
||||
@@ -622,7 +616,7 @@ for_each_vdev_run_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_vcdl)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for selected vdevs here, if any */
|
||||
/* Check for whitelisted vdevs here, if any */
|
||||
for (i = 0; i < vcdl->vdev_names_count; i++) {
|
||||
vname = zpool_vdev_name(g_zfs, zhp, nv, vcdl->cb_name_flags);
|
||||
if (strcmp(vcdl->vdev_names[i], vname) == 0) {
|
||||
@@ -633,7 +627,7 @@ for_each_vdev_run_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_vcdl)
|
||||
free(vname);
|
||||
}
|
||||
|
||||
/* If we selected vdevs, and this isn't one of them, then bail out */
|
||||
/* If we whitelisted vdevs, and this isn't one of them, then bail out */
|
||||
if (!match && vcdl->vdev_names_count)
|
||||
return (0);
|
||||
|
||||
@@ -717,7 +711,7 @@ all_pools_for_each_vdev_run(int argc, char **argv, char *cmd,
|
||||
vcdl->g_zfs = g_zfs;
|
||||
|
||||
/* Gather our list of all vdevs in all pools */
|
||||
for_each_pool(argc, argv, B_TRUE, NULL, B_FALSE,
|
||||
for_each_pool(argc, argv, B_TRUE, NULL,
|
||||
all_pools_for_each_vdev_gather_cb, vcdl);
|
||||
|
||||
/* Run command on all vdevs in all pools */
|
||||
|
||||
+435
-1583
File diff suppressed because it is too large
Load Diff
@@ -98,6 +98,20 @@ array64_max(uint64_t array[], unsigned int len)
|
||||
return (max);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if "str" is a number string, 0 otherwise. Works for integer and
|
||||
* floating point numbers.
|
||||
*/
|
||||
int
|
||||
isnumber(char *str)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (!(isdigit(*str) || (*str == '.')))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find highest one bit set.
|
||||
* Returns bit number + 1 of highest bit that is set, otherwise returns 0.
|
||||
|
||||
+5
-10
@@ -42,6 +42,7 @@ void *safe_malloc(size_t);
|
||||
void zpool_no_memory(void);
|
||||
uint_t num_logs(nvlist_t *nv);
|
||||
uint64_t array64_max(uint64_t array[], unsigned int len);
|
||||
int isnumber(char *str);
|
||||
int highbit64(uint64_t i);
|
||||
int lowbit64(uint64_t i);
|
||||
|
||||
@@ -64,7 +65,7 @@ nvlist_t *split_mirror_vdev(zpool_handle_t *zhp, char *newname,
|
||||
* Pool list functions
|
||||
*/
|
||||
int for_each_pool(int, char **, boolean_t unavail, zprop_list_t **,
|
||||
boolean_t, zpool_iter_f, void *);
|
||||
zpool_iter_f, void *);
|
||||
|
||||
/* Vdev list functions */
|
||||
typedef int (*pool_vdev_iter_f)(zpool_handle_t *, nvlist_t *, void *);
|
||||
@@ -72,14 +73,14 @@ int for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func, void *data);
|
||||
|
||||
typedef struct zpool_list zpool_list_t;
|
||||
|
||||
zpool_list_t *pool_list_get(int, char **, zprop_list_t **, boolean_t, int *);
|
||||
zpool_list_t *pool_list_get(int, char **, zprop_list_t **, int *);
|
||||
void pool_list_update(zpool_list_t *);
|
||||
int pool_list_iter(zpool_list_t *, int unavail, zpool_iter_f, void *);
|
||||
void pool_list_free(zpool_list_t *);
|
||||
int pool_list_count(zpool_list_t *);
|
||||
void pool_list_remove(zpool_list_t *, zpool_handle_t *);
|
||||
|
||||
extern libzfs_handle_t *g_zfs;
|
||||
libzfs_handle_t *g_zfs;
|
||||
|
||||
|
||||
typedef struct vdev_cmd_data
|
||||
@@ -103,7 +104,7 @@ typedef struct vdev_cmd_data_list
|
||||
char *cmd; /* Command to run */
|
||||
unsigned int count; /* Number of vdev_cmd_data items (vdevs) */
|
||||
|
||||
/* fields used to select only certain vdevs, if requested */
|
||||
/* vars to whitelist only certain vdevs, if requested */
|
||||
libzfs_handle_t *g_zfs;
|
||||
char **vdev_names;
|
||||
int vdev_names_count;
|
||||
@@ -124,12 +125,6 @@ vdev_cmd_data_list_t *all_pools_for_each_vdev_run(int argc, char **argv,
|
||||
|
||||
void free_vdev_cmd_data_list(vdev_cmd_data_list_t *vcdl);
|
||||
|
||||
int check_device(const char *path, boolean_t force,
|
||||
boolean_t isspare, boolean_t iswholedisk);
|
||||
boolean_t check_sector_size_database(char *path, int *sector_size);
|
||||
void vdev_error(const char *fmt, ...);
|
||||
int check_file(const char *file, boolean_t force, boolean_t isspare);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+342
-14
@@ -64,6 +64,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <devid.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libintl.h>
|
||||
@@ -71,12 +72,19 @@
|
||||
#include <libzutil.h>
|
||||
#include <limits.h>
|
||||
#include <sys/spa.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/sg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/efi_partition.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vtoc.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <blkid/blkid.h>
|
||||
#include "zpool_util.h"
|
||||
#include <sys/zfs_context.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* For any given vdev specification, we can have multiple errors. The
|
||||
@@ -86,11 +94,191 @@
|
||||
boolean_t error_seen;
|
||||
boolean_t is_force;
|
||||
|
||||
typedef struct vdev_disk_db_entry
|
||||
{
|
||||
char id[24];
|
||||
int sector_size;
|
||||
} vdev_disk_db_entry_t;
|
||||
|
||||
/*
|
||||
* Database of block devices that lie about physical sector sizes. The
|
||||
* identification string must be precisely 24 characters to avoid false
|
||||
* negatives
|
||||
*/
|
||||
static vdev_disk_db_entry_t vdev_disk_database[] = {
|
||||
{"ATA ADATA SSD S396 3", 8192},
|
||||
{"ATA APPLE SSD SM128E", 8192},
|
||||
{"ATA APPLE SSD SM256E", 8192},
|
||||
{"ATA APPLE SSD SM512E", 8192},
|
||||
{"ATA APPLE SSD SM768E", 8192},
|
||||
{"ATA C400-MTFDDAC064M", 8192},
|
||||
{"ATA C400-MTFDDAC128M", 8192},
|
||||
{"ATA C400-MTFDDAC256M", 8192},
|
||||
{"ATA C400-MTFDDAC512M", 8192},
|
||||
{"ATA Corsair Force 3 ", 8192},
|
||||
{"ATA Corsair Force GS", 8192},
|
||||
{"ATA INTEL SSDSA2CT04", 8192},
|
||||
{"ATA INTEL SSDSA2BZ10", 8192},
|
||||
{"ATA INTEL SSDSA2BZ20", 8192},
|
||||
{"ATA INTEL SSDSA2BZ30", 8192},
|
||||
{"ATA INTEL SSDSA2CW04", 8192},
|
||||
{"ATA INTEL SSDSA2CW08", 8192},
|
||||
{"ATA INTEL SSDSA2CW12", 8192},
|
||||
{"ATA INTEL SSDSA2CW16", 8192},
|
||||
{"ATA INTEL SSDSA2CW30", 8192},
|
||||
{"ATA INTEL SSDSA2CW60", 8192},
|
||||
{"ATA INTEL SSDSC2CT06", 8192},
|
||||
{"ATA INTEL SSDSC2CT12", 8192},
|
||||
{"ATA INTEL SSDSC2CT18", 8192},
|
||||
{"ATA INTEL SSDSC2CT24", 8192},
|
||||
{"ATA INTEL SSDSC2CW06", 8192},
|
||||
{"ATA INTEL SSDSC2CW12", 8192},
|
||||
{"ATA INTEL SSDSC2CW18", 8192},
|
||||
{"ATA INTEL SSDSC2CW24", 8192},
|
||||
{"ATA INTEL SSDSC2CW48", 8192},
|
||||
{"ATA KINGSTON SH100S3", 8192},
|
||||
{"ATA KINGSTON SH103S3", 8192},
|
||||
{"ATA M4-CT064M4SSD2 ", 8192},
|
||||
{"ATA M4-CT128M4SSD2 ", 8192},
|
||||
{"ATA M4-CT256M4SSD2 ", 8192},
|
||||
{"ATA M4-CT512M4SSD2 ", 8192},
|
||||
{"ATA OCZ-AGILITY2 ", 8192},
|
||||
{"ATA OCZ-AGILITY3 ", 8192},
|
||||
{"ATA OCZ-VERTEX2 3.5 ", 8192},
|
||||
{"ATA OCZ-VERTEX3 ", 8192},
|
||||
{"ATA OCZ-VERTEX3 LT ", 8192},
|
||||
{"ATA OCZ-VERTEX3 MI ", 8192},
|
||||
{"ATA OCZ-VERTEX4 ", 8192},
|
||||
{"ATA SAMSUNG MZ7WD120", 8192},
|
||||
{"ATA SAMSUNG MZ7WD240", 8192},
|
||||
{"ATA SAMSUNG MZ7WD480", 8192},
|
||||
{"ATA SAMSUNG MZ7WD960", 8192},
|
||||
{"ATA SAMSUNG SSD 830 ", 8192},
|
||||
{"ATA Samsung SSD 840 ", 8192},
|
||||
{"ATA SanDisk SSD U100", 8192},
|
||||
{"ATA TOSHIBA THNSNH06", 8192},
|
||||
{"ATA TOSHIBA THNSNH12", 8192},
|
||||
{"ATA TOSHIBA THNSNH25", 8192},
|
||||
{"ATA TOSHIBA THNSNH51", 8192},
|
||||
{"ATA APPLE SSD TS064C", 4096},
|
||||
{"ATA APPLE SSD TS128C", 4096},
|
||||
{"ATA APPLE SSD TS256C", 4096},
|
||||
{"ATA APPLE SSD TS512C", 4096},
|
||||
{"ATA INTEL SSDSA2M040", 4096},
|
||||
{"ATA INTEL SSDSA2M080", 4096},
|
||||
{"ATA INTEL SSDSA2M160", 4096},
|
||||
{"ATA INTEL SSDSC2MH12", 4096},
|
||||
{"ATA INTEL SSDSC2MH25", 4096},
|
||||
{"ATA OCZ CORE_SSD ", 4096},
|
||||
{"ATA OCZ-VERTEX ", 4096},
|
||||
{"ATA SAMSUNG MCCOE32G", 4096},
|
||||
{"ATA SAMSUNG MCCOE64G", 4096},
|
||||
{"ATA SAMSUNG SSD PM80", 4096},
|
||||
/* Flash drives optimized for 4KB IOs on larger pages */
|
||||
{"ATA INTEL SSDSC2BA10", 4096},
|
||||
{"ATA INTEL SSDSC2BA20", 4096},
|
||||
{"ATA INTEL SSDSC2BA40", 4096},
|
||||
{"ATA INTEL SSDSC2BA80", 4096},
|
||||
{"ATA INTEL SSDSC2BB08", 4096},
|
||||
{"ATA INTEL SSDSC2BB12", 4096},
|
||||
{"ATA INTEL SSDSC2BB16", 4096},
|
||||
{"ATA INTEL SSDSC2BB24", 4096},
|
||||
{"ATA INTEL SSDSC2BB30", 4096},
|
||||
{"ATA INTEL SSDSC2BB40", 4096},
|
||||
{"ATA INTEL SSDSC2BB48", 4096},
|
||||
{"ATA INTEL SSDSC2BB60", 4096},
|
||||
{"ATA INTEL SSDSC2BB80", 4096},
|
||||
{"ATA INTEL SSDSC2BW24", 4096},
|
||||
{"ATA INTEL SSDSC2BW48", 4096},
|
||||
{"ATA INTEL SSDSC2BP24", 4096},
|
||||
{"ATA INTEL SSDSC2BP48", 4096},
|
||||
{"NA SmrtStorSDLKAE9W", 4096},
|
||||
{"NVMe Amazon EC2 NVMe ", 4096},
|
||||
/* Imported from Open Solaris */
|
||||
{"ATA MARVELL SD88SA02", 4096},
|
||||
/* Advanced format Hard drives */
|
||||
{"ATA Hitachi HDS5C303", 4096},
|
||||
{"ATA SAMSUNG HD204UI ", 4096},
|
||||
{"ATA ST2000DL004 HD20", 4096},
|
||||
{"ATA WDC WD10EARS-00M", 4096},
|
||||
{"ATA WDC WD10EARS-00S", 4096},
|
||||
{"ATA WDC WD10EARS-00Z", 4096},
|
||||
{"ATA WDC WD15EARS-00M", 4096},
|
||||
{"ATA WDC WD15EARS-00S", 4096},
|
||||
{"ATA WDC WD15EARS-00Z", 4096},
|
||||
{"ATA WDC WD20EARS-00M", 4096},
|
||||
{"ATA WDC WD20EARS-00S", 4096},
|
||||
{"ATA WDC WD20EARS-00Z", 4096},
|
||||
{"ATA WDC WD1600BEVT-0", 4096},
|
||||
{"ATA WDC WD2500BEVT-0", 4096},
|
||||
{"ATA WDC WD3200BEVT-0", 4096},
|
||||
{"ATA WDC WD5000BEVT-0", 4096},
|
||||
/* Virtual disks: Assume zvols with default volblocksize */
|
||||
#if 0
|
||||
{"ATA QEMU HARDDISK ", 8192},
|
||||
{"IET VIRTUAL-DISK ", 8192},
|
||||
{"OI COMSTAR ", 8192},
|
||||
{"SUN COMSTAR ", 8192},
|
||||
{"NETAPP LUN ", 8192},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const int vdev_disk_database_size =
|
||||
sizeof (vdev_disk_database) / sizeof (vdev_disk_database[0]);
|
||||
|
||||
#define INQ_REPLY_LEN 96
|
||||
#define INQ_CMD_LEN 6
|
||||
|
||||
static boolean_t
|
||||
check_sector_size_database(char *path, int *sector_size)
|
||||
{
|
||||
unsigned char inq_buff[INQ_REPLY_LEN];
|
||||
unsigned char sense_buffer[32];
|
||||
unsigned char inq_cmd_blk[INQ_CMD_LEN] =
|
||||
{INQUIRY, 0, 0, 0, INQ_REPLY_LEN, 0};
|
||||
sg_io_hdr_t io_hdr;
|
||||
int error;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
/* Prepare INQUIRY command */
|
||||
memset(&io_hdr, 0, sizeof (sg_io_hdr_t));
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmd_len = sizeof (inq_cmd_blk);
|
||||
io_hdr.mx_sb_len = sizeof (sense_buffer);
|
||||
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
||||
io_hdr.dxfer_len = INQ_REPLY_LEN;
|
||||
io_hdr.dxferp = inq_buff;
|
||||
io_hdr.cmdp = inq_cmd_blk;
|
||||
io_hdr.sbp = sense_buffer;
|
||||
io_hdr.timeout = 10; /* 10 milliseconds is ample time */
|
||||
|
||||
if ((fd = open(path, O_RDONLY|O_DIRECT)) < 0)
|
||||
return (B_FALSE);
|
||||
|
||||
error = ioctl(fd, SG_IO, (unsigned long) &io_hdr);
|
||||
|
||||
(void) close(fd);
|
||||
|
||||
if (error < 0)
|
||||
return (B_FALSE);
|
||||
|
||||
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
|
||||
return (B_FALSE);
|
||||
|
||||
for (i = 0; i < vdev_disk_database_size; i++) {
|
||||
if (memcmp(inq_buff + 8, vdev_disk_database[i].id, 24))
|
||||
continue;
|
||||
|
||||
*sector_size = vdev_disk_database[i].sector_size;
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
/*PRINTFLIKE1*/
|
||||
void
|
||||
static void
|
||||
vdev_error(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -115,7 +303,7 @@ vdev_error(const char *fmt, ...)
|
||||
* Check that a file is valid. All we can do in this case is check that it's
|
||||
* not in use by another pool, and not in use by swap.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
check_file(const char *file, boolean_t force, boolean_t isspare)
|
||||
{
|
||||
char *name;
|
||||
@@ -179,6 +367,150 @@ check_file(const char *file, boolean_t force, boolean_t isspare)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
check_slice(const char *path, blkid_cache cache, int force, boolean_t isspare)
|
||||
{
|
||||
int err;
|
||||
char *value;
|
||||
|
||||
/* No valid type detected device is safe to use */
|
||||
value = blkid_get_tag_value(cache, "TYPE", path);
|
||||
if (value == NULL)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* If libblkid detects a ZFS device, we check the device
|
||||
* using check_file() to see if it's safe. The one safe
|
||||
* case is a spare device shared between multiple pools.
|
||||
*/
|
||||
if (strcmp(value, "zfs_member") == 0) {
|
||||
err = check_file(path, force, isspare);
|
||||
} else {
|
||||
if (force) {
|
||||
err = 0;
|
||||
} else {
|
||||
err = -1;
|
||||
vdev_error(gettext("%s contains a filesystem of "
|
||||
"type '%s'\n"), path, value);
|
||||
}
|
||||
}
|
||||
|
||||
free(value);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that a disk including all partitions are safe to use.
|
||||
*
|
||||
* For EFI labeled disks this can done relatively easily with the libefi
|
||||
* library. The partition numbers are extracted from the label and used
|
||||
* to generate the expected /dev/ paths. Each partition can then be
|
||||
* checked for conflicts.
|
||||
*
|
||||
* For non-EFI labeled disks (MBR/EBR/etc) the same process is possible
|
||||
* but due to the lack of a readily available libraries this scanning is
|
||||
* not implemented. Instead only the device path as given is checked.
|
||||
*/
|
||||
static int
|
||||
check_disk(const char *path, blkid_cache cache, int force,
|
||||
boolean_t isspare, boolean_t iswholedisk)
|
||||
{
|
||||
struct dk_gpt *vtoc;
|
||||
char slice_path[MAXPATHLEN];
|
||||
int err = 0;
|
||||
int fd, i;
|
||||
int flags = O_RDONLY|O_DIRECT;
|
||||
|
||||
if (!iswholedisk)
|
||||
return (check_slice(path, cache, force, isspare));
|
||||
|
||||
/* only spares can be shared, other devices require exclusive access */
|
||||
if (!isspare)
|
||||
flags |= O_EXCL;
|
||||
|
||||
if ((fd = open(path, flags)) < 0) {
|
||||
char *value = blkid_get_tag_value(cache, "TYPE", path);
|
||||
(void) fprintf(stderr, gettext("%s is in use and contains "
|
||||
"a %s filesystem.\n"), path, value ? value : "unknown");
|
||||
free(value);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expected to fail for non-EFI labled disks. Just check the device
|
||||
* as given and do not attempt to detect and scan partitions.
|
||||
*/
|
||||
err = efi_alloc_and_read(fd, &vtoc);
|
||||
if (err) {
|
||||
(void) close(fd);
|
||||
return (check_slice(path, cache, force, isspare));
|
||||
}
|
||||
|
||||
/*
|
||||
* The primary efi partition label is damaged however the secondary
|
||||
* label at the end of the device is intact. Rather than use this
|
||||
* label we should play it safe and treat this as a non efi device.
|
||||
*/
|
||||
if (vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
|
||||
efi_free(vtoc);
|
||||
(void) close(fd);
|
||||
|
||||
if (force) {
|
||||
/* Partitions will now be created using the backup */
|
||||
return (0);
|
||||
} else {
|
||||
vdev_error(gettext("%s contains a corrupt primary "
|
||||
"EFI label.\n"), path);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < vtoc->efi_nparts; i++) {
|
||||
|
||||
if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED ||
|
||||
uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_guid))
|
||||
continue;
|
||||
|
||||
if (strncmp(path, UDISK_ROOT, strlen(UDISK_ROOT)) == 0)
|
||||
(void) snprintf(slice_path, sizeof (slice_path),
|
||||
"%s%s%d", path, "-part", i+1);
|
||||
else
|
||||
(void) snprintf(slice_path, sizeof (slice_path),
|
||||
"%s%s%d", path, isdigit(path[strlen(path)-1]) ?
|
||||
"p" : "", i+1);
|
||||
|
||||
err = check_slice(slice_path, cache, force, isspare);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
efi_free(vtoc);
|
||||
(void) close(fd);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
check_device(const char *path, boolean_t force,
|
||||
boolean_t isspare, boolean_t iswholedisk)
|
||||
{
|
||||
blkid_cache cache;
|
||||
int error;
|
||||
|
||||
error = blkid_get_cache(&cache, NULL);
|
||||
if (error != 0) {
|
||||
(void) fprintf(stderr, gettext("unable to access the blkid "
|
||||
"cache.\n"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
error = check_disk(path, cache, force, isspare, iswholedisk);
|
||||
blkid_put_cache(cache);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* This may be a shorthand device path or it could be total gibberish.
|
||||
* Check to see if it is a known device available in zfs_vdev_paths.
|
||||
@@ -497,7 +829,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
rep.zprl_children = 1;
|
||||
rep.zprl_parity = 0;
|
||||
} else {
|
||||
int64_t vdev_size;
|
||||
uint64_t vdev_size;
|
||||
|
||||
/*
|
||||
* This is a mirror or RAID-Z vdev. Go through and make
|
||||
@@ -527,12 +859,12 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
*/
|
||||
type = NULL;
|
||||
dontreport = 0;
|
||||
vdev_size = -1LL;
|
||||
vdev_size = -1ULL;
|
||||
for (c = 0; c < children; c++) {
|
||||
nvlist_t *cnv = child[c];
|
||||
char *path;
|
||||
struct stat64 statbuf;
|
||||
int64_t size = -1LL;
|
||||
uint64_t size = -1ULL;
|
||||
char *childtype;
|
||||
int fd, err;
|
||||
|
||||
@@ -623,8 +955,8 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
* (~16MB) then report an error.
|
||||
*/
|
||||
if (!dontreport &&
|
||||
(vdev_size != -1LL &&
|
||||
(llabs(size - vdev_size) >
|
||||
(vdev_size != -1ULL &&
|
||||
(labs(size - vdev_size) >
|
||||
ZPOOL_FUZZ))) {
|
||||
if (ret != NULL)
|
||||
free(ret);
|
||||
@@ -941,10 +1273,6 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
|
||||
if (fd == -1) {
|
||||
if (errno == EBUSY)
|
||||
is_exclusive = 1;
|
||||
#ifdef __FreeBSD__
|
||||
if (errno == EPERM)
|
||||
is_exclusive = 1;
|
||||
#endif
|
||||
} else {
|
||||
(void) close(fd);
|
||||
}
|
||||
@@ -1173,7 +1501,7 @@ is_grouping(const char *type, int *mindev, int *maxdev)
|
||||
* Note: we don't bother freeing anything in the error paths
|
||||
* because the program is just going to exit anyway.
|
||||
*/
|
||||
static nvlist_t *
|
||||
nvlist_t *
|
||||
construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
{
|
||||
nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
|
||||
@@ -1539,7 +1867,7 @@ make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep,
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate each device to make sure that it's not shared with another
|
||||
* Validate each device to make sure that its not shared with another
|
||||
* subsystem. We do this even if 'force' is set, because there are some
|
||||
* uses (such as a dedicated dump device) that even '-f' cannot
|
||||
* override.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user