mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 19:04:45 +03:00
Compare commits
270 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8c2b7ebc6 | |||
| 2af898ee24 | |||
| c32c2f17d0 | |||
| 2254b2bbbe | |||
| 5c4ec382a7 | |||
| e22bfd8149 | |||
| f45ad7bff6 | |||
| 0a3a4d067a | |||
| ba8024a284 | |||
| edc2675aed | |||
| 98bb45e27a | |||
| 44f463824b | |||
| b0d579bc55 | |||
| 7e5def8ae0 | |||
| 89019a846b | |||
| 41f7723e9c | |||
| 2b8c3cb0c8 | |||
| f325d76e96 | |||
| e3fb781c5f | |||
| 14a5e48fb9 | |||
| 01937958ce | |||
| edb504f9db | |||
| 2428fbbfcf | |||
| 16d298188f | |||
| f42f8702ce | |||
| 9e58d5ef38 | |||
| 320f9de8ab | |||
| 262275ab26 | |||
| 55f39a01e6 | |||
| b884768e46 | |||
| f8f4e13776 | |||
| 5f07d51751 | |||
| b2f003c4f4 | |||
| 9014da2b01 | |||
| 45579c9515 | |||
| b32f1279d4 | |||
| 1b0cd07131 | |||
| 8c6867dae4 | |||
| 99310c0aa0 | |||
| d126980e5f | |||
| 88ef5b238b | |||
| 30d8b85702 | |||
| 45f0437912 | |||
| dc3eea871a | |||
| d2c8103a68 | |||
| 3ea1f7f193 | |||
| 4356dd23a9 | |||
| 75318ec497 | |||
| c1629734ab | |||
| 778290d5bc | |||
| 98bc8e0b23 | |||
| caafa436eb | |||
| fe8de1c8a6 | |||
| 1bd93ea1e0 | |||
| 6857950e46 | |||
| 716ce2b89e | |||
| 9daae583d8 | |||
| b5ee3df776 | |||
| 17cd9a8e0c | |||
| 2a16d4cfaf | |||
| 3350a33908 | |||
| 3eef58c9b6 | |||
| 4805781c74 | |||
| b06f40ea9b | |||
| 6b5cc49d81 | |||
| ef7a79488a | |||
| a2f759146d | |||
| f79c0de208 | |||
| 1667816089 | |||
| d1ed1be3cd | |||
| e749242a99 | |||
| 9267ef84fd | |||
| 0ee129199f | |||
| 245be00597 | |||
| c38d702330 | |||
| 3f729907c8 | |||
| cca220d7c6 | |||
| 4ed30958ce | |||
| 2f118072cb | |||
| 7440f10ec1 | |||
| 8bb800d6b4 | |||
| bbf61c118f | |||
| d296b09456 | |||
| 5ac017fc04 | |||
| f5ecab3aef | |||
| fd01167ffd | |||
| 3b118f0a34 | |||
| ebe443c8ff | |||
| 63f3396233 | |||
| 2deb4526ee | |||
| a1662ffcaa | |||
| ea921bf6a6 | |||
| 6e627cc468 | |||
| 3eb3a13628 | |||
| c234706270 | |||
| 6059ba27c4 | |||
| 927f40d089 | |||
| 6356d50e67 | |||
| bd69ae3b53 | |||
| 9a2e90c9fc | |||
| 240ccfc13a | |||
| c30e716c81 | |||
| 267fd7b0f1 | |||
| dc0176eeec | |||
| 0a0af41bd9 | |||
| 3808006edf | |||
| c17922b8a9 | |||
| 8d7f17798d | |||
| 6dc40e2ada | |||
| 792f88131c | |||
| 33bb1e8256 | |||
| bcaba38e42 | |||
| 5e3085e360 | |||
| 99920d823e | |||
| 338523dd6e | |||
| 2644784f49 | |||
| b1f61f05b4 | |||
| e5ba614d05 | |||
| 30ac8de48a | |||
| c705d8386b | |||
| d5b10b3ef3 | |||
| 5a84c60fb9 | |||
| 26941ce90b | |||
| 07ce5d7390 | |||
| 1d805a534b | |||
| a9ff89e05c | |||
| d85011ed69 | |||
| b3da003ebf | |||
| 478754a8f5 | |||
| 31ff122aa2 | |||
| 18c662b845 | |||
| c797f0898e | |||
| 5e566c5772 | |||
| 23227313a2 | |||
| 3713b73335 | |||
| 310e63dfd1 | |||
| a196b3bc3d | |||
| a58e1284d8 | |||
| f1dde3fb20 | |||
| 5f38142e7b | |||
| 29b79dcfe9 | |||
| ecc972c7f0 | |||
| 6c891ade8b | |||
| 03658d5081 | |||
| 5d62588032 | |||
| 6897ea475f | |||
| 3790bfa80f | |||
| 6b278f3223 | |||
| f1236ebf35 | |||
| 184087f822 | |||
| 834815e9f7 | |||
| 0f1ff38476 | |||
| e3b28e16ce | |||
| 2f62fdd644 | |||
| 137b3e6cff | |||
| d1630dda58 | |||
| 701ebd014a | |||
| 5b8ec2cf39 | |||
| 9d1a39cec6 | |||
| 2a7b736dce | |||
| ecc8af1812 | |||
| 129e3e8dc3 | |||
| 9fb09f79e5 | |||
| a2ee6568c6 | |||
| 9c1a8eaa51 | |||
| a8fa31b50b | |||
| 8d82a19def | |||
| c2aacf2087 | |||
| 9a6c57845a | |||
| d27a40d28f | |||
| aebc5df418 | |||
| 7a8bef3983 | |||
| d486dee89e | |||
| 7de8fb33a2 | |||
| 904c03672b | |||
| 03955e3488 | |||
| 88e4e0d5dd | |||
| 03f638a8ef | |||
| 5dc25de668 | |||
| 53e5890cff | |||
| a94447ddf3 | |||
| 7192ec7942 | |||
| 06acbbc429 | |||
| 6116bbd744 | |||
| a803eacf26 | |||
| 504bfc8b49 | |||
| 53a8cbd70e | |||
| 505b97ae20 | |||
| 30a64ebaed | |||
| da16fc5739 | |||
| 3c7fa6ca33 | |||
| 36e0ddb744 | |||
| cf21b5b5b2 | |||
| 1030f807ba | |||
| d45702bcfa | |||
| ddd20dbe0b | |||
| 4a98780933 | |||
| 6db8f1a0d1 | |||
| e06711412b | |||
| 68ba1d2fa9 | |||
| 4e11137989 | |||
| be9be1cc3e | |||
| eab4536081 | |||
| 954516cec1 | |||
| 841cb5ee2a | |||
| d4cf31275b | |||
| fedc1d96a8 | |||
| 59511072b4 | |||
| a5c8119eba | |||
| d7881a6dca | |||
| 951e62169e | |||
| 9add19b37d | |||
| b2d633202d | |||
| 414f4a9c54 | |||
| 1c4f5e7d92 | |||
| 246e515cf8 | |||
| 2d41e75e52 | |||
| d834d6811b | |||
| 029a1b0c20 | |||
| c45254b0ec | |||
| 318fdeb51f | |||
| d3d20bf442 | |||
| 99598264fc | |||
| abe30b7b40 | |||
| f90ee0ca3d | |||
| 4ed955e280 | |||
| 1721f13e76 | |||
| 6e893ef62a | |||
| e0eaaf8144 | |||
| cb8a074dcb | |||
| c3ac4ccabb | |||
| 8d688ce66a | |||
| b544fe4123 | |||
| 926c6ec453 | |||
| 91b2f6ab1c | |||
| 851a7cd833 | |||
| 83d4d1a784 | |||
| 80cc2f6111 | |||
| b97948276d | |||
| 4cfc086e4d | |||
| 25d232f407 | |||
| edd7c24623 | |||
| bef6a8bc3a | |||
| 266b181e75 | |||
| c474f5e9a7 | |||
| 4e6a9e4598 | |||
| 661907e6bc | |||
| d3e7d981d4 | |||
| a2a0440918 | |||
| 45d1abc74d | |||
| 89950722c6 | |||
| 4810a108e8 | |||
| ae5b4a05ff | |||
| 3468fdbd34 | |||
| fb3f1fdbd6 | |||
| 426563be70 | |||
| aec4318870 | |||
| 2d9b57d39f | |||
| 4bdb8fcfa8 | |||
| 58c1c40a5e | |||
| 751575fe6f | |||
| 751941e248 | |||
| ef605a5517 | |||
| 8eb6dcec7d | |||
| 07cbcd5089 | |||
| 12acabe2a4 | |||
| 20c88dc3ef | |||
| 0c8fedeb35 | |||
| affb7141d7 | |||
| e0031d86b7 |
+27
-94
@@ -27,14 +27,11 @@ started?](#what-should-i-know-before-i-get-started)
|
||||
* [Commit Message Formats](#commit-message-formats)
|
||||
* [New Changes](#new-changes)
|
||||
* [OpenZFS Patch Ports](#openzfs-patch-ports)
|
||||
* [Coverity Defect Fixes](#coverity-defect-fixes)
|
||||
* [Signed Off By](#signed-off-by)
|
||||
|
||||
Helpful resources
|
||||
|
||||
* [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?
|
||||
|
||||
@@ -51,20 +48,19 @@ 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
|
||||
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 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.
|
||||
The [mailing list](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists)
|
||||
is the best place to ask for help.
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting Bugs
|
||||
*Please* contact us via the [zfs-discuss mailing
|
||||
list or IRC](http://list.zfsonlinux.org) if you aren't
|
||||
*Please* contact us via the [mailing
|
||||
list](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists) if you aren't
|
||||
certain that you are experiencing a bug.
|
||||
|
||||
If you run into an issue, please search our [issue
|
||||
@@ -171,10 +167,18 @@ first line in the commit message.
|
||||
please summarize important information such as why the proposed
|
||||
approach was chosen or a brief description of the bug you are resolving.
|
||||
Each line of the body must be 72 characters or less.
|
||||
* The last line must be a `Signed-off-by:` tag. See the
|
||||
[Signed Off By](#signed-off-by) section for more information.
|
||||
* The last line must be a `Signed-off-by:` tag with the developer's
|
||||
name followed by their email. This is the developer's certification
|
||||
that they have the right to submit the patch for inclusion into
|
||||
the code base and indicates agreement to the [Developer's Certificate
|
||||
of Origin](https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin).
|
||||
Code without a proper signoff cannot be merged.
|
||||
|
||||
An example commit message for new changes is provided below.
|
||||
Git can append the `Signed-off-by` line to your commit messages. Simply
|
||||
provide the `-s` or `--signoff` option when performing a `git commit`.
|
||||
For more information about writing commit messages, visit [How to Write
|
||||
a Git Commit Message](https://chris.beams.io/posts/git-commit/).
|
||||
An example commit message is provided below.
|
||||
|
||||
```
|
||||
This line is a brief summary of your change
|
||||
@@ -188,23 +192,23 @@ Signed-off-by: Contributor <contributor@email.com>
|
||||
```
|
||||
|
||||
#### OpenZFS Patch Ports
|
||||
If you are porting OpenZFS patches, the commit message must meet
|
||||
If you are porting an OpenZFS patch, 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
|
||||
* The first line must be the summary line from the OpenZFS commit.
|
||||
It must begin with `OpenZFS dddd - ` where `dddd` is the OpenZFS issue number.
|
||||
* Provides a `Authored by:` line to attribute the patch to the original author.
|
||||
* Provides the `Reviewed by:` and `Approved by:` lines from the 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
|
||||
their email.
|
||||
* Provides a `OpenZFS-issue:` line which is a link to the original illumos
|
||||
issue.
|
||||
* Provides a `OpenZFS-commit:` line with link for each original OpenZFS commit.
|
||||
* Provides a `OpenZFS-commit:` line which links back to the original OpenZFS
|
||||
commit.
|
||||
* If necessary, provide some porting notes to describe any deviations from
|
||||
the original OpenZFS commits.
|
||||
the original OpenZFS commit.
|
||||
|
||||
An example OpenZFS patch port commit message for a single patch is provided
|
||||
below.
|
||||
An example OpenZFS patch port commit message is provided below.
|
||||
```
|
||||
OpenZFS 1234 - Summary from the original OpenZFS commit
|
||||
|
||||
@@ -219,74 +223,3 @@ 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),
|
||||
the commit message should meet the following guidelines:
|
||||
* Provides a subject line in the format of
|
||||
`Fix coverity defects: CID dddd, dddd...` where `dddd` represents
|
||||
each CID fixed by the commit.
|
||||
* Provides a body which lists each Coverity defect and how it was corrected.
|
||||
* The last line must be a `Signed-off-by:` tag. See the
|
||||
[Signed Off By](#signed-off-by) section for more information.
|
||||
|
||||
An example Coverity defect fix commit message is provided below.
|
||||
```
|
||||
Fix coverity defects: CID 12345, 67890
|
||||
|
||||
CID 12345: Logically dead code (DEADCODE)
|
||||
|
||||
Removed the if(var != 0) block because the condition could never be
|
||||
satisfied.
|
||||
|
||||
CID 67890: Resource Leak (RESOURCE_LEAK)
|
||||
|
||||
Ensure free is called after allocating memory in function().
|
||||
|
||||
Signed-off-by: Contributor <contributor@email.com>
|
||||
```
|
||||
|
||||
#### Signed Off By
|
||||
A line tagged as `Signed-off-by:` must contain the developer's
|
||||
name followed by their email. This is the developer's certification
|
||||
that they have the right to submit the patch for inclusion into
|
||||
the code base and indicates agreement to the [Developer's Certificate
|
||||
of Origin](https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin).
|
||||
Code without a proper signoff cannot be merged.
|
||||
|
||||
Git can append the `Signed-off-by` line to your commit messages. Simply
|
||||
provide the `-s` or `--signoff` option when performing a `git commit`.
|
||||
For more information about writing commit messages, visit [How to Write
|
||||
a Git Commit Message](https://chris.beams.io/posts/git-commit/).
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<!-- Please fill out the following template, which will help other contributors address your issue. -->
|
||||
|
||||
<!--
|
||||
Thank you for reporting an issue.
|
||||
|
||||
@@ -16,15 +14,15 @@ 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 |
|
||||
<!-- add version after "|" character -->
|
||||
Type | Version/Name
|
||||
--- | ---
|
||||
Distribution Name |
|
||||
Distribution Version |
|
||||
Linux Kernel |
|
||||
Architecture |
|
||||
ZFS Version |
|
||||
SPL Version |
|
||||
<!--
|
||||
Commands to find ZFS/SPL versions:
|
||||
modinfo zfs | grep -iw version
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<!--- Please fill out the following template, which will help other contributors review your Pull Request. -->
|
||||
|
||||
<!--- Provide a general summary of your changes in the Title above -->
|
||||
|
||||
<!---
|
||||
@@ -7,13 +5,13 @@ Documentation on ZFS Buildbot options can be found at
|
||||
https://github.com/zfsonlinux/zfs/wiki/Buildbot-Options
|
||||
-->
|
||||
|
||||
### Description
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
### Motivation and Context
|
||||
<!--- Why is this change required? What problem does it solve? -->
|
||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
### Description
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
### How Has This Been Tested?
|
||||
<!--- Please describe in detail how you tested your changes. -->
|
||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||
@@ -32,9 +30,10 @@ https://github.com/zfsonlinux/zfs/wiki/Buildbot-Options
|
||||
### Checklist:
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
- [ ] My code follows the ZFS on Linux [code style requirements](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md#coding-conventions).
|
||||
- [ ] My code follows the ZFS on Linux code style requirements.
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have 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 read the **CONTRIBUTING** document.
|
||||
- [ ] I have added tests to cover my changes.
|
||||
- [ ] All new and existing tests passed.
|
||||
- [ ] All commit messages are properly formatted and contain [`Signed-off-by`](https://github.com/zfsonlinux/zfs/blob/master/.github/CONTRIBUTING.md#signed-off-by).
|
||||
- [ ] All commit messages are properly formatted and contain `Signed-off-by`.
|
||||
- [ ] Change has been approved by a ZFS on Linux member.
|
||||
|
||||
+17
-9
@@ -1,22 +1,30 @@
|
||||
codecov:
|
||||
notify:
|
||||
require_ci_to_pass: false # always post
|
||||
after_n_builds: 2 # user and kernel
|
||||
require_ci_to_pass: no
|
||||
|
||||
coverage:
|
||||
precision: 2 # 2 digits of precision
|
||||
range: "50...90" # red -> yellow -> green
|
||||
precision: 2
|
||||
round: down
|
||||
range: "50...100"
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 1% # allow 1% coverage variance
|
||||
threshold: 1%
|
||||
|
||||
patch:
|
||||
default:
|
||||
threshold: 1% # allow 1% coverage variance
|
||||
threshold: 1%
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
layout: "reach, diff, flags, footer"
|
||||
behavior: once # update if exists; post new; skip if deleted
|
||||
require_changes: yes # only post when coverage changes
|
||||
layout: "header, sunburst, diff"
|
||||
behavior: default
|
||||
require_changes: no
|
||||
|
||||
+2
-6
@@ -14,7 +14,6 @@
|
||||
# Normal rules
|
||||
#
|
||||
*.[oa]
|
||||
*.o.ur-safe
|
||||
*.lo
|
||||
*.la
|
||||
*.mod.c
|
||||
@@ -22,8 +21,6 @@
|
||||
*.swp
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.pyc
|
||||
*.pyo
|
||||
.deps
|
||||
.libs
|
||||
.dirstamp
|
||||
@@ -36,7 +33,6 @@ Makefile.in
|
||||
# Top level generated files specific to this top level dir
|
||||
#
|
||||
/bin
|
||||
/build
|
||||
/configure
|
||||
/config.log
|
||||
/config.status
|
||||
@@ -45,6 +41,8 @@ Makefile.in
|
||||
/zfs_config.h.in
|
||||
/zfs.release
|
||||
/stamp-h1
|
||||
/.script-config
|
||||
/zfs-script-config.sh
|
||||
/aclocal.m4
|
||||
/autom4te.cache
|
||||
|
||||
@@ -61,5 +59,3 @@ cscope.*
|
||||
*.tar.gz
|
||||
*.patch
|
||||
*.orig
|
||||
*.log
|
||||
venv
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
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 {} \;
|
||||
@@ -1,304 +1,95 @@
|
||||
MAINTAINERS:
|
||||
Brian Behlendorf is the principal developer of the ZFS on Linux port.
|
||||
He works full time as a computer scientist at Lawrence Livermore
|
||||
National Laboratory on the ZFS and Lustre filesystems. However,
|
||||
this port would not have been possible without the help of many
|
||||
others who have contributed their time, effort, and insight.
|
||||
|
||||
Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
Tony Hutter <hutter2@llnl.gov>
|
||||
Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
|
||||
PAST MAINTAINERS:
|
||||
First and foremost the hard working ZFS developers at Sun/Oracle.
|
||||
They are responsible for the bulk of the code in this project and
|
||||
without their efforts there never would have been a ZFS filesystem.
|
||||
|
||||
Ned Bass <bass6@llnl.gov>
|
||||
The ZFS Development Team at Sun/Oracle
|
||||
|
||||
CONTRIBUTORS:
|
||||
Next all the developers at KQ Infotech who implemented a prototype
|
||||
ZFS Posix Layer (ZPL). Their implementation provided an excellent
|
||||
reference for adding the ZPL functionality.
|
||||
|
||||
Aaron Fineman <abyxcos@gmail.com>
|
||||
Adam Leventhal <ahl@delphix.com>
|
||||
Adam Stevko <adam.stevko@gmail.com>
|
||||
Ahmed G <ahmedg@delphix.com>
|
||||
Akash Ayare <aayare@delphix.com>
|
||||
Alan Somers <asomers@gmail.com>
|
||||
Alar Aun <spamtoaun@gmail.com>
|
||||
Albert Lee <trisk@nexenta.com>
|
||||
Alec Salazar <alec.j.salazar@gmail.com>
|
||||
Alejandro R. Sedeño <asedeno@mit.edu>
|
||||
Alek Pinchuk <alek@nexenta.com>
|
||||
Alex Braunegg <alex.braunegg@gmail.com>
|
||||
Alex McWhirter <alexmcwhirter@triadic.us>
|
||||
Alex Reece <alex@delphix.com>
|
||||
Alex Wilson <alex.wilson@joyent.com>
|
||||
Alex Zhuravlev <alexey.zhuravlev@intel.com>
|
||||
Alexander Eremin <a.eremin@nexenta.com>
|
||||
Alexander Motin <mav@freebsd.org>
|
||||
Alexander Pyhalov <apyhalov@gmail.com>
|
||||
Alexander Stetsenko <ams@nexenta.com>
|
||||
Alexey Shvetsov <alexxy@gentoo.org>
|
||||
Alexey Smirnoff <fling@member.fsf.org>
|
||||
Allan Jude <allanjude@freebsd.org>
|
||||
AndCycle <andcycle@andcycle.idv.tw>
|
||||
Andreas Buschmann <andreas.buschmann@tech.net.de>
|
||||
Andreas Dilger <adilger@intel.com>
|
||||
Andrew Barnes <barnes333@gmail.com>
|
||||
Andrew Hamilton <ahamilto@tjhsst.edu>
|
||||
Andrew Reid <ColdCanuck@nailedtotheperch.com>
|
||||
Andrew Stormont <andrew.stormont@nexenta.com>
|
||||
Andrew Tselischev <andrewtselischev@gmail.com>
|
||||
Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
|
||||
Andriy Gapon <avg@freebsd.org>
|
||||
Andy Bakun <github@thwartedefforts.org>
|
||||
Aniruddha Shankar <k@191a.net>
|
||||
Antonio Russo <antonio.e.russo@gmail.com>
|
||||
Arkadiusz Bubała <arkadiusz.bubala@open-e.com>
|
||||
Arne Jansen <arne@die-jansens.de>
|
||||
Aron Xu <happyaron.xu@gmail.com>
|
||||
Bart Coddens <bart.coddens@gmail.com>
|
||||
Basil Crow <basil.crow@delphix.com>
|
||||
Huang Liu <liu.huang@zte.com.cn>
|
||||
Ben Allen <bsallen@alcf.anl.gov>
|
||||
Ben Rubson <ben.rubson@gmail.com>
|
||||
Benjamin Albrecht <git@albrecht.io>
|
||||
Bill McGonigle <bill-github.com-public1@bfccomputing.com>
|
||||
Bill Pijewski <wdp@joyent.com>
|
||||
Boris Protopopov <boris.protopopov@nexenta.com>
|
||||
Brad Lewis <brad.lewis@delphix.com>
|
||||
Brian Behlendorf <behlendorf1@llnl.gov>
|
||||
Brian J. Murrell <brian@sun.com>
|
||||
Caleb James DeLisle <calebdelisle@lavabit.com>
|
||||
Cao Xuewen <cao.xuewen@zte.com.cn>
|
||||
Carlo Landmeter <clandmeter@gmail.com>
|
||||
Carlos Alberto Lopez Perez <clopez@igalia.com>
|
||||
Chaoyu Zhang <zhang.chaoyu@zte.com.cn>
|
||||
Chen Can <chen.can2@zte.com.cn>
|
||||
Chen Haiquan <oc@yunify.com>
|
||||
Chip Parker <aparker@enthought.com>
|
||||
Chris Burroughs <chris.burroughs@gmail.com>
|
||||
Chris Dunlap <cdunlap@llnl.gov>
|
||||
Chris Dunlop <chris@onthe.net.au>
|
||||
Chris Siden <chris.siden@delphix.com>
|
||||
Chris Wedgwood <cw@f00f.org>
|
||||
Chris Williamson <chris.williamson@delphix.com>
|
||||
Chris Zubrzycki <github@mid-earth.net>
|
||||
Christ Schlacta <aarcane@aarcane.info>
|
||||
Christer Ekholm <che@chrekh.se>
|
||||
Christian Kohlschütter <christian@kohlschutter.com>
|
||||
Christian Neukirchen <chneukirchen@gmail.com>
|
||||
Christian Schwarz <me@cschwarz.com>
|
||||
Christopher Voltz <cjunk@voltz.ws>
|
||||
Chunwei Chen <david.chen@nutanix.com>
|
||||
Clemens Fruhwirth <clemens@endorphin.org>
|
||||
Colin Ian King <colin.king@canonical.com>
|
||||
Craig Loomis <cloomis@astro.princeton.edu>
|
||||
Craig Sanders <github@taz.net.au>
|
||||
Cyril Plisko <cyril.plisko@infinidat.com>
|
||||
DHE <git@dehacked.net>
|
||||
Damian Wojsław <damian@wojslaw.pl>
|
||||
Dan Kimmel <dan.kimmel@delphix.com>
|
||||
Dan McDonald <danmcd@nexenta.com>
|
||||
Dan Swartzendruber <dswartz@druber.com>
|
||||
Dan Vatca <dan.vatca@gmail.com>
|
||||
Daniel Hoffman <dj.hoffman@delphix.com>
|
||||
Daniel Verite <daniel@verite.pro>
|
||||
Daniil Lunev <d.lunev.mail@gmail.com>
|
||||
Darik Horn <dajhorn@vanadac.com>
|
||||
Dave Eddy <dave@daveeddy.com>
|
||||
David Lamparter <equinox@diac24.net>
|
||||
David Qian <david.qian@intel.com>
|
||||
David Quigley <david.quigley@intel.com>
|
||||
Debabrata Banerjee <dbanerje@akamai.com>
|
||||
Denys Rtveliashvili <denys@rtveliashvili.name>
|
||||
Derek Dai <daiderek@gmail.com>
|
||||
Dimitri John Ledkov <xnox@ubuntu.com>
|
||||
Dmitry Khasanov <pik4ez@gmail.com>
|
||||
Dominik Hassler <hadfl@omniosce.org>
|
||||
Dominik Honnef <dominikh@fork-bomb.org>
|
||||
Don Brady <don.brady@delphix.com>
|
||||
Dr. András Korn <korn-github.com@elan.rulez.org>
|
||||
Eli Rosenthal <eli.rosenthal@delphix.com>
|
||||
Eric Desrochers <eric.desrochers@canonical.com>
|
||||
Eric Dillmann <eric@jave.fr>
|
||||
Eric Schrock <Eric.Schrock@delphix.com>
|
||||
Etienne Dechamps <etienne@edechamps.fr>
|
||||
Evan Susarret <evansus@gmail.com>
|
||||
Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
||||
Fajar A. Nugraha <github@fajar.net>
|
||||
Fan Yong <fan.yong@intel.com>
|
||||
Feng Sun <loyou85@gmail.com>
|
||||
Frederik Wessels <wessels147@gmail.com>
|
||||
Frédéric Vanniere <f.vanniere@planet-work.com>
|
||||
Garrett D'Amore <garrett@nexenta.com>
|
||||
Garrison Jensen <garrison.jensen@gmail.com>
|
||||
Gary Mills <gary_mills@fastmail.fm>
|
||||
Gaurav Kumar <gauravk.18@gmail.com>
|
||||
GeLiXin <ge.lixin@zte.com.cn>
|
||||
George Amanakis <g_amanakis@yahoo.com>
|
||||
George Melikov <mail@gmelikov.ru>
|
||||
George Wilson <gwilson@delphix.com>
|
||||
Georgy Yakovlev <ya@sysdump.net>
|
||||
Giuseppe Di Natale <guss80@gmail.com>
|
||||
Gordan Bobic <gordan@redsleeve.org>
|
||||
Gordon Ross <gwr@nexenta.com>
|
||||
Gregor Kopka <gregor@kopka.net>
|
||||
Grischa Zengel <github.zfsonlinux@zengel.info>
|
||||
Gunnar Beutner <gunnar@beutner.name>
|
||||
Gvozden Neskovic <neskovic@gmail.com>
|
||||
Hajo Möller <dasjoe@gmail.com>
|
||||
Hans Rosenfeld <hans.rosenfeld@nexenta.com>
|
||||
Håkan Johansson <f96hajo@chalmers.se>
|
||||
Igor Kozhukhov <ikozhukhov@gmail.com>
|
||||
Igor Lvovsky <ilvovsky@gmail.com>
|
||||
Isaac Huang <he.huang@intel.com>
|
||||
JK Dingwall <james@dingwall.me.uk>
|
||||
Jacek Fefliński <feflik@gmail.com>
|
||||
James Cowgill <james.cowgill@mips.com>
|
||||
James Lee <jlee@thestaticvoid.com>
|
||||
James Pan <jiaming.pan@yahoo.com>
|
||||
Jan Engelhardt <jengelh@inai.de>
|
||||
Jan Kryl <jan.kryl@nexenta.com>
|
||||
Jan Sanislo <oystr@cs.washington.edu>
|
||||
Jason King <jason.brian.king@gmail.com>
|
||||
Jason Zaman <jasonzaman@gmail.com>
|
||||
Javen Wu <wu.javen@gmail.com>
|
||||
Jeremy Gill <jgill@parallax-innovations.com>
|
||||
Jeremy Jones <jeremy@delphix.com>
|
||||
Jerry Jelinek <jerry.jelinek@joyent.com>
|
||||
Jinshan Xiong <jinshan.xiong@intel.com>
|
||||
Joe Stein <joe.stein@delphix.com>
|
||||
John Albietz <inthecloud247@gmail.com>
|
||||
John Eismeier <john.eismeier@gmail.com>
|
||||
John L. Hammond <john.hammond@intel.com>
|
||||
John Layman <jlayman@sagecloud.com>
|
||||
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
|
||||
John Wren Kennedy <john.kennedy@delphix.com>
|
||||
Johnny Stenback <github@jstenback.com>
|
||||
Jorgen Lundman <lundman@lundman.net>
|
||||
Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
|
||||
Joshua M. Clulow <josh@sysmgr.org>
|
||||
Justin Bedő <cu@cua0.org>
|
||||
Justin Lecher <jlec@gentoo.org>
|
||||
Justin T. Gibbs <gibbs@FreeBSD.org>
|
||||
Jörg Thalheim <joerg@higgsboson.tk>
|
||||
KORN Andras <korn@elan.rulez.org>
|
||||
Kamil Domański <kamil@domanski.co>
|
||||
Karsten Kretschmer <kkretschmer@gmail.com>
|
||||
Kash Pande <kash@tripleback.net>
|
||||
Keith M Wesolowski <wesolows@foobazco.org>
|
||||
Kevin Tanguy <kevin.tanguy@ovh.net>
|
||||
KireinaHoro <i@jsteward.moe>
|
||||
Kohsuke Kawaguchi <kk@kohsuke.org>
|
||||
Kyle Blatter <kyleblatter@llnl.gov>
|
||||
Kyle Fuller <inbox@kylefuller.co.uk>
|
||||
Loli <ezomori.nozomu@gmail.com>
|
||||
Lars Johannsen <laj@it.dk>
|
||||
Li Dongyang <dongyang.li@anu.edu.au>
|
||||
Li Wei <W.Li@Sun.COM>
|
||||
Lukas Wunner <lukas@wunner.de>
|
||||
Madhav Suresh <madhav.suresh@delphix.com>
|
||||
Manoj Joseph <manoj.joseph@delphix.com>
|
||||
Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
|
||||
Marcel Huber <marcelhuberfoo@gmail.com>
|
||||
Marcel Telka <marcel.telka@nexenta.com>
|
||||
Marcel Wysocki <maci.stgn@gmail.com>
|
||||
Mark Shellenbaum <Mark.Shellenbaum@Oracle.COM>
|
||||
Mark Wright <markwright@internode.on.net>
|
||||
Martin Matuska <mm@FreeBSD.org>
|
||||
Massimo Maggi <me@massimo-maggi.eu>
|
||||
Matt Johnston <matt@fugro-fsi.com.au>
|
||||
Matt Kemp <matt@mattikus.com>
|
||||
Matthew Ahrens <matt@delphix.com>
|
||||
Matthew Thode <mthode@mthode.org>
|
||||
Matus Kral <matuskral@me.com>
|
||||
Max Grossman <max.grossman@delphix.com>
|
||||
Maximilian Mehnert <maximilian.mehnert@gmx.de>
|
||||
Michael Gebetsroither <michael@mgeb.org>
|
||||
Michael Kjorling <michael@kjorling.se>
|
||||
Michael Martin <mgmartin.mgm@gmail.com>
|
||||
Mike Gerdts <mike.gerdts@joyent.com>
|
||||
Mike Harsch <mike@harschsystems.com>
|
||||
Mike Leddy <mike.leddy@gmail.com>
|
||||
Mike Swanson <mikeonthecomputer@gmail.com>
|
||||
Milan Jurik <milan.jurik@xylab.cz>
|
||||
Morgan Jones <mjones@rice.edu>
|
||||
Moritz Maxeiner <moritz@ucworks.org>
|
||||
Nathaniel Clark <Nathaniel.Clark@misrule.us>
|
||||
Nathaniel Wesley Filardo <nwf@cs.jhu.edu>
|
||||
Nav Ravindranath <nav@delphix.com>
|
||||
Neal Gompa (ニール・ゴンパ) <ngompa13@gmail.com>
|
||||
Ned Bass <bass6@llnl.gov>
|
||||
Neependra Khare <neependra@kqinfotech.com>
|
||||
Neil Stockbridge <neil@dist.ro>
|
||||
Nick Garvey <garvey.nick@gmail.com>
|
||||
Nikolay Borisov <n.borisov.lkml@gmail.com>
|
||||
Olaf Faaland <faaland1@llnl.gov>
|
||||
Oleg Drokin <green@linuxhacker.ru>
|
||||
Oleg Stepura <oleg@stepura.com>
|
||||
Patrik Greco <sikevux@sikevux.se>
|
||||
Paul B. Henson <henson@acm.org>
|
||||
Paul Dagnelie <pcd@delphix.com>
|
||||
Paul Zuchowski <pzuchowski@datto.com>
|
||||
Pavel Boldin <boldin.pavel@gmail.com>
|
||||
Pavel Zakharov <pavel.zakharov@delphix.com>
|
||||
Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
Pedro Giffuni <pfg@freebsd.org>
|
||||
Peng <peng.hse@xtaotech.com>
|
||||
Peter Ashford <ashford@accs.com>
|
||||
Prakash Surya <prakash.surya@delphix.com>
|
||||
Prasad Joshi <prasadjoshi124@gmail.com>
|
||||
Ralf Ertzinger <ralf@skytale.net>
|
||||
Randall Mason <ClashTheBunny@gmail.com>
|
||||
Remy Blank <remy.blank@pobox.com>
|
||||
Ricardo M. Correia <ricardo.correia@oracle.com>
|
||||
Rich Ercolani <rincebrain@gmail.com>
|
||||
Richard Elling <Richard.Elling@RichardElling.com>
|
||||
Richard Laager <rlaager@wiktel.com>
|
||||
Richard Lowe <richlowe@richlowe.net>
|
||||
Richard Sharpe <rsharpe@samba.org>
|
||||
Richard Yao <ryao@gentoo.org>
|
||||
Rohan Puri <rohan.puri15@gmail.com>
|
||||
Romain Dolbeau <romain.dolbeau@atos.net>
|
||||
Roman Strashkin <roman.strashkin@nexenta.com>
|
||||
Ruben Kerkhof <ruben@rubenkerkhof.com>
|
||||
Saso Kiselkov <saso.kiselkov@nexenta.com>
|
||||
Scot W. Stevenson <scot.stevenson@gmail.com>
|
||||
Sean Eric Fagan <sef@ixsystems.com>
|
||||
Sen Haerens <sen@senhaerens.be>
|
||||
Serapheim Dimitropoulos <serapheim@delphix.com>
|
||||
Seth Forshee <seth.forshee@canonical.com>
|
||||
Shampavman <sham.pavman@nexenta.com>
|
||||
Shen Yan <shenyanxxxy@qq.com>
|
||||
Simon Guest <simon.guest@tesujimath.org>
|
||||
Simon Klinkert <simon.klinkert@gmail.com>
|
||||
Sowrabha Gopal <sowrabha.gopal@delphix.com>
|
||||
Stanislav Seletskiy <s.seletskiy@gmail.com>
|
||||
Steffen Müthing <steffen.muething@iwr.uni-heidelberg.de>
|
||||
Stephen Blinick <stephen.blinick@delphix.com>
|
||||
Steve Dougherty <sdougherty@barracuda.com>
|
||||
Steven Burgess <sburgess@dattobackup.com>
|
||||
Steven Hartland <smh@freebsd.org>
|
||||
Steven Johnson <sjohnson@sakuraindustries.com>
|
||||
Stian Ellingsen <stian@plaimi.net>
|
||||
Suman Chakravartula <schakrava@gmail.com>
|
||||
Sydney Vanda <sydney.m.vanda@intel.com>
|
||||
Sören Tempel <soeren+git@soeren-tempel.net>
|
||||
Thijs Cramer <thijs.cramer@gmail.com>
|
||||
Tim Chase <tim@chase2k.com>
|
||||
Tim Connors <tconnors@rather.puzzling.org>
|
||||
Tim Crawford <tcrawford@datto.com>
|
||||
Tim Haley <Tim.Haley@Sun.COM>
|
||||
Tobin Harding <me@tobin.cc>
|
||||
Tom Caputi <tcaputi@datto.com>
|
||||
Tom Matthews <tom@axiom-partners.com>
|
||||
Tom Prince <tom.prince@ualberta.net>
|
||||
Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
|
||||
Tony Hutter <hutter2@llnl.gov>
|
||||
Toomas Soome <tsoome@me.com>
|
||||
Trey Dockendorf <treydock@gmail.com>
|
||||
Turbo Fredriksson <turbo@bayour.com>
|
||||
Tyler J. Stachecki <stachecki.tyler@gmail.com>
|
||||
Vitaut Bajaryn <vitaut.bayaryn@gmail.com>
|
||||
Weigang Li <weigang.li@intel.com>
|
||||
Will Andrews <will@freebsd.org>
|
||||
Will Rouesnel <w.rouesnel@gmail.com>
|
||||
Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||
Xin Li <delphij@FreeBSD.org>
|
||||
Ying Zhu <casualfisher@gmail.com>
|
||||
YunQiang Su <syq@debian.org>
|
||||
Yuri Pankov <yuri.pankov@gmail.com>
|
||||
Yuxuan Shui <yshuiv7@gmail.com>
|
||||
Zachary Bedell <zac@thebedells.org>
|
||||
Anand Mitra <mitra@kqinfotech.com>
|
||||
Anurag Agarwal <anurag@kqinfotech.com>
|
||||
Neependra Khare <neependra@kqinfotech.com>
|
||||
Prasad Joshi <prasad@kqinfotech.com>
|
||||
Rohan Puri <rohan@kqinfotech.com>
|
||||
Sandip Divekar <sandipd@kqinfotech.com>
|
||||
Shoaib <shoaib@kqinfotech.com>
|
||||
Shrirang <shrirang@kqinfotech.com>
|
||||
|
||||
Additionally the following individuals have all made contributions
|
||||
to the project and deserve to be acknowledged.
|
||||
|
||||
Albert Lee <trisk@nexenta.com>
|
||||
Alejandro R. Sedeño <asedeno@mit.edu>
|
||||
Alex Zhuravlev <bzzz@whamcloud.com>
|
||||
Alexander Eremin <a.eremin@nexenta.com>
|
||||
Alexander Stetsenko <ams@nexenta.com>
|
||||
Alexey Shvetsov <alexxy@gentoo.org>
|
||||
Andreas Dilger <adilger@whamcloud.com>
|
||||
Andrew Reid <ColdCanuck@nailedtotheperch.com>
|
||||
Andrew Stormont <andrew.stormont@nexenta.com>
|
||||
Andrew Tselischev <andrewtselischev@gmail.com>
|
||||
Andriy Gapon <avg@FreeBSD.org>
|
||||
Aniruddha Shankar <k@191a.net>
|
||||
Bill Pijewski <wdp@joyent.com>
|
||||
Chris Dunlap <cdunlap@llnl.gov>
|
||||
Chris Dunlop <chris@onthe.net.au>
|
||||
Chris Siden <chris.siden@delphix.com>
|
||||
Chris Wedgwood <cw@f00f.org>
|
||||
Christian Kohlschütter <christian@kohlschutter.com>
|
||||
Christopher Siden <chris.siden@delphix.com>
|
||||
Craig Sanders <github@taz.net.au>
|
||||
Cyril Plisko <cyril.plisko@mountall.com>
|
||||
Dan McDonald <danmcd@nexenta.com>
|
||||
Daniel Verite <daniel@verite.pro>
|
||||
Darik Horn <dajhorn@vanadac.com>
|
||||
Eric Schrock <Eric.Schrock@delphix.com>
|
||||
Etienne Dechamps <etienne.dechamps@ovh.net>
|
||||
Fajar A. Nugraha <github@fajar.net>
|
||||
Frederik Wessels <wessels147@gmail.com>
|
||||
Garrett D'Amore <garrett@nexenta.com>
|
||||
George Wilson <george.wilson@delphix.com>
|
||||
Gordon Ross <gwr@nexenta.com>
|
||||
Gregor Kopka <mailfrom-github.com@kopka.net>
|
||||
Gunnar Beutner <gunnar@beutner.name>
|
||||
James H <james@kagisoft.co.uk>
|
||||
Javen Wu <wu.javen@gmail.com>
|
||||
Jeremy Gill <jgill@parallax-innovations.com>
|
||||
Jorgen Lundman <lundman@lundman.net>
|
||||
KORN Andras <korn@elan.rulez.org>
|
||||
Kyle Fuller <inbox@kylefuller.co.uk>
|
||||
Manuel Amador (Rudd-O) <rudd-o@rudd-o.com>
|
||||
Martin Matuska <mm@FreeBSD.org>
|
||||
Massimo Maggi <massimo@mmmm.it>
|
||||
Matthew Ahrens <mahrens@delphix.com>
|
||||
Michael Martin <mgmartin.mgm@gmail.com>
|
||||
Mike Harsch <mike@harschsystems.com>
|
||||
Ned Bass <bass6@llnl.gov>
|
||||
Oleg Stepura <oleg@stepura.com>
|
||||
P.SCH <p88@yahoo.com>
|
||||
Pawel Jakub Dawidek <pawel@dawidek.net>
|
||||
Prakash Surya <surya1@llnl.gov>
|
||||
Prasad Joshi <pjoshi@stec-inc.com>
|
||||
Ricardo M. Correia <Ricardo.M.Correia@Sun.COM>
|
||||
Richard Laager <rlaager@wiktel.com>
|
||||
Richard Lowe <richlowe@richlowe.net>
|
||||
Richard Yao <ryao@cs.stonybrook.edu>
|
||||
Rohan Puri <rohan.puri15@gmail.com>
|
||||
Shampavman <sham.pavman@nexenta.com>
|
||||
Simon Klinkert <klinkert@webgods.de>
|
||||
Suman Chakravartula <suman@gogrid.com>
|
||||
Tim Haley <Tim.Haley@Sun.COM>
|
||||
Turbo Fredriksson <turbo@bayour.com>
|
||||
Xin Li <delphij@FreeBSD.org>
|
||||
Yuxuan Shui <yshuiv7@gmail.com>
|
||||
Zachary Bedell <zac@thebedells.org>
|
||||
nordaux <nordaux@gmail.com>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
The [OpenZFS Code of Conduct](http://www.open-zfs.org/wiki/Code_of_Conduct)
|
||||
applies to spaces associated with the ZFS on Linux project, including GitHub.
|
||||
@@ -1,27 +1,33 @@
|
||||
Refer to the git commit log for authoritative copyright attribution.
|
||||
The majority of the code in the ZFS on Linux port comes from OpenSolaris
|
||||
which has been released under the terms of the CDDL open source license.
|
||||
This includes the core ZFS code, libavl, libnvpair, libefi, libunicode,
|
||||
and libutil. The original OpenSolaris source can be downloaded from:
|
||||
|
||||
The original ZFS source code was obtained from Open Solaris which was
|
||||
released under the terms of the CDDL open source license. Additional
|
||||
changes have been included from OpenZFS and the Illumos project which
|
||||
are similarly licensed. These projects can be found on Github at:
|
||||
http://dlc.sun.com/osol/on/downloads/b121/on-src.tar.bz2
|
||||
|
||||
* https://github.com/illumos/illumos-gate
|
||||
* https://github.com/openzfs/openzfs
|
||||
Files which do not originate from OpenSolaris are noted in the file header
|
||||
and attributed properly. These exceptions include, but are not limited
|
||||
to, the vdev_disk.c and zvol.c implementation which are licensed under
|
||||
the CDDL.
|
||||
|
||||
The zpios test code is originally derived from the Lustre pios test code
|
||||
which is licensed under the GPLv2. As such the heavily modified zpios
|
||||
kernel test code also remains licensed under the GPLv2.
|
||||
|
||||
The latest stable and development versions of this port can be downloaded
|
||||
from the official ZFS on Linux site located at:
|
||||
|
||||
http://zfsonlinux.org/
|
||||
|
||||
This ZFS on Linux port was produced at the Lawrence Livermore National
|
||||
Laboratory (LLNL) under Contract No. DE-AC52-07NA27344 (Contract 44)
|
||||
between the U.S. Department of Energy (DOE) and Lawrence Livermore
|
||||
National Security, LLC (LLNS) for the operation of LLNL. It has been
|
||||
approved for release under LLNL-CODE-403049.
|
||||
|
||||
Unless otherwise noted, all files in this distribution are released
|
||||
under the Common Development and Distribution License (CDDL).
|
||||
Exceptions are noted within the associated source files. See the file
|
||||
OPENSOLARIS.LICENSE for more information.
|
||||
|
||||
Exceptions are noted within the associated source files headers and
|
||||
by including a THIRDPARTYLICENSE file with the license terms. A few
|
||||
notable exceptions and their respective licenses include:
|
||||
|
||||
* Skein Checksum Implementation: module/icp/algs/skein/THIRDPARTYLICENSE
|
||||
* AES Implementation: module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.gladman
|
||||
* AES Implementation: module/icp/asm-x86_64/aes/THIRDPARTYLICENSE.openssl
|
||||
* PBKDF2 Implementation: lib/libzfs/THIRDPARTYLICENSE.openssl
|
||||
* SPL Implementation: module/spl/THIRDPARTYLICENSE.gplv2
|
||||
|
||||
This product includes software developed by the OpenSSL Project for use
|
||||
in the OpenSSL Toolkit (http://www.openssl.org/)
|
||||
|
||||
See the LICENSE and NOTICE for more information.
|
||||
Refer to the git commit log for authoritative copyright attribution.
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
This work was produced at the Lawrence Livermore National Laboratory
|
||||
(LLNL) under Contract No. DE-AC52-07NA27344 (Contract 44) between
|
||||
the U.S. Department of Energy (DOE) and Lawrence Livermore National
|
||||
Security, LLC (LLNS) for the operation of LLNL.
|
||||
|
||||
This work was prepared as an account of work sponsored by an agency of
|
||||
the United States Government. Neither the United States Government nor
|
||||
Lawrence Livermore National Security, LLC nor any of their employees,
|
||||
makes any warranty, express or implied, or assumes any liability or
|
||||
responsibility for the accuracy, completeness, or usefulness of any
|
||||
information, apparatus, product, or process disclosed, or represents
|
||||
that its use would not infringe privately-owned rights.
|
||||
|
||||
Reference herein to any specific commercial products, process, or
|
||||
services by trade name, trademark, manufacturer or otherwise does
|
||||
not necessarily constitute or imply its endorsement, recommendation,
|
||||
or favoring by the United States Government or Lawrence Livermore
|
||||
National Security, LLC. The views and opinions of authors expressed
|
||||
herein do not necessarily state or reflect those of the United States
|
||||
Government or Lawrence Livermore National Security, LLC, and shall
|
||||
not be used for advertising or product endorsement purposes.
|
||||
|
||||
The precise terms and conditions for copying, distribution, and
|
||||
modification are specified in the file OPENSOLARIS.LICENSE.
|
||||
@@ -1,10 +1,8 @@
|
||||
Meta: 1
|
||||
Name: zfs
|
||||
Branch: 1.0
|
||||
Version: 0.8.3
|
||||
Release: 1
|
||||
Release-Tags: relext
|
||||
License: CDDL
|
||||
Author: OpenZFS on Linux
|
||||
Linux-Maximum: 5.4
|
||||
Linux-Minimum: 2.6.32
|
||||
Meta: 1
|
||||
Name: zfs
|
||||
Branch: 1.0
|
||||
Version: 0.7.13
|
||||
Release: 1
|
||||
Release-Tags: relext
|
||||
License: CDDL
|
||||
Author: OpenZFS on Linux
|
||||
|
||||
+18
-93
@@ -11,42 +11,22 @@ endif
|
||||
if CONFIG_KERNEL
|
||||
SUBDIRS += module
|
||||
|
||||
extradir = $(prefix)/src/zfs-$(VERSION)
|
||||
extradir = @prefix@/src/zfs-$(VERSION)
|
||||
extra_HEADERS = zfs.release.in zfs_config.h.in
|
||||
|
||||
kerneldir = $(prefix)/src/zfs-$(VERSION)/$(LINUX_VERSION)
|
||||
kerneldir = @prefix@/src/zfs-$(VERSION)/$(LINUX_VERSION)
|
||||
nodist_kernel_HEADERS = zfs.release zfs_config.h module/$(LINUX_SYMBOLS)
|
||||
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
|
||||
|
||||
# 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/spl/THIRDPARTYLICENSE.gplv2
|
||||
EXTRA_DIST += module/spl/THIRDPARTYLICENSE.gplv2.descrip
|
||||
EXTRA_DIST += module/zfs/THIRDPARTYLICENSE.cityhash
|
||||
EXTRA_DIST += module/zfs/THIRDPARTYLICENSE.cityhash.descrip
|
||||
EXTRA_DIST += META DISCLAIMER COPYRIGHT README.markdown OPENSOLARIS.LICENSE
|
||||
|
||||
@CODE_COVERAGE_RULES@
|
||||
|
||||
.PHONY: gitrev
|
||||
gitrev:
|
||||
-${top_srcdir}/scripts/make_gitrev.sh
|
||||
|
||||
BUILT_SOURCES = gitrev
|
||||
|
||||
# Double-colon rules are allowed; there are multiple independent definitions.
|
||||
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 '*~' \
|
||||
@@ -57,79 +37,30 @@ distclean-local::
|
||||
-o -name '*.gcno' \) \
|
||||
-type f -print | xargs $(RM)
|
||||
|
||||
all-local:
|
||||
-[ -x ${top_builddir}/scripts/zfs-tests.sh ] && \
|
||||
${top_builddir}/scripts/zfs-tests.sh -c
|
||||
|
||||
dist-hook: gitrev
|
||||
cp ${top_srcdir}/include/zfs_gitrev.h $(distdir)/include; \
|
||||
dist-hook:
|
||||
sed -i 's/Release:[[:print:]]*/Release: $(RELEASE)/' \
|
||||
$(distdir)/META
|
||||
|
||||
# For compatibility, create a matching spl-x.y.z directly which contains
|
||||
# symlinks to the updated header and object file locations. These
|
||||
# compatibility links will be removed in the next major release.
|
||||
if CONFIG_KERNEL
|
||||
install-data-hook:
|
||||
rm -rf $(DESTDIR)$(prefix)/src/spl-$(VERSION) && \
|
||||
mkdir $(DESTDIR)$(prefix)/src/spl-$(VERSION) && \
|
||||
cd $(DESTDIR)$(prefix)/src/spl-$(VERSION) && \
|
||||
ln -s ../zfs-$(VERSION)/include/spl include && \
|
||||
ln -s ../zfs-$(VERSION)/$(LINUX_VERSION) $(LINUX_VERSION) && \
|
||||
ln -s ../zfs-$(VERSION)/zfs_config.h.in spl_config.h.in && \
|
||||
ln -s ../zfs-$(VERSION)/zfs.release.in spl.release.in && \
|
||||
cd $(DESTDIR)$(prefix)/src/zfs-$(VERSION)/$(LINUX_VERSION) && \
|
||||
ln -fs zfs_config.h spl_config.h && \
|
||||
ln -fs zfs.release spl.release
|
||||
endif
|
||||
|
||||
codecheck: cstyle shellcheck flake8 mancheck testscheck vcscheck
|
||||
|
||||
checkstyle: codecheck commitcheck
|
||||
checkstyle: cstyle shellcheck flake8 commitcheck
|
||||
|
||||
commitcheck:
|
||||
@if git rev-parse --git-dir > /dev/null 2>&1; then \
|
||||
${top_srcdir}/scripts/commitcheck.sh; \
|
||||
scripts/commitcheck.sh; \
|
||||
fi
|
||||
|
||||
cstyle:
|
||||
@find ${top_srcdir} -name build -prune -o -name '*.[hc]' \
|
||||
! -name 'zfs_config.*' ! -name '*.mod.c' -type f \
|
||||
-exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
|
||||
@find ${top_srcdir} -name '*.[hc]' ! -name 'zfs_config.*' \
|
||||
! -name '*.mod.c' -type f -exec scripts/cstyle.pl -cpP {} \+
|
||||
|
||||
shellcheck:
|
||||
@if type shellcheck > /dev/null 2>&1; then \
|
||||
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/* -executable); \
|
||||
else \
|
||||
echo "skipping shellcheck because shellcheck is not installed"; \
|
||||
fi
|
||||
|
||||
mancheck:
|
||||
@if type mandoc > /dev/null 2>&1; then \
|
||||
find ${top_srcdir}/man/man8 -type f -name 'zfs.8' \
|
||||
-o -name 'zpool.8' -o -name 'zdb.8' \
|
||||
-o -name 'zgenhostid.8' | \
|
||||
xargs mandoc -Tlint -Werror; \
|
||||
else \
|
||||
echo "skipping mancheck because mandoc is not installed"; \
|
||||
fi
|
||||
|
||||
testscheck:
|
||||
@find ${top_srcdir}/tests/zfs-tests -type f \
|
||||
\( -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}'
|
||||
|
||||
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}' ; \
|
||||
shellcheck --exclude=SC1090 --format=gcc scripts/paxcheck.sh \
|
||||
scripts/zloop.sh \
|
||||
scripts/zfs-tests.sh \
|
||||
scripts/zfs.sh \
|
||||
scripts/commitcheck.sh \
|
||||
$$(find cmd/zed/zed.d/*.sh -type f) \
|
||||
$$(find cmd/zpool/zpool.d/* -executable); \
|
||||
fi
|
||||
|
||||
lint: cppcheck paxcheck
|
||||
@@ -139,23 +70,17 @@ cppcheck:
|
||||
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"; \
|
||||
-UHAVE_DNLC ${top_srcdir}; \
|
||||
fi
|
||||
|
||||
paxcheck:
|
||||
@if type scanelf > /dev/null 2>&1; then \
|
||||
${top_srcdir}/scripts/paxcheck.sh ${top_srcdir}; \
|
||||
else \
|
||||
echo "skipping paxcheck because scanelf is not installed"; \
|
||||
scripts/paxcheck.sh ${top_srcdir}; \
|
||||
fi
|
||||
|
||||
flake8:
|
||||
@if type flake8 > /dev/null 2>&1; then \
|
||||
flake8 ${top_srcdir}; \
|
||||
else \
|
||||
echo "skipping flake8 because flake8 is not installed"; \
|
||||
fi
|
||||
|
||||
ctags:
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Descriptions of all releases can be found on github:
|
||||
|
||||
https://github.com/zfsonlinux/zfs/releases
|
||||
@@ -1,16 +0,0 @@
|
||||
This work was produced under the auspices of the U.S. Department of Energy by
|
||||
Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344.
|
||||
|
||||
This work was prepared as an account of work sponsored by an agency of the
|
||||
United States Government. Neither the United States Government nor Lawrence
|
||||
Livermore National Security, LLC, nor any of their employees makes any warranty,
|
||||
expressed or implied, or assumes any legal liability or responsibility for the
|
||||
accuracy, completeness, or usefulness of any information, apparatus, product, or
|
||||
process disclosed, or represents that its use would not infringe privately owned
|
||||
rights. Reference herein to any specific commercial product, process, or service
|
||||
by trade name, trademark, manufacturer, or otherwise does not necessarily
|
||||
constitute or imply its endorsement, recommendation, or favoring by the United
|
||||
States Government or Lawrence Livermore National Security, LLC. The views and
|
||||
opinions of authors expressed herein do not necessarily state or reflect those
|
||||
of the United States Government or Lawrence Livermore National Security, LLC,
|
||||
and shall not be used for advertising or product endorsement purposes.
|
||||
@@ -4,28 +4,16 @@ ZFS on Linux is an advanced file system and volume manager which was originally
|
||||
developed for Solaris and is now maintained by the OpenZFS community.
|
||||
|
||||
[](https://codecov.io/gh/zfsonlinux/zfs)
|
||||
[](https://scan.coverity.com/projects/zfsonlinux-zfs)
|
||||
|
||||
# Official Resources
|
||||
|
||||
* [Site](http://zfsonlinux.org)
|
||||
* [Wiki](https://github.com/zfsonlinux/zfs/wiki)
|
||||
* [Mailing lists](https://github.com/zfsonlinux/zfs/wiki/Mailing-Lists)
|
||||
* [OpenZFS site](http://open-zfs.org/)
|
||||
|
||||
# Installation
|
||||
|
||||
Full documentation for installing ZoL on your favorite Linux distribution can
|
||||
be found at [our site](http://zfsonlinux.org/).
|
||||
|
||||
# Contribute & Develop
|
||||
|
||||
We have a separate document with [contribution guidelines](./.github/CONTRIBUTING.md).
|
||||
|
||||
# Release
|
||||
|
||||
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 kernel versions.
|
||||
@@ -1,15 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
### prepare
|
||||
#TEST_PREPARE_WATCHDOG="yes"
|
||||
#TEST_PREPARE_SHARES="yes"
|
||||
#TEST_PREPARE_WATCHDOG="no"
|
||||
|
||||
### SPLAT
|
||||
#TEST_SPLAT_SKIP="yes"
|
||||
#TEST_SPLAT_OPTIONS="-acvx"
|
||||
|
||||
### ztest
|
||||
#TEST_ZTEST_SKIP="yes"
|
||||
#TEST_ZTEST_TIMEOUT=1800
|
||||
#TEST_ZTEST_DIR="/var/tmp/"
|
||||
#TEST_ZTEST_OPTIONS="-V"
|
||||
#TEST_ZTEST_CORE_DIR="/mnt/zloop"
|
||||
|
||||
### zimport
|
||||
#TEST_ZIMPORT_SKIP="yes"
|
||||
@@ -29,13 +31,9 @@
|
||||
|
||||
### zfs-tests.sh
|
||||
#TEST_ZFSTESTS_SKIP="yes"
|
||||
#TEST_ZFSTESTS_DIR="/mnt/"
|
||||
#TEST_ZFSTESTS_DISKS="vdb vdc vdd"
|
||||
#TEST_ZFSTESTS_DISKSIZE="8G"
|
||||
#TEST_ZFSTESTS_ITERS="1"
|
||||
#TEST_ZFSTESTS_OPTIONS="-vx"
|
||||
#TEST_ZFSTESTS_RUNFILE="linux.run"
|
||||
#TEST_ZFSTESTS_TAGS="functional"
|
||||
|
||||
### zfsstress
|
||||
#TEST_ZFSSTRESS_SKIP="yes"
|
||||
@@ -44,7 +42,6 @@
|
||||
#TEST_ZFSSTRESS_RUNTIME=300
|
||||
#TEST_ZFSSTRESS_POOL="tank"
|
||||
#TEST_ZFSSTRESS_FS="fish"
|
||||
#TEST_ZFSSTRESS_FSOPT="-o overlay=on"
|
||||
#TEST_ZFSSTRESS_VDEV="/var/tmp/vdev"
|
||||
#TEST_ZFSSTRESS_DIR="/$TEST_ZFSSTRESS_POOL/$TEST_ZFSSTRESS_FS"
|
||||
#TEST_ZFSSTRESS_OPTIONS=""
|
||||
@@ -86,20 +83,6 @@ 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.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
autoreconf -fiv || exit 1
|
||||
autoreconf -fiv
|
||||
rm -Rf autom4te.cache
|
||||
|
||||
+3
-8
@@ -1,8 +1,3 @@
|
||||
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
|
||||
|
||||
SUBDIRS += mount_zfs zed zvol_id zvol_wait
|
||||
SUBDIRS = zfs zpool zdb zhack zinject zstreamdump ztest zpios
|
||||
SUBDIRS += mount_zfs fsck_zfs zvol_id vdev_id arcstat dbufstat zed
|
||||
SUBDIRS += arc_summary raidz_test zgenhostid
|
||||
|
||||
@@ -1,11 +1 @@
|
||||
EXTRA_DIST = arc_summary2 arc_summary3
|
||||
|
||||
if USING_PYTHON_2
|
||||
dist_bin_SCRIPTS = arc_summary2
|
||||
install-exec-hook:
|
||||
mv $(DESTDIR)$(bindir)/arc_summary2 $(DESTDIR)$(bindir)/arc_summary
|
||||
else
|
||||
dist_bin_SCRIPTS = arc_summary3
|
||||
install-exec-hook:
|
||||
mv $(DESTDIR)$(bindir)/arc_summary3 $(DESTDIR)$(bindir)/arc_summary
|
||||
endif
|
||||
dist_bin_SCRIPTS = arc_summary.py
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# $Id: arc_summary.pl,v 388:e27800740aa2 2011-07-08 02:53:29Z jhell $
|
||||
#
|
||||
@@ -35,8 +35,6 @@
|
||||
# Note some of this code uses older code (eg getopt instead of argparse,
|
||||
# subprocess.Popen() instead of subprocess.run()) because we need to support
|
||||
# some very old versions of Python.
|
||||
#
|
||||
|
||||
"""Print statistics on the ZFS Adjustable Replacement Cache (ARC)
|
||||
|
||||
Provides basic information on the ARC, its efficiency, the L2ARC (if present),
|
||||
@@ -206,10 +204,6 @@ def get_arc_summary(Kstat):
|
||||
arc_size = Kstat["kstat.zfs.misc.arcstats.size"]
|
||||
mru_size = Kstat["kstat.zfs.misc.arcstats.mru_size"]
|
||||
mfu_size = Kstat["kstat.zfs.misc.arcstats.mfu_size"]
|
||||
meta_limit = Kstat["kstat.zfs.misc.arcstats.arc_meta_limit"]
|
||||
meta_size = Kstat["kstat.zfs.misc.arcstats.arc_meta_used"]
|
||||
dnode_limit = Kstat["kstat.zfs.misc.arcstats.arc_dnode_limit"]
|
||||
dnode_size = Kstat["kstat.zfs.misc.arcstats.dnode_size"]
|
||||
target_max_size = Kstat["kstat.zfs.misc.arcstats.c_max"]
|
||||
target_min_size = Kstat["kstat.zfs.misc.arcstats.c_min"]
|
||||
target_size = Kstat["kstat.zfs.misc.arcstats.c"]
|
||||
@@ -234,22 +228,6 @@ def get_arc_summary(Kstat):
|
||||
'per': fPerc(target_size, target_max_size),
|
||||
'num': fBytes(target_size),
|
||||
}
|
||||
output['arc_sizing']['meta_limit'] = {
|
||||
'per': fPerc(meta_limit, target_max_size),
|
||||
'num': fBytes(meta_limit),
|
||||
}
|
||||
output['arc_sizing']['meta_size'] = {
|
||||
'per': fPerc(meta_size, meta_limit),
|
||||
'num': fBytes(meta_size),
|
||||
}
|
||||
output['arc_sizing']['dnode_limit'] = {
|
||||
'per': fPerc(dnode_limit, meta_limit),
|
||||
'num': fBytes(dnode_limit),
|
||||
}
|
||||
output['arc_sizing']['dnode_size'] = {
|
||||
'per': fPerc(dnode_size, dnode_limit),
|
||||
'num': fBytes(dnode_size),
|
||||
}
|
||||
|
||||
# ARC Hash Breakdown
|
||||
output['arc_hash_break'] = {}
|
||||
@@ -355,26 +333,6 @@ def _arc_summary(Kstat):
|
||||
arc['arc_size_break']['frequently_used_cache_size']['num'],
|
||||
)
|
||||
)
|
||||
sys.stdout.write("\tMetadata Size (Hard Limit):\t%s\t%s\n" % (
|
||||
arc['arc_sizing']['meta_limit']['per'],
|
||||
arc['arc_sizing']['meta_limit']['num'],
|
||||
)
|
||||
)
|
||||
sys.stdout.write("\tMetadata Size:\t\t\t%s\t%s\n" % (
|
||||
arc['arc_sizing']['meta_size']['per'],
|
||||
arc['arc_sizing']['meta_size']['num'],
|
||||
)
|
||||
)
|
||||
sys.stdout.write("\tDnode Size (Hard Limit):\t%s\t%s\n" % (
|
||||
arc['arc_sizing']['dnode_limit']['per'],
|
||||
arc['arc_sizing']['dnode_limit']['num'],
|
||||
)
|
||||
)
|
||||
sys.stdout.write("\tDnode Size:\t\t\t%s\t%s\n" % (
|
||||
arc['arc_sizing']['dnode_size']['per'],
|
||||
arc['arc_sizing']['dnode_size']['num'],
|
||||
)
|
||||
)
|
||||
|
||||
sys.stdout.write("\n")
|
||||
|
||||
@@ -1007,7 +965,7 @@ def zfs_header():
|
||||
def usage():
|
||||
"""Print usage information"""
|
||||
|
||||
sys.stdout.write("Usage: arc_summary [-h] [-a] [-d] [-p PAGE]\n\n")
|
||||
sys.stdout.write("Usage: arc_summary.py [-h] [-a] [-d] [-p PAGE]\n\n")
|
||||
sys.stdout.write("\t -h, --help : "
|
||||
"Print this help message and exit\n")
|
||||
sys.stdout.write("\t -a, --alternate : "
|
||||
@@ -1020,10 +978,10 @@ def usage():
|
||||
"should be an integer between 1 and " +
|
||||
str(len(unSub)) + "\n\n")
|
||||
sys.stdout.write("Examples:\n")
|
||||
sys.stdout.write("\tarc_summary -a\n")
|
||||
sys.stdout.write("\tarc_summary -p 4\n")
|
||||
sys.stdout.write("\tarc_summary -ad\n")
|
||||
sys.stdout.write("\tarc_summary --page=2\n")
|
||||
sys.stdout.write("\tarc_summary.py -a\n")
|
||||
sys.stdout.write("\tarc_summary.py -p 4\n")
|
||||
sys.stdout.write("\tarc_summary.py -ad\n")
|
||||
sys.stdout.write("\tarc_summary.py --page=2\n")
|
||||
|
||||
|
||||
def main():
|
||||
@@ -1,875 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2008 Ben Rockwood <benr@cuddletech.com>,
|
||||
# Copyright (c) 2010 Martin Matuska <mm@FreeBSD.org>,
|
||||
# Copyright (c) 2010-2011 Jason J. Hellenthal <jhell@DataIX.net>,
|
||||
# Copyright (c) 2017 Scot W. Stevenson <scot.stevenson@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
"""Print statistics on the ZFS ARC Cache and other information
|
||||
|
||||
Provides basic information on the ARC, its efficiency, the L2ARC (if present),
|
||||
the Data Management Unit (DMU), Virtual Devices (VDEVs), and tunables. See
|
||||
the in-source documentation and code at
|
||||
https://github.com/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
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
DESCRIPTION = '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'
|
||||
|
||||
SECTIONS = 'arc archits dmu l2arc spl tunables vdev zil'.split()
|
||||
SECTION_HELP = 'print info from one section ('+' '.join(SECTIONS)+')'
|
||||
|
||||
# Tunables and SPL are handled separately because they come from
|
||||
# different sources
|
||||
SECTION_PATHS = {'arc': 'arcstats',
|
||||
'dmu': 'dmu_tx',
|
||||
'l2arc': 'arcstats', # L2ARC stuff lives in arcstats
|
||||
'vdev': 'vdev_cache_stats',
|
||||
'xuio': 'xuio_stats',
|
||||
'zfetch': 'zfetchstats',
|
||||
'zil': 'zil'}
|
||||
|
||||
parser = argparse.ArgumentParser(description=DESCRIPTION)
|
||||
parser.add_argument('-a', '--alternate', action='store_true', default=False,
|
||||
help='use alternate formatting for tunables and SPL',
|
||||
dest='alt')
|
||||
parser.add_argument('-d', '--description', action='store_true', default=False,
|
||||
help='print descriptions with tunables and SPL',
|
||||
dest='desc')
|
||||
parser.add_argument('-g', '--graph', action='store_true', default=False,
|
||||
help='print graph on ARC use and exit', dest='graph')
|
||||
parser.add_argument('-p', '--page', type=int, dest='page',
|
||||
help='print page by number (DEPRECATED, use "-s")')
|
||||
parser.add_argument('-r', '--raw', action='store_true', default=False,
|
||||
help='dump all available data with minimal formatting',
|
||||
dest='raw')
|
||||
parser.add_argument('-s', '--section', dest='section', help=SECTION_HELP)
|
||||
ARGS = parser.parse_args()
|
||||
|
||||
|
||||
def cleanup_line(single_line):
|
||||
"""Format a raw line of data from /proc and isolate the name value
|
||||
part, returning a tuple with each. Currently, this gets rid of the
|
||||
middle '4'. For example "arc_no_grow 4 0" returns the tuple
|
||||
("arc_no_grow", "0").
|
||||
"""
|
||||
name, _, value = single_line.split()
|
||||
|
||||
return name, value
|
||||
|
||||
|
||||
def draw_graph(kstats_dict):
|
||||
"""Draw a primitive graph representing the basic information on the
|
||||
ARC -- its size and the proportion used by MFU and MRU -- and quit.
|
||||
We use max size of the ARC to calculate how full it is. This is a
|
||||
very rough representation.
|
||||
"""
|
||||
|
||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
||||
|
||||
GRAPH_INDENT = ' '*4
|
||||
GRAPH_WIDTH = 60
|
||||
arc_size = f_bytes(arc_stats['size'])
|
||||
arc_perc = f_perc(arc_stats['size'], arc_stats['c_max'])
|
||||
mfu_size = f_bytes(arc_stats['mfu_size'])
|
||||
mru_size = f_bytes(arc_stats['mru_size'])
|
||||
meta_limit = f_bytes(arc_stats['arc_meta_limit'])
|
||||
meta_size = f_bytes(arc_stats['arc_meta_used'])
|
||||
dnode_limit = f_bytes(arc_stats['arc_dnode_limit'])
|
||||
dnode_size = f_bytes(arc_stats['dnode_size'])
|
||||
|
||||
info_form = ('ARC: {0} ({1}) MFU: {2} MRU: {3} META: {4} ({5}) '
|
||||
'DNODE {6} ({7})')
|
||||
info_line = info_form.format(arc_size, arc_perc, mfu_size, mru_size,
|
||||
meta_size, meta_limit, dnode_size,
|
||||
dnode_limit)
|
||||
info_spc = ' '*int((GRAPH_WIDTH-len(info_line))/2)
|
||||
info_line = GRAPH_INDENT+info_spc+info_line
|
||||
|
||||
graph_line = GRAPH_INDENT+'+'+('-'*(GRAPH_WIDTH-2))+'+'
|
||||
|
||||
mfu_perc = float(int(arc_stats['mfu_size'])/int(arc_stats['c_max']))
|
||||
mru_perc = float(int(arc_stats['mru_size'])/int(arc_stats['c_max']))
|
||||
arc_perc = float(int(arc_stats['size'])/int(arc_stats['c_max']))
|
||||
total_ticks = float(arc_perc)*GRAPH_WIDTH
|
||||
mfu_ticks = mfu_perc*GRAPH_WIDTH
|
||||
mru_ticks = mru_perc*GRAPH_WIDTH
|
||||
other_ticks = total_ticks-(mfu_ticks+mru_ticks)
|
||||
|
||||
core_form = 'F'*int(mfu_ticks)+'R'*int(mru_ticks)+'O'*int(other_ticks)
|
||||
core_spc = ' '*(GRAPH_WIDTH-(2+len(core_form)))
|
||||
core_line = GRAPH_INDENT+'|'+core_form+core_spc+'|'
|
||||
|
||||
for line in ('', info_line, graph_line, core_line, graph_line, ''):
|
||||
print(line)
|
||||
|
||||
|
||||
def f_bytes(byte_string):
|
||||
"""Return human-readable representation of a byte value in
|
||||
powers of 2 (eg "KiB" for "kibibytes", etc) to two decimal
|
||||
points. Values smaller than one KiB are returned without
|
||||
decimal points. Note "bytes" is a reserved keyword.
|
||||
"""
|
||||
|
||||
prefixes = ([2**80, "YiB"], # yobibytes (yotta)
|
||||
[2**70, "ZiB"], # zebibytes (zetta)
|
||||
[2**60, "EiB"], # exbibytes (exa)
|
||||
[2**50, "PiB"], # pebibytes (peta)
|
||||
[2**40, "TiB"], # tebibytes (tera)
|
||||
[2**30, "GiB"], # gibibytes (giga)
|
||||
[2**20, "MiB"], # mebibytes (mega)
|
||||
[2**10, "KiB"]) # kibibytes (kilo)
|
||||
|
||||
bites = int(byte_string)
|
||||
|
||||
if bites >= 2**10:
|
||||
for limit, unit in prefixes:
|
||||
|
||||
if bites >= limit:
|
||||
value = bites / limit
|
||||
break
|
||||
|
||||
result = '{0:.1f} {1}'.format(value, unit)
|
||||
else:
|
||||
result = '{0} Bytes'.format(bites)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def f_hits(hits_string):
|
||||
"""Create a human-readable representation of the number of hits.
|
||||
The single-letter symbols used are SI to avoid the confusion caused
|
||||
by the different "short scale" and "long scale" representations in
|
||||
English, which use the same words for different values. See
|
||||
https://en.wikipedia.org/wiki/Names_of_large_numbers and:
|
||||
https://physics.nist.gov/cuu/Units/prefixes.html
|
||||
"""
|
||||
|
||||
numbers = ([10**24, 'Y'], # yotta (septillion)
|
||||
[10**21, 'Z'], # zetta (sextillion)
|
||||
[10**18, 'E'], # exa (quintrillion)
|
||||
[10**15, 'P'], # peta (quadrillion)
|
||||
[10**12, 'T'], # tera (trillion)
|
||||
[10**9, 'G'], # giga (billion)
|
||||
[10**6, 'M'], # mega (million)
|
||||
[10**3, 'k']) # kilo (thousand)
|
||||
|
||||
hits = int(hits_string)
|
||||
|
||||
if hits >= 1000:
|
||||
for limit, symbol in numbers:
|
||||
|
||||
if hits >= limit:
|
||||
value = hits/limit
|
||||
break
|
||||
|
||||
result = "%0.1f%s" % (value, symbol)
|
||||
else:
|
||||
result = "%d" % hits
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def f_perc(value1, value2):
|
||||
"""Calculate percentage and return in human-readable form. If
|
||||
rounding produces the result '0.0' though the first number is
|
||||
not zero, include a 'less-than' symbol to avoid confusion.
|
||||
Division by zero is handled by returning 'n/a'; no error
|
||||
is called.
|
||||
"""
|
||||
|
||||
v1 = float(value1)
|
||||
v2 = float(value2)
|
||||
|
||||
try:
|
||||
perc = 100 * v1/v2
|
||||
except ZeroDivisionError:
|
||||
result = 'n/a'
|
||||
else:
|
||||
result = '{0:0.1f} %'.format(perc)
|
||||
|
||||
if result == '0.0 %' and v1 > 0:
|
||||
result = '< 0.1 %'
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def format_raw_line(name, value):
|
||||
"""For the --raw option for the tunable and SPL outputs, decide on the
|
||||
correct formatting based on the --alternate flag.
|
||||
"""
|
||||
|
||||
if ARGS.alt:
|
||||
result = '{0}{1}={2}'.format(INDENT, name, value)
|
||||
else:
|
||||
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 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 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 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 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 via modinfo.
|
||||
"""
|
||||
|
||||
if request not in ('spl', 'zfs'):
|
||||
error_msg = '(ERROR: "{0}" requested)'.format(request)
|
||||
return error_msg
|
||||
|
||||
# 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
|
||||
Linux and ZFS versions. This is not called for the graph.
|
||||
"""
|
||||
|
||||
# datetime is now recommended over time but we keep the exact formatting
|
||||
# from the older version of arc_summary in case there are scripts
|
||||
# that expect it in this way
|
||||
daydate = time.strftime(DATE_FORMAT)
|
||||
spc_date = LINE_LENGTH-len(daydate)
|
||||
sys_version = os.uname()
|
||||
|
||||
sys_msg = sys_version.sysname+' '+sys_version.release
|
||||
zfs = get_version('zfs')
|
||||
spc_zfs = LINE_LENGTH-len(zfs)
|
||||
|
||||
machine_msg = 'Machine: '+sys_version.nodename+' ('+sys_version.machine+')'
|
||||
spl = get_version('spl')
|
||||
spc_spl = LINE_LENGTH-len(spl)
|
||||
|
||||
print('\n'+('-'*LINE_LENGTH))
|
||||
print('{0:<{spc}}{1}'.format(TITLE, daydate, spc=spc_date))
|
||||
print('{0:<{spc}}{1}'.format(sys_msg, zfs, spc=spc_zfs))
|
||||
print('{0:<{spc}}{1}\n'.format(machine_msg, spl, spc=spc_spl))
|
||||
|
||||
|
||||
def print_raw(kstats_dict):
|
||||
"""Print all available data from the system in a minimally sorted format.
|
||||
This can be used as a source to be piped through 'grep'.
|
||||
"""
|
||||
|
||||
sections = sorted(kstats_dict.keys())
|
||||
|
||||
for section in sections:
|
||||
|
||||
print('\n{0}:'.format(section.upper()))
|
||||
lines = sorted(kstats_dict[section])
|
||||
|
||||
for line in lines:
|
||||
name, value = cleanup_line(line)
|
||||
print(format_raw_line(name, value))
|
||||
|
||||
# Tunables and SPL must be handled separately because they come from a
|
||||
# different source and have descriptions the user might request
|
||||
print()
|
||||
section_spl()
|
||||
section_tunables()
|
||||
|
||||
|
||||
def isolate_section(section_name, kstats_dict):
|
||||
"""From the complete information on all sections, retrieve only those
|
||||
for one section.
|
||||
"""
|
||||
|
||||
try:
|
||||
section_data = kstats_dict[section_name]
|
||||
except KeyError:
|
||||
print('ERROR: Data on {0} not available'.format(section_data))
|
||||
sys.exit(1)
|
||||
|
||||
section_dict = dict(cleanup_line(l) for l in section_data)
|
||||
|
||||
return section_dict
|
||||
|
||||
|
||||
# Formatted output helper functions
|
||||
|
||||
|
||||
def prt_1(text, value):
|
||||
"""Print text and one value, no indent"""
|
||||
spc = ' '*(LINE_LENGTH-(len(text)+len(value)))
|
||||
print('{0}{spc}{1}'.format(text, value, spc=spc))
|
||||
|
||||
|
||||
def prt_i1(text, value):
|
||||
"""Print text and one value, with indent"""
|
||||
spc = ' '*(LINE_LENGTH-(len(INDENT)+len(text)+len(value)))
|
||||
print(INDENT+'{0}{spc}{1}'.format(text, value, spc=spc))
|
||||
|
||||
|
||||
def prt_2(text, value1, value2):
|
||||
"""Print text and two values, no indent"""
|
||||
values = '{0:>9} {1:>9}'.format(value1, value2)
|
||||
spc = ' '*(LINE_LENGTH-(len(text)+len(values)+2))
|
||||
print('{0}{spc} {1}'.format(text, values, spc=spc))
|
||||
|
||||
|
||||
def prt_i2(text, value1, value2):
|
||||
"""Print text and two values, with indent"""
|
||||
values = '{0:>9} {1:>9}'.format(value1, value2)
|
||||
spc = ' '*(LINE_LENGTH-(len(INDENT)+len(text)+len(values)+2))
|
||||
print(INDENT+'{0}{spc} {1}'.format(text, values, spc=spc))
|
||||
|
||||
|
||||
# The section output concentrates on important parameters instead of
|
||||
# being exhaustive (that is what the --raw parameter is for)
|
||||
|
||||
|
||||
def section_arc(kstats_dict):
|
||||
"""Give basic information on the ARC, MRU and MFU. This is the first
|
||||
and most used section.
|
||||
"""
|
||||
|
||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
||||
|
||||
throttle = arc_stats['memory_throttle_count']
|
||||
|
||||
if throttle == '0':
|
||||
health = 'HEALTHY'
|
||||
else:
|
||||
health = 'THROTTLED'
|
||||
|
||||
prt_1('ARC status:', health)
|
||||
prt_i1('Memory throttle count:', throttle)
|
||||
print()
|
||||
|
||||
arc_size = arc_stats['size']
|
||||
arc_target_size = arc_stats['c']
|
||||
arc_max = arc_stats['c_max']
|
||||
arc_min = arc_stats['c_min']
|
||||
mfu_size = arc_stats['mfu_size']
|
||||
mru_size = arc_stats['mru_size']
|
||||
meta_limit = arc_stats['arc_meta_limit']
|
||||
meta_size = arc_stats['arc_meta_used']
|
||||
dnode_limit = arc_stats['arc_dnode_limit']
|
||||
dnode_size = arc_stats['dnode_size']
|
||||
target_size_ratio = '{0}:1'.format(int(arc_max) // int(arc_min))
|
||||
|
||||
prt_2('ARC size (current):',
|
||||
f_perc(arc_size, arc_max), f_bytes(arc_size))
|
||||
prt_i2('Target size (adaptive):',
|
||||
f_perc(arc_target_size, arc_max), f_bytes(arc_target_size))
|
||||
prt_i2('Min size (hard limit):',
|
||||
f_perc(arc_min, arc_max), f_bytes(arc_min))
|
||||
prt_i2('Max size (high water):',
|
||||
target_size_ratio, f_bytes(arc_max))
|
||||
caches_size = int(mfu_size)+int(mru_size)
|
||||
prt_i2('Most Frequently Used (MFU) cache size:',
|
||||
f_perc(mfu_size, caches_size), f_bytes(mfu_size))
|
||||
prt_i2('Most Recently Used (MRU) cache size:',
|
||||
f_perc(mru_size, caches_size), f_bytes(mru_size))
|
||||
prt_i2('Metadata cache size (hard limit):',
|
||||
f_perc(meta_limit, arc_max), f_bytes(meta_limit))
|
||||
prt_i2('Metadata cache size (current):',
|
||||
f_perc(meta_size, meta_limit), f_bytes(meta_size))
|
||||
prt_i2('Dnode cache size (hard limit):',
|
||||
f_perc(dnode_limit, meta_limit), f_bytes(dnode_limit))
|
||||
prt_i2('Dnode cache size (current):',
|
||||
f_perc(dnode_size, dnode_limit), f_bytes(dnode_size))
|
||||
print()
|
||||
|
||||
print('ARC hash breakdown:')
|
||||
prt_i1('Elements max:', f_hits(arc_stats['hash_elements_max']))
|
||||
prt_i2('Elements current:',
|
||||
f_perc(arc_stats['hash_elements'], arc_stats['hash_elements_max']),
|
||||
f_hits(arc_stats['hash_elements']))
|
||||
prt_i1('Collisions:', f_hits(arc_stats['hash_collisions']))
|
||||
|
||||
prt_i1('Chain max:', f_hits(arc_stats['hash_chain_max']))
|
||||
prt_i1('Chains:', f_hits(arc_stats['hash_chains']))
|
||||
print()
|
||||
|
||||
print('ARC misc:')
|
||||
prt_i1('Deleted:', f_hits(arc_stats['deleted']))
|
||||
prt_i1('Mutex misses:', f_hits(arc_stats['mutex_miss']))
|
||||
prt_i1('Eviction skips:', f_hits(arc_stats['evict_skip']))
|
||||
print()
|
||||
|
||||
|
||||
def section_archits(kstats_dict):
|
||||
"""Print information on how the caches are accessed ("arc hits").
|
||||
"""
|
||||
|
||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
||||
all_accesses = int(arc_stats['hits'])+int(arc_stats['misses'])
|
||||
actual_hits = int(arc_stats['mfu_hits'])+int(arc_stats['mru_hits'])
|
||||
|
||||
prt_1('ARC total accesses (hits + misses):', f_hits(all_accesses))
|
||||
ta_todo = (('Cache hit ratio:', arc_stats['hits']),
|
||||
('Cache miss ratio:', arc_stats['misses']),
|
||||
('Actual hit ratio (MFU + MRU hits):', actual_hits))
|
||||
|
||||
for title, value in ta_todo:
|
||||
prt_i2(title, f_perc(value, all_accesses), f_hits(value))
|
||||
|
||||
dd_total = int(arc_stats['demand_data_hits']) +\
|
||||
int(arc_stats['demand_data_misses'])
|
||||
prt_i2('Data demand efficiency:',
|
||||
f_perc(arc_stats['demand_data_hits'], dd_total),
|
||||
f_hits(dd_total))
|
||||
|
||||
dp_total = int(arc_stats['prefetch_data_hits']) +\
|
||||
int(arc_stats['prefetch_data_misses'])
|
||||
prt_i2('Data prefetch efficiency:',
|
||||
f_perc(arc_stats['prefetch_data_hits'], dp_total),
|
||||
f_hits(dp_total))
|
||||
|
||||
known_hits = int(arc_stats['mfu_hits']) +\
|
||||
int(arc_stats['mru_hits']) +\
|
||||
int(arc_stats['mfu_ghost_hits']) +\
|
||||
int(arc_stats['mru_ghost_hits'])
|
||||
|
||||
anon_hits = int(arc_stats['hits'])-known_hits
|
||||
|
||||
print()
|
||||
print('Cache hits by cache type:')
|
||||
cl_todo = (('Most frequently used (MFU):', arc_stats['mfu_hits']),
|
||||
('Most recently used (MRU):', arc_stats['mru_hits']),
|
||||
('Most frequently used (MFU) ghost:',
|
||||
arc_stats['mfu_ghost_hits']),
|
||||
('Most recently used (MRU) ghost:',
|
||||
arc_stats['mru_ghost_hits']))
|
||||
|
||||
for title, value in cl_todo:
|
||||
prt_i2(title, f_perc(value, arc_stats['hits']), f_hits(value))
|
||||
|
||||
# For some reason, anon_hits can turn negative, which is weird. Until we
|
||||
# have figured out why this happens, we just hide the problem, following
|
||||
# the behavior of the original arc_summary.
|
||||
if anon_hits >= 0:
|
||||
prt_i2('Anonymously used:',
|
||||
f_perc(anon_hits, arc_stats['hits']), f_hits(anon_hits))
|
||||
|
||||
print()
|
||||
print('Cache hits by data type:')
|
||||
dt_todo = (('Demand data:', arc_stats['demand_data_hits']),
|
||||
('Demand prefetch data:', arc_stats['prefetch_data_hits']),
|
||||
('Demand metadata:', arc_stats['demand_metadata_hits']),
|
||||
('Demand prefetch metadata:',
|
||||
arc_stats['prefetch_metadata_hits']))
|
||||
|
||||
for title, value in dt_todo:
|
||||
prt_i2(title, f_perc(value, arc_stats['hits']), f_hits(value))
|
||||
|
||||
print()
|
||||
print('Cache misses by data type:')
|
||||
dm_todo = (('Demand data:', arc_stats['demand_data_misses']),
|
||||
('Demand prefetch data:',
|
||||
arc_stats['prefetch_data_misses']),
|
||||
('Demand metadata:', arc_stats['demand_metadata_misses']),
|
||||
('Demand prefetch metadata:',
|
||||
arc_stats['prefetch_metadata_misses']))
|
||||
|
||||
for title, value in dm_todo:
|
||||
prt_i2(title, f_perc(value, arc_stats['misses']), f_hits(value))
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def section_dmu(kstats_dict):
|
||||
"""Collect information on the DMU"""
|
||||
|
||||
zfetch_stats = isolate_section('zfetchstats', kstats_dict)
|
||||
|
||||
zfetch_access_total = int(zfetch_stats['hits'])+int(zfetch_stats['misses'])
|
||||
|
||||
prt_1('DMU prefetch efficiency:', f_hits(zfetch_access_total))
|
||||
prt_i2('Hit ratio:', f_perc(zfetch_stats['hits'], zfetch_access_total),
|
||||
f_hits(zfetch_stats['hits']))
|
||||
prt_i2('Miss ratio:', f_perc(zfetch_stats['misses'], zfetch_access_total),
|
||||
f_hits(zfetch_stats['misses']))
|
||||
print()
|
||||
|
||||
|
||||
def section_l2arc(kstats_dict):
|
||||
"""Collect information on L2ARC device if present. If not, tell user
|
||||
that we're skipping the section.
|
||||
"""
|
||||
|
||||
# The L2ARC statistics live in the same section as the normal ARC stuff
|
||||
arc_stats = isolate_section('arcstats', kstats_dict)
|
||||
|
||||
if arc_stats['l2_size'] == '0':
|
||||
print('L2ARC not detected, skipping section\n')
|
||||
return
|
||||
|
||||
l2_errors = int(arc_stats['l2_writes_error']) +\
|
||||
int(arc_stats['l2_cksum_bad']) +\
|
||||
int(arc_stats['l2_io_error'])
|
||||
|
||||
l2_access_total = int(arc_stats['l2_hits'])+int(arc_stats['l2_misses'])
|
||||
health = 'HEALTHY'
|
||||
|
||||
if l2_errors > 0:
|
||||
health = 'DEGRADED'
|
||||
|
||||
prt_1('L2ARC status:', health)
|
||||
|
||||
l2_todo = (('Low memory aborts:', 'l2_abort_lowmem'),
|
||||
('Free on write:', 'l2_free_on_write'),
|
||||
('R/W clashes:', 'l2_rw_clash'),
|
||||
('Bad checksums:', 'l2_cksum_bad'),
|
||||
('I/O errors:', 'l2_io_error'))
|
||||
|
||||
for title, value in l2_todo:
|
||||
prt_i1(title, f_hits(arc_stats[value]))
|
||||
|
||||
print()
|
||||
prt_1('L2ARC size (adaptive):', f_bytes(arc_stats['l2_size']))
|
||||
prt_i2('Compressed:', f_perc(arc_stats['l2_asize'], arc_stats['l2_size']),
|
||||
f_bytes(arc_stats['l2_asize']))
|
||||
prt_i2('Header size:',
|
||||
f_perc(arc_stats['l2_hdr_size'], arc_stats['l2_size']),
|
||||
f_bytes(arc_stats['l2_hdr_size']))
|
||||
|
||||
print()
|
||||
prt_1('L2ARC breakdown:', f_hits(l2_access_total))
|
||||
prt_i2('Hit ratio:',
|
||||
f_perc(arc_stats['l2_hits'], l2_access_total),
|
||||
f_hits(arc_stats['l2_hits']))
|
||||
prt_i2('Miss ratio:',
|
||||
f_perc(arc_stats['l2_misses'], l2_access_total),
|
||||
f_hits(arc_stats['l2_misses']))
|
||||
prt_i1('Feeds:', f_hits(arc_stats['l2_feeds']))
|
||||
|
||||
print()
|
||||
print('L2ARC writes:')
|
||||
|
||||
if arc_stats['l2_writes_done'] != arc_stats['l2_writes_sent']:
|
||||
prt_i2('Writes sent:', 'FAULTED', f_hits(arc_stats['l2_writes_sent']))
|
||||
prt_i2('Done ratio:',
|
||||
f_perc(arc_stats['l2_writes_done'],
|
||||
arc_stats['l2_writes_sent']),
|
||||
f_bytes(arc_stats['l2_writes_done']))
|
||||
prt_i2('Error ratio:',
|
||||
f_perc(arc_stats['l2_writes_error'],
|
||||
arc_stats['l2_writes_sent']),
|
||||
f_bytes(arc_stats['l2_writes_error']))
|
||||
else:
|
||||
prt_i2('Writes sent:', '100 %', f_bytes(arc_stats['l2_writes_sent']))
|
||||
|
||||
print()
|
||||
print('L2ARC evicts:')
|
||||
prt_i1('Lock retries:', f_hits(arc_stats['l2_evict_lock_retry']))
|
||||
prt_i1('Upon reading:', f_hits(arc_stats['l2_evict_reading']))
|
||||
print()
|
||||
|
||||
|
||||
def section_spl(*_):
|
||||
"""Print the SPL parameters, if requested with alternative format
|
||||
and/or descriptions. This does not use kstats.
|
||||
"""
|
||||
|
||||
spls = get_spl_tunables(SPL_PATH)
|
||||
keylist = sorted(spls.keys())
|
||||
print('Solaris Porting Layer (SPL):')
|
||||
|
||||
if ARGS.desc:
|
||||
descriptions = get_descriptions('spl')
|
||||
|
||||
for key in keylist:
|
||||
value = spls[key]
|
||||
|
||||
if ARGS.desc:
|
||||
try:
|
||||
print(INDENT+'#', descriptions[key])
|
||||
except KeyError:
|
||||
print(INDENT+'# (No description found)') # paranoid
|
||||
|
||||
print(format_raw_line(key, value))
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def section_tunables(*_):
|
||||
"""Print the tunables, if requested with alternative format and/or
|
||||
descriptions. This does not use kstasts.
|
||||
"""
|
||||
|
||||
tunables = get_spl_tunables(TUNABLES_PATH)
|
||||
keylist = sorted(tunables.keys())
|
||||
print('Tunables:')
|
||||
|
||||
if ARGS.desc:
|
||||
descriptions = get_descriptions('zfs')
|
||||
|
||||
for key in keylist:
|
||||
value = tunables[key]
|
||||
|
||||
if ARGS.desc:
|
||||
try:
|
||||
print(INDENT+'#', descriptions[key])
|
||||
except KeyError:
|
||||
print(INDENT+'# (No description found)') # paranoid
|
||||
|
||||
print(format_raw_line(key, value))
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def section_vdev(kstats_dict):
|
||||
"""Collect information on VDEV caches"""
|
||||
|
||||
# Currently [Nov 2017] the VDEV cache is disabled, because it is actually
|
||||
# harmful. When this is the case, we just skip the whole entry. See
|
||||
# https://github.com/zfsonlinux/zfs/blob/master/module/zfs/vdev_cache.c
|
||||
# for details
|
||||
tunables = get_spl_tunables(TUNABLES_PATH)
|
||||
|
||||
if tunables['zfs_vdev_cache_size'] == '0':
|
||||
print('VDEV cache disabled, skipping section\n')
|
||||
return
|
||||
|
||||
vdev_stats = isolate_section('vdev_cache_stats', kstats_dict)
|
||||
|
||||
vdev_cache_total = int(vdev_stats['hits']) +\
|
||||
int(vdev_stats['misses']) +\
|
||||
int(vdev_stats['delegations'])
|
||||
|
||||
prt_1('VDEV cache summary:', f_hits(vdev_cache_total))
|
||||
prt_i2('Hit ratio:', f_perc(vdev_stats['hits'], vdev_cache_total),
|
||||
f_hits(vdev_stats['hits']))
|
||||
prt_i2('Miss ratio:', f_perc(vdev_stats['misses'], vdev_cache_total),
|
||||
f_hits(vdev_stats['misses']))
|
||||
prt_i2('Delegations:', f_perc(vdev_stats['delegations'], vdev_cache_total),
|
||||
f_hits(vdev_stats['delegations']))
|
||||
print()
|
||||
|
||||
|
||||
def section_zil(kstats_dict):
|
||||
"""Collect information on the ZFS Intent Log. Some of the information
|
||||
taken from https://github.com/zfsonlinux/zfs/blob/master/include/sys/zil.h
|
||||
"""
|
||||
|
||||
zil_stats = isolate_section('zil', kstats_dict)
|
||||
|
||||
prt_1('ZIL committed transactions:',
|
||||
f_hits(zil_stats['zil_itx_count']))
|
||||
prt_i1('Commit requests:', f_hits(zil_stats['zil_commit_count']))
|
||||
prt_i1('Flushes to stable storage:',
|
||||
f_hits(zil_stats['zil_commit_writer_count']))
|
||||
prt_i2('Transactions to SLOG storage pool:',
|
||||
f_bytes(zil_stats['zil_itx_metaslab_slog_bytes']),
|
||||
f_hits(zil_stats['zil_itx_metaslab_slog_count']))
|
||||
prt_i2('Transactions to non-SLOG storage pool:',
|
||||
f_bytes(zil_stats['zil_itx_metaslab_normal_bytes']),
|
||||
f_hits(zil_stats['zil_itx_metaslab_normal_count']))
|
||||
print()
|
||||
|
||||
|
||||
section_calls = {'arc': section_arc,
|
||||
'archits': section_archits,
|
||||
'dmu': section_dmu,
|
||||
'l2arc': section_l2arc,
|
||||
'spl': section_spl,
|
||||
'tunables': section_tunables,
|
||||
'vdev': section_vdev,
|
||||
'zil': section_zil}
|
||||
|
||||
|
||||
def main():
|
||||
"""Run program. The options to draw a graph and to print all data raw are
|
||||
treated separately because they come with their own call.
|
||||
"""
|
||||
|
||||
kstats = get_kstats()
|
||||
|
||||
if ARGS.graph:
|
||||
draw_graph(kstats)
|
||||
sys.exit(0)
|
||||
|
||||
print_header()
|
||||
|
||||
if ARGS.raw:
|
||||
print_raw(kstats)
|
||||
|
||||
elif ARGS.section:
|
||||
|
||||
try:
|
||||
section_calls[ARGS.section](kstats)
|
||||
except KeyError:
|
||||
print('Error: Section "{0}" unknown'.format(ARGS.section))
|
||||
sys.exit(1)
|
||||
|
||||
elif ARGS.page:
|
||||
print('WARNING: Pages are deprecated, please use "--section"\n')
|
||||
|
||||
pages_to_calls = {1: 'arc',
|
||||
2: 'archits',
|
||||
3: 'l2arc',
|
||||
4: 'dmu',
|
||||
5: 'vdev',
|
||||
6: 'tunables'}
|
||||
|
||||
try:
|
||||
call = pages_to_calls[ARGS.page]
|
||||
except KeyError:
|
||||
print('Error: Page "{0}" not supported'.format(ARGS.page))
|
||||
sys.exit(1)
|
||||
else:
|
||||
section_calls[call](kstats)
|
||||
|
||||
else:
|
||||
# If no parameters were given, we print all sections. We might want to
|
||||
# change the sequence by hand
|
||||
calls = sorted(section_calls.keys())
|
||||
|
||||
for section in calls:
|
||||
section_calls[section](kstats)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+1
-13
@@ -1,13 +1 @@
|
||||
dist_bin_SCRIPTS = arcstat
|
||||
|
||||
#
|
||||
# The arcstat script is compatible 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/env python3|#!/usr/bin/env python2|' \
|
||||
$(DESTDIR)$(bindir)/arcstat
|
||||
endif
|
||||
dist_bin_SCRIPTS = arcstat.py
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Print out ZFS ARC Statistics exported via kstat(1)
|
||||
# For a definition of fields, or usage, use arctstat.pl -v
|
||||
@@ -42,8 +42,7 @@
|
||||
# @hdr is the array of fields that needs to be printed, so we
|
||||
# just iterate over this array and print the values using our pretty printer.
|
||||
#
|
||||
# This script must remain compatible with Python 2.6+ and Python 3.4+.
|
||||
#
|
||||
|
||||
|
||||
import sys
|
||||
import time
|
||||
@@ -72,7 +71,7 @@ cols = {
|
||||
"pm%": [3, 100, "Prefetch miss percentage"],
|
||||
"mhit": [4, 1000, "Metadata hits per second"],
|
||||
"mmis": [4, 1000, "Metadata misses per second"],
|
||||
"mread": [5, 1000, "Metadata accesses per second"],
|
||||
"mread": [4, 1000, "Metadata accesses per second"],
|
||||
"mh%": [3, 100, "Metadata hit percentage"],
|
||||
"mm%": [3, 100, "Metadata miss percentage"],
|
||||
"arcsz": [5, 1024, "ARC Size"],
|
||||
@@ -93,9 +92,6 @@ cols = {
|
||||
"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"],
|
||||
}
|
||||
|
||||
v = {}
|
||||
@@ -110,7 +106,7 @@ opfile = None
|
||||
sep = " " # Default separator is 2 spaces
|
||||
version = "0.4"
|
||||
l2exist = False
|
||||
cmd = ("Usage: arcstat [-hvx] [-f fields] [-o file] [-s string] [interval "
|
||||
cmd = ("Usage: arcstat.py [-hvx] [-f fields] [-o file] [-s string] [interval "
|
||||
"[count]]\n")
|
||||
cur = {}
|
||||
d = {}
|
||||
@@ -139,10 +135,10 @@ def usage():
|
||||
sys.stderr.write("\t -s : Override default field separator with custom "
|
||||
"character or string\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")
|
||||
sys.stderr.write("\tarcstat -v\n")
|
||||
sys.stderr.write("\tarcstat -f time,hit%,dh%,ph%,mh% 1\n")
|
||||
sys.stderr.write("\tarcstat.py -o /tmp/a.log 2 10\n")
|
||||
sys.stderr.write("\tarcstat.py -s \",\" -o /tmp/a.log 2 10\n")
|
||||
sys.stderr.write("\tarcstat.py -v\n")
|
||||
sys.stderr.write("\tarcstat.py -f time,hit%,dh%,ph%,mh% 1\n")
|
||||
sys.stderr.write("\n")
|
||||
|
||||
sys.exit(1)
|
||||
@@ -427,10 +423,6 @@ def calculate():
|
||||
v["l2size"] = cur["l2_size"]
|
||||
v["l2bytes"] = d["l2_read_bytes"] / sint
|
||||
|
||||
v["grow"] = 0 if cur["arc_no_grow"] else 1
|
||||
v["need"] = cur["arc_need_free"]
|
||||
v["free"] = cur["arc_sys_free"]
|
||||
|
||||
|
||||
def main():
|
||||
global sint
|
||||
@@ -1,13 +1 @@
|
||||
dist_bin_SCRIPTS = dbufstat
|
||||
|
||||
#
|
||||
# The dbufstat script is compatible 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/env python3|#!/usr/bin/env python2|' \
|
||||
$(DESTDIR)$(bindir)/dbufstat
|
||||
endif
|
||||
dist_bin_SCRIPTS = dbufstat.py
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Print out statistics for all cached dmu buffers. This information
|
||||
# is available through the dbufs kstat and may be post-processed as
|
||||
@@ -27,17 +27,14 @@
|
||||
# Copyright (C) 2013 Lawrence Livermore National Security, LLC.
|
||||
# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
#
|
||||
# This script must remain compatible with Python 2.6+ and Python 3.4+.
|
||||
#
|
||||
|
||||
import sys
|
||||
import getopt
|
||||
import errno
|
||||
import re
|
||||
|
||||
bhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize"]
|
||||
bxhdr = ["pool", "objset", "object", "level", "blkid", "offset", "dbsize",
|
||||
"meta", "state", "dbholds", "dbc", "list", "atype", "flags",
|
||||
"meta", "state", "dbholds", "list", "atype", "flags",
|
||||
"count", "asize", "access", "mru", "gmru", "mfu", "gmfu", "l2",
|
||||
"l2_dattr", "l2_asize", "l2_comp", "aholds", "dtype", "btype",
|
||||
"data_bs", "meta_bs", "bsize", "lvls", "dholds", "blocks", "dsize"]
|
||||
@@ -48,7 +45,7 @@ dxhdr = ["pool", "objset", "object", "dtype", "btype", "data_bs", "meta_bs",
|
||||
"bsize", "lvls", "dholds", "blocks", "dsize", "cached", "direct",
|
||||
"indirect", "bonus", "spill"]
|
||||
dincompat = ["level", "blkid", "offset", "dbsize", "meta", "state", "dbholds",
|
||||
"dbc", "list", "atype", "flags", "count", "asize", "access",
|
||||
"list", "atype", "flags", "count", "asize", "access",
|
||||
"mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
|
||||
"l2_comp", "aholds"]
|
||||
|
||||
@@ -56,7 +53,7 @@ thdr = ["pool", "objset", "dtype", "cached"]
|
||||
txhdr = ["pool", "objset", "dtype", "cached", "direct", "indirect",
|
||||
"bonus", "spill"]
|
||||
tincompat = ["object", "level", "blkid", "offset", "dbsize", "meta", "state",
|
||||
"dbc", "dbholds", "list", "atype", "flags", "count", "asize",
|
||||
"dbholds", "list", "atype", "flags", "count", "asize",
|
||||
"access", "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr",
|
||||
"l2_asize", "l2_comp", "aholds", "btype", "data_bs", "meta_bs",
|
||||
"bsize", "lvls", "dholds", "blocks", "dsize"]
|
||||
@@ -73,10 +70,9 @@ cols = {
|
||||
"meta": [4, -1, "is this buffer metadata?"],
|
||||
"state": [5, -1, "state of buffer (read, cached, etc)"],
|
||||
"dbholds": [7, 1000, "number of holds on buffer"],
|
||||
"dbc": [3, -1, "in dbuf cache"],
|
||||
"list": [4, -1, "which ARC list contains this buffer"],
|
||||
"atype": [7, -1, "ARC header type (data or metadata)"],
|
||||
"flags": [9, -1, "ARC read flags"],
|
||||
"flags": [8, -1, "ARC read flags"],
|
||||
"count": [5, -1, "ARC data count"],
|
||||
"asize": [7, 1024, "size of this ARC buffer"],
|
||||
"access": [10, -1, "time this ARC buffer was last accessed"],
|
||||
@@ -108,8 +104,8 @@ cols = {
|
||||
hdr = None
|
||||
xhdr = None
|
||||
sep = " " # Default separator is 2 spaces
|
||||
cmd = ("Usage: dbufstat [-bdhnrtvx] [-i file] [-f fields] [-o file] "
|
||||
"[-s string] [-F filter]\n")
|
||||
cmd = ("Usage: dbufstat.py [-bdhrtvx] [-i file] [-f fields] [-o file] "
|
||||
"[-s string]\n")
|
||||
raw = 0
|
||||
|
||||
|
||||
@@ -155,7 +151,6 @@ def usage():
|
||||
sys.stderr.write("\t -b : Print table of information for each dbuf\n")
|
||||
sys.stderr.write("\t -d : Print table of information for each dnode\n")
|
||||
sys.stderr.write("\t -h : Print this help message\n")
|
||||
sys.stderr.write("\t -n : Exclude header from output\n")
|
||||
sys.stderr.write("\t -r : Print raw values\n")
|
||||
sys.stderr.write("\t -t : Print table of information for each dnode type"
|
||||
"\n")
|
||||
@@ -167,13 +162,11 @@ 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 -F : Filter output by value or regex\n")
|
||||
sys.stderr.write("\nExamples:\n")
|
||||
sys.stderr.write("\tdbufstat -d -o /tmp/d.log\n")
|
||||
sys.stderr.write("\tdbufstat -t -s \",\" -o /tmp/t.log\n")
|
||||
sys.stderr.write("\tdbufstat -v\n")
|
||||
sys.stderr.write("\tdbufstat -d -f pool,object,objset,dsize,cached\n")
|
||||
sys.stderr.write("\tdbufstat -bx -F dbc=1,objset=54,pool=testpool\n")
|
||||
sys.stderr.write("\tdbufstat.py -d -o /tmp/d.log\n")
|
||||
sys.stderr.write("\tdbufstat.py -t -s \",\" -o /tmp/t.log\n")
|
||||
sys.stderr.write("\tdbufstat.py -v\n")
|
||||
sys.stderr.write("\tdbufstat.py -d -f pool,object,objset,dsize,cached\n")
|
||||
sys.stderr.write("\n")
|
||||
|
||||
sys.exit(1)
|
||||
@@ -235,8 +228,7 @@ def print_header():
|
||||
|
||||
|
||||
def get_typestring(t):
|
||||
ot_strings = [
|
||||
"DMU_OT_NONE",
|
||||
type_strings = ["DMU_OT_NONE",
|
||||
# general:
|
||||
"DMU_OT_OBJECT_DIRECTORY",
|
||||
"DMU_OT_OBJECT_ARRAY",
|
||||
@@ -299,39 +291,15 @@ def get_typestring(t):
|
||||
"DMU_OT_DEADLIST_HDR",
|
||||
"DMU_OT_DSL_CLONES",
|
||||
"DMU_OT_BPOBJ_SUBOBJ"]
|
||||
otn_strings = {
|
||||
0x80: "DMU_OTN_UINT8_DATA",
|
||||
0xc0: "DMU_OTN_UINT8_METADATA",
|
||||
0x81: "DMU_OTN_UINT16_DATA",
|
||||
0xc1: "DMU_OTN_UINT16_METADATA",
|
||||
0x82: "DMU_OTN_UINT32_DATA",
|
||||
0xc2: "DMU_OTN_UINT32_METADATA",
|
||||
0x83: "DMU_OTN_UINT64_DATA",
|
||||
0xc3: "DMU_OTN_UINT64_METADATA",
|
||||
0x84: "DMU_OTN_ZAP_DATA",
|
||||
0xc4: "DMU_OTN_ZAP_METADATA",
|
||||
0xa0: "DMU_OTN_UINT8_ENC_DATA",
|
||||
0xe0: "DMU_OTN_UINT8_ENC_METADATA",
|
||||
0xa1: "DMU_OTN_UINT16_ENC_DATA",
|
||||
0xe1: "DMU_OTN_UINT16_ENC_METADATA",
|
||||
0xa2: "DMU_OTN_UINT32_ENC_DATA",
|
||||
0xe2: "DMU_OTN_UINT32_ENC_METADATA",
|
||||
0xa3: "DMU_OTN_UINT64_ENC_DATA",
|
||||
0xe3: "DMU_OTN_UINT64_ENC_METADATA",
|
||||
0xa4: "DMU_OTN_ZAP_ENC_DATA",
|
||||
0xe4: "DMU_OTN_ZAP_ENC_METADATA"}
|
||||
|
||||
# If "-rr" option is used, don't convert to string representation
|
||||
if raw > 1:
|
||||
return "%i" % t
|
||||
|
||||
try:
|
||||
if t < len(ot_strings):
|
||||
return ot_strings[t]
|
||||
else:
|
||||
return otn_strings[t]
|
||||
except (IndexError, KeyError):
|
||||
return "(UNKNOWN)"
|
||||
return type_strings[t]
|
||||
except IndexError:
|
||||
return "%i" % t
|
||||
|
||||
|
||||
def get_compstring(c):
|
||||
@@ -416,32 +384,12 @@ def update_dict(d, k, line, labels):
|
||||
return d
|
||||
|
||||
|
||||
def skip_line(vals, filters):
|
||||
'''
|
||||
Determines if a line should be skipped during printing
|
||||
based on a set of filters
|
||||
'''
|
||||
if len(filters) == 0:
|
||||
return False
|
||||
|
||||
for key in vals:
|
||||
if key in filters:
|
||||
val = prettynum(cols[key][0], cols[key][1], vals[key]).strip()
|
||||
# we want a full match here
|
||||
if re.match("(?:" + filters[key] + r")\Z", val) is None:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def print_dict(d, filters, noheader):
|
||||
if not noheader:
|
||||
print_header()
|
||||
def print_dict(d):
|
||||
print_header()
|
||||
for pool in list(d.keys()):
|
||||
for objset in list(d[pool].keys()):
|
||||
for v in list(d[pool][objset].values()):
|
||||
if not skip_line(v, filters):
|
||||
print_values(v)
|
||||
print_values(v)
|
||||
|
||||
|
||||
def dnodes_build_dict(filehandle):
|
||||
@@ -482,7 +430,7 @@ def types_build_dict(filehandle):
|
||||
return types
|
||||
|
||||
|
||||
def buffers_print_all(filehandle, filters, noheader):
|
||||
def buffers_print_all(filehandle):
|
||||
labels = dict()
|
||||
|
||||
# First 3 lines are header information, skip the first two
|
||||
@@ -493,14 +441,11 @@ def buffers_print_all(filehandle, filters, noheader):
|
||||
for i, v in enumerate(next(filehandle).split()):
|
||||
labels[v] = i
|
||||
|
||||
if not noheader:
|
||||
print_header()
|
||||
print_header()
|
||||
|
||||
# The rest of the file is buffer information
|
||||
for line in filehandle:
|
||||
vals = parse_line(line.split(), labels)
|
||||
if not skip_line(vals, filters):
|
||||
print_values(vals)
|
||||
print_values(parse_line(line.split(), labels))
|
||||
|
||||
|
||||
def main():
|
||||
@@ -517,13 +462,11 @@ def main():
|
||||
tflag = False
|
||||
vflag = False
|
||||
xflag = False
|
||||
nflag = False
|
||||
filters = dict()
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
sys.argv[1:],
|
||||
"bdf:hi:o:rs:tvxF:n",
|
||||
"bdf:hi:o:rs:tvx",
|
||||
[
|
||||
"buffers",
|
||||
"dnodes",
|
||||
@@ -534,8 +477,7 @@ def main():
|
||||
"separator",
|
||||
"types",
|
||||
"verbose",
|
||||
"extended",
|
||||
"filter"
|
||||
"extended"
|
||||
]
|
||||
)
|
||||
except getopt.error:
|
||||
@@ -565,35 +507,6 @@ def main():
|
||||
vflag = True
|
||||
if opt in ('-x', '--extended'):
|
||||
xflag = True
|
||||
if opt in ('-n', '--noheader'):
|
||||
nflag = True
|
||||
if opt in ('-F', '--filter'):
|
||||
fils = [x.strip() for x in arg.split(",")]
|
||||
|
||||
for fil in fils:
|
||||
f = [x.strip() for x in fil.split("=")]
|
||||
|
||||
if len(f) != 2:
|
||||
sys.stderr.write("Invalid filter '%s'.\n" % fil)
|
||||
sys.exit(1)
|
||||
|
||||
if f[0] not in cols:
|
||||
sys.stderr.write("Invalid field '%s' in filter.\n" % f[0])
|
||||
sys.exit(1)
|
||||
|
||||
if f[0] in filters:
|
||||
sys.stderr.write("Field '%s' specified multiple times in "
|
||||
"filter.\n" % f[0])
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
re.compile("(?:" + f[1] + r")\Z")
|
||||
except re.error:
|
||||
sys.stderr.write("Invalid regex for field '%s' in "
|
||||
"filter.\n" % f[0])
|
||||
sys.exit(1)
|
||||
|
||||
filters[f[0]] = f[1]
|
||||
|
||||
if hflag or (xflag and desired_cols):
|
||||
usage()
|
||||
@@ -656,13 +569,13 @@ def main():
|
||||
sys.exit(1)
|
||||
|
||||
if bflag:
|
||||
buffers_print_all(sys.stdin, filters, nflag)
|
||||
buffers_print_all(sys.stdin)
|
||||
|
||||
if dflag:
|
||||
print_dict(dnodes_build_dict(sys.stdin), filters, nflag)
|
||||
print_dict(dnodes_build_dict(sys.stdin))
|
||||
|
||||
if tflag:
|
||||
print_dict(types_build_dict(sys.stdin), filters, nflag)
|
||||
print_dict(types_build_dict(sys.stdin))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -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'.
|
||||
|
||||
@@ -18,4 +18,7 @@ mount_zfs_SOURCES = \
|
||||
|
||||
mount_zfs_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
@@ -31,11 +31,9 @@
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libzfs.h>
|
||||
#include <libzutil.h>
|
||||
#include <locale.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define ZS_COMMENT 0x00000000 /* comment */
|
||||
#define ZS_ZFSUTIL 0x00000001 /* caller is zfs(8) */
|
||||
@@ -489,7 +487,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
# Includes kernel code, generate warnings for large stack frames
|
||||
AM_CFLAGS += $(FRAME_LARGER_THAN)
|
||||
|
||||
# Unconditionally enable ASSERTs
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG
|
||||
AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN)
|
||||
AM_CPPFLAGS += -DDEBUG
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
@@ -18,6 +15,8 @@ raidz_test_SOURCES = \
|
||||
raidz_bench.c
|
||||
|
||||
raidz_test_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la
|
||||
|
||||
raidz_test_LDADD += -lm -ldl
|
||||
|
||||
@@ -702,8 +702,10 @@ run_sweep(void)
|
||||
opts->rto_dsize = size_v[s];
|
||||
opts->rto_v = 0; /* be quiet */
|
||||
|
||||
VERIFY3P(thread_create(NULL, 0, sweep_thread, (void *) opts,
|
||||
0, NULL, TS_RUN, defclsyspri), !=, NULL);
|
||||
VERIFY3P(zk_thread_create(NULL, 0,
|
||||
(thread_func_t)sweep_thread,
|
||||
(void *) opts, 0, NULL, TS_RUN, 0,
|
||||
PTHREAD_CREATE_JOINABLE), !=, NULL);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
+1
-1
@@ -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"]
|
||||
|
||||
+6
-5
@@ -1,7 +1,6 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
# Unconditionally enable debugging for zdb
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG
|
||||
AM_CPPFLAGS += -DDEBUG
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
@@ -11,9 +10,11 @@ sbin_PROGRAMS = zdb
|
||||
|
||||
zdb_SOURCES = \
|
||||
zdb.c \
|
||||
zdb_il.c \
|
||||
zdb.h
|
||||
zdb_il.c
|
||||
|
||||
zdb_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
+401
-2224
File diff suppressed because it is too large
Load Diff
+66
-92
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013, 2017 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, 2016 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -42,14 +42,11 @@
|
||||
#include <sys/resource.h>
|
||||
#include <sys/zil.h>
|
||||
#include <sys/zil_impl.h>
|
||||
#include <sys/spa_impl.h>
|
||||
#include <sys/abd.h>
|
||||
|
||||
#include "zdb.h"
|
||||
|
||||
extern uint8_t dump_opt[256];
|
||||
|
||||
static char tab_prefix[4] = "\t\t\t";
|
||||
static char prefix[4] = "\t\t\t";
|
||||
|
||||
static void
|
||||
print_log_bp(const blkptr_t *bp, const char *prefix)
|
||||
@@ -62,9 +59,8 @@ print_log_bp(const blkptr_t *bp, const char *prefix)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_create(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_create(zilog_t *zilog, int txtype, lr_create_t *lr)
|
||||
{
|
||||
lr_create_t *lr = arg;
|
||||
time_t crtime = lr->lr_crtime[0];
|
||||
char *name, *link;
|
||||
lr_attr_t *lrattr;
|
||||
@@ -79,55 +75,49 @@ zil_prt_rec_create(zilog_t *zilog, int txtype, void *arg)
|
||||
|
||||
if (txtype == TX_SYMLINK) {
|
||||
link = name + strlen(name) + 1;
|
||||
(void) printf("%s%s -> %s\n", tab_prefix, name, link);
|
||||
(void) printf("%s%s -> %s\n", prefix, name, link);
|
||||
} else if (txtype != TX_MKXATTR) {
|
||||
(void) printf("%s%s\n", tab_prefix, name);
|
||||
(void) printf("%s%s\n", prefix, name);
|
||||
}
|
||||
|
||||
(void) printf("%s%s", tab_prefix, ctime(&crtime));
|
||||
(void) printf("%sdoid %llu, foid %llu, slots %llu, mode %llo\n",
|
||||
tab_prefix, (u_longlong_t)lr->lr_doid,
|
||||
(void) printf("%s%s", prefix, ctime(&crtime));
|
||||
(void) printf("%sdoid %llu, foid %llu, slots %llu, mode %llo\n", prefix,
|
||||
(u_longlong_t)lr->lr_doid,
|
||||
(u_longlong_t)LR_FOID_GET_OBJ(lr->lr_foid),
|
||||
(u_longlong_t)LR_FOID_GET_SLOTS(lr->lr_foid),
|
||||
(longlong_t)lr->lr_mode);
|
||||
(void) printf("%suid %llu, gid %llu, gen %llu, rdev 0x%llx\n",
|
||||
tab_prefix,
|
||||
(void) printf("%suid %llu, gid %llu, gen %llu, rdev 0x%llx\n", prefix,
|
||||
(u_longlong_t)lr->lr_uid, (u_longlong_t)lr->lr_gid,
|
||||
(u_longlong_t)lr->lr_gen, (u_longlong_t)lr->lr_rdev);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_remove(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_remove(zilog_t *zilog, int txtype, lr_remove_t *lr)
|
||||
{
|
||||
lr_remove_t *lr = arg;
|
||||
|
||||
(void) printf("%sdoid %llu, name %s\n", tab_prefix,
|
||||
(void) printf("%sdoid %llu, name %s\n", prefix,
|
||||
(u_longlong_t)lr->lr_doid, (char *)(lr + 1));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_link(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_link(zilog_t *zilog, int txtype, lr_link_t *lr)
|
||||
{
|
||||
lr_link_t *lr = arg;
|
||||
|
||||
(void) printf("%sdoid %llu, link_obj %llu, name %s\n", tab_prefix,
|
||||
(void) printf("%sdoid %llu, link_obj %llu, name %s\n", prefix,
|
||||
(u_longlong_t)lr->lr_doid, (u_longlong_t)lr->lr_link_obj,
|
||||
(char *)(lr + 1));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_rename(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_rename(zilog_t *zilog, int txtype, lr_rename_t *lr)
|
||||
{
|
||||
lr_rename_t *lr = arg;
|
||||
char *snm = (char *)(lr + 1);
|
||||
char *tnm = snm + strlen(snm) + 1;
|
||||
|
||||
(void) printf("%ssdoid %llu, tdoid %llu\n", tab_prefix,
|
||||
(void) printf("%ssdoid %llu, tdoid %llu\n", prefix,
|
||||
(u_longlong_t)lr->lr_sdoid, (u_longlong_t)lr->lr_tdoid);
|
||||
(void) printf("%ssrc %s tgt %s\n", tab_prefix, snm, tnm);
|
||||
(void) printf("%ssrc %s tgt %s\n", prefix, snm, tnm);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -135,8 +125,9 @@ static int
|
||||
zil_prt_rec_write_cb(void *data, size_t len, void *unused)
|
||||
{
|
||||
char *cdata = data;
|
||||
int i;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (isprint(*cdata))
|
||||
(void) printf("%c ", *cdata);
|
||||
else
|
||||
@@ -148,16 +139,15 @@ zil_prt_rec_write_cb(void *data, size_t len, void *unused)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_write(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
|
||||
{
|
||||
lr_write_t *lr = arg;
|
||||
abd_t *data;
|
||||
blkptr_t *bp = &lr->lr_blkptr;
|
||||
zbookmark_phys_t zb;
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
int error;
|
||||
|
||||
(void) printf("%sfoid %llu, offset %llx, length %llx\n", tab_prefix,
|
||||
(void) printf("%sfoid %llu, offset %llx, length %llx\n", prefix,
|
||||
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_offset,
|
||||
(u_longlong_t)lr->lr_length);
|
||||
|
||||
@@ -165,21 +155,20 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, void *arg)
|
||||
return;
|
||||
|
||||
if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
|
||||
(void) printf("%shas blkptr, %s\n", tab_prefix,
|
||||
(void) printf("%shas blkptr, %s\n", prefix,
|
||||
!BP_IS_HOLE(bp) &&
|
||||
bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa) ?
|
||||
bp->blk_birth >= spa_first_txg(zilog->zl_spa) ?
|
||||
"will claim" : "won't claim");
|
||||
print_log_bp(bp, tab_prefix);
|
||||
print_log_bp(bp, prefix);
|
||||
|
||||
if (BP_IS_HOLE(bp)) {
|
||||
(void) printf("\t\t\tLSIZE 0x%llx\n",
|
||||
(u_longlong_t)BP_GET_LSIZE(bp));
|
||||
(void) printf("%s<hole>\n", tab_prefix);
|
||||
(void) printf("%s<hole>\n", prefix);
|
||||
return;
|
||||
}
|
||||
if (bp->blk_birth < zilog->zl_header->zh_claim_txg) {
|
||||
(void) printf("%s<block already committed>\n",
|
||||
tab_prefix);
|
||||
(void) printf("%s<block already committed>\n", prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -199,7 +188,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, void *arg)
|
||||
abd_copy_from_buf(data, lr + 1, lr->lr_length);
|
||||
}
|
||||
|
||||
(void) printf("%s", tab_prefix);
|
||||
(void) printf("%s", prefix);
|
||||
(void) abd_iterate_func(data,
|
||||
0, MIN(lr->lr_length, (verbose < 6 ? 20 : SPA_MAXBLOCKSIZE)),
|
||||
zil_prt_rec_write_cb, NULL);
|
||||
@@ -211,55 +200,52 @@ out:
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_truncate(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_truncate(zilog_t *zilog, int txtype, lr_truncate_t *lr)
|
||||
{
|
||||
lr_truncate_t *lr = arg;
|
||||
|
||||
(void) printf("%sfoid %llu, offset 0x%llx, length 0x%llx\n", tab_prefix,
|
||||
(void) printf("%sfoid %llu, offset 0x%llx, length 0x%llx\n", prefix,
|
||||
(u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset,
|
||||
(u_longlong_t)lr->lr_length);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_setattr(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_setattr(zilog_t *zilog, int txtype, lr_setattr_t *lr)
|
||||
{
|
||||
lr_setattr_t *lr = arg;
|
||||
time_t atime = (time_t)lr->lr_atime[0];
|
||||
time_t mtime = (time_t)lr->lr_mtime[0];
|
||||
|
||||
(void) printf("%sfoid %llu, mask 0x%llx\n", tab_prefix,
|
||||
(void) printf("%sfoid %llu, mask 0x%llx\n", prefix,
|
||||
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_mask);
|
||||
|
||||
if (lr->lr_mask & AT_MODE) {
|
||||
(void) printf("%sAT_MODE %llo\n", tab_prefix,
|
||||
(void) printf("%sAT_MODE %llo\n", prefix,
|
||||
(longlong_t)lr->lr_mode);
|
||||
}
|
||||
|
||||
if (lr->lr_mask & AT_UID) {
|
||||
(void) printf("%sAT_UID %llu\n", tab_prefix,
|
||||
(void) printf("%sAT_UID %llu\n", prefix,
|
||||
(u_longlong_t)lr->lr_uid);
|
||||
}
|
||||
|
||||
if (lr->lr_mask & AT_GID) {
|
||||
(void) printf("%sAT_GID %llu\n", tab_prefix,
|
||||
(void) printf("%sAT_GID %llu\n", prefix,
|
||||
(u_longlong_t)lr->lr_gid);
|
||||
}
|
||||
|
||||
if (lr->lr_mask & AT_SIZE) {
|
||||
(void) printf("%sAT_SIZE %llu\n", tab_prefix,
|
||||
(void) printf("%sAT_SIZE %llu\n", prefix,
|
||||
(u_longlong_t)lr->lr_size);
|
||||
}
|
||||
|
||||
if (lr->lr_mask & AT_ATIME) {
|
||||
(void) printf("%sAT_ATIME %llu.%09llu %s", tab_prefix,
|
||||
(void) printf("%sAT_ATIME %llu.%09llu %s", prefix,
|
||||
(u_longlong_t)lr->lr_atime[0],
|
||||
(u_longlong_t)lr->lr_atime[1],
|
||||
ctime(&atime));
|
||||
}
|
||||
|
||||
if (lr->lr_mask & AT_MTIME) {
|
||||
(void) printf("%sAT_MTIME %llu.%09llu %s", tab_prefix,
|
||||
(void) printf("%sAT_MTIME %llu.%09llu %s", prefix,
|
||||
(u_longlong_t)lr->lr_mtime[0],
|
||||
(u_longlong_t)lr->lr_mtime[1],
|
||||
ctime(&mtime));
|
||||
@@ -268,43 +254,41 @@ zil_prt_rec_setattr(zilog_t *zilog, int txtype, void *arg)
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
zil_prt_rec_acl(zilog_t *zilog, int txtype, void *arg)
|
||||
zil_prt_rec_acl(zilog_t *zilog, int txtype, lr_acl_t *lr)
|
||||
{
|
||||
lr_acl_t *lr = arg;
|
||||
|
||||
(void) printf("%sfoid %llu, aclcnt %llu\n", tab_prefix,
|
||||
(void) printf("%sfoid %llu, aclcnt %llu\n", prefix,
|
||||
(u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_aclcnt);
|
||||
}
|
||||
|
||||
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;
|
||||
char *zri_name;
|
||||
uint64_t zri_count;
|
||||
} zil_rec_info_t;
|
||||
|
||||
static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
||||
{.zri_print = NULL, .zri_name = "Total "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKXATTR "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_SYMLINK "},
|
||||
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_REMOVE "},
|
||||
{.zri_print = zil_prt_rec_remove, .zri_name = "TX_RMDIR "},
|
||||
{.zri_print = zil_prt_rec_link, .zri_name = "TX_LINK "},
|
||||
{.zri_print = zil_prt_rec_rename, .zri_name = "TX_RENAME "},
|
||||
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE "},
|
||||
{.zri_print = zil_prt_rec_truncate, .zri_name = "TX_TRUNCATE "},
|
||||
{.zri_print = zil_prt_rec_setattr, .zri_name = "TX_SETATTR "},
|
||||
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_V0 "},
|
||||
{.zri_print = zil_prt_rec_acl, .zri_name = "TX_ACL_ACL "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE_ACL "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE_ATTR "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_CREATE_ACL_ATTR "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ACL "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ATTR "},
|
||||
{.zri_print = zil_prt_rec_create, .zri_name = "TX_MKDIR_ACL_ATTR "},
|
||||
{.zri_print = zil_prt_rec_write, .zri_name = "TX_WRITE2 "},
|
||||
{ NULL, "Total " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKXATTR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_SYMLINK " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_remove, "TX_REMOVE " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_remove, "TX_RMDIR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_link, "TX_LINK " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_rename, "TX_RENAME " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_write, "TX_WRITE " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_truncate, "TX_TRUNCATE " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_setattr, "TX_SETATTR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_acl, "TX_ACL_V0 " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_acl, "TX_ACL_ACL " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE_ACL " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE_ATTR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_CREATE_ACL_ATTR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR_ACL " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR_ATTR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_create, "TX_MKDIR_ACL_ATTR " },
|
||||
{ (zil_prt_rec_func_t)zil_prt_rec_write, "TX_WRITE2 " },
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -327,13 +311,8 @@ print_log_record(zilog_t *zilog, lr_t *lr, void *arg, uint64_t claim_txg)
|
||||
(u_longlong_t)lr->lrc_txg,
|
||||
(u_longlong_t)lr->lrc_seq);
|
||||
|
||||
if (txtype && verbose >= 3) {
|
||||
if (!zilog->zl_os->os_encrypted) {
|
||||
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
|
||||
} else {
|
||||
(void) printf("%s(encrypted)\n", tab_prefix);
|
||||
}
|
||||
}
|
||||
if (txtype && verbose >= 3)
|
||||
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
|
||||
|
||||
zil_rec_info[txtype].zri_count++;
|
||||
zil_rec_info[0].zri_count++;
|
||||
@@ -347,7 +326,7 @@ 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']);
|
||||
const char *claim;
|
||||
char *claim;
|
||||
|
||||
if (verbose <= 3)
|
||||
return (0);
|
||||
@@ -362,7 +341,7 @@ print_log_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
|
||||
|
||||
if (claim_txg != 0)
|
||||
claim = "already claimed";
|
||||
else if (bp->blk_birth >= spa_min_claim_txg(zilog->zl_spa))
|
||||
else if (bp->blk_birth >= spa_first_txg(zilog->zl_spa))
|
||||
claim = "will claim";
|
||||
else
|
||||
claim = "won't claim";
|
||||
@@ -376,7 +355,7 @@ print_log_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
|
||||
static void
|
||||
print_log_stats(int verbose)
|
||||
{
|
||||
unsigned i, w, p10;
|
||||
int i, w, p10;
|
||||
|
||||
if (verbose > 3)
|
||||
(void) printf("\n");
|
||||
@@ -417,15 +396,10 @@ dump_intent_log(zilog_t *zilog)
|
||||
for (i = 0; i < TX_MAX_TYPE; i++)
|
||||
zil_rec_info[i].zri_count = 0;
|
||||
|
||||
/* see comment in zil_claim() or zil_check_log_chain() */
|
||||
if (zilog->zl_spa->spa_uberblock.ub_checkpoint_txg != 0 &&
|
||||
zh->zh_claim_txg == 0)
|
||||
return;
|
||||
|
||||
if (verbose >= 2) {
|
||||
(void) printf("\n");
|
||||
(void) zil_parse(zilog, print_log_block, print_log_record, NULL,
|
||||
zh->zh_claim_txg, B_FALSE);
|
||||
zh->zh_claim_txg);
|
||||
print_log_stats(verbose);
|
||||
}
|
||||
}
|
||||
|
||||
+51
-5
@@ -1,11 +1,11 @@
|
||||
SUBDIRS = zed.d
|
||||
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
EXTRA_DIST = zed.d/README
|
||||
|
||||
sbin_PROGRAMS = zed
|
||||
|
||||
ZED_SRC = \
|
||||
@@ -40,9 +40,55 @@ FMA_SRC = \
|
||||
zed_SOURCES = $(ZED_SRC) $(FMA_SRC)
|
||||
|
||||
zed_LDADD = \
|
||||
$(top_builddir)/lib/libavl/libavl.la \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libspl/libspl.la \
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
zed_LDADD += -lrt
|
||||
zed_LDFLAGS = -pthread
|
||||
zed_LDFLAGS = -lrt -pthread
|
||||
|
||||
zedconfdir = $(sysconfdir)/zfs/zed.d
|
||||
|
||||
dist_zedconf_DATA = \
|
||||
zed.d/zed-functions.sh \
|
||||
zed.d/zed.rc
|
||||
|
||||
zedexecdir = $(libexecdir)/zfs/zed.d
|
||||
|
||||
dist_zedexec_SCRIPTS = \
|
||||
zed.d/all-debug.sh \
|
||||
zed.d/all-syslog.sh \
|
||||
zed.d/data-notify.sh \
|
||||
zed.d/generic-notify.sh \
|
||||
zed.d/resilver_finish-notify.sh \
|
||||
zed.d/scrub_finish-notify.sh \
|
||||
zed.d/statechange-led.sh \
|
||||
zed.d/statechange-notify.sh \
|
||||
zed.d/vdev_clear-led.sh \
|
||||
zed.d/vdev_attach-led.sh \
|
||||
zed.d/pool_import-led.sh \
|
||||
zed.d/resilver_finish-start-scrub.sh
|
||||
|
||||
zedconfdefaults = \
|
||||
all-syslog.sh \
|
||||
data-notify.sh \
|
||||
resilver_finish-notify.sh \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
resilver_finish-start-scrub.sh
|
||||
|
||||
install-data-hook:
|
||||
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
||||
for f in $(zedconfdefaults); do \
|
||||
test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \
|
||||
-L "$(DESTDIR)$(zedconfdir)/$${f}" || \
|
||||
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
||||
done
|
||||
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements the minimal FMD module API required to support the
|
||||
* This file imlements the minimal FMD module API required to support the
|
||||
* fault logic modules in ZED. This support includes module registration,
|
||||
* 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));
|
||||
|
||||
+38
-92
@@ -12,7 +12,6 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016, Intel Corporation.
|
||||
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
|
||||
*/
|
||||
|
||||
#include <libnvpair.h>
|
||||
@@ -54,25 +53,13 @@ pthread_t g_agents_tid;
|
||||
libzfs_handle_t *g_zfs_hdl;
|
||||
|
||||
/* guid search data */
|
||||
typedef enum device_type {
|
||||
DEVICE_TYPE_L2ARC, /* l2arc device */
|
||||
DEVICE_TYPE_SPARE, /* spare device */
|
||||
DEVICE_TYPE_PRIMARY /* any primary pool storage device */
|
||||
} device_type_t;
|
||||
|
||||
typedef struct guid_search {
|
||||
uint64_t gs_pool_guid;
|
||||
uint64_t gs_vdev_guid;
|
||||
char *gs_devid;
|
||||
device_type_t gs_vdev_type;
|
||||
uint64_t gs_vdev_expandtime; /* vdev expansion time */
|
||||
} guid_search_t;
|
||||
|
||||
/*
|
||||
* Walks the vdev tree recursively looking for a matching devid.
|
||||
* Returns B_TRUE as soon as a matching device is found, B_FALSE otherwise.
|
||||
*/
|
||||
static boolean_t
|
||||
static void
|
||||
zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||
{
|
||||
guid_search_t *gsp = arg;
|
||||
@@ -85,48 +72,19 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||
*/
|
||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
||||
gsp->gs_vdev_type = DEVICE_TYPE_PRIMARY;
|
||||
return (B_TRUE);
|
||||
}
|
||||
}
|
||||
for (c = 0; c < children; c++)
|
||||
zfs_agent_iter_vdev(zhp, child[c], gsp);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Iterate over any spares and cache devices
|
||||
* On a devid match, grab the vdev guid
|
||||
*/
|
||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_SPARES,
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
||||
gsp->gs_vdev_type = DEVICE_TYPE_L2ARC;
|
||||
return (B_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_L2CACHE,
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
if (zfs_agent_iter_vdev(zhp, child[c], gsp)) {
|
||||
gsp->gs_vdev_type = DEVICE_TYPE_SPARE;
|
||||
return (B_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* On a devid match, grab the vdev guid and expansion time, if any.
|
||||
*/
|
||||
if (gsp->gs_devid != NULL &&
|
||||
if ((gsp->gs_vdev_guid == 0) &&
|
||||
(nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID, &path) == 0) &&
|
||||
(strcmp(gsp->gs_devid, path) == 0)) {
|
||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
|
||||
&gsp->gs_vdev_guid);
|
||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_EXPANSION_TIME,
|
||||
&gsp->gs_vdev_expandtime);
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -141,7 +99,7 @@ zfs_agent_iter_pool(zpool_handle_t *zhp, void *arg)
|
||||
if ((config = zpool_get_config(zhp, NULL)) != NULL) {
|
||||
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvl) == 0) {
|
||||
(void) zfs_agent_iter_vdev(zhp, nvl, gsp);
|
||||
zfs_agent_iter_vdev(zhp, nvl, gsp);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -190,8 +148,6 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||
struct timeval tv;
|
||||
int64_t tod[2];
|
||||
uint64_t pool_guid = 0, vdev_guid = 0;
|
||||
guid_search_t search = { 0 };
|
||||
device_type_t devtype = DEVICE_TYPE_PRIMARY;
|
||||
|
||||
class = "resource.fs.zfs.removed";
|
||||
subclass = "";
|
||||
@@ -200,55 +156,30 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||
(void) nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID, &pool_guid);
|
||||
(void) nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &vdev_guid);
|
||||
|
||||
(void) gettimeofday(&tv, NULL);
|
||||
tod[0] = tv.tv_sec;
|
||||
tod[1] = tv.tv_usec;
|
||||
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
|
||||
|
||||
/*
|
||||
* For multipath, spare and l2arc devices ZFS_EV_VDEV_GUID or
|
||||
* ZFS_EV_POOL_GUID may be missing so find them.
|
||||
* For multipath, ZFS_EV_VDEV_GUID is missing so find it.
|
||||
*/
|
||||
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
||||
&search.gs_devid);
|
||||
(void) zpool_iter(g_zfs_hdl, zfs_agent_iter_pool, &search);
|
||||
pool_guid = search.gs_pool_guid;
|
||||
vdev_guid = search.gs_vdev_guid;
|
||||
devtype = search.gs_vdev_type;
|
||||
if (vdev_guid == 0) {
|
||||
guid_search_t search = { 0 };
|
||||
|
||||
/*
|
||||
* We want to avoid reporting "remove" events coming from
|
||||
* libudev for VDEVs which were expanded recently (10s) and
|
||||
* avoid activating spares in response to partitions being
|
||||
* deleted and created in rapid succession.
|
||||
*/
|
||||
if (search.gs_vdev_expandtime != 0 &&
|
||||
search.gs_vdev_expandtime + 10 > tv.tv_sec) {
|
||||
zed_log_msg(LOG_INFO, "agent post event: ignoring '%s' "
|
||||
"for recently expanded device '%s'", EC_DEV_REMOVE,
|
||||
search.gs_devid);
|
||||
goto out;
|
||||
(void) nvlist_lookup_string(nvl, DEV_IDENTIFIER,
|
||||
&search.gs_devid);
|
||||
|
||||
(void) zpool_iter(g_zfs_hdl, zfs_agent_iter_pool,
|
||||
&search);
|
||||
pool_guid = search.gs_pool_guid;
|
||||
vdev_guid = search.gs_vdev_guid;
|
||||
}
|
||||
|
||||
(void) nvlist_add_uint64(payload,
|
||||
FM_EREPORT_PAYLOAD_ZFS_POOL_GUID, pool_guid);
|
||||
(void) nvlist_add_uint64(payload,
|
||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, vdev_guid);
|
||||
switch (devtype) {
|
||||
case DEVICE_TYPE_L2ARC:
|
||||
(void) nvlist_add_string(payload,
|
||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
|
||||
VDEV_TYPE_L2CACHE);
|
||||
break;
|
||||
case DEVICE_TYPE_SPARE:
|
||||
(void) nvlist_add_string(payload,
|
||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE, VDEV_TYPE_SPARE);
|
||||
break;
|
||||
case DEVICE_TYPE_PRIMARY:
|
||||
(void) nvlist_add_string(payload,
|
||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE, VDEV_TYPE_DISK);
|
||||
break;
|
||||
}
|
||||
|
||||
(void) gettimeofday(&tv, NULL);
|
||||
tod[0] = tv.tv_sec;
|
||||
tod[1] = tv.tv_usec;
|
||||
(void) nvlist_add_int64_array(payload, FM_EREPORT_TIME, tod, 2);
|
||||
|
||||
zed_log_msg(LOG_INFO, "agent post event: mapping '%s' to '%s'",
|
||||
EC_DEV_REMOVE, class);
|
||||
@@ -262,7 +193,6 @@ zfs_agent_post_event(const char *class, const char *subclass, nvlist_t *nvl)
|
||||
list_insert_tail(&agent_events, event);
|
||||
(void) pthread_mutex_unlock(&agent_lock);
|
||||
|
||||
out:
|
||||
(void) pthread_cond_signal(&agent_cond);
|
||||
}
|
||||
|
||||
@@ -420,3 +350,19 @@ zfs_agent_fini(void)
|
||||
|
||||
g_zfs_hdl = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* In ZED context, all the FMA agents run in the same thread
|
||||
* and do not require a unique libzfs instance. Modules should
|
||||
* use these stubs.
|
||||
*/
|
||||
libzfs_handle_t *
|
||||
__libzfs_init(void)
|
||||
{
|
||||
return (g_zfs_hdl);
|
||||
}
|
||||
|
||||
void
|
||||
__libzfs_fini(libzfs_handle_t *hdl)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -39,6 +39,13 @@ extern int zfs_slm_init(void);
|
||||
extern void zfs_slm_fini(void);
|
||||
extern void zfs_slm_event(const char *, const char *, nvlist_t *);
|
||||
|
||||
/*
|
||||
* In ZED context, all the FMA agents run in the same thread
|
||||
* and do not require a unique libzfs instance.
|
||||
*/
|
||||
extern libzfs_handle_t *__libzfs_init(void);
|
||||
extern void __libzfs_fini(libzfs_handle_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <libuutil.h>
|
||||
#include <libzfs.h>
|
||||
@@ -168,12 +167,14 @@ zfs_case_unserialize(fmd_hdl_t *hdl, fmd_case_t *cp)
|
||||
static void
|
||||
zfs_mark_vdev(uint64_t pool_guid, nvlist_t *vd, er_timeval_t *loaded)
|
||||
{
|
||||
uint64_t vdev_guid = 0;
|
||||
uint64_t vdev_guid;
|
||||
uint_t c, children;
|
||||
nvlist_t **child;
|
||||
zfs_case_t *zcp;
|
||||
int ret;
|
||||
|
||||
(void) nvlist_lookup_uint64(vd, ZPOOL_CONFIG_GUID, &vdev_guid);
|
||||
ret = nvlist_lookup_uint64(vd, ZPOOL_CONFIG_GUID, &vdev_guid);
|
||||
assert(ret == 0);
|
||||
|
||||
/*
|
||||
* Mark any cases associated with this (pool, vdev) pair.
|
||||
@@ -252,10 +253,7 @@ zfs_mark_pool(zpool_handle_t *zhp, void *unused)
|
||||
}
|
||||
|
||||
ret = nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &vd);
|
||||
if (ret) {
|
||||
zpool_close(zhp);
|
||||
return (-1);
|
||||
}
|
||||
assert(ret == 0);
|
||||
|
||||
zfs_mark_vdev(pool_guid, vd, &loaded);
|
||||
|
||||
@@ -379,6 +377,11 @@ zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname,
|
||||
nvlist_t *detector, *fault;
|
||||
boolean_t serialize;
|
||||
nvlist_t *fru = NULL;
|
||||
#ifdef HAVE_LIBTOPO
|
||||
nvlist_t *fmri;
|
||||
topo_hdl_t *thp;
|
||||
int err;
|
||||
#endif
|
||||
fmd_hdl_debug(hdl, "solving fault '%s'", faultname);
|
||||
|
||||
/*
|
||||
@@ -397,6 +400,64 @@ zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname,
|
||||
zcp->zc_data.zc_vdev_guid);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBTOPO
|
||||
/*
|
||||
* We also want to make sure that the detector (pool or vdev) properly
|
||||
* reflects the diagnosed state, when the fault corresponds to internal
|
||||
* ZFS state (i.e. not checksum or I/O error-induced). Otherwise, a
|
||||
* device which was unavailable early in boot (because the driver/file
|
||||
* wasn't available) and is now healthy will be mis-diagnosed.
|
||||
*/
|
||||
if (!fmd_nvl_fmri_present(hdl, detector) ||
|
||||
(checkunusable && !fmd_nvl_fmri_unusable(hdl, detector))) {
|
||||
fmd_case_close(hdl, zcp->zc_case);
|
||||
nvlist_free(detector);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fru = NULL;
|
||||
if (zcp->zc_fru != NULL &&
|
||||
(thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) != NULL) {
|
||||
/*
|
||||
* If the vdev had an associated FRU, then get the FRU nvlist
|
||||
* from the topo handle and use that in the suspect list. We
|
||||
* explicitly lookup the FRU because the fmri reported from the
|
||||
* kernel may not have up to date details about the disk itself
|
||||
* (serial, part, etc).
|
||||
*/
|
||||
if (topo_fmri_str2nvl(thp, zcp->zc_fru, &fmri, &err) == 0) {
|
||||
libzfs_handle_t *zhdl = fmd_hdl_getspecific(hdl);
|
||||
|
||||
/*
|
||||
* If the disk is part of the system chassis, but the
|
||||
* FRU indicates a different chassis ID than our
|
||||
* current system, then ignore the error. This
|
||||
* indicates that the device was part of another
|
||||
* cluster head, and for obvious reasons cannot be
|
||||
* imported on this system.
|
||||
*/
|
||||
if (libzfs_fru_notself(zhdl, zcp->zc_fru)) {
|
||||
fmd_case_close(hdl, zcp->zc_case);
|
||||
nvlist_free(fmri);
|
||||
fmd_hdl_topo_rele(hdl, thp);
|
||||
nvlist_free(detector);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device is no longer present on the system, or
|
||||
* topo_fmri_fru() fails for other reasons, then fall
|
||||
* back to the fmri specified in the vdev.
|
||||
*/
|
||||
if (topo_fmri_fru(thp, fmri, &fru, &err) != 0)
|
||||
fru = fmd_nvl_dup(hdl, fmri, FMD_SLEEP);
|
||||
nvlist_free(fmri);
|
||||
}
|
||||
|
||||
fmd_hdl_topo_rele(hdl, thp);
|
||||
}
|
||||
#endif
|
||||
fault = fmd_nvl_create_fault(hdl, faultname, 100, detector,
|
||||
fru, detector);
|
||||
fmd_case_add_suspect(hdl, zcp->zc_case, fault);
|
||||
@@ -921,27 +982,27 @@ _zfs_diagnosis_init(fmd_hdl_t *hdl)
|
||||
{
|
||||
libzfs_handle_t *zhdl;
|
||||
|
||||
if ((zhdl = libzfs_init()) == NULL)
|
||||
if ((zhdl = __libzfs_init()) == NULL)
|
||||
return;
|
||||
|
||||
if ((zfs_case_pool = uu_list_pool_create("zfs_case_pool",
|
||||
sizeof (zfs_case_t), offsetof(zfs_case_t, zc_node),
|
||||
NULL, UU_LIST_POOL_DEBUG)) == NULL) {
|
||||
libzfs_fini(zhdl);
|
||||
__libzfs_fini(zhdl);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((zfs_cases = uu_list_create(zfs_case_pool, NULL,
|
||||
UU_LIST_DEBUG)) == NULL) {
|
||||
uu_list_pool_destroy(zfs_case_pool);
|
||||
libzfs_fini(zhdl);
|
||||
__libzfs_fini(zhdl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) {
|
||||
uu_list_destroy(zfs_cases);
|
||||
uu_list_pool_destroy(zfs_case_pool);
|
||||
libzfs_fini(zhdl);
|
||||
__libzfs_fini(zhdl);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -977,5 +1038,5 @@ _zfs_diagnosis_fini(fmd_hdl_t *hdl)
|
||||
uu_list_pool_destroy(zfs_case_pool);
|
||||
|
||||
zhdl = fmd_hdl_getspecific(hdl);
|
||||
libzfs_fini(zhdl);
|
||||
__libzfs_fini(zhdl);
|
||||
}
|
||||
|
||||
+62
-101
@@ -23,7 +23,6 @@
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, Intel Corporation.
|
||||
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -64,6 +63,7 @@
|
||||
* trigger the FMA fault that we skipped earlier.
|
||||
*
|
||||
* ZFS on Linux porting notes:
|
||||
* In lieu of a thread pool, just spawn a thread on demmand.
|
||||
* Linux udev provides a disk insert for both the disk and the partition
|
||||
*
|
||||
*/
|
||||
@@ -73,7 +73,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <libnvpair.h>
|
||||
#include <libzfs.h>
|
||||
#include <libzutil.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -83,10 +82,8 @@
|
||||
#include <sys/sunddi.h>
|
||||
#include <sys/sysevent/eventdefs.h>
|
||||
#include <sys/sysevent/dev.h>
|
||||
#include <thread_pool.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "zfs_agents.h"
|
||||
#include "../zed_log.h"
|
||||
|
||||
@@ -99,12 +96,12 @@ typedef void (*zfs_process_func_t)(zpool_handle_t *, nvlist_t *, boolean_t);
|
||||
libzfs_handle_t *g_zfshdl;
|
||||
list_t g_pool_list; /* list of unavailable pools at initialization */
|
||||
list_t g_device_list; /* list of disks with asynchronous label request */
|
||||
tpool_t *g_tpool;
|
||||
boolean_t g_enumeration_done;
|
||||
pthread_t g_zfs_tid; /* zfs_enum_pools() thread */
|
||||
pthread_t g_zfs_tid;
|
||||
|
||||
typedef struct unavailpool {
|
||||
zpool_handle_t *uap_zhp;
|
||||
pthread_t uap_enable_tid; /* dataset enable thread if activated */
|
||||
list_node_t uap_node;
|
||||
} unavailpool_t;
|
||||
|
||||
@@ -137,6 +134,7 @@ zfs_unavail_pool(zpool_handle_t *zhp, void *data)
|
||||
unavailpool_t *uap;
|
||||
uap = malloc(sizeof (unavailpool_t));
|
||||
uap->uap_zhp = zhp;
|
||||
uap->uap_enable_tid = 0;
|
||||
list_insert_tail((list_t *)data, uap);
|
||||
} else {
|
||||
zpool_close(zhp);
|
||||
@@ -157,7 +155,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
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -428,16 +426,8 @@ zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t labeled)
|
||||
nvlist_free(newvd);
|
||||
|
||||
/*
|
||||
* Wait for udev to verify the links exist, then auto-replace
|
||||
* the leaf disk at same physical location.
|
||||
* auto replace a leaf disk at same physical location
|
||||
*/
|
||||
if (zpool_label_disk_wait(path, 3000) != 0) {
|
||||
zed_log_msg(LOG_WARNING, "zfs_mod: expected replacement "
|
||||
"disk %s is missing", path);
|
||||
nvlist_free(nvroot);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE);
|
||||
|
||||
zed_log_msg(LOG_INFO, " zpool_vdev_replace: %s with %s (%s)",
|
||||
@@ -476,20 +466,7 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++)
|
||||
zfs_iter_vdev(zhp, child[c], data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over any spares and cache devices
|
||||
*/
|
||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_SPARES,
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++)
|
||||
zfs_iter_vdev(zhp, child[c], data);
|
||||
}
|
||||
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_L2CACHE,
|
||||
&child, &children) == 0) {
|
||||
for (c = 0; c < children; c++)
|
||||
zfs_iter_vdev(zhp, child[c], data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* once a vdev was matched and processed there is nothing left to do */
|
||||
@@ -534,14 +511,19 @@ zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
|
||||
(dp->dd_func)(zhp, nvl, dp->dd_islabeled);
|
||||
}
|
||||
|
||||
void
|
||||
static void *
|
||||
zfs_enable_ds(void *arg)
|
||||
{
|
||||
unavailpool_t *pool = (unavailpool_t *)arg;
|
||||
|
||||
assert(pool->uap_enable_tid = pthread_self());
|
||||
|
||||
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0);
|
||||
zpool_close(pool->uap_zhp);
|
||||
free(pool);
|
||||
pool->uap_zhp = NULL;
|
||||
|
||||
/* Note: zfs_slm_fini() will cleanup this pool entry on exit */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -576,13 +558,15 @@ zfs_iter_pool(zpool_handle_t *zhp, void *data)
|
||||
for (pool = list_head(&g_pool_list); pool != NULL;
|
||||
pool = list_next(&g_pool_list, pool)) {
|
||||
|
||||
if (pool->uap_enable_tid != 0)
|
||||
continue; /* entry already processed */
|
||||
if (strcmp(zpool_get_name(zhp),
|
||||
zpool_get_name(pool->uap_zhp)))
|
||||
continue;
|
||||
if (zfs_toplevel_state(zhp) >= VDEV_STATE_DEGRADED) {
|
||||
list_remove(&g_pool_list, pool);
|
||||
(void) tpool_dispatch(g_tpool, zfs_enable_ds,
|
||||
pool);
|
||||
/* send to a background thread; keep on list */
|
||||
(void) pthread_create(&pool->uap_enable_tid,
|
||||
NULL, zfs_enable_ds, pool);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -674,7 +658,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).
|
||||
*
|
||||
@@ -719,8 +703,8 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
||||
{
|
||||
char *devname = data;
|
||||
boolean_t avail_spare, l2cache;
|
||||
vdev_state_t newstate;
|
||||
nvlist_t *tgt;
|
||||
int error;
|
||||
|
||||
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: searching for '%s' in '%s'",
|
||||
devname, zpool_get_name(zhp));
|
||||
@@ -728,58 +712,40 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
||||
if ((tgt = zpool_find_vdev_by_physpath(zhp, devname,
|
||||
&avail_spare, &l2cache, NULL)) != NULL) {
|
||||
char *path, fullpath[MAXPATHLEN];
|
||||
uint64_t wholedisk;
|
||||
uint64_t wholedisk = 0ULL;
|
||||
|
||||
error = nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH, &path);
|
||||
if (error) {
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
error = nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
&wholedisk);
|
||||
if (error)
|
||||
wholedisk = 0;
|
||||
verify(nvlist_lookup_string(tgt, ZPOOL_CONFIG_PATH,
|
||||
&path) == 0);
|
||||
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
&wholedisk) == 0);
|
||||
|
||||
(void) strlcpy(fullpath, path, sizeof (fullpath));
|
||||
if (wholedisk) {
|
||||
path = strrchr(path, '/');
|
||||
if (path != NULL) {
|
||||
path = zfs_strip_partition(path + 1);
|
||||
if (path == NULL) {
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
zpool_close(zhp);
|
||||
char *spath = zfs_strip_partition(fullpath);
|
||||
if (!spath) {
|
||||
zed_log_msg(LOG_INFO, "%s: Can't alloc",
|
||||
__func__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
(void) strlcpy(fullpath, path, sizeof (fullpath));
|
||||
free(path);
|
||||
(void) strlcpy(fullpath, spath, sizeof (fullpath));
|
||||
free(spath);
|
||||
|
||||
/*
|
||||
* We need to reopen the pool associated with this
|
||||
* device so that the kernel can update the size of
|
||||
* the expanded device. When expanding there is no
|
||||
* need to restart the scrub from the beginning.
|
||||
* device so that the kernel can update the size
|
||||
* of the expanded device.
|
||||
*/
|
||||
boolean_t scrub_restart = B_FALSE;
|
||||
(void) zpool_reopen_one(zhp, &scrub_restart);
|
||||
} else {
|
||||
(void) strlcpy(fullpath, path, sizeof (fullpath));
|
||||
(void) zpool_reopen(zhp);
|
||||
}
|
||||
|
||||
if (zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOEXPAND, NULL)) {
|
||||
vdev_state_t newstate;
|
||||
|
||||
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
|
||||
error = zpool_vdev_online(zhp, fullpath, 0,
|
||||
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: setting "
|
||||
"device '%s' to ONLINE state in pool '%s'",
|
||||
fullpath, zpool_get_name(zhp));
|
||||
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL)
|
||||
(void) zpool_vdev_online(zhp, fullpath, 0,
|
||||
&newstate);
|
||||
zed_log_msg(LOG_INFO, "zfsdle_vdev_online: "
|
||||
"setting device '%s' to ONLINE state "
|
||||
"in pool '%s': %d", fullpath,
|
||||
zpool_get_name(zhp), error);
|
||||
}
|
||||
}
|
||||
zpool_close(zhp);
|
||||
return (1);
|
||||
@@ -789,32 +755,23 @@ zfsdle_vdev_online(zpool_handle_t *zhp, void *data)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the ESC_DEV_DLE device change event. Use the
|
||||
* provided vdev guid when looking up a disk or partition, when the guid
|
||||
* is not present assume the entire disk is owned by ZFS and append the
|
||||
* expected -part1 partition information then lookup by physical path.
|
||||
* This function handles the ESC_DEV_DLE event.
|
||||
*/
|
||||
static int
|
||||
zfs_deliver_dle(nvlist_t *nvl)
|
||||
{
|
||||
char *devname, name[MAXPATHLEN];
|
||||
uint64_t guid;
|
||||
char *devname;
|
||||
|
||||
if (nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID, &guid) == 0) {
|
||||
sprintf(name, "%llu", (u_longlong_t)guid);
|
||||
} else if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devname) == 0) {
|
||||
strlcpy(name, devname, MAXPATHLEN);
|
||||
zfs_append_partition(name, MAXPATHLEN);
|
||||
} else {
|
||||
zed_log_msg(LOG_INFO, "zfs_deliver_dle: no guid or physpath");
|
||||
if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devname) != 0) {
|
||||
zed_log_msg(LOG_INFO, "zfs_deliver_dle: no physpath");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (zpool_iter(g_zfshdl, zfsdle_vdev_online, name) != 1) {
|
||||
if (zpool_iter(g_zfshdl, zfsdle_vdev_online, devname) != 1) {
|
||||
zed_log_msg(LOG_INFO, "zfs_deliver_dle: device '%s' not "
|
||||
"found", name);
|
||||
"found", devname);
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -892,12 +849,12 @@ 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()
|
||||
{
|
||||
if ((g_zfshdl = libzfs_init()) == NULL)
|
||||
if ((g_zfshdl = __libzfs_init()) == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
@@ -909,7 +866,7 @@ zfs_slm_init()
|
||||
|
||||
if (pthread_create(&g_zfs_tid, NULL, zfs_enum_pools, NULL) != 0) {
|
||||
list_destroy(&g_pool_list);
|
||||
libzfs_fini(g_zfshdl);
|
||||
__libzfs_fini(g_zfshdl);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -927,15 +884,19 @@ zfs_slm_fini()
|
||||
|
||||
/* wait for zfs_enum_pools thread to complete */
|
||||
(void) pthread_join(g_zfs_tid, NULL);
|
||||
/* destroy the thread pool */
|
||||
if (g_tpool != NULL) {
|
||||
tpool_wait(g_tpool);
|
||||
tpool_destroy(g_tpool);
|
||||
}
|
||||
|
||||
while ((pool = (list_head(&g_pool_list))) != NULL) {
|
||||
/*
|
||||
* each pool entry has two possibilities
|
||||
* 1. was made available (so wait for zfs_enable_ds thread)
|
||||
* 2. still unavailable (just close the pool)
|
||||
*/
|
||||
if (pool->uap_enable_tid)
|
||||
(void) pthread_join(pool->uap_enable_tid, NULL);
|
||||
else if (pool->uap_zhp != NULL)
|
||||
zpool_close(pool->uap_zhp);
|
||||
|
||||
list_remove(&g_pool_list, pool);
|
||||
zpool_close(pool->uap_zhp);
|
||||
free(pool);
|
||||
}
|
||||
list_destroy(&g_pool_list);
|
||||
@@ -946,7 +907,7 @@ zfs_slm_fini()
|
||||
}
|
||||
list_destroy(&g_device_list);
|
||||
|
||||
libzfs_fini(g_zfshdl);
|
||||
__libzfs_fini(g_zfshdl);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+154
-67
@@ -22,7 +22,6 @@
|
||||
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2016, Intel Corporation.
|
||||
* Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -72,6 +71,7 @@ zfs_retire_clear_data(fmd_hdl_t *hdl, zfs_retire_data_t *zdp)
|
||||
*/
|
||||
typedef struct find_cbdata {
|
||||
uint64_t cb_guid;
|
||||
const char *cb_fru;
|
||||
zpool_handle_t *cb_zhp;
|
||||
nvlist_t *cb_vdev;
|
||||
} find_cbdata_t;
|
||||
@@ -95,18 +95,26 @@ find_pool(zpool_handle_t *zhp, void *data)
|
||||
* Find a vdev within a tree with a matching GUID.
|
||||
*/
|
||||
static nvlist_t *
|
||||
find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
||||
find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, const char *search_fru,
|
||||
uint64_t search_guid)
|
||||
{
|
||||
uint64_t guid;
|
||||
nvlist_t **child;
|
||||
uint_t c, children;
|
||||
nvlist_t *ret;
|
||||
char *fru;
|
||||
|
||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
|
||||
guid == search_guid) {
|
||||
fmd_hdl_debug(fmd_module_hdl("zfs-retire"),
|
||||
"matched vdev %llu", guid);
|
||||
return (nv);
|
||||
if (search_fru != NULL) {
|
||||
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_FRU, &fru) == 0 &&
|
||||
libzfs_fru_compare(zhdl, fru, search_fru))
|
||||
return (nv);
|
||||
} else {
|
||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
|
||||
guid == search_guid) {
|
||||
fmd_hdl_debug(fmd_module_hdl("zfs-retire"),
|
||||
"matched vdev %llu", guid);
|
||||
return (nv);
|
||||
}
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
@@ -114,7 +122,8 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
||||
return (NULL);
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL)
|
||||
if ((ret = find_vdev(zhdl, child[c], search_fru,
|
||||
search_guid)) != NULL)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -123,16 +132,8 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid)
|
||||
return (NULL);
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
|
||||
&child, &children) != 0)
|
||||
return (NULL);
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL)
|
||||
if ((ret = find_vdev(zhdl, child[c], search_fru,
|
||||
search_guid)) != NULL)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -166,7 +167,8 @@ find_by_guid(libzfs_handle_t *zhdl, uint64_t pool_guid, uint64_t vdev_guid,
|
||||
}
|
||||
|
||||
if (vdev_guid != 0) {
|
||||
if ((*vdevp = find_vdev(zhdl, nvroot, vdev_guid)) == NULL) {
|
||||
if ((*vdevp = find_vdev(zhdl, nvroot, NULL,
|
||||
vdev_guid)) == NULL) {
|
||||
zpool_close(zhp);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -175,37 +177,72 @@ find_by_guid(libzfs_handle_t *zhdl, uint64_t pool_guid, uint64_t vdev_guid,
|
||||
return (zhp);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBTOPO
|
||||
static int
|
||||
search_pool(zpool_handle_t *zhp, void *data)
|
||||
{
|
||||
find_cbdata_t *cbp = data;
|
||||
nvlist_t *config;
|
||||
nvlist_t *nvroot;
|
||||
|
||||
config = zpool_get_config(zhp, NULL);
|
||||
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot) != 0) {
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((cbp->cb_vdev = find_vdev(zpool_get_handle(zhp), nvroot,
|
||||
cbp->cb_fru, 0)) != NULL) {
|
||||
cbp->cb_zhp = zhp;
|
||||
return (1);
|
||||
}
|
||||
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a FRU FMRI, find the matching pool and vdev.
|
||||
*/
|
||||
static zpool_handle_t *
|
||||
find_by_fru(libzfs_handle_t *zhdl, const char *fru, nvlist_t **vdevp)
|
||||
{
|
||||
find_cbdata_t cb;
|
||||
|
||||
cb.cb_fru = fru;
|
||||
cb.cb_zhp = NULL;
|
||||
if (zpool_iter(zhdl, search_pool, &cb) != 1)
|
||||
return (NULL);
|
||||
|
||||
*vdevp = cb.cb_vdev;
|
||||
return (cb.cb_zhp);
|
||||
}
|
||||
#endif /* HAVE_LIBTOPO */
|
||||
|
||||
/*
|
||||
* Given a vdev, attempt to replace it with every known spare until one
|
||||
* succeeds or we run out of devices to try.
|
||||
* Return whether we were successful or not in replacing the device.
|
||||
* succeeds.
|
||||
*/
|
||||
static boolean_t
|
||||
static void
|
||||
replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
||||
{
|
||||
nvlist_t *config, *nvroot, *replacement;
|
||||
nvlist_t **spares;
|
||||
uint_t s, nspares;
|
||||
char *dev_name;
|
||||
zprop_source_t source;
|
||||
int ashift;
|
||||
|
||||
config = zpool_get_config(zhp, NULL);
|
||||
if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot) != 0)
|
||||
return (B_FALSE);
|
||||
return;
|
||||
|
||||
/*
|
||||
* Find out if there are any hot spares available in the pool.
|
||||
*/
|
||||
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
||||
&spares, &nspares) != 0)
|
||||
return (B_FALSE);
|
||||
|
||||
/*
|
||||
* lookup "ashift" pool property, we may need it for the replacement
|
||||
*/
|
||||
ashift = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &source);
|
||||
return;
|
||||
|
||||
replacement = fmd_nvl_alloc(hdl, FMD_SLEEP);
|
||||
|
||||
@@ -225,11 +262,6 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
||||
&spare_name) != 0)
|
||||
continue;
|
||||
|
||||
/* if set, add the "ashift" pool property to the spare nvlist */
|
||||
if (source != ZPROP_SRC_DEFAULT)
|
||||
(void) nvlist_add_uint64(spares[s],
|
||||
ZPOOL_CONFIG_ASHIFT, ashift);
|
||||
|
||||
(void) nvlist_add_nvlist_array(replacement,
|
||||
ZPOOL_CONFIG_CHILDREN, &spares[s], 1);
|
||||
|
||||
@@ -237,17 +269,12 @@ replace_with_spare(fmd_hdl_t *hdl, zpool_handle_t *zhp, nvlist_t *vdev)
|
||||
dev_name, basename(spare_name));
|
||||
|
||||
if (zpool_vdev_attach(zhp, dev_name, spare_name,
|
||||
replacement, B_TRUE) == 0) {
|
||||
free(dev_name);
|
||||
nvlist_free(replacement);
|
||||
return (B_TRUE);
|
||||
}
|
||||
replacement, B_TRUE) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
free(dev_name);
|
||||
nvlist_free(replacement);
|
||||
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -262,6 +289,10 @@ zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl)
|
||||
zfs_retire_data_t *zdp = fmd_hdl_getspecific(hdl);
|
||||
zfs_retire_repaired_t *zrp;
|
||||
uint64_t pool_guid, vdev_guid;
|
||||
#ifdef HAVE_LIBTOPO
|
||||
nvlist_t *asru;
|
||||
#endif
|
||||
|
||||
if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
|
||||
&pool_guid) != 0 || nvlist_lookup_uint64(nvl,
|
||||
FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
|
||||
@@ -284,6 +315,47 @@ zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBTOPO
|
||||
asru = fmd_nvl_alloc(hdl, FMD_SLEEP);
|
||||
|
||||
(void) nvlist_add_uint8(asru, FM_VERSION, ZFS_SCHEME_VERSION0);
|
||||
(void) nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_ZFS);
|
||||
(void) nvlist_add_uint64(asru, FM_FMRI_ZFS_POOL, pool_guid);
|
||||
(void) nvlist_add_uint64(asru, FM_FMRI_ZFS_VDEV, vdev_guid);
|
||||
|
||||
/*
|
||||
* We explicitly check for the unusable state here to make sure we
|
||||
* aren't responding to a transient state change. As part of opening a
|
||||
* vdev, it's possible to see the 'statechange' event, only to be
|
||||
* followed by a vdev failure later. If we don't check the current
|
||||
* state of the vdev (or pool) before marking it repaired, then we risk
|
||||
* generating spurious repair events followed immediately by the same
|
||||
* diagnosis.
|
||||
*
|
||||
* This assumes that the ZFS scheme code associated unusable (i.e.
|
||||
* isolated) with its own definition of faulty state. In the case of a
|
||||
* DEGRADED leaf vdev (due to checksum errors), this is not the case.
|
||||
* This works, however, because the transient state change is not
|
||||
* posted in this case. This could be made more explicit by not
|
||||
* relying on the scheme's unusable callback and instead directly
|
||||
* checking the vdev state, where we could correctly account for
|
||||
* DEGRADED state.
|
||||
*/
|
||||
if (!fmd_nvl_fmri_unusable(hdl, asru) && fmd_nvl_fmri_has_fault(hdl,
|
||||
asru, FMD_HAS_FAULT_ASRU, NULL)) {
|
||||
topo_hdl_t *thp;
|
||||
char *fmri = NULL;
|
||||
int err;
|
||||
|
||||
thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
|
||||
if (topo_fmri_nvl2str(thp, asru, &fmri, &err) == 0)
|
||||
(void) fmd_repair_asru(hdl, fmri);
|
||||
fmd_hdl_topo_rele(hdl, thp);
|
||||
|
||||
topo_hdl_strfree(thp, fmri);
|
||||
}
|
||||
nvlist_free(asru);
|
||||
#endif
|
||||
zrp = fmd_hdl_alloc(hdl, sizeof (zfs_retire_repaired_t), FMD_SLEEP);
|
||||
zrp->zrr_next = zdp->zrd_repaired;
|
||||
zrp->zrr_pool = pool_guid;
|
||||
@@ -320,14 +392,10 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
fmd_hdl_debug(hdl, "zfs_retire_recv: '%s'", class);
|
||||
|
||||
/*
|
||||
* 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 this is a resource notifying us of device removal, then simply
|
||||
* check for an available spare and continue.
|
||||
*/
|
||||
if (strcmp(class, "resource.fs.zfs.removed") == 0) {
|
||||
char *devtype;
|
||||
char *devname;
|
||||
|
||||
if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
|
||||
&pool_guid) != 0 ||
|
||||
nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID,
|
||||
@@ -338,21 +406,8 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
&vdev)) == NULL)
|
||||
return;
|
||||
|
||||
devname = zpool_vdev_name(NULL, zhp, vdev, B_FALSE);
|
||||
|
||||
/* Can't replace l2arc with a spare: offline the device */
|
||||
if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
|
||||
&devtype) == 0 && strcmp(devtype, VDEV_TYPE_L2CACHE) == 0) {
|
||||
fmd_hdl_debug(hdl, "zpool_vdev_offline '%s'", devname);
|
||||
zpool_vdev_offline(zhp, devname, B_TRUE);
|
||||
} else if (!fmd_prop_get_int32(hdl, "spare_on_remove") ||
|
||||
replace_with_spare(hdl, zhp, vdev) == B_FALSE) {
|
||||
/* Could not handle with spare: offline the device */
|
||||
fmd_hdl_debug(hdl, "zpool_vdev_offline '%s'", devname);
|
||||
zpool_vdev_offline(zhp, devname, B_TRUE);
|
||||
}
|
||||
|
||||
free(devname);
|
||||
if (fmd_prop_get_int32(hdl, "spare_on_remove"))
|
||||
replace_with_spare(hdl, zhp, vdev);
|
||||
zpool_close(zhp);
|
||||
return;
|
||||
}
|
||||
@@ -422,7 +477,39 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
}
|
||||
|
||||
if (is_disk) {
|
||||
#ifdef HAVE_LIBTOPO
|
||||
/*
|
||||
* This is a disk fault. Lookup the FRU, convert it to
|
||||
* an FMRI string, and attempt to find a matching vdev.
|
||||
*/
|
||||
if (nvlist_lookup_nvlist(fault, FM_FAULT_FRU,
|
||||
&fru) != 0 ||
|
||||
nvlist_lookup_string(fru, FM_FMRI_SCHEME,
|
||||
&scheme) != 0)
|
||||
continue;
|
||||
|
||||
if (strcmp(scheme, FM_FMRI_SCHEME_HC) != 0)
|
||||
continue;
|
||||
|
||||
thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
|
||||
if (topo_fmri_nvl2str(thp, fru, &fmri, &err) != 0) {
|
||||
fmd_hdl_topo_rele(hdl, thp);
|
||||
continue;
|
||||
}
|
||||
|
||||
zhp = find_by_fru(zhdl, fmri, &vdev);
|
||||
topo_hdl_strfree(thp, fmri);
|
||||
fmd_hdl_topo_rele(hdl, thp);
|
||||
|
||||
if (zhp == NULL)
|
||||
continue;
|
||||
|
||||
(void) nvlist_lookup_uint64(vdev,
|
||||
ZPOOL_CONFIG_GUID, &vdev_guid);
|
||||
aux = VDEV_AUX_EXTERNAL;
|
||||
#else
|
||||
continue;
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* This is a ZFS fault. Lookup the resource, and
|
||||
@@ -496,7 +583,7 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
|
||||
/*
|
||||
* Attempt to substitute a hot spare.
|
||||
*/
|
||||
(void) replace_with_spare(hdl, zhp, vdev);
|
||||
replace_with_spare(hdl, zhp, vdev);
|
||||
zpool_close(zhp);
|
||||
}
|
||||
|
||||
@@ -528,7 +615,7 @@ _zfs_retire_init(fmd_hdl_t *hdl)
|
||||
zfs_retire_data_t *zdp;
|
||||
libzfs_handle_t *zhdl;
|
||||
|
||||
if ((zhdl = libzfs_init()) == NULL)
|
||||
if ((zhdl = __libzfs_init()) == NULL)
|
||||
return;
|
||||
|
||||
if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) {
|
||||
@@ -549,7 +636,7 @@ _zfs_retire_fini(fmd_hdl_t *hdl)
|
||||
|
||||
if (zdp != NULL) {
|
||||
zfs_retire_clear_data(hdl, zdp);
|
||||
libzfs_fini(zdp->zrd_hdl);
|
||||
__libzfs_fini(zdp->zrd_hdl);
|
||||
fmd_hdl_free(hdl, zdp, sizeof (zfs_retire_data_t));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
history_event-zfs-list-cacher.sh
|
||||
@@ -1,57 +0,0 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
EXTRA_DIST = \
|
||||
README \
|
||||
history_event-zfs-list-cacher.sh.in
|
||||
|
||||
zedconfdir = $(sysconfdir)/zfs/zed.d
|
||||
|
||||
dist_zedconf_DATA = \
|
||||
zed-functions.sh \
|
||||
zed.rc
|
||||
|
||||
zedexecdir = $(zfsexecdir)/zed.d
|
||||
|
||||
dist_zedexec_SCRIPTS = \
|
||||
all-debug.sh \
|
||||
all-syslog.sh \
|
||||
data-notify.sh \
|
||||
generic-notify.sh \
|
||||
resilver_finish-notify.sh \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
resilver_finish-start-scrub.sh
|
||||
|
||||
nodist_zedexec_SCRIPTS = history_event-zfs-list-cacher.sh
|
||||
|
||||
$(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 \
|
||||
resilver_finish-notify.sh \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
resilver_finish-start-scrub.sh
|
||||
|
||||
install-data-hook:
|
||||
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
||||
for f in $(zedconfdefaults); do \
|
||||
test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \
|
||||
-L "$(DESTDIR)$(zedconfdir)/$${f}" || \
|
||||
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
||||
done
|
||||
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
|
||||
@@ -1,76 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Track changes to enumerated pools for use in early-boot
|
||||
set -ef
|
||||
|
||||
FSLIST_DIR="@sysconfdir@/zfs/zfs-list.cache"
|
||||
FSLIST_TMP="@runstatedir@/zfs-list.cache.new"
|
||||
FSLIST="${FSLIST_DIR}/${ZEVENT_POOL}"
|
||||
|
||||
# If the pool specific cache file is not writeable, abort
|
||||
[ -w "${FSLIST}" ] || exit 0
|
||||
|
||||
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
|
||||
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
|
||||
|
||||
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
|
||||
printf '%s' "${ZEVENT_HISTORY_DSNAME}" | grep '@' && exit 0
|
||||
|
||||
# We obtain a lock on zfs-list to avoid any simultaneous writes.
|
||||
# If we run into trouble, log and drop the lock
|
||||
abort_alter() {
|
||||
zed_log_msg "Error updating zfs-list.cache!"
|
||||
zed_unlock zfs-list
|
||||
}
|
||||
|
||||
finished() {
|
||||
zed_unlock zfs-list
|
||||
trap - EXIT
|
||||
exit 0
|
||||
}
|
||||
|
||||
case "${ZEVENT_HISTORY_INTERNAL_NAME}" in
|
||||
create|"finish receiving"|import|destroy|rename)
|
||||
;;
|
||||
|
||||
export)
|
||||
zed_lock zfs-list
|
||||
trap abort_alter EXIT
|
||||
echo > "${FSLIST}"
|
||||
finished
|
||||
;;
|
||||
|
||||
set|inherit)
|
||||
# Only act if one of the tracked properties is altered.
|
||||
case "${ZEVENT_HISTORY_INTERNAL_STR%%=*}" in
|
||||
canmount|mountpoint|atime|relatime|devices|exec| \
|
||||
readonly|setuid|nbmand|encroot|keylocation) ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
# Ignore all other events.
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
zed_lock zfs-list
|
||||
trap abort_alter EXIT
|
||||
|
||||
PROPS="name,mountpoint,canmount,atime,relatime,devices,exec,readonly"
|
||||
PROPS="${PROPS},setuid,nbmand,encroot,keylocation"
|
||||
|
||||
"${ZFS}" list -H -t filesystem -o $PROPS -r "${ZEVENT_POOL}" > "${FSLIST_TMP}"
|
||||
|
||||
# Sort the output so that it is stable
|
||||
sort "${FSLIST_TMP}" -o "${FSLIST_TMP}"
|
||||
|
||||
# Don't modify the file if it hasn't changed
|
||||
diff -q "${FSLIST_TMP}" "${FSLIST}" || mv "${FSLIST_TMP}" "${FSLIST}"
|
||||
rm -f "${FSLIST_TMP}"
|
||||
|
||||
finished
|
||||
@@ -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}")
|
||||
|
||||
@@ -165,7 +165,7 @@ process_pool()
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ -n "$ZEVENT_VDEV_STATE_STR" ] ; then
|
||||
if [ ! -z "$ZEVENT_VDEV_ENC_SYSFS_PATH" ] && [ ! -z "$ZEVENT_VDEV_STATE_STR" ] ; then
|
||||
# Got a statechange for an individual VDEV
|
||||
val=$(state_to_val "$ZEVENT_VDEV_STATE_STR")
|
||||
vdev=$(basename "$ZEVENT_VDEV_PATH")
|
||||
|
||||
@@ -434,7 +434,7 @@ zed_guid_to_pool()
|
||||
fi
|
||||
|
||||
guid=$(printf "%llu" "$1")
|
||||
if [ -n "$guid" ] ; then
|
||||
if [ ! -z "$guid" ] ; then
|
||||
$ZPOOL get -H -ovalue,name guid | awk '$1=='"$guid"' {print $2}'
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -52,9 +52,9 @@
|
||||
|
||||
##
|
||||
# Send notifications for 'ereport.fs.zfs.data' events.
|
||||
# Disabled by default, any non-empty value will enable the feature.
|
||||
# Disabled by default
|
||||
#
|
||||
#ZED_NOTIFY_DATA=
|
||||
#ZED_NOTIFY_DATA=1
|
||||
|
||||
##
|
||||
# Pushbullet access token.
|
||||
@@ -88,8 +88,7 @@ ZED_USE_ENCLOSURE_LEDS=1
|
||||
|
||||
##
|
||||
# Run a scrub after every resilver
|
||||
# Disabled by default, 1 to enable and 0 to disable.
|
||||
#ZED_SCRUB_AFTER_RESILVER=0
|
||||
#ZED_SCRUB_AFTER_RESILVER=1
|
||||
|
||||
##
|
||||
# The syslog priority (e.g., specified as a "facility.level" pair).
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <libnvpair.h>
|
||||
#include <libudev.h>
|
||||
#include <libzfs.h>
|
||||
#include <libzutil.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -38,7 +37,7 @@
|
||||
* A libudev monitor is established to monitor block device actions and pass
|
||||
* them on to internal ZED logic modules. Initially, zfs_mod.c is the only
|
||||
* consumer and is the Linux equivalent for the illumos syseventd ZFS SLM
|
||||
* module responsible for handling disk events for ZFS.
|
||||
* module responsible for handeling disk events for ZFS.
|
||||
*/
|
||||
|
||||
pthread_t g_mon_tid;
|
||||
|
||||
+4
-3
@@ -10,12 +10,13 @@ zfs_SOURCES = \
|
||||
zfs_iter.c \
|
||||
zfs_iter.h \
|
||||
zfs_main.c \
|
||||
zfs_util.h \
|
||||
zfs_project.c \
|
||||
zfs_projectutil.h
|
||||
zfs_util.h
|
||||
|
||||
zfs_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
zfs_LDFLAGS = -pthread
|
||||
|
||||
+6
-22
@@ -31,7 +31,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <libzfs.h>
|
||||
@@ -134,31 +133,16 @@ zfs_callback(zfs_handle_t *zhp, void *data)
|
||||
((cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
|
||||
cb->cb_depth < cb->cb_depth_limit)) {
|
||||
cb->cb_depth++;
|
||||
|
||||
/*
|
||||
* If we are not looking for filesystems, we don't need to
|
||||
* recurse into filesystems when we are at our depth limit.
|
||||
*/
|
||||
if ((cb->cb_depth < cb->cb_depth_limit ||
|
||||
(cb->cb_flags & ZFS_ITER_DEPTH_LIMIT) == 0 ||
|
||||
(cb->cb_types &
|
||||
(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) &&
|
||||
zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
|
||||
if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
|
||||
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
|
||||
}
|
||||
|
||||
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
|
||||
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps) {
|
||||
ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
|
||||
(void) zfs_iter_snapshots(zhp,
|
||||
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0,
|
||||
zfs_callback, data, 0, 0);
|
||||
}
|
||||
|
||||
(cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
|
||||
data);
|
||||
if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
|
||||
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks) {
|
||||
ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
|
||||
(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
|
||||
}
|
||||
|
||||
cb->cb_depth--;
|
||||
}
|
||||
|
||||
@@ -240,7 +224,7 @@ zfs_compare(const void *larg, const void *rarg, void *unused)
|
||||
*rat = '\0';
|
||||
|
||||
ret = strcmp(lname, rname);
|
||||
if (ret == 0 && (lat != NULL || rat != NULL)) {
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* If we're comparing a dataset to one of its snapshots, we
|
||||
* always make the full dataset first.
|
||||
|
||||
+162
-1247
File diff suppressed because it is too large
Load Diff
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017, Intle Corporation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <stddef.h>
|
||||
#include <libintl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/list.h>
|
||||
#include <sys/zfs_project.h>
|
||||
|
||||
#include "zfs_util.h"
|
||||
#include "zfs_projectutil.h"
|
||||
|
||||
typedef struct zfs_project_item {
|
||||
list_node_t zpi_list;
|
||||
char zpi_name[0];
|
||||
} zfs_project_item_t;
|
||||
|
||||
static void
|
||||
zfs_project_item_alloc(list_t *head, const char *name)
|
||||
{
|
||||
zfs_project_item_t *zpi;
|
||||
|
||||
zpi = safe_malloc(sizeof (zfs_project_item_t) + strlen(name) + 1);
|
||||
strcpy(zpi->zpi_name, name);
|
||||
list_insert_tail(head, zpi);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_project_sanity_check(const char *name, zfs_project_control_t *zpc,
|
||||
struct stat *st)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = stat(name, st);
|
||||
if (ret) {
|
||||
(void) fprintf(stderr, gettext("failed to stat %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) {
|
||||
(void) fprintf(stderr, gettext("only support project quota on "
|
||||
"regular file or directory\n"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st->st_mode)) {
|
||||
if (zpc->zpc_dironly) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"'-d' option on non-dir target %s\n"), name);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (zpc->zpc_recursive) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"'-r' option on non-dir target %s\n"), name);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_project_load_projid(const char *name, zfs_project_control_t *zpc)
|
||||
{
|
||||
zfsxattr_t fsx;
|
||||
int ret, fd;
|
||||
|
||||
fd = open(name, O_RDONLY | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
return (fd);
|
||||
}
|
||||
|
||||
ret = ioctl(fd, ZFS_IOC_FSGETXATTR, &fsx);
|
||||
if (ret)
|
||||
(void) fprintf(stderr,
|
||||
gettext("failed to get xattr for %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
else
|
||||
zpc->zpc_expected_projid = fsx.fsx_projid;
|
||||
|
||||
close(fd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_project_handle_one(const char *name, zfs_project_control_t *zpc)
|
||||
{
|
||||
zfsxattr_t fsx;
|
||||
int ret, fd;
|
||||
|
||||
fd = open(name, O_RDONLY | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT && zpc->zpc_ignore_noent)
|
||||
return (0);
|
||||
|
||||
(void) fprintf(stderr, gettext("failed to open %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
return (fd);
|
||||
}
|
||||
|
||||
ret = ioctl(fd, ZFS_IOC_FSGETXATTR, &fsx);
|
||||
if (ret) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("failed to get xattr for %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (zpc->zpc_op) {
|
||||
case ZFS_PROJECT_OP_LIST:
|
||||
(void) printf("%5u %c %s\n", fsx.fsx_projid,
|
||||
(fsx.fsx_xflags & ZFS_PROJINHERIT_FL) ? 'P' : '-', name);
|
||||
goto out;
|
||||
case ZFS_PROJECT_OP_CHECK:
|
||||
if (fsx.fsx_projid == zpc->zpc_expected_projid &&
|
||||
fsx.fsx_xflags & ZFS_PROJINHERIT_FL)
|
||||
goto out;
|
||||
|
||||
if (!zpc->zpc_newline) {
|
||||
char c = '\0';
|
||||
|
||||
(void) printf("%s%c", name, c);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fsx.fsx_projid != zpc->zpc_expected_projid)
|
||||
(void) printf("%s - project ID is not set properly "
|
||||
"(%u/%u)\n", name, fsx.fsx_projid,
|
||||
(uint32_t)zpc->zpc_expected_projid);
|
||||
|
||||
if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
|
||||
(void) printf("%s - project inherit flag is not set\n",
|
||||
name);
|
||||
|
||||
goto out;
|
||||
case ZFS_PROJECT_OP_CLEAR:
|
||||
if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL) &&
|
||||
(zpc->zpc_keep_projid ||
|
||||
fsx.fsx_projid == ZFS_DEFAULT_PROJID))
|
||||
goto out;
|
||||
|
||||
fsx.fsx_xflags &= ~ZFS_PROJINHERIT_FL;
|
||||
if (!zpc->zpc_keep_projid)
|
||||
fsx.fsx_projid = ZFS_DEFAULT_PROJID;
|
||||
break;
|
||||
case ZFS_PROJECT_OP_SET:
|
||||
if (fsx.fsx_projid == zpc->zpc_expected_projid &&
|
||||
(!zpc->zpc_set_flag || fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
|
||||
goto out;
|
||||
|
||||
fsx.fsx_projid = zpc->zpc_expected_projid;
|
||||
if (zpc->zpc_set_flag)
|
||||
fsx.fsx_xflags |= ZFS_PROJINHERIT_FL;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, ZFS_IOC_FSSETXATTR, &fsx);
|
||||
if (ret)
|
||||
(void) fprintf(stderr,
|
||||
gettext("failed to set xattr for %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
|
||||
out:
|
||||
close(fd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
|
||||
list_t *head)
|
||||
{
|
||||
char fullname[PATH_MAX];
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
int ret = 0;
|
||||
|
||||
dir = opendir(name);
|
||||
if (dir == NULL) {
|
||||
if (errno == ENOENT && zpc->zpc_ignore_noent)
|
||||
return (0);
|
||||
|
||||
ret = -errno;
|
||||
(void) fprintf(stderr, gettext("failed to opendir %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Non-top item, ignore the case of being removed or renamed by race. */
|
||||
zpc->zpc_ignore_noent = B_TRUE;
|
||||
errno = 0;
|
||||
while (!ret && (ent = readdir(dir)) != NULL) {
|
||||
/* skip "." and ".." */
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
if (strlen(ent->d_name) + strlen(name) >=
|
||||
sizeof (fullname) + 1) {
|
||||
errno = ENAMETOOLONG;
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(fullname, "%s/%s", name, ent->d_name);
|
||||
ret = zfs_project_handle_one(fullname, zpc);
|
||||
if (!ret && zpc->zpc_recursive && ent->d_type == DT_DIR)
|
||||
zfs_project_item_alloc(head, fullname);
|
||||
}
|
||||
|
||||
if (errno && !ret) {
|
||||
ret = -errno;
|
||||
(void) fprintf(stderr, gettext("failed to readdir %s: %s\n"),
|
||||
name, strerror(errno));
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
zfs_project_handle(const char *name, zfs_project_control_t *zpc)
|
||||
{
|
||||
zfs_project_item_t *zpi;
|
||||
struct stat st;
|
||||
list_t head;
|
||||
int ret;
|
||||
|
||||
ret = zfs_project_sanity_check(name, zpc, &st);
|
||||
if (ret)
|
||||
return (ret);
|
||||
|
||||
if ((zpc->zpc_op == ZFS_PROJECT_OP_SET ||
|
||||
zpc->zpc_op == ZFS_PROJECT_OP_CHECK) &&
|
||||
zpc->zpc_expected_projid == ZFS_INVALID_PROJID) {
|
||||
ret = zfs_project_load_projid(name, zpc);
|
||||
if (ret)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
zpc->zpc_ignore_noent = B_FALSE;
|
||||
ret = zfs_project_handle_one(name, zpc);
|
||||
if (ret || !S_ISDIR(st.st_mode) || zpc->zpc_dironly ||
|
||||
(!zpc->zpc_recursive &&
|
||||
zpc->zpc_op != ZFS_PROJECT_OP_LIST &&
|
||||
zpc->zpc_op != ZFS_PROJECT_OP_CHECK))
|
||||
return (ret);
|
||||
|
||||
list_create(&head, sizeof (zfs_project_item_t),
|
||||
offsetof(zfs_project_item_t, zpi_list));
|
||||
zfs_project_item_alloc(&head, name);
|
||||
while ((zpi = list_remove_head(&head)) != NULL) {
|
||||
if (!ret)
|
||||
ret = zfs_project_handle_dir(zpi->zpi_name, zpc, &head);
|
||||
free(zpi);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2017, Intel Corporation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ZFS_PROJECTUTIL_H
|
||||
#define _ZFS_PROJECTUTIL_H
|
||||
|
||||
typedef enum {
|
||||
ZFS_PROJECT_OP_DEFAULT = 0,
|
||||
ZFS_PROJECT_OP_LIST = 1,
|
||||
ZFS_PROJECT_OP_CHECK = 2,
|
||||
ZFS_PROJECT_OP_CLEAR = 3,
|
||||
ZFS_PROJECT_OP_SET = 4,
|
||||
} zfs_project_ops_t;
|
||||
|
||||
typedef struct zfs_project_control {
|
||||
uint64_t zpc_expected_projid;
|
||||
zfs_project_ops_t zpc_op;
|
||||
boolean_t zpc_dironly;
|
||||
boolean_t zpc_ignore_noent;
|
||||
boolean_t zpc_keep_projid;
|
||||
boolean_t zpc_newline;
|
||||
boolean_t zpc_recursive;
|
||||
boolean_t zpc_set_flag;
|
||||
} zfs_project_control_t;
|
||||
|
||||
int zfs_project_handle(const char *name, zfs_project_control_t *zpc);
|
||||
|
||||
#endif /* _ZFS_PROJECTUTIL_H */
|
||||
@@ -11,4 +11,7 @@ zhack_SOURCES = \
|
||||
|
||||
zhack_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
+10
-5
@@ -48,11 +48,12 @@
|
||||
#include <sys/zio_compress.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/dmu_tx.h>
|
||||
#include <libzutil.h>
|
||||
#include <libzfs.h>
|
||||
|
||||
extern boolean_t zfeature_checks_disable;
|
||||
|
||||
const char cmdname[] = "zhack";
|
||||
libzfs_handle_t *g_zfs;
|
||||
static importargs_t g_importargs;
|
||||
static char *g_pool;
|
||||
static boolean_t g_readonly;
|
||||
@@ -104,7 +105,7 @@ fatal(spa_t *spa, void *tag, const char *fmt, ...)
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
space_delta_cb(dmu_object_type_t bonustype, void *data,
|
||||
uint64_t *userp, uint64_t *groupp, uint64_t *projectp)
|
||||
uint64_t *userp, uint64_t *groupp)
|
||||
{
|
||||
/*
|
||||
* Is it a valid type of object to track?
|
||||
@@ -127,17 +128,20 @@ zhack_import(char *target, boolean_t readonly)
|
||||
int error;
|
||||
|
||||
kernel_init(readonly ? FREAD : (FREAD | FWRITE));
|
||||
g_zfs = libzfs_init();
|
||||
ASSERT(g_zfs != NULL);
|
||||
|
||||
dmu_objset_register_type(DMU_OST_ZFS, space_delta_cb);
|
||||
|
||||
g_readonly = readonly;
|
||||
g_importargs.unique = B_TRUE;
|
||||
g_importargs.can_be_active = readonly;
|
||||
g_pool = strdup(target);
|
||||
|
||||
error = zpool_find_config(NULL, target, &config, &g_importargs,
|
||||
&libzpool_config_ops);
|
||||
error = zpool_tryimport(g_zfs, target, &config, &g_importargs);
|
||||
if (error)
|
||||
fatal(NULL, FTAG, "cannot import '%s'", target);
|
||||
fatal(NULL, FTAG, "cannot import '%s': %s", target,
|
||||
libzfs_error_description(g_zfs));
|
||||
|
||||
props = NULL;
|
||||
if (readonly) {
|
||||
@@ -525,6 +529,7 @@ main(int argc, char **argv)
|
||||
"changes may not be committed to disk\n");
|
||||
}
|
||||
|
||||
libzfs_fini(g_zfs);
|
||||
kernel_fini();
|
||||
|
||||
return (rv);
|
||||
|
||||
@@ -13,4 +13,7 @@ zinject_SOURCES = \
|
||||
|
||||
zinject_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
+111
-17
@@ -25,6 +25,8 @@
|
||||
|
||||
#include <libzfs.h>
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
@@ -47,6 +49,9 @@
|
||||
|
||||
#include "zinject.h"
|
||||
|
||||
extern void kernel_init(int);
|
||||
extern void kernel_fini(void);
|
||||
|
||||
static int debug;
|
||||
|
||||
static void
|
||||
@@ -156,32 +161,51 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert from a dataset to a objset id. Note that
|
||||
* we grab the object number from the inode number.
|
||||
* Convert from a (dataset, path) pair into a (objset, object) pair. Note that
|
||||
* we grab the object number from the inode number, since looking this up via
|
||||
* libzpool is a real pain.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
object_from_path(const char *dataset, uint64_t object, zinject_record_t *record)
|
||||
object_from_path(const char *dataset, const char *path, struct stat64 *statbuf,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
zfs_handle_t *zhp;
|
||||
objset_t *os;
|
||||
int err;
|
||||
|
||||
if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
|
||||
/*
|
||||
* Before doing any libzpool operations, call sync() to ensure that the
|
||||
* on-disk state is consistent with the in-core state.
|
||||
*/
|
||||
sync();
|
||||
|
||||
err = dmu_objset_own(dataset, DMU_OST_ZFS, B_TRUE, FTAG, &os);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||
dataset, strerror(err));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
record->zi_objset = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
|
||||
record->zi_object = object;
|
||||
record->zi_objset = dmu_objset_id(os);
|
||||
record->zi_object = statbuf->st_ino;
|
||||
|
||||
zfs_close(zhp);
|
||||
dmu_objset_disown(os, FTAG);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the range based on the type, level, and range given.
|
||||
* Calculate the real range based on the type, level, and range given.
|
||||
*/
|
||||
static int
|
||||
initialize_range(err_type_t type, int level, char *range,
|
||||
calculate_range(const char *dataset, err_type_t type, int level, char *range,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
objset_t *os = NULL;
|
||||
dnode_t *dn = NULL;
|
||||
int err;
|
||||
int ret = -1;
|
||||
|
||||
/*
|
||||
* Determine the numeric range from the string.
|
||||
*/
|
||||
@@ -209,7 +233,7 @@ initialize_range(err_type_t type, int level, char *range,
|
||||
(void) fprintf(stderr, "invalid range '%s': must be "
|
||||
"a numeric range of the form 'start[,end]'\n",
|
||||
range);
|
||||
return (-1);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +253,7 @@ initialize_range(err_type_t type, int level, char *range,
|
||||
if (range != NULL) {
|
||||
(void) fprintf(stderr, "range cannot be specified when "
|
||||
"type is 'dnode'\n");
|
||||
return (-1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
record->zi_start = record->zi_object * sizeof (dnode_phys_t);
|
||||
@@ -238,9 +262,76 @@ initialize_range(err_type_t type, int level, char *range,
|
||||
break;
|
||||
}
|
||||
|
||||
record->zi_level = level;
|
||||
/*
|
||||
* Get the dnode associated with object, so we can calculate the block
|
||||
* size.
|
||||
*/
|
||||
if ((err = dmu_objset_own(dataset, DMU_OST_ANY,
|
||||
B_TRUE, FTAG, &os)) != 0) {
|
||||
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||
dataset, strerror(err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
return (0);
|
||||
if (record->zi_object == 0) {
|
||||
dn = DMU_META_DNODE(os);
|
||||
} else {
|
||||
err = dnode_hold(os, record->zi_object, FTAG, &dn);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "failed to hold dnode "
|
||||
"for object %llu\n",
|
||||
(u_longlong_t)record->zi_object);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ziprintf("data shift: %d\n", (int)dn->dn_datablkshift);
|
||||
ziprintf(" ind shift: %d\n", (int)dn->dn_indblkshift);
|
||||
|
||||
/*
|
||||
* Translate range into block IDs.
|
||||
*/
|
||||
if (record->zi_start != 0 || record->zi_end != -1ULL) {
|
||||
record->zi_start >>= dn->dn_datablkshift;
|
||||
record->zi_end >>= dn->dn_datablkshift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check level, and then translate level 0 blkids into ranges
|
||||
* appropriate for level of indirection.
|
||||
*/
|
||||
record->zi_level = level;
|
||||
if (level > 0) {
|
||||
ziprintf("level 0 blkid range: [%llu, %llu]\n",
|
||||
record->zi_start, record->zi_end);
|
||||
|
||||
if (level >= dn->dn_nlevels) {
|
||||
(void) fprintf(stderr, "level %d exceeds max level "
|
||||
"of object (%d)\n", level, dn->dn_nlevels - 1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (record->zi_start != 0 || record->zi_end != 0) {
|
||||
int shift = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
|
||||
|
||||
for (; level > 0; level--) {
|
||||
record->zi_start >>= shift;
|
||||
record->zi_end >>= shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (dn) {
|
||||
if (dn != DMU_META_DNODE(os))
|
||||
dnode_rele(dn, FTAG);
|
||||
}
|
||||
if (os)
|
||||
dmu_objset_disown(os, FTAG);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -252,6 +343,8 @@ translate_record(err_type_t type, const char *object, const char *range,
|
||||
struct stat64 statbuf;
|
||||
int ret = -1;
|
||||
|
||||
kernel_init(FREAD);
|
||||
|
||||
debug = (getenv("ZINJECT_DEBUG") != NULL);
|
||||
|
||||
ziprintf("translating: %s\n", object);
|
||||
@@ -303,16 +396,16 @@ translate_record(err_type_t type, const char *object, const char *range,
|
||||
/*
|
||||
* Convert (dataset, file) into (objset, object)
|
||||
*/
|
||||
if (object_from_path(dataset, statbuf.st_ino, record) != 0)
|
||||
if (object_from_path(dataset, path, &statbuf, record) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf("raw objset: %llu\n", record->zi_objset);
|
||||
ziprintf("raw object: %llu\n", record->zi_object);
|
||||
|
||||
/*
|
||||
* For the given object, initialize the range in bytes
|
||||
* For the given object, calculate the real (type, level, range)
|
||||
*/
|
||||
if (initialize_range(type, level, (char *)range, record) != 0)
|
||||
if (calculate_range(dataset, type, level, (char *)range, record) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf(" objset: %llu\n", record->zi_objset);
|
||||
@@ -334,6 +427,7 @@ translate_record(err_type_t type, const char *object, const char *range,
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
kernel_fini();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
+30
-163
@@ -36,15 +36,12 @@
|
||||
*
|
||||
* Errors can be injected into a particular vdev using the '-d' option. This
|
||||
* option takes a path or vdev GUID to uniquely identify the device within a
|
||||
* pool. There are four types of errors that can be injected, IO, ENXIO,
|
||||
* ECHILD, and EILSEQ. These can be controlled through the '-e' option and the
|
||||
* default is ENXIO. For EIO failures, any attempt to read data from the device
|
||||
* will return EIO, but a subsequent attempt to reopen the device will succeed.
|
||||
* For ENXIO failures, any attempt to read from the device will return EIO, but
|
||||
* any attempt to reopen the device will also return ENXIO. The EILSEQ failures
|
||||
* only apply to read operations (-T read) and will flip a bit after the device
|
||||
* has read the original data.
|
||||
*
|
||||
* pool. There are two types of errors that can be injected, EIO and ENXIO,
|
||||
* that can be controlled through the '-e' option. The default is ENXIO. For
|
||||
* EIO failures, any attempt to read data from the device will return EIO, but
|
||||
* subsequent attempt to reopen the device will succeed. For ENXIO failures,
|
||||
* any attempt to read from the device will return EIO, but any attempt to
|
||||
* reopen the device will also return ENXIO.
|
||||
* For label faults, the -L option must be specified. This allows faults
|
||||
* to be injected into either the nvlist, uberblock, pad1, or pad2 region
|
||||
* of all the labels for the specified device.
|
||||
@@ -116,9 +113,9 @@
|
||||
* specified.
|
||||
*
|
||||
* The '-e' option takes a string describing the errno to simulate. This must
|
||||
* be one of 'io', 'checksum', 'decompress', or 'decrypt'. In most cases this
|
||||
* will result in the same behavior, but RAID-Z will produce a different set of
|
||||
* ereports for this situation.
|
||||
* be either 'io' or 'checksum'. In most cases this will result in the same
|
||||
* behavior, but RAID-Z will produce a different set of ereports for this
|
||||
* situation.
|
||||
*
|
||||
* The '-a', '-u', and '-m' flags toggle internal flush behavior. If '-a' is
|
||||
* specified, then the ARC cache is flushed appropriately. If '-u' is
|
||||
@@ -234,12 +231,11 @@ usage(void)
|
||||
"\t\tspa_vdev_exit() will trigger a panic.\n"
|
||||
"\n"
|
||||
"\tzinject -d device [-e errno] [-L <nvlist|uber|pad1|pad2>] [-F]\n"
|
||||
"\t\t[-T <read|write|free|claim|all>] [-f frequency] pool\n\n"
|
||||
"\t [-T <read|write|free|claim|all>] [-f frequency] pool\n"
|
||||
"\t\tInject a fault into a particular device or the device's\n"
|
||||
"\t\tlabel. Label injection can either be 'nvlist', 'uber',\n "
|
||||
"\t\t'pad1', or 'pad2'.\n"
|
||||
"\t\t'errno' can be 'nxio' (the default), 'io', 'dtl', or\n"
|
||||
"\t\t'corrupt' (bit flip).\n"
|
||||
"\t\t'errno' can be 'nxio' (the default), 'io', or 'dtl'.\n"
|
||||
"\t\t'frequency' is a value between 0.0001 and 100.0 that limits\n"
|
||||
"\t\tdevice error injection to a percentage of the IOs.\n"
|
||||
"\n"
|
||||
@@ -291,19 +287,16 @@ usage(void)
|
||||
"\t\tspecified by the remaining tuple. Each number is in\n"
|
||||
"\t\thexadecimal, and only one block can be specified.\n"
|
||||
"\n"
|
||||
"\tzinject [-q] <-t type> [-C dvas] [-e errno] [-l level]\n"
|
||||
"\t\t[-r range] [-a] [-m] [-u] [-f freq] <object>\n"
|
||||
"\tzinject [-q] <-t type> [-e errno] [-l level] [-r range]\n"
|
||||
"\t [-a] [-m] [-u] [-f freq] <object>\n"
|
||||
"\n"
|
||||
"\t\tInject an error into the object specified by the '-t' option\n"
|
||||
"\t\tand the object descriptor. The 'object' parameter is\n"
|
||||
"\t\tinterpreted depending on the '-t' option.\n"
|
||||
"\n"
|
||||
"\t\t-q\tQuiet mode. Only print out the handler number added.\n"
|
||||
"\t\t-e\tInject a specific error. Must be one of 'io',\n"
|
||||
"\t\t\t'checksum', 'decompress', or 'decrypt'. Default is 'io'.\n"
|
||||
"\t\t-C\tInject the given error only into specific DVAs. The\n"
|
||||
"\t\t\tDVAs should be specified as a list of 0-indexed DVAs\n"
|
||||
"\t\t\tseparated by commas (ex. '0,2').\n"
|
||||
"\t\t-e\tInject a specific error. Must be either 'io' or\n"
|
||||
"\t\t\t'checksum'. Default is 'io'.\n"
|
||||
"\t\t-l\tInject error at a particular block level. Default is "
|
||||
"0.\n"
|
||||
"\t\t-m\tAutomatically remount underlying filesystem.\n"
|
||||
@@ -364,20 +357,17 @@ print_data_handler(int id, const char *pool, zinject_record_t *record,
|
||||
return (0);
|
||||
|
||||
if (*count == 0) {
|
||||
(void) printf("%3s %-15s %-6s %-6s %-8s %3s %-4s "
|
||||
"%-15s\n", "ID", "POOL", "OBJSET", "OBJECT", "TYPE",
|
||||
"LVL", "DVAs", "RANGE");
|
||||
(void) printf("%3s %-15s %-6s %-6s %-8s %3s %-15s\n",
|
||||
"ID", "POOL", "OBJSET", "OBJECT", "TYPE", "LVL", "RANGE");
|
||||
(void) printf("--- --------------- ------ "
|
||||
"------ -------- --- ---- ---------------\n");
|
||||
"------ -------- --- ---------------\n");
|
||||
}
|
||||
|
||||
*count += 1;
|
||||
|
||||
(void) printf("%3d %-15s %-6llu %-6llu %-8s %-3d 0x%02x ",
|
||||
id, pool, (u_longlong_t)record->zi_objset,
|
||||
(u_longlong_t)record->zi_object, type_to_name(record->zi_type),
|
||||
record->zi_level, record->zi_dvas);
|
||||
|
||||
(void) printf("%3d %-15s %-6llu %-6llu %-8s %3d ", id, pool,
|
||||
(u_longlong_t)record->zi_objset, (u_longlong_t)record->zi_object,
|
||||
type_to_name(record->zi_type), record->zi_level);
|
||||
|
||||
if (record->zi_start == 0 &&
|
||||
record->zi_end == -1ULL)
|
||||
@@ -567,7 +557,6 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
|
||||
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));
|
||||
return (1);
|
||||
}
|
||||
@@ -608,7 +597,6 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
(void) printf(" range: [%llu, %llu)\n",
|
||||
(u_longlong_t)record->zi_start,
|
||||
(u_longlong_t)record->zi_end);
|
||||
(void) printf(" dvas: 0x%x\n", record->zi_dvas);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -681,59 +669,6 @@ parse_frequency(const char *str, uint32_t *percent)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function converts a string specifier for DVAs into a bit mask.
|
||||
* The dva's provided by the user should be 0 indexed and separated by
|
||||
* a comma. For example:
|
||||
* "1" -> 0b0010 (0x2)
|
||||
* "0,1" -> 0b0011 (0x3)
|
||||
* "0,1,2" -> 0b0111 (0x7)
|
||||
*/
|
||||
static int
|
||||
parse_dvas(const char *str, uint32_t *dvas_out)
|
||||
{
|
||||
const char *c = str;
|
||||
uint32_t mask = 0;
|
||||
boolean_t need_delim = B_FALSE;
|
||||
|
||||
/* max string length is 5 ("0,1,2") */
|
||||
if (strlen(str) > 5 || strlen(str) == 0)
|
||||
return (EINVAL);
|
||||
|
||||
while (*c != '\0') {
|
||||
switch (*c) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
/* check for pipe between DVAs */
|
||||
if (need_delim)
|
||||
return (EINVAL);
|
||||
|
||||
/* check if this DVA has been set already */
|
||||
if (mask & (1 << ((*c) - '0')))
|
||||
return (EINVAL);
|
||||
|
||||
mask |= (1 << ((*c) - '0'));
|
||||
need_delim = B_TRUE;
|
||||
break;
|
||||
case ',':
|
||||
need_delim = B_FALSE;
|
||||
break;
|
||||
default:
|
||||
/* check for invalid character */
|
||||
return (EINVAL);
|
||||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
/* check for dangling delimiter */
|
||||
if (!need_delim)
|
||||
return (EINVAL);
|
||||
|
||||
*dvas_out = mask;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -760,10 +695,9 @@ main(int argc, char **argv)
|
||||
int dur_secs = 0;
|
||||
int ret;
|
||||
int flags = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -791,7 +725,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
while ((c = getopt(argc, argv,
|
||||
":aA:b:C:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) {
|
||||
":aA:b:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
flags |= ZINJECT_FLUSH_ARC;
|
||||
@@ -815,17 +749,6 @@ main(int argc, char **argv)
|
||||
case 'c':
|
||||
cancel = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
ret = parse_dvas(optarg, &dvas);
|
||||
if (ret != 0) {
|
||||
(void) fprintf(stderr, "invalid DVA list '%s': "
|
||||
"DVAs should be 0 indexed and separated by "
|
||||
"commas.\n", optarg);
|
||||
usage();
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
device = optarg;
|
||||
break;
|
||||
@@ -847,16 +770,10 @@ main(int argc, char **argv)
|
||||
error = EIO;
|
||||
} else if (strcasecmp(optarg, "checksum") == 0) {
|
||||
error = ECKSUM;
|
||||
} else if (strcasecmp(optarg, "decompress") == 0) {
|
||||
error = EINVAL;
|
||||
} else if (strcasecmp(optarg, "decrypt") == 0) {
|
||||
error = EACCES;
|
||||
} else if (strcasecmp(optarg, "nxio") == 0) {
|
||||
error = ENXIO;
|
||||
} else if (strcasecmp(optarg, "dtl") == 0) {
|
||||
error = ECHILD;
|
||||
} else if (strcasecmp(optarg, "corrupt") == 0) {
|
||||
error = EILSEQ;
|
||||
} else {
|
||||
(void) fprintf(stderr, "invalid error type "
|
||||
"'%s': must be 'io', 'checksum' or "
|
||||
@@ -926,7 +843,6 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case 'r':
|
||||
range = optarg;
|
||||
flags |= ZINJECT_CALC_RANGE;
|
||||
break;
|
||||
case 's':
|
||||
dur_secs = 1;
|
||||
@@ -1009,7 +925,7 @@ main(int argc, char **argv)
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED ||
|
||||
record.zi_freq > 0 || dvas != 0) {
|
||||
record.zi_freq > 0) {
|
||||
(void) fprintf(stderr, "cancel (-c) incompatible with "
|
||||
"any other options\n");
|
||||
usage();
|
||||
@@ -1044,8 +960,7 @@ main(int argc, char **argv)
|
||||
* for doing injection, so handle it separately here.
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED ||
|
||||
dvas != 0) {
|
||||
level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) {
|
||||
(void) fprintf(stderr, "device (-d) incompatible with "
|
||||
"data error injection\n");
|
||||
usage();
|
||||
@@ -1066,15 +981,7 @@ main(int argc, char **argv)
|
||||
|
||||
if (error == ECKSUM) {
|
||||
(void) fprintf(stderr, "device error type must be "
|
||||
"'io', 'nxio' or 'corrupt'\n");
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (error == EILSEQ &&
|
||||
(record.zi_freq == 0 || io_type != ZIO_TYPE_READ)) {
|
||||
(void) fprintf(stderr, "device corrupt errors require "
|
||||
"io type read and a frequency value\n");
|
||||
"'io' or 'nxio'\n");
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
@@ -1093,7 +1000,7 @@ main(int argc, char **argv)
|
||||
} else if (raw != NULL) {
|
||||
if (range != NULL || type != TYPE_INVAL || level != 0 ||
|
||||
record.zi_cmd != ZINJECT_UNINITIALIZED ||
|
||||
record.zi_freq > 0 || dvas != 0) {
|
||||
record.zi_freq > 0) {
|
||||
(void) fprintf(stderr, "raw (-b) format with "
|
||||
"any other options\n");
|
||||
usage();
|
||||
@@ -1128,8 +1035,7 @@ main(int argc, char **argv)
|
||||
error = EIO;
|
||||
} else if (record.zi_cmd == ZINJECT_PANIC) {
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0 || device != NULL || record.zi_freq > 0 ||
|
||||
dvas != 0) {
|
||||
level != 0 || device != NULL || record.zi_freq > 0) {
|
||||
(void) fprintf(stderr, "panic (-p) incompatible with "
|
||||
"other options\n");
|
||||
usage();
|
||||
@@ -1150,15 +1056,6 @@ main(int argc, char **argv)
|
||||
record.zi_type = atoi(argv[1]);
|
||||
dataset[0] = '\0';
|
||||
} else if (record.zi_cmd == ZINJECT_IGNORED_WRITES) {
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0 || record.zi_freq > 0 || dvas != 0) {
|
||||
(void) fprintf(stderr, "hardware failure (-I) "
|
||||
"incompatible with other options\n");
|
||||
usage();
|
||||
libzfs_fini(g_zfs);
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (nowrites == 0) {
|
||||
(void) fprintf(stderr, "-s or -g meaningless "
|
||||
"without -I (ignore writes)\n");
|
||||
@@ -1212,44 +1109,14 @@ main(int argc, char **argv)
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (error == ENXIO || error == EILSEQ) {
|
||||
if (error == ENXIO) {
|
||||
(void) fprintf(stderr, "data error type must be "
|
||||
"'checksum' or 'io'\n");
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (dvas != 0) {
|
||||
if (error == EACCES || error == EINVAL) {
|
||||
(void) fprintf(stderr, "the '-C' option may "
|
||||
"not be used with logical data errors "
|
||||
"'decrypt' and 'decompress'\n");
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
record.zi_dvas = dvas;
|
||||
}
|
||||
|
||||
if (error == EACCES) {
|
||||
if (type != TYPE_DATA) {
|
||||
(void) fprintf(stderr, "decryption errors "
|
||||
"may only be injected for 'data' types\n");
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
record.zi_cmd = ZINJECT_DECRYPT_FAULT;
|
||||
/*
|
||||
* Internally, ZFS actually uses ECKSUM for decryption
|
||||
* errors since EACCES is used to indicate the key was
|
||||
* not found.
|
||||
*/
|
||||
error = ECKSUM;
|
||||
} else {
|
||||
record.zi_cmd = ZINJECT_DATA_FAULT;
|
||||
}
|
||||
|
||||
record.zi_cmd = ZINJECT_DATA_FAULT;
|
||||
if (translate_record(type, argv[0], range, level, &record, pool,
|
||||
dataset) != 0) {
|
||||
libzfs_fini(g_zfs);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/zpios
|
||||
@@ -0,0 +1,11 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include
|
||||
|
||||
sbin_PROGRAMS = zpios
|
||||
|
||||
zpios_SOURCES = \
|
||||
zpios_main.c \
|
||||
zpios_util.c \
|
||||
zpios.h
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* ZPIOS is a heavily modified version of the original PIOS test code.
|
||||
* It is designed to have the test code running in the Linux kernel
|
||||
* against ZFS while still being flexibly controlled from user space.
|
||||
*
|
||||
* Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC.
|
||||
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
* Written by Brian Behlendorf <behlendorf1@llnl.gov>.
|
||||
* LLNL-CODE-403049
|
||||
*
|
||||
* Original PIOS Test Code
|
||||
* Copyright (C) 2004 Cluster File Systems, Inc.
|
||||
* Written by Peter Braam <braam@clusterfs.com>
|
||||
* Atul Vidwansa <atul@clusterfs.com>
|
||||
* Milind Dumbare <milind@clusterfs.com>
|
||||
*
|
||||
* This file is part of ZFS on Linux.
|
||||
* For details, see <http://zfsonlinux.org/>.
|
||||
*
|
||||
* ZPIOS is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* ZPIOS is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with ZPIOS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (c) 2015, Intel Corporation.
|
||||
*/
|
||||
|
||||
#ifndef _ZPIOS_H
|
||||
#define _ZPIOS_H
|
||||
|
||||
#include <zpios-ctl.h>
|
||||
|
||||
#define VERSION_SIZE 64
|
||||
|
||||
/* Regular expressions */
|
||||
#define REGEX_NUMBERS "^[0-9]+$"
|
||||
#define REGEX_NUMBERS_COMMA "^([0-9]+,)*[0-9]+$"
|
||||
#define REGEX_SIZE "^[0-9]+[kKmMgGtT]?$"
|
||||
#define REGEX_SIZE_COMMA "^([0-9]+[kKmMgGtT]?,)*[0-9]+[kKmMgGtT]?$"
|
||||
|
||||
/* Flags for low, high, incr */
|
||||
#define FLAG_SET 0x01
|
||||
#define FLAG_LOW 0x02
|
||||
#define FLAG_HIGH 0x04
|
||||
#define FLAG_INCR 0x08
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define KB (1024)
|
||||
#define MB (KB * 1024)
|
||||
#define GB (MB * 1024)
|
||||
#define TB (GB * 1024)
|
||||
|
||||
#define KMGT_SIZE 16
|
||||
|
||||
/*
|
||||
* All offsets, sizes and counts can be passed to the application in
|
||||
* multiple ways.
|
||||
* 1. a value (stored in val[0], val_count will be 1)
|
||||
* 2. a comma separated list of values (stored in val[], using val_count)
|
||||
* 3. a range and block sizes, low, high, factor (val_count must be 0)
|
||||
*/
|
||||
typedef struct pios_range_repeat {
|
||||
uint64_t val[32]; /* Comma sep array, or low, high, inc */
|
||||
uint64_t val_count; /* Num of values */
|
||||
uint64_t val_low;
|
||||
uint64_t val_high;
|
||||
uint64_t val_inc_perc;
|
||||
uint64_t next_val; /* For multiple runs in get_next() */
|
||||
} range_repeat_t;
|
||||
|
||||
typedef struct cmd_args {
|
||||
range_repeat_t T; /* Thread count */
|
||||
range_repeat_t N; /* Region count */
|
||||
range_repeat_t O; /* Offset count */
|
||||
range_repeat_t C; /* Chunksize */
|
||||
range_repeat_t S; /* Regionsize */
|
||||
range_repeat_t B; /* Blocksize */
|
||||
|
||||
const char *pool; /* Pool */
|
||||
const char *name; /* Name */
|
||||
uint32_t flags; /* Flags */
|
||||
uint32_t block_size; /* ZFS block size */
|
||||
uint32_t io_type; /* DMUIO only */
|
||||
uint32_t verbose; /* Verbose */
|
||||
uint32_t human_readable; /* Human readable output */
|
||||
|
||||
uint64_t regionnoise; /* Region noise */
|
||||
uint64_t chunknoise; /* Chunk noise */
|
||||
uint64_t thread_delay; /* Thread delay */
|
||||
|
||||
char pre[ZPIOS_PATH_SIZE]; /* Pre-exec hook */
|
||||
char post[ZPIOS_PATH_SIZE]; /* Post-exec hook */
|
||||
char log[ZPIOS_PATH_SIZE]; /* Requested log dir */
|
||||
|
||||
/* Control */
|
||||
int current_id;
|
||||
uint64_t current_T;
|
||||
uint64_t current_N;
|
||||
uint64_t current_C;
|
||||
uint64_t current_S;
|
||||
uint64_t current_O;
|
||||
uint64_t current_B;
|
||||
|
||||
uint32_t rc;
|
||||
} cmd_args_t;
|
||||
|
||||
int set_count(char *pattern1, char *pattern2, range_repeat_t *range,
|
||||
char *optarg, uint32_t *flags, char *arg);
|
||||
int set_lhi(char *pattern, range_repeat_t *range, char *optarg,
|
||||
int flag, uint32_t *flag_thread, char *arg);
|
||||
int set_noise(uint64_t *noise, char *optarg, char *arg);
|
||||
int set_load_params(cmd_args_t *args, char *optarg);
|
||||
int check_mutual_exclusive_command_lines(uint32_t flag, char *arg);
|
||||
void print_stats_header(cmd_args_t *args);
|
||||
void print_stats(cmd_args_t *args, zpios_cmd_t *cmd);
|
||||
|
||||
#endif /* _ZPIOS_H */
|
||||
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* ZPIOS is a heavily modified version of the original PIOS test code.
|
||||
* It is designed to have the test code running in the Linux kernel
|
||||
* against ZFS while still being flexibly controlled from user space.
|
||||
*
|
||||
* Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC.
|
||||
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
* Written by Brian Behlendorf <behlendorf1@llnl.gov>.
|
||||
* LLNL-CODE-403049
|
||||
*
|
||||
* Original PIOS Test Code
|
||||
* Copyright (C) 2004 Cluster File Systems, Inc.
|
||||
* Written by Peter Braam <braam@clusterfs.com>
|
||||
* Atul Vidwansa <atul@clusterfs.com>
|
||||
* Milind Dumbare <milind@clusterfs.com>
|
||||
*
|
||||
* This file is part of ZFS on Linux.
|
||||
* For details, see <http://zfsonlinux.org/>.
|
||||
*
|
||||
* ZPIOS is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* ZPIOS is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with ZPIOS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (c) 2015, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "zpios.h"
|
||||
|
||||
static const char short_opt[] =
|
||||
"t:l:h:e:n:i:j:k:o:m:q:r:c:a:b:g:s:A:B:C:"
|
||||
"S:L:p:M:xP:R:G:I:N:T:VzOfHv?";
|
||||
static const struct option long_opt[] = {
|
||||
{"threadcount", required_argument, 0, 't' },
|
||||
{"threadcount_low", required_argument, 0, 'l' },
|
||||
{"threadcount_high", required_argument, 0, 'h' },
|
||||
{"threadcount_incr", required_argument, 0, 'e' },
|
||||
{"regioncount", required_argument, 0, 'n' },
|
||||
{"regioncount_low", required_argument, 0, 'i' },
|
||||
{"regioncount_high", required_argument, 0, 'j' },
|
||||
{"regioncount_incr", required_argument, 0, 'k' },
|
||||
{"offset", required_argument, 0, 'o' },
|
||||
{"offset_low", required_argument, 0, 'm' },
|
||||
{"offset_high", required_argument, 0, 'q' },
|
||||
{"offset_incr", required_argument, 0, 'r' },
|
||||
{"chunksize", required_argument, 0, 'c' },
|
||||
{"chunksize_low", required_argument, 0, 'a' },
|
||||
{"chunksize_high", required_argument, 0, 'b' },
|
||||
{"chunksize_incr", required_argument, 0, 'g' },
|
||||
{"regionsize", required_argument, 0, 's' },
|
||||
{"regionsize_low", required_argument, 0, 'A' },
|
||||
{"regionsize_high", required_argument, 0, 'B' },
|
||||
{"regionsize_incr", required_argument, 0, 'C' },
|
||||
{"blocksize", required_argument, 0, 'S' },
|
||||
{"load", required_argument, 0, 'L' },
|
||||
{"pool", required_argument, 0, 'p' },
|
||||
{"name", required_argument, 0, 'M' },
|
||||
{"cleanup", no_argument, 0, 'x' },
|
||||
{"prerun", required_argument, 0, 'P' },
|
||||
{"postrun", required_argument, 0, 'R' },
|
||||
{"log", required_argument, 0, 'G' },
|
||||
{"regionnoise", required_argument, 0, 'I' },
|
||||
{"chunknoise", required_argument, 0, 'N' },
|
||||
{"threaddelay", required_argument, 0, 'T' },
|
||||
{"verify", no_argument, 0, 'V' },
|
||||
{"zerocopy", no_argument, 0, 'z' },
|
||||
{"nowait", no_argument, 0, 'O' },
|
||||
{"noprefetch", no_argument, 0, 'f' },
|
||||
{"human-readable", no_argument, 0, 'H' },
|
||||
{"verbose", no_argument, 0, 'v' },
|
||||
{"help", no_argument, 0, '?' },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static int zpiosctl_fd; /* Control file descriptor */
|
||||
static char zpios_version[VERSION_SIZE]; /* Kernel version string */
|
||||
static char *zpios_buffer = NULL; /* Scratch space area */
|
||||
static int zpios_buffer_size = 0; /* Scratch space size */
|
||||
|
||||
static int
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: zpios\n");
|
||||
fprintf(stderr,
|
||||
" --threadcount -t =values\n"
|
||||
" --threadcount_low -l =value\n"
|
||||
" --threadcount_high -h =value\n"
|
||||
" --threadcount_incr -e =value\n"
|
||||
" --regioncount -n =values\n"
|
||||
" --regioncount_low -i =value\n"
|
||||
" --regioncount_high -j =value\n"
|
||||
" --regioncount_incr -k =value\n"
|
||||
" --offset -o =values\n"
|
||||
" --offset_low -m =value\n"
|
||||
" --offset_high -q =value\n"
|
||||
" --offset_incr -r =value\n"
|
||||
" --chunksize -c =values\n"
|
||||
" --chunksize_low -a =value\n"
|
||||
" --chunksize_high -b =value\n"
|
||||
" --chunksize_incr -g =value\n"
|
||||
" --regionsize -s =values\n"
|
||||
" --regionsize_low -A =value\n"
|
||||
" --regionsize_high -B =value\n"
|
||||
" --regionsize_incr -C =value\n"
|
||||
" --blocksize -S =values\n"
|
||||
" --load -L =dmuio|ssf|fpp\n"
|
||||
" --pool -p =pool name\n"
|
||||
" --name -M =test name\n"
|
||||
" --cleanup -x\n"
|
||||
" --prerun -P =pre-command\n"
|
||||
" --postrun -R =post-command\n"
|
||||
" --log -G =log directory\n"
|
||||
" --regionnoise -I =shift\n"
|
||||
" --chunknoise -N =bytes\n"
|
||||
" --threaddelay -T =jiffies\n"
|
||||
" --verify -V\n"
|
||||
" --zerocopy -z\n"
|
||||
" --nowait -O\n"
|
||||
" --noprefetch -f\n"
|
||||
" --human-readable -H\n"
|
||||
" --verbose -v =increase verbosity\n"
|
||||
" --help -? =this help\n\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void args_fini(cmd_args_t *args)
|
||||
{
|
||||
assert(args != NULL);
|
||||
free(args);
|
||||
}
|
||||
|
||||
/* block size is 128K to 16M, power of 2 */
|
||||
#define MIN_BLKSIZE (128ULL << 10)
|
||||
#define MAX_BLKSIZE (16ULL << 20)
|
||||
#define POW_OF_TWO(x) (((x) & ((x) - 1)) == 0)
|
||||
|
||||
static cmd_args_t *
|
||||
args_init(int argc, char **argv)
|
||||
{
|
||||
cmd_args_t *args;
|
||||
uint32_t fl_th = 0;
|
||||
uint32_t fl_rc = 0;
|
||||
uint32_t fl_of = 0;
|
||||
uint32_t fl_rs = 0;
|
||||
uint32_t fl_cs = 0;
|
||||
uint32_t fl_bs = 0;
|
||||
int c, rc, i;
|
||||
|
||||
if (argc == 1) {
|
||||
usage();
|
||||
return ((cmd_args_t *)NULL);
|
||||
}
|
||||
|
||||
/* Configure and populate the args structures */
|
||||
args = malloc(sizeof (*args));
|
||||
if (args == NULL)
|
||||
return (NULL);
|
||||
|
||||
memset(args, 0, sizeof (*args));
|
||||
|
||||
/* provide a default block size of 128K */
|
||||
args->B.next_val = 0;
|
||||
args->B.val[0] = MIN_BLKSIZE;
|
||||
args->B.val_count = 1;
|
||||
|
||||
while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
|
||||
rc = 0;
|
||||
|
||||
switch (c) {
|
||||
case 't': /* --thread count */
|
||||
rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA,
|
||||
&args->T, optarg, &fl_th, "threadcount");
|
||||
break;
|
||||
case 'l': /* --threadcount_low */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->T, optarg,
|
||||
FLAG_LOW, &fl_th, "threadcount_low");
|
||||
break;
|
||||
case 'h': /* --threadcount_high */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->T, optarg,
|
||||
FLAG_HIGH, &fl_th, "threadcount_high");
|
||||
break;
|
||||
case 'e': /* --threadcount_inc */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->T, optarg,
|
||||
FLAG_INCR, &fl_th, "threadcount_incr");
|
||||
break;
|
||||
case 'n': /* --regioncount */
|
||||
rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA,
|
||||
&args->N, optarg, &fl_rc, "regioncount");
|
||||
break;
|
||||
case 'i': /* --regioncount_low */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->N, optarg,
|
||||
FLAG_LOW, &fl_rc, "regioncount_low");
|
||||
break;
|
||||
case 'j': /* --regioncount_high */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->N, optarg,
|
||||
FLAG_HIGH, &fl_rc, "regioncount_high");
|
||||
break;
|
||||
case 'k': /* --regioncount_inc */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->N, optarg,
|
||||
FLAG_INCR, &fl_rc, "regioncount_incr");
|
||||
break;
|
||||
case 'o': /* --offset */
|
||||
rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA,
|
||||
&args->O, optarg, &fl_of, "offset");
|
||||
break;
|
||||
case 'm': /* --offset_low */
|
||||
rc = set_lhi(REGEX_SIZE, &args->O, optarg,
|
||||
FLAG_LOW, &fl_of, "offset_low");
|
||||
break;
|
||||
case 'q': /* --offset_high */
|
||||
rc = set_lhi(REGEX_SIZE, &args->O, optarg,
|
||||
FLAG_HIGH, &fl_of, "offset_high");
|
||||
break;
|
||||
case 'r': /* --offset_inc */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->O, optarg,
|
||||
FLAG_INCR, &fl_of, "offset_incr");
|
||||
break;
|
||||
case 'c': /* --chunksize */
|
||||
rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA,
|
||||
&args->C, optarg, &fl_cs, "chunksize");
|
||||
break;
|
||||
case 'a': /* --chunksize_low */
|
||||
rc = set_lhi(REGEX_SIZE, &args->C, optarg,
|
||||
FLAG_LOW, &fl_cs, "chunksize_low");
|
||||
break;
|
||||
case 'b': /* --chunksize_high */
|
||||
rc = set_lhi(REGEX_SIZE, &args->C, optarg,
|
||||
FLAG_HIGH, &fl_cs, "chunksize_high");
|
||||
break;
|
||||
case 'g': /* --chunksize_inc */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->C, optarg,
|
||||
FLAG_INCR, &fl_cs, "chunksize_incr");
|
||||
break;
|
||||
case 's': /* --regionsize */
|
||||
rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA,
|
||||
&args->S, optarg, &fl_rs, "regionsize");
|
||||
break;
|
||||
case 'A': /* --regionsize_low */
|
||||
rc = set_lhi(REGEX_SIZE, &args->S, optarg,
|
||||
FLAG_LOW, &fl_rs, "regionsize_low");
|
||||
break;
|
||||
case 'B': /* --regionsize_high */
|
||||
rc = set_lhi(REGEX_SIZE, &args->S, optarg,
|
||||
FLAG_HIGH, &fl_rs, "regionsize_high");
|
||||
break;
|
||||
case 'C': /* --regionsize_inc */
|
||||
rc = set_lhi(REGEX_NUMBERS, &args->S, optarg,
|
||||
FLAG_INCR, &fl_rs, "regionsize_incr");
|
||||
break;
|
||||
case 'S': /* --blocksize */
|
||||
rc = set_count(REGEX_SIZE, REGEX_SIZE_COMMA,
|
||||
&args->B, optarg, &fl_bs, "blocksize");
|
||||
break;
|
||||
case 'L': /* --load */
|
||||
rc = set_load_params(args, optarg);
|
||||
break;
|
||||
case 'p': /* --pool */
|
||||
args->pool = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
args->name = optarg;
|
||||
break;
|
||||
case 'x': /* --cleanup */
|
||||
args->flags |= DMU_REMOVE;
|
||||
break;
|
||||
case 'P': /* --prerun */
|
||||
strncpy(args->pre, optarg, ZPIOS_PATH_SIZE - 1);
|
||||
break;
|
||||
case 'R': /* --postrun */
|
||||
strncpy(args->post, optarg, ZPIOS_PATH_SIZE - 1);
|
||||
break;
|
||||
case 'G': /* --log */
|
||||
strncpy(args->log, optarg, ZPIOS_PATH_SIZE - 1);
|
||||
break;
|
||||
case 'I': /* --regionnoise */
|
||||
rc = set_noise(&args->regionnoise, optarg,
|
||||
"regionnoise");
|
||||
break;
|
||||
case 'N': /* --chunknoise */
|
||||
rc = set_noise(&args->chunknoise, optarg, "chunknoise");
|
||||
break;
|
||||
case 'T': /* --threaddelay */
|
||||
rc = set_noise(&args->thread_delay, optarg,
|
||||
"threaddelay");
|
||||
break;
|
||||
case 'V': /* --verify */
|
||||
args->flags |= DMU_VERIFY;
|
||||
break;
|
||||
case 'z': /* --zerocopy */
|
||||
args->flags |= (DMU_WRITE_ZC | DMU_READ_ZC);
|
||||
break;
|
||||
case 'O': /* --nowait */
|
||||
args->flags |= DMU_WRITE_NOWAIT;
|
||||
break;
|
||||
case 'f': /* --noprefetch */
|
||||
args->flags |= DMU_READ_NOPF;
|
||||
break;
|
||||
case 'H': /* --human-readable */
|
||||
args->human_readable = 1;
|
||||
break;
|
||||
case 'v': /* --verbose */
|
||||
args->verbose++;
|
||||
break;
|
||||
case '?':
|
||||
rc = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option '%s'\n",
|
||||
argv[optind - 1]);
|
||||
rc = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
usage();
|
||||
args_fini(args);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
check_mutual_exclusive_command_lines(fl_th, "threadcount");
|
||||
check_mutual_exclusive_command_lines(fl_rc, "regioncount");
|
||||
check_mutual_exclusive_command_lines(fl_of, "offset");
|
||||
check_mutual_exclusive_command_lines(fl_rs, "regionsize");
|
||||
check_mutual_exclusive_command_lines(fl_cs, "chunksize");
|
||||
|
||||
if (args->pool == NULL) {
|
||||
fprintf(stderr, "Error: Pool not specified\n");
|
||||
usage();
|
||||
args_fini(args);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((args->flags & (DMU_WRITE_ZC | DMU_READ_ZC)) &&
|
||||
(args->flags & DMU_VERIFY)) {
|
||||
fprintf(stderr, "Error, --zerocopy incompatible --verify, "
|
||||
"used for performance analysis only\n");
|
||||
usage();
|
||||
args_fini(args);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* validate block size(s) */
|
||||
for (i = 0; i < args->B.val_count; i++) {
|
||||
int bs = args->B.val[i];
|
||||
|
||||
if (bs < MIN_BLKSIZE || bs > MAX_BLKSIZE || !POW_OF_TWO(bs)) {
|
||||
fprintf(stderr, "Error: invalid block size %d\n", bs);
|
||||
args_fini(args);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (args);
|
||||
}
|
||||
|
||||
static int
|
||||
dev_clear(void)
|
||||
{
|
||||
zpios_cfg_t cfg;
|
||||
int rc;
|
||||
|
||||
memset(&cfg, 0, sizeof (cfg));
|
||||
cfg.cfg_magic = ZPIOS_CFG_MAGIC;
|
||||
cfg.cfg_cmd = ZPIOS_CFG_BUFFER_CLEAR;
|
||||
cfg.cfg_arg1 = 0;
|
||||
|
||||
rc = ioctl(zpiosctl_fd, ZPIOS_CFG, &cfg);
|
||||
if (rc)
|
||||
fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
|
||||
(unsigned long) ZPIOS_CFG, cfg.cfg_cmd, errno);
|
||||
|
||||
(void) lseek(zpiosctl_fd, 0, SEEK_SET);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/* Passing a size of zero simply results in querying the current size */
|
||||
static int
|
||||
dev_size(int size)
|
||||
{
|
||||
zpios_cfg_t cfg;
|
||||
int rc;
|
||||
|
||||
memset(&cfg, 0, sizeof (cfg));
|
||||
cfg.cfg_magic = ZPIOS_CFG_MAGIC;
|
||||
cfg.cfg_cmd = ZPIOS_CFG_BUFFER_SIZE;
|
||||
cfg.cfg_arg1 = size;
|
||||
|
||||
rc = ioctl(zpiosctl_fd, ZPIOS_CFG, &cfg);
|
||||
if (rc) {
|
||||
fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
|
||||
(unsigned long) ZPIOS_CFG, cfg.cfg_cmd, errno);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
return (cfg.cfg_rc1);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_fini(void)
|
||||
{
|
||||
if (zpios_buffer)
|
||||
free(zpios_buffer);
|
||||
|
||||
if (zpiosctl_fd != -1) {
|
||||
if (close(zpiosctl_fd) == -1) {
|
||||
fprintf(stderr, "Unable to close %s: %d\n",
|
||||
ZPIOS_DEV, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dev_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
zpiosctl_fd = open(ZPIOS_DEV, O_RDONLY);
|
||||
if (zpiosctl_fd == -1) {
|
||||
fprintf(stderr, "Unable to open %s: %d\n"
|
||||
"Is the zpios module loaded?\n", ZPIOS_DEV, errno);
|
||||
rc = errno;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((rc = dev_clear()))
|
||||
goto error;
|
||||
|
||||
if ((rc = dev_size(0)) < 0)
|
||||
goto error;
|
||||
|
||||
zpios_buffer_size = rc;
|
||||
zpios_buffer = (char *)malloc(zpios_buffer_size);
|
||||
if (zpios_buffer == NULL) {
|
||||
rc = ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
memset(zpios_buffer, 0, zpios_buffer_size);
|
||||
return (0);
|
||||
error:
|
||||
if (zpiosctl_fd != -1) {
|
||||
if (close(zpiosctl_fd) == -1) {
|
||||
fprintf(stderr, "Unable to close %s: %d\n",
|
||||
ZPIOS_DEV, errno);
|
||||
}
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
get_next(uint64_t *val, range_repeat_t *range)
|
||||
{
|
||||
/* if low, incr, high is given */
|
||||
if (range->val_count == 0) {
|
||||
*val = (range->val_low) +
|
||||
(range->val_low * range->next_val / 100);
|
||||
|
||||
if (*val > range->val_high)
|
||||
return (0); /* No more values, limit exceeded */
|
||||
|
||||
if (!range->next_val)
|
||||
range->next_val = range->val_inc_perc;
|
||||
else
|
||||
range->next_val = range->next_val + range->val_inc_perc;
|
||||
|
||||
return (1); /* more values to come */
|
||||
|
||||
/* if only one val is given */
|
||||
} else if (range->val_count == 1) {
|
||||
if (range->next_val)
|
||||
return (0); /* No more values, we only have one */
|
||||
|
||||
*val = range->val[0];
|
||||
range->next_val = 1;
|
||||
return (1); /* more values to come */
|
||||
|
||||
/* if comma separated values are given */
|
||||
} else if (range->val_count > 1) {
|
||||
if (range->next_val > range->val_count - 1)
|
||||
return (0); /* No more values, limit exceeded */
|
||||
|
||||
*val = range->val[range->next_val];
|
||||
range->next_val++;
|
||||
return (1); /* more values to come */
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
run_one(cmd_args_t *args, uint32_t id, uint32_t T, uint32_t N,
|
||||
uint64_t C, uint64_t S, uint64_t O, uint64_t B)
|
||||
{
|
||||
zpios_cmd_t *cmd;
|
||||
int rc, rc2, cmd_size;
|
||||
|
||||
dev_clear();
|
||||
|
||||
cmd_size = sizeof (zpios_cmd_t) +
|
||||
((T + N + 1) * sizeof (zpios_stats_t));
|
||||
cmd = (zpios_cmd_t *)malloc(cmd_size);
|
||||
if (cmd == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
memset(cmd, 0, cmd_size);
|
||||
cmd->cmd_magic = ZPIOS_CMD_MAGIC;
|
||||
snprintf(cmd->cmd_pool, sizeof (cmd->cmd_pool), "%s", args->pool);
|
||||
snprintf(cmd->cmd_pre, sizeof (cmd->cmd_pre), "%s", args->pre);
|
||||
snprintf(cmd->cmd_post, sizeof (cmd->cmd_post), "%s", args->post);
|
||||
snprintf(cmd->cmd_log, sizeof (cmd->cmd_log), "%s", args->log);
|
||||
|
||||
cmd->cmd_id = id;
|
||||
cmd->cmd_chunk_size = C;
|
||||
cmd->cmd_thread_count = T;
|
||||
cmd->cmd_region_count = N;
|
||||
cmd->cmd_region_size = S;
|
||||
cmd->cmd_offset = O;
|
||||
cmd->cmd_block_size = B;
|
||||
cmd->cmd_region_noise = args->regionnoise;
|
||||
cmd->cmd_chunk_noise = args->chunknoise;
|
||||
cmd->cmd_thread_delay = args->thread_delay;
|
||||
cmd->cmd_flags = args->flags;
|
||||
cmd->cmd_data_size = (T + N + 1) * sizeof (zpios_stats_t);
|
||||
|
||||
rc = ioctl(zpiosctl_fd, ZPIOS_CMD, cmd);
|
||||
if (rc)
|
||||
args->rc = errno;
|
||||
|
||||
print_stats(args, cmd);
|
||||
|
||||
if (args->verbose) {
|
||||
rc2 = read(zpiosctl_fd, zpios_buffer, zpios_buffer_size);
|
||||
zpios_buffer[zpios_buffer_size - 1] = '\0';
|
||||
if (rc2 < 0) {
|
||||
fprintf(stdout, "Error reading results: %d\n", rc2);
|
||||
} else if ((rc2 > 0) && (strlen(zpios_buffer) > 0)) {
|
||||
fprintf(stdout, "\n%s\n", zpios_buffer);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
run_offsets(cmd_args_t *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (rc == 0 && get_next(&args->current_O, &args->O)) {
|
||||
rc = run_one(args, args->current_id,
|
||||
args->current_T, args->current_N, args->current_C,
|
||||
args->current_S, args->current_O, args->current_B);
|
||||
args->current_id++;
|
||||
}
|
||||
|
||||
args->O.next_val = 0;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
run_region_counts(cmd_args_t *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (rc == 0 && get_next((uint64_t *)&args->current_N, &args->N))
|
||||
rc = run_offsets(args);
|
||||
|
||||
args->N.next_val = 0;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
run_region_sizes(cmd_args_t *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (rc == 0 && get_next(&args->current_S, &args->S)) {
|
||||
if (args->current_S < args->current_C) {
|
||||
fprintf(stderr, "Error: in any run chunksize must "
|
||||
"be strictly smaller than regionsize.\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
rc = run_region_counts(args);
|
||||
}
|
||||
|
||||
args->S.next_val = 0;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
run_chunk_sizes(cmd_args_t *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (rc == 0 && get_next(&args->current_C, &args->C)) {
|
||||
rc = run_region_sizes(args);
|
||||
}
|
||||
|
||||
args->C.next_val = 0;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
run_block_sizes(cmd_args_t *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (rc == 0 && get_next(&args->current_B, &args->B)) {
|
||||
rc = run_chunk_sizes(args);
|
||||
}
|
||||
|
||||
args->B.next_val = 0;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
run_thread_counts(cmd_args_t *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (rc == 0 && get_next((uint64_t *)&args->current_T, &args->T))
|
||||
rc = run_block_sizes(args);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
cmd_args_t *args;
|
||||
int rc = 0;
|
||||
|
||||
/* Argument init and parsing */
|
||||
if ((args = args_init(argc, argv)) == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Device specific init */
|
||||
if ((rc = dev_init()))
|
||||
goto out;
|
||||
|
||||
/* Generic kernel version string */
|
||||
if (args->verbose)
|
||||
fprintf(stdout, "%s", zpios_version);
|
||||
|
||||
print_stats_header(args);
|
||||
rc = run_thread_counts(args);
|
||||
out:
|
||||
if (args != NULL)
|
||||
args_fini(args);
|
||||
|
||||
dev_fini();
|
||||
return (rc);
|
||||
}
|
||||
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* ZPIOS is a heavily modified version of the original PIOS test code.
|
||||
* It is designed to have the test code running in the Linux kernel
|
||||
* against ZFS while still being flexibly controlled from user space.
|
||||
*
|
||||
* Copyright (C) 2008-2010 Lawrence Livermore National Security, LLC.
|
||||
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
* Written by Brian Behlendorf <behlendorf1@llnl.gov>.
|
||||
* LLNL-CODE-403049
|
||||
*
|
||||
* Original PIOS Test Code
|
||||
* Copyright (C) 2004 Cluster File Systems, Inc.
|
||||
* Written by Peter Braam <braam@clusterfs.com>
|
||||
* Atul Vidwansa <atul@clusterfs.com>
|
||||
* Milind Dumbare <milind@clusterfs.com>
|
||||
*
|
||||
* This file is part of ZFS on Linux.
|
||||
* For details, see <http://zfsonlinux.org/>.
|
||||
*
|
||||
* ZPIOS is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* ZPIOS is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with ZPIOS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (c) 2015, Intel Corporation.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <regex.h>
|
||||
#include "zpios.h"
|
||||
|
||||
/* extracts an unsigned int (64) and K,M,G,T from the string */
|
||||
/* and returns a 64 bit value converted to the proper units */
|
||||
static int
|
||||
kmgt_to_uint64(const char *str, uint64_t *val)
|
||||
{
|
||||
char *endptr;
|
||||
int rc = 0;
|
||||
|
||||
*val = strtoll(str, &endptr, 0);
|
||||
if ((str == endptr) && (*val == 0))
|
||||
return (EINVAL);
|
||||
|
||||
switch (endptr[0]) {
|
||||
case 'k': case 'K':
|
||||
*val = (*val) << 10;
|
||||
break;
|
||||
case 'm': case 'M':
|
||||
*val = (*val) << 20;
|
||||
break;
|
||||
case 'g': case 'G':
|
||||
*val = (*val) << 30;
|
||||
break;
|
||||
case 't': case 'T':
|
||||
*val = (*val) << 40;
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
rc = EINVAL;
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static char *
|
||||
uint64_to_kmgt(char *str, uint64_t val)
|
||||
{
|
||||
char postfix[] = "kmgt";
|
||||
int i = -1;
|
||||
|
||||
while ((val >= KB) && (i < 4)) {
|
||||
val = (val >> 10);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= 4)
|
||||
(void) snprintf(str, KMGT_SIZE-1, "inf");
|
||||
else
|
||||
(void) snprintf(str, KMGT_SIZE-1, "%lu%c", (unsigned long)val,
|
||||
(i == -1) ? '\0' : postfix[i]);
|
||||
|
||||
return (str);
|
||||
}
|
||||
|
||||
static char *
|
||||
kmgt_per_sec(char *str, uint64_t v, double t)
|
||||
{
|
||||
char postfix[] = "kmgt";
|
||||
double val = ((double)v) / t;
|
||||
int i = -1;
|
||||
|
||||
while ((val >= (double)KB) && (i < 4)) {
|
||||
val /= (double)KB;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= 4)
|
||||
(void) snprintf(str, KMGT_SIZE-1, "inf");
|
||||
else
|
||||
(void) snprintf(str, KMGT_SIZE-1, "%.2f%c", val,
|
||||
(i == -1) ? '\0' : postfix[i]);
|
||||
|
||||
return (str);
|
||||
}
|
||||
|
||||
static char *
|
||||
print_flags(char *str, uint32_t flags)
|
||||
{
|
||||
str[0] = (flags & DMU_WRITE) ? 'w' : '-';
|
||||
str[1] = (flags & DMU_READ) ? 'r' : '-';
|
||||
str[2] = (flags & DMU_VERIFY) ? 'v' : '-';
|
||||
str[3] = (flags & DMU_REMOVE) ? 'c' : '-';
|
||||
str[4] = (flags & DMU_FPP) ? 'p' : 's';
|
||||
str[5] = (flags & (DMU_WRITE_ZC | DMU_READ_ZC)) ? 'z' : '-';
|
||||
str[6] = (flags & DMU_WRITE_NOWAIT) ? 'O' : '-';
|
||||
str[7] = '\0';
|
||||
|
||||
return (str);
|
||||
}
|
||||
|
||||
static int
|
||||
regex_match(const char *string, char *pattern)
|
||||
{
|
||||
regex_t re = { 0 };
|
||||
int rc;
|
||||
|
||||
rc = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE);
|
||||
if (rc) {
|
||||
fprintf(stderr, "Error: Couldn't do regcomp, %d\n", rc);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
rc = regexec(&re, string, (size_t)0, NULL, 0);
|
||||
regfree(&re);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/* fills the pios_range_repeat structure of comma separated values */
|
||||
static int
|
||||
split_string(const char *optarg, char *pattern, range_repeat_t *range)
|
||||
{
|
||||
const char comma[] = ",";
|
||||
char *cp, *token[32];
|
||||
int rc, i = 0;
|
||||
|
||||
if ((rc = regex_match(optarg, pattern)))
|
||||
return (rc);
|
||||
|
||||
cp = strdup(optarg);
|
||||
if (cp == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
do {
|
||||
/*
|
||||
* STRTOK(3) Each subsequent call, with a null pointer as the
|
||||
* value of the * first argument, starts searching from the
|
||||
* saved pointer and behaves as described above.
|
||||
*/
|
||||
if (i == 0) {
|
||||
token[i] = strtok(cp, comma);
|
||||
} else {
|
||||
token[i] = strtok(NULL, comma);
|
||||
}
|
||||
} while ((token[i++] != NULL) && (i < 32));
|
||||
|
||||
range->val_count = i - 1;
|
||||
|
||||
for (i = 0; i < range->val_count; i++)
|
||||
kmgt_to_uint64(token[i], &range->val[i]);
|
||||
|
||||
free(cp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
set_count(char *pattern1, char *pattern2, range_repeat_t *range,
|
||||
char *optarg, uint32_t *flags, char *arg)
|
||||
{
|
||||
uint64_t count = range->val_count;
|
||||
|
||||
if (flags)
|
||||
*flags |= FLAG_SET;
|
||||
|
||||
range->next_val = 0;
|
||||
|
||||
if (regex_match(optarg, pattern1) == 0) {
|
||||
kmgt_to_uint64(optarg, &range->val[0]);
|
||||
range->val_count = 1;
|
||||
} else if (split_string(optarg, pattern2, range) < 0) {
|
||||
fprintf(stderr, "Error: Incorrect pattern for %s, '%s'\n",
|
||||
arg, optarg);
|
||||
return (EINVAL);
|
||||
} else if (count == range->val_count) {
|
||||
fprintf(stderr, "Error: input ignored for %s, '%s'\n",
|
||||
arg, optarg);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validates the value with regular expression and sets low, high, incr
|
||||
* according to value at which flag will be set. Sets the flag after.
|
||||
*/
|
||||
int
|
||||
set_lhi(char *pattern, range_repeat_t *range, char *optarg,
|
||||
int flag, uint32_t *flag_thread, char *arg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((rc = regex_match(optarg, pattern))) {
|
||||
fprintf(stderr, "Error: Wrong pattern in %s, '%s'\n",
|
||||
arg, optarg);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case FLAG_LOW:
|
||||
kmgt_to_uint64(optarg, &range->val_low);
|
||||
break;
|
||||
case FLAG_HIGH:
|
||||
kmgt_to_uint64(optarg, &range->val_high);
|
||||
break;
|
||||
case FLAG_INCR:
|
||||
kmgt_to_uint64(optarg, &range->val_inc_perc);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
*flag_thread |= flag;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
set_noise(uint64_t *noise, char *optarg, char *arg)
|
||||
{
|
||||
if (regex_match(optarg, REGEX_NUMBERS) == 0) {
|
||||
kmgt_to_uint64(optarg, noise);
|
||||
} else {
|
||||
fprintf(stderr, "Error: Incorrect pattern for %s\n", arg);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
set_load_params(cmd_args_t *args, char *optarg)
|
||||
{
|
||||
char *param, *search, *searchdup, comma[] = ",";
|
||||
int rc = 0;
|
||||
|
||||
search = strdup(optarg);
|
||||
if (search == NULL)
|
||||
return (ENOMEM);
|
||||
searchdup = search;
|
||||
|
||||
while ((param = strtok(search, comma)) != NULL) {
|
||||
search = NULL;
|
||||
|
||||
if (strcmp("fpp", param) == 0) {
|
||||
args->flags |= DMU_FPP; /* File Per Process/Thread */
|
||||
} else if (strcmp("ssf", param) == 0) {
|
||||
args->flags &= ~DMU_FPP; /* Single Shared File */
|
||||
} else if (strcmp("dmuio", param) == 0) {
|
||||
args->io_type |= DMU_IO;
|
||||
args->flags |= (DMU_WRITE | DMU_READ);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid load: %s\n", param);
|
||||
rc = EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
free(searchdup);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Checks the low, high, increment values against the single value for
|
||||
* mutual exclusion, for e.g threadcount is mutually exclusive to
|
||||
* threadcount_low, ..._high, ..._incr
|
||||
*/
|
||||
int
|
||||
check_mutual_exclusive_command_lines(uint32_t flag, char *arg)
|
||||
{
|
||||
if ((flag & FLAG_SET) && (flag & (FLAG_LOW | FLAG_HIGH | FLAG_INCR))) {
|
||||
fprintf(stderr, "Error: --%s can not be given with --%s_low, "
|
||||
"--%s_high or --%s_incr.\n", arg, arg, arg, arg);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((flag & (FLAG_LOW | FLAG_HIGH | FLAG_INCR)) && !(flag & FLAG_SET)) {
|
||||
if (flag != (FLAG_LOW | FLAG_HIGH | FLAG_INCR)) {
|
||||
fprintf(stderr, "Error: One or more values missing "
|
||||
"from --%s_low, --%s_high, --%s_incr.\n",
|
||||
arg, arg, arg);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
print_stats_header(cmd_args_t *args)
|
||||
{
|
||||
if (args->verbose) {
|
||||
printf(
|
||||
"status name id\tth-cnt\trg-cnt\trg-sz\t"
|
||||
"ch-sz\toffset\trg-no\tch-no\tth-dly\tflags\tblksz\ttime\t"
|
||||
"cr-time\trm-time\twr-time\trd-time\twr-data\twr-ch\t"
|
||||
"wr-bw\trd-data\trd-ch\trd-bw\n");
|
||||
printf(
|
||||
"-------------------------------------------------"
|
||||
"-------------------------------------------------"
|
||||
"-------------------------------------------------"
|
||||
"--------------------------------------------------\n");
|
||||
} else {
|
||||
printf(
|
||||
"status name id\t"
|
||||
"wr-data\twr-ch\twr-bw\t"
|
||||
"rd-data\trd-ch\trd-bw\n");
|
||||
printf(
|
||||
"-----------------------------------------"
|
||||
"--------------------------------------\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_stats_human_readable(cmd_args_t *args, zpios_cmd_t *cmd)
|
||||
{
|
||||
zpios_stats_t *summary_stats;
|
||||
double t_time, wr_time, rd_time, cr_time, rm_time;
|
||||
char str[KMGT_SIZE];
|
||||
|
||||
if (args->rc)
|
||||
printf("FAIL: %3d ", args->rc);
|
||||
else
|
||||
printf("PASS: ");
|
||||
|
||||
printf("%-12s", args->name ? args->name : ZPIOS_NAME);
|
||||
printf("%2u\t", cmd->cmd_id);
|
||||
|
||||
if (args->verbose) {
|
||||
printf("%u\t", cmd->cmd_thread_count);
|
||||
printf("%u\t", cmd->cmd_region_count);
|
||||
printf("%s\t", uint64_to_kmgt(str, cmd->cmd_region_size));
|
||||
printf("%s\t", uint64_to_kmgt(str, cmd->cmd_chunk_size));
|
||||
printf("%s\t", uint64_to_kmgt(str, cmd->cmd_offset));
|
||||
printf("%s\t", uint64_to_kmgt(str, cmd->cmd_region_noise));
|
||||
printf("%s\t", uint64_to_kmgt(str, cmd->cmd_chunk_noise));
|
||||
printf("%s\t", uint64_to_kmgt(str, cmd->cmd_thread_delay));
|
||||
printf("%s\t", print_flags(str, cmd->cmd_flags));
|
||||
printf("%s\t", uint64_to_kmgt(str, cmd->cmd_block_size));
|
||||
}
|
||||
|
||||
if (args->rc) {
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
summary_stats = (zpios_stats_t *)cmd->cmd_data_str;
|
||||
t_time = zpios_timespec_to_double(summary_stats->total_time.delta);
|
||||
wr_time = zpios_timespec_to_double(summary_stats->wr_time.delta);
|
||||
rd_time = zpios_timespec_to_double(summary_stats->rd_time.delta);
|
||||
cr_time = zpios_timespec_to_double(summary_stats->cr_time.delta);
|
||||
rm_time = zpios_timespec_to_double(summary_stats->rm_time.delta);
|
||||
|
||||
if (args->verbose) {
|
||||
printf("%.2f\t", t_time);
|
||||
printf("%.3f\t", cr_time);
|
||||
printf("%.3f\t", rm_time);
|
||||
printf("%.2f\t", wr_time);
|
||||
printf("%.2f\t", rd_time);
|
||||
}
|
||||
|
||||
printf("%s\t", uint64_to_kmgt(str, summary_stats->wr_data));
|
||||
printf("%s\t", uint64_to_kmgt(str, summary_stats->wr_chunks));
|
||||
printf("%s\t", kmgt_per_sec(str, summary_stats->wr_data, wr_time));
|
||||
|
||||
printf("%s\t", uint64_to_kmgt(str, summary_stats->rd_data));
|
||||
printf("%s\t", uint64_to_kmgt(str, summary_stats->rd_chunks));
|
||||
printf("%s\n", kmgt_per_sec(str, summary_stats->rd_data, rd_time));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
print_stats_table(cmd_args_t *args, zpios_cmd_t *cmd)
|
||||
{
|
||||
zpios_stats_t *summary_stats;
|
||||
double wr_time, rd_time;
|
||||
|
||||
if (args->rc)
|
||||
printf("FAIL: %3d ", args->rc);
|
||||
else
|
||||
printf("PASS: ");
|
||||
|
||||
printf("%-12s", args->name ? args->name : ZPIOS_NAME);
|
||||
printf("%2u\t", cmd->cmd_id);
|
||||
|
||||
if (args->verbose) {
|
||||
printf("%u\t", cmd->cmd_thread_count);
|
||||
printf("%u\t", cmd->cmd_region_count);
|
||||
printf("%llu\t", (long long unsigned)cmd->cmd_region_size);
|
||||
printf("%llu\t", (long long unsigned)cmd->cmd_chunk_size);
|
||||
printf("%llu\t", (long long unsigned)cmd->cmd_offset);
|
||||
printf("%u\t", cmd->cmd_region_noise);
|
||||
printf("%u\t", cmd->cmd_chunk_noise);
|
||||
printf("%u\t", cmd->cmd_thread_delay);
|
||||
printf("0x%x\t", cmd->cmd_flags);
|
||||
printf("%u\t", cmd->cmd_block_size);
|
||||
}
|
||||
|
||||
if (args->rc) {
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
summary_stats = (zpios_stats_t *)cmd->cmd_data_str;
|
||||
wr_time = zpios_timespec_to_double(summary_stats->wr_time.delta);
|
||||
rd_time = zpios_timespec_to_double(summary_stats->rd_time.delta);
|
||||
|
||||
if (args->verbose) {
|
||||
printf("%ld.%02ld\t",
|
||||
(long)summary_stats->total_time.delta.ts_sec,
|
||||
(long)summary_stats->total_time.delta.ts_nsec);
|
||||
printf("%ld.%02ld\t",
|
||||
(long)summary_stats->cr_time.delta.ts_sec,
|
||||
(long)summary_stats->cr_time.delta.ts_nsec);
|
||||
printf("%ld.%02ld\t",
|
||||
(long)summary_stats->rm_time.delta.ts_sec,
|
||||
(long)summary_stats->rm_time.delta.ts_nsec);
|
||||
printf("%ld.%02ld\t",
|
||||
(long)summary_stats->wr_time.delta.ts_sec,
|
||||
(long)summary_stats->wr_time.delta.ts_nsec);
|
||||
printf("%ld.%02ld\t",
|
||||
(long)summary_stats->rd_time.delta.ts_sec,
|
||||
(long)summary_stats->rd_time.delta.ts_nsec);
|
||||
}
|
||||
|
||||
printf("%lld\t", (long long unsigned)summary_stats->wr_data);
|
||||
printf("%lld\t", (long long unsigned)summary_stats->wr_chunks);
|
||||
printf("%.4f\t", (double)summary_stats->wr_data / wr_time);
|
||||
|
||||
printf("%lld\t", (long long unsigned)summary_stats->rd_data);
|
||||
printf("%lld\t", (long long unsigned)summary_stats->rd_chunks);
|
||||
printf("%.4f\n", (double)summary_stats->rd_data / rd_time);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
print_stats(cmd_args_t *args, zpios_cmd_t *cmd)
|
||||
{
|
||||
if (args->human_readable)
|
||||
print_stats_human_readable(args, cmd);
|
||||
else
|
||||
print_stats_table(args, cmd);
|
||||
}
|
||||
@@ -16,12 +16,13 @@ zpool_SOURCES = \
|
||||
zpool_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
|
||||
zpool_LDADD += -lm $(LIBBLKID)
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la \
|
||||
-lm $(LIBBLKID)
|
||||
|
||||
zpoolconfdir = $(sysconfdir)/zfs/zpool.d
|
||||
zpoolexecdir = $(zfsexecdir)/zpool.d
|
||||
zpoolexecdir = $(libexecdir)/zfs/zpool.d
|
||||
|
||||
EXTRA_DIST = zpool.d/README
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ if [ "$1" = "-h" ] ; then
|
||||
exit
|
||||
fi
|
||||
|
||||
smartctl_path=$(command -v smartctl)
|
||||
smartctl_path=$(which smartctl)
|
||||
|
||||
if [ -b "$VDEV_UPATH" ] && [ -x "$smartctl_path" ] || [ -n "$samples" ] ; then
|
||||
if [ -n "$samples" ] ; then
|
||||
@@ -228,7 +228,7 @@ smart_test)
|
||||
esac
|
||||
|
||||
with_vals=$(echo "$out" | grep -E "$scripts")
|
||||
if [ -n "$with_vals" ]; then
|
||||
if [ ! -z "$with_vals" ]; then
|
||||
echo "$with_vals"
|
||||
without_vals=$(echo "$scripts" | tr "|" "\n" |
|
||||
grep -v -E "$(echo "$with_vals" |
|
||||
@@ -237,6 +237,6 @@ else
|
||||
without_vals=$(echo "$scripts" | tr "|" "\n" | awk '{print $0"="}')
|
||||
fi
|
||||
|
||||
if [ -n "$without_vals" ]; then
|
||||
if [ ! -z "$without_vals" ]; then
|
||||
echo "$without_vals"
|
||||
fi
|
||||
|
||||
+20
-9
@@ -33,10 +33,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <thread_pool.h>
|
||||
|
||||
#include <libzfs.h>
|
||||
#include <libzutil.h>
|
||||
#include <sys/zfs_context.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
@@ -670,21 +668,34 @@ all_pools_for_each_vdev_gather_cb(zpool_handle_t *zhp, void *cb_vcdl)
|
||||
static void
|
||||
all_pools_for_each_vdev_run_vcdl(vdev_cmd_data_list_t *vcdl)
|
||||
{
|
||||
tpool_t *t;
|
||||
taskq_t *t;
|
||||
int i;
|
||||
/* 5 * boot_ncpus selfishly chosen since it works best on LLNL's HW */
|
||||
int max_threads = 5 * boot_ncpus;
|
||||
|
||||
t = tpool_create(1, 5 * sysconf(_SC_NPROCESSORS_ONLN), 0, NULL);
|
||||
/*
|
||||
* Under Linux we use a taskq to parallelize running a command
|
||||
* on each vdev. It is therefore necessary to initialize this
|
||||
* functionality for the duration of the threads.
|
||||
*/
|
||||
thread_init();
|
||||
|
||||
t = taskq_create("z_pool_cmd", max_threads, defclsyspri, max_threads,
|
||||
INT_MAX, 0);
|
||||
if (t == NULL)
|
||||
return;
|
||||
|
||||
/* Spawn off the command for each vdev */
|
||||
for (int i = 0; i < vcdl->count; i++) {
|
||||
(void) tpool_dispatch(t, vdev_run_cmd_thread,
|
||||
(void *) &vcdl->data[i]);
|
||||
for (i = 0; i < vcdl->count; i++) {
|
||||
(void) taskq_dispatch(t, vdev_run_cmd_thread,
|
||||
(void *) &vcdl->data[i], TQ_SLEEP);
|
||||
}
|
||||
|
||||
/* Wait for threads to finish */
|
||||
tpool_wait(t);
|
||||
tpool_destroy(t);
|
||||
taskq_wait(t);
|
||||
taskq_destroy(t);
|
||||
thread_fini();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+342
-1645
File diff suppressed because it is too large
Load Diff
@@ -111,29 +111,3 @@ isnumber(char *str)
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find highest one bit set.
|
||||
* Returns bit number + 1 of highest bit that is set, otherwise returns 0.
|
||||
*/
|
||||
int
|
||||
highbit64(uint64_t i)
|
||||
{
|
||||
if (i == 0)
|
||||
return (0);
|
||||
|
||||
return (NBBY * sizeof (uint64_t) - __builtin_clzll(i));
|
||||
}
|
||||
|
||||
/*
|
||||
* Find lowest one bit set.
|
||||
* Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
|
||||
*/
|
||||
int
|
||||
lowbit64(uint64_t i)
|
||||
{
|
||||
if (i == 0)
|
||||
return (0);
|
||||
|
||||
return (__builtin_ffsll(i));
|
||||
}
|
||||
|
||||
@@ -43,8 +43,6 @@ 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);
|
||||
|
||||
/*
|
||||
* Misc utility functions
|
||||
|
||||
+19
-120
@@ -21,8 +21,8 @@
|
||||
|
||||
/*
|
||||
* 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 (c) 2013, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
|
||||
*/
|
||||
|
||||
@@ -69,7 +69,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <libintl.h>
|
||||
#include <libnvpair.h>
|
||||
#include <libzutil.h>
|
||||
#include <limits.h>
|
||||
#include <sys/spa.h>
|
||||
#include <scsi/scsi.h>
|
||||
@@ -189,7 +188,6 @@ static vdev_disk_db_entry_t vdev_disk_database[] = {
|
||||
{"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},
|
||||
@@ -420,25 +418,19 @@ check_disk(const char *path, blkid_cache cache, int force,
|
||||
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) {
|
||||
if ((fd = open(path, O_RDONLY|O_DIRECT|O_EXCL)) < 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
|
||||
* 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);
|
||||
@@ -554,7 +546,7 @@ is_spare(nvlist_t *config, const char *path)
|
||||
uint_t i, nspares;
|
||||
boolean_t inuse;
|
||||
|
||||
if ((fd = open(path, O_RDONLY|O_DIRECT)) < 0)
|
||||
if ((fd = open(path, O_RDONLY)) < 0)
|
||||
return (B_FALSE);
|
||||
|
||||
if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0 ||
|
||||
@@ -691,9 +683,6 @@ make_leaf_vdev(nvlist_t *props, const char *arg, uint64_t is_log)
|
||||
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
|
||||
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
|
||||
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
|
||||
if (is_log)
|
||||
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||
VDEV_ALLOC_BIAS_LOG) == 0);
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0)
|
||||
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
(uint64_t)wholedisk) == 0);
|
||||
@@ -752,9 +741,6 @@ make_leaf_vdev(nvlist_t *props, const char *arg, uint64_t is_log)
|
||||
*
|
||||
* Otherwise, make sure that the current spec (if there is one) and the new
|
||||
* spec have consistent replication levels.
|
||||
*
|
||||
* If there is no current spec (create), make sure new spec has at least
|
||||
* one general purpose vdev.
|
||||
*/
|
||||
typedef struct replication_level {
|
||||
char *zprl_type;
|
||||
@@ -829,7 +815,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
|
||||
@@ -859,12 +845,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;
|
||||
|
||||
@@ -955,7 +941,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
* (~16MB) then report an error.
|
||||
*/
|
||||
if (!dontreport &&
|
||||
(vdev_size != -1LL &&
|
||||
(vdev_size != -1ULL &&
|
||||
(labs(size - vdev_size) >
|
||||
ZPOOL_FUZZ))) {
|
||||
if (ret != NULL)
|
||||
@@ -978,7 +964,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
|
||||
/*
|
||||
* At this point, we have the replication of the last toplevel
|
||||
* vdev in 'rep'. Compare it to 'lastrep' to see if it is
|
||||
* vdev in 'rep'. Compare it to 'lastrep' to see if its
|
||||
* different.
|
||||
*/
|
||||
if (lastrep.zprl_type != NULL) {
|
||||
@@ -1287,7 +1273,7 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
|
||||
* symbolic link will be removed, partition table created,
|
||||
* and then block until udev creates the new link.
|
||||
*/
|
||||
if (!is_exclusive && !is_spare(NULL, udevpath)) {
|
||||
if (!is_exclusive || !is_spare(NULL, udevpath)) {
|
||||
char *devnode = strrchr(devpath, '/') + 1;
|
||||
|
||||
ret = strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT));
|
||||
@@ -1479,13 +1465,6 @@ is_grouping(const char *type, int *mindev, int *maxdev)
|
||||
return (VDEV_TYPE_LOG);
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_ALLOC_BIAS_SPECIAL) == 0 ||
|
||||
strcmp(type, VDEV_ALLOC_BIAS_DEDUP) == 0) {
|
||||
if (mindev != NULL)
|
||||
*mindev = 1;
|
||||
return (type);
|
||||
}
|
||||
|
||||
if (strcmp(type, "cache") == 0) {
|
||||
if (mindev != NULL)
|
||||
*mindev = 1;
|
||||
@@ -1507,7 +1486,7 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
|
||||
int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
|
||||
const char *type;
|
||||
uint64_t is_log, is_special, is_dedup;
|
||||
uint64_t is_log;
|
||||
boolean_t seen_logs;
|
||||
|
||||
top = NULL;
|
||||
@@ -1517,7 +1496,7 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
nspares = 0;
|
||||
nlogs = 0;
|
||||
nl2cache = 0;
|
||||
is_log = is_special = is_dedup = B_FALSE;
|
||||
is_log = B_FALSE;
|
||||
seen_logs = B_FALSE;
|
||||
nvroot = NULL;
|
||||
|
||||
@@ -1540,7 +1519,7 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
"specified only once\n"));
|
||||
goto spec_out;
|
||||
}
|
||||
is_log = is_special = is_dedup = B_FALSE;
|
||||
is_log = B_FALSE;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_LOG) == 0) {
|
||||
@@ -1553,8 +1532,6 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
}
|
||||
seen_logs = B_TRUE;
|
||||
is_log = B_TRUE;
|
||||
is_special = B_FALSE;
|
||||
is_dedup = B_FALSE;
|
||||
argc--;
|
||||
argv++;
|
||||
/*
|
||||
@@ -1564,24 +1541,6 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_ALLOC_BIAS_SPECIAL) == 0) {
|
||||
is_special = B_TRUE;
|
||||
is_log = B_FALSE;
|
||||
is_dedup = B_FALSE;
|
||||
argc--;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_ALLOC_BIAS_DEDUP) == 0) {
|
||||
is_dedup = B_TRUE;
|
||||
is_log = B_FALSE;
|
||||
is_special = B_FALSE;
|
||||
argc--;
|
||||
argv++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
|
||||
if (l2cache != NULL) {
|
||||
(void) fprintf(stderr,
|
||||
@@ -1590,16 +1549,15 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
"specified only once\n"));
|
||||
goto spec_out;
|
||||
}
|
||||
is_log = is_special = is_dedup = B_FALSE;
|
||||
is_log = B_FALSE;
|
||||
}
|
||||
|
||||
if (is_log || is_special || is_dedup) {
|
||||
if (is_log) {
|
||||
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: unsupported '%s' "
|
||||
"device: %s\n"), is_log ? "log" :
|
||||
"special", type);
|
||||
"specification: unsupported 'log' "
|
||||
"device: %s\n"), type);
|
||||
goto spec_out;
|
||||
}
|
||||
nlogs++;
|
||||
@@ -1656,27 +1614,12 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
nl2cache = children;
|
||||
continue;
|
||||
} else {
|
||||
/* create a top-level vdev with children */
|
||||
verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
|
||||
0) == 0);
|
||||
verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
|
||||
type) == 0);
|
||||
verify(nvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_IS_LOG, is_log) == 0);
|
||||
if (is_log)
|
||||
verify(nvlist_add_string(nv,
|
||||
ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||
VDEV_ALLOC_BIAS_LOG) == 0);
|
||||
if (is_special) {
|
||||
verify(nvlist_add_string(nv,
|
||||
ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||
VDEV_ALLOC_BIAS_SPECIAL) == 0);
|
||||
}
|
||||
if (is_dedup) {
|
||||
verify(nvlist_add_string(nv,
|
||||
ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||
VDEV_ALLOC_BIAS_DEDUP) == 0);
|
||||
}
|
||||
if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
|
||||
verify(nvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_NPARITY,
|
||||
@@ -1701,16 +1644,6 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
|
||||
if (is_log)
|
||||
nlogs++;
|
||||
if (is_special) {
|
||||
verify(nvlist_add_string(nv,
|
||||
ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||
VDEV_ALLOC_BIAS_SPECIAL) == 0);
|
||||
}
|
||||
if (is_dedup) {
|
||||
verify(nvlist_add_string(nv,
|
||||
ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||
VDEV_ALLOC_BIAS_DEDUP) == 0);
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
@@ -1811,30 +1744,6 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
|
||||
return (newroot);
|
||||
}
|
||||
|
||||
static int
|
||||
num_normal_vdevs(nvlist_t *nvroot)
|
||||
{
|
||||
nvlist_t **top;
|
||||
uint_t t, toplevels, normal = 0;
|
||||
|
||||
verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
|
||||
&top, &toplevels) == 0);
|
||||
|
||||
for (t = 0; t < toplevels; t++) {
|
||||
uint64_t log = B_FALSE;
|
||||
|
||||
(void) nvlist_lookup_uint64(top[t], ZPOOL_CONFIG_IS_LOG, &log);
|
||||
if (log)
|
||||
continue;
|
||||
if (nvlist_exists(top[t], ZPOOL_CONFIG_ALLOCATION_BIAS))
|
||||
continue;
|
||||
|
||||
normal++;
|
||||
}
|
||||
|
||||
return (normal);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and validate the contents of the given vdev specification. This ensures
|
||||
* that the nvlist returned is well-formed, that all the devices exist, and that
|
||||
@@ -1867,7 +1776,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.
|
||||
@@ -1887,16 +1796,6 @@ make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* On pool create the new vdev spec must have one normal vdev.
|
||||
*/
|
||||
if (poolconfig == NULL && num_normal_vdevs(newroot) == 0) {
|
||||
vdev_error(gettext("at least one general top-level vdev must "
|
||||
"be specified\n"));
|
||||
nvlist_free(newroot);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run through the vdev specification and label any whole disks found.
|
||||
*/
|
||||
|
||||
@@ -11,4 +11,7 @@ zstreamdump_SOURCES = \
|
||||
|
||||
zstreamdump_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
+51
-174
@@ -53,6 +53,7 @@
|
||||
*/
|
||||
#define DUMP_GROUPING 4
|
||||
|
||||
uint64_t total_write_size = 0;
|
||||
uint64_t total_stream_len = 0;
|
||||
FILE *send_stream = 0;
|
||||
boolean_t do_byteswap = B_FALSE;
|
||||
@@ -196,36 +197,12 @@ print_block(char *buf, int length)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an array of bytes to stdout as hexadecimal characters. str must
|
||||
* have buf_len * 2 + 1 bytes of space.
|
||||
*/
|
||||
static void
|
||||
sprintf_bytes(char *str, uint8_t *buf, uint_t buf_len)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
for (i = 0; i < buf_len; i++) {
|
||||
n = sprintf(str, "%02x", buf[i] & 0xff);
|
||||
str += n;
|
||||
}
|
||||
|
||||
str[0] = '\0';
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *buf = safe_malloc(SPA_MAXBLOCKSIZE);
|
||||
uint64_t drr_record_count[DRR_NUMTYPES] = { 0 };
|
||||
uint64_t total_payload_size = 0;
|
||||
uint64_t total_overhead_size = 0;
|
||||
uint64_t drr_byte_count[DRR_NUMTYPES] = { 0 };
|
||||
char salt[ZIO_DATA_SALT_LEN * 2 + 1];
|
||||
char iv[ZIO_DATA_IV_LEN * 2 + 1];
|
||||
char mac[ZIO_DATA_MAC_LEN * 2 + 1];
|
||||
uint64_t total_records = 0;
|
||||
uint64_t payload_size;
|
||||
dmu_replay_record_t thedrr;
|
||||
dmu_replay_record_t *drr = &thedrr;
|
||||
struct drr_begin *drrb = &thedrr.drr_u.drr_begin;
|
||||
@@ -237,9 +214,8 @@ main(int argc, char *argv[])
|
||||
struct drr_free *drrf = &thedrr.drr_u.drr_free;
|
||||
struct drr_spill *drrs = &thedrr.drr_u.drr_spill;
|
||||
struct drr_write_embedded *drrwe = &thedrr.drr_u.drr_write_embedded;
|
||||
struct drr_object_range *drror = &thedrr.drr_u.drr_object_range;
|
||||
struct drr_checksum *drrc = &thedrr.drr_u.drr_checksum;
|
||||
int c;
|
||||
char c;
|
||||
boolean_t verbose = B_FALSE;
|
||||
boolean_t very_verbose = B_FALSE;
|
||||
boolean_t first = B_TRUE;
|
||||
@@ -338,9 +314,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
drr_record_count[drr->drr_type]++;
|
||||
total_overhead_size += sizeof (*drr);
|
||||
total_records++;
|
||||
payload_size = 0;
|
||||
|
||||
switch (drr->drr_type) {
|
||||
case DRR_BEGIN:
|
||||
@@ -388,13 +362,10 @@ main(int argc, char *argv[])
|
||||
if (ferror(send_stream))
|
||||
perror("fread");
|
||||
err = nvlist_unpack(buf, sz, &nv, 0);
|
||||
if (err) {
|
||||
if (err)
|
||||
perror(strerror(err));
|
||||
} else {
|
||||
nvlist_print(stdout, nv);
|
||||
nvlist_free(nv);
|
||||
}
|
||||
payload_size = sz;
|
||||
nvlist_print(stdout, nv);
|
||||
nvlist_free(nv);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -447,39 +418,26 @@ main(int argc, char *argv[])
|
||||
drro->drr_blksz = BSWAP_32(drro->drr_blksz);
|
||||
drro->drr_bonuslen =
|
||||
BSWAP_32(drro->drr_bonuslen);
|
||||
drro->drr_raw_bonuslen =
|
||||
BSWAP_32(drro->drr_raw_bonuslen);
|
||||
drro->drr_toguid = BSWAP_64(drro->drr_toguid);
|
||||
drro->drr_maxblkid =
|
||||
BSWAP_64(drro->drr_maxblkid);
|
||||
}
|
||||
|
||||
payload_size = DRR_OBJECT_PAYLOAD_SIZE(drro);
|
||||
|
||||
if (verbose) {
|
||||
(void) printf("OBJECT object = %llu type = %u "
|
||||
"bonustype = %u blksz = %u bonuslen = %u "
|
||||
"dn_slots = %u raw_bonuslen = %u "
|
||||
"flags = %u maxblkid = %llu "
|
||||
"indblkshift = %u nlevels = %u "
|
||||
"nblkptr = %u\n",
|
||||
"dn_slots = %u\n",
|
||||
(u_longlong_t)drro->drr_object,
|
||||
drro->drr_type,
|
||||
drro->drr_bonustype,
|
||||
drro->drr_blksz,
|
||||
drro->drr_bonuslen,
|
||||
drro->drr_dn_slots,
|
||||
drro->drr_raw_bonuslen,
|
||||
drro->drr_flags,
|
||||
(u_longlong_t)drro->drr_maxblkid,
|
||||
drro->drr_indblkshift,
|
||||
drro->drr_nlevels,
|
||||
drro->drr_nblkptr);
|
||||
drro->drr_dn_slots);
|
||||
}
|
||||
if (drro->drr_bonuslen > 0) {
|
||||
(void) ssread(buf, payload_size, &zc);
|
||||
if (dump)
|
||||
print_block(buf, payload_size);
|
||||
(void) ssread(buf,
|
||||
P2ROUNDUP(drro->drr_bonuslen, 8), &zc);
|
||||
if (dump) {
|
||||
print_block(buf,
|
||||
P2ROUNDUP(drro->drr_bonuslen, 8));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -513,40 +471,28 @@ main(int argc, char *argv[])
|
||||
BSWAP_64(drrw->drr_compressed_size);
|
||||
}
|
||||
|
||||
payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
|
||||
uint64_t payload_size = DRR_WRITE_PAYLOAD_SIZE(drrw);
|
||||
|
||||
/*
|
||||
* If this is verbose and/or dump output,
|
||||
* print info on the modified block
|
||||
*/
|
||||
if (verbose) {
|
||||
sprintf_bytes(salt, drrw->drr_salt,
|
||||
ZIO_DATA_SALT_LEN);
|
||||
sprintf_bytes(iv, drrw->drr_iv,
|
||||
ZIO_DATA_IV_LEN);
|
||||
sprintf_bytes(mac, drrw->drr_mac,
|
||||
ZIO_DATA_MAC_LEN);
|
||||
|
||||
(void) printf("WRITE object = %llu type = %u "
|
||||
"checksum type = %u compression type = %u "
|
||||
"flags = %u offset = %llu "
|
||||
"logical_size = %llu "
|
||||
"checksum type = %u compression type = %u\n"
|
||||
" offset = %llu logical_size = %llu "
|
||||
"compressed_size = %llu "
|
||||
"payload_size = %llu props = %llx "
|
||||
"salt = %s iv = %s mac = %s\n",
|
||||
"payload_size = %llu "
|
||||
"props = %llx\n",
|
||||
(u_longlong_t)drrw->drr_object,
|
||||
drrw->drr_type,
|
||||
drrw->drr_checksumtype,
|
||||
drrw->drr_compressiontype,
|
||||
drrw->drr_flags,
|
||||
(u_longlong_t)drrw->drr_offset,
|
||||
(u_longlong_t)drrw->drr_logical_size,
|
||||
(u_longlong_t)drrw->drr_compressed_size,
|
||||
(u_longlong_t)payload_size,
|
||||
(u_longlong_t)drrw->drr_key.ddk_prop,
|
||||
salt,
|
||||
iv,
|
||||
mac);
|
||||
(u_longlong_t)drrw->drr_key.ddk_prop);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -559,6 +505,7 @@ main(int argc, char *argv[])
|
||||
if (dump) {
|
||||
print_block(buf, payload_size);
|
||||
}
|
||||
total_write_size += payload_size;
|
||||
break;
|
||||
|
||||
case DRR_WRITE_BYREF:
|
||||
@@ -582,10 +529,10 @@ main(int argc, char *argv[])
|
||||
}
|
||||
if (verbose) {
|
||||
(void) printf("WRITE_BYREF object = %llu "
|
||||
"checksum type = %u props = %llx "
|
||||
"offset = %llu length = %llu "
|
||||
"toguid = %llx refguid = %llx "
|
||||
"refobject = %llu refoffset = %llu\n",
|
||||
"checksum type = %u props = %llx\n"
|
||||
" offset = %llu length = %llu\n"
|
||||
"toguid = %llx refguid = %llx\n"
|
||||
" refobject = %llu refoffset = %llu\n",
|
||||
(u_longlong_t)drrwbr->drr_object,
|
||||
drrwbr->drr_checksumtype,
|
||||
(u_longlong_t)drrwbr->drr_key.ddk_prop,
|
||||
@@ -616,40 +563,16 @@ main(int argc, char *argv[])
|
||||
if (do_byteswap) {
|
||||
drrs->drr_object = BSWAP_64(drrs->drr_object);
|
||||
drrs->drr_length = BSWAP_64(drrs->drr_length);
|
||||
drrs->drr_compressed_size =
|
||||
BSWAP_64(drrs->drr_compressed_size);
|
||||
drrs->drr_type = BSWAP_32(drrs->drr_type);
|
||||
}
|
||||
|
||||
payload_size = DRR_SPILL_PAYLOAD_SIZE(drrs);
|
||||
|
||||
if (verbose) {
|
||||
sprintf_bytes(salt, drrs->drr_salt,
|
||||
ZIO_DATA_SALT_LEN);
|
||||
sprintf_bytes(iv, drrs->drr_iv,
|
||||
ZIO_DATA_IV_LEN);
|
||||
sprintf_bytes(mac, drrs->drr_mac,
|
||||
ZIO_DATA_MAC_LEN);
|
||||
|
||||
(void) printf("SPILL block for object = %llu "
|
||||
"length = %llu flags = %u "
|
||||
"compression type = %u "
|
||||
"compressed_size = %llu "
|
||||
"payload_size = %llu "
|
||||
"salt = %s iv = %s mac = %s\n",
|
||||
(u_longlong_t)drrs->drr_object,
|
||||
(u_longlong_t)drrs->drr_length,
|
||||
drrs->drr_flags,
|
||||
drrs->drr_compressiontype,
|
||||
(u_longlong_t)drrs->drr_compressed_size,
|
||||
(u_longlong_t)payload_size,
|
||||
salt,
|
||||
iv,
|
||||
mac);
|
||||
"length = %llu\n",
|
||||
(long long unsigned int)drrs->drr_object,
|
||||
(long long unsigned int)drrs->drr_length);
|
||||
}
|
||||
(void) ssread(buf, payload_size, &zc);
|
||||
(void) ssread(buf, drrs->drr_length, &zc);
|
||||
if (dump) {
|
||||
print_block(buf, payload_size);
|
||||
print_block(buf, drrs->drr_length);
|
||||
}
|
||||
break;
|
||||
case DRR_WRITE_EMBEDDED:
|
||||
@@ -669,8 +592,8 @@ main(int argc, char *argv[])
|
||||
}
|
||||
if (verbose) {
|
||||
(void) printf("WRITE_EMBEDDED object = %llu "
|
||||
"offset = %llu length = %llu "
|
||||
"toguid = %llx comp = %u etype = %u "
|
||||
"offset = %llu length = %llu\n"
|
||||
" toguid = %llx comp = %u etype = %u "
|
||||
"lsize = %u psize = %u\n",
|
||||
(u_longlong_t)drrwe->drr_object,
|
||||
(u_longlong_t)drrwe->drr_offset,
|
||||
@@ -683,38 +606,6 @@ main(int argc, char *argv[])
|
||||
}
|
||||
(void) ssread(buf,
|
||||
P2ROUNDUP(drrwe->drr_psize, 8), &zc);
|
||||
if (dump) {
|
||||
print_block(buf,
|
||||
P2ROUNDUP(drrwe->drr_psize, 8));
|
||||
}
|
||||
payload_size = P2ROUNDUP(drrwe->drr_psize, 8);
|
||||
break;
|
||||
case DRR_OBJECT_RANGE:
|
||||
if (do_byteswap) {
|
||||
drror->drr_firstobj =
|
||||
BSWAP_64(drror->drr_firstobj);
|
||||
drror->drr_numslots =
|
||||
BSWAP_64(drror->drr_numslots);
|
||||
drror->drr_toguid = BSWAP_64(drror->drr_toguid);
|
||||
}
|
||||
if (verbose) {
|
||||
sprintf_bytes(salt, drror->drr_salt,
|
||||
ZIO_DATA_SALT_LEN);
|
||||
sprintf_bytes(iv, drror->drr_iv,
|
||||
ZIO_DATA_IV_LEN);
|
||||
sprintf_bytes(mac, drror->drr_mac,
|
||||
ZIO_DATA_MAC_LEN);
|
||||
|
||||
(void) printf("OBJECT_RANGE firstobj = %llu "
|
||||
"numslots = %llu flags = %u "
|
||||
"salt = %s iv = %s mac = %s\n",
|
||||
(u_longlong_t)drror->drr_firstobj,
|
||||
(u_longlong_t)drror->drr_numslots,
|
||||
drror->drr_flags,
|
||||
salt,
|
||||
iv,
|
||||
mac);
|
||||
}
|
||||
break;
|
||||
case DRR_NUMTYPES:
|
||||
/* should never be reached */
|
||||
@@ -728,8 +619,6 @@ main(int argc, char *argv[])
|
||||
(longlong_t)drrc->drr_checksum.zc_word[3]);
|
||||
}
|
||||
pcksum = zc;
|
||||
drr_byte_count[drr->drr_type] += payload_size;
|
||||
total_payload_size += payload_size;
|
||||
}
|
||||
free(buf);
|
||||
fletcher_4_fini();
|
||||
@@ -737,40 +626,28 @@ main(int argc, char *argv[])
|
||||
/* Print final summary */
|
||||
|
||||
(void) printf("SUMMARY:\n");
|
||||
(void) printf("\tTotal DRR_BEGIN records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_BEGIN],
|
||||
(u_longlong_t)drr_byte_count[DRR_BEGIN]);
|
||||
(void) printf("\tTotal DRR_END records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_END],
|
||||
(u_longlong_t)drr_byte_count[DRR_END]);
|
||||
(void) printf("\tTotal DRR_OBJECT records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_OBJECT],
|
||||
(u_longlong_t)drr_byte_count[DRR_OBJECT]);
|
||||
(void) printf("\tTotal DRR_FREEOBJECTS records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREEOBJECTS],
|
||||
(u_longlong_t)drr_byte_count[DRR_FREEOBJECTS]);
|
||||
(void) printf("\tTotal DRR_WRITE records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE],
|
||||
(u_longlong_t)drr_byte_count[DRR_WRITE]);
|
||||
(void) printf("\tTotal DRR_WRITE_BYREF records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE_BYREF],
|
||||
(u_longlong_t)drr_byte_count[DRR_WRITE_BYREF]);
|
||||
(void) printf("\tTotal DRR_WRITE_EMBEDDED records = %lld (%llu "
|
||||
"bytes)\n", (u_longlong_t)drr_record_count[DRR_WRITE_EMBEDDED],
|
||||
(u_longlong_t)drr_byte_count[DRR_WRITE_EMBEDDED]);
|
||||
(void) printf("\tTotal DRR_FREE records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREE],
|
||||
(u_longlong_t)drr_byte_count[DRR_FREE]);
|
||||
(void) printf("\tTotal DRR_SPILL records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_SPILL],
|
||||
(u_longlong_t)drr_byte_count[DRR_SPILL]);
|
||||
(void) printf("\tTotal DRR_BEGIN records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_BEGIN]);
|
||||
(void) printf("\tTotal DRR_END records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_END]);
|
||||
(void) printf("\tTotal DRR_OBJECT records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_OBJECT]);
|
||||
(void) printf("\tTotal DRR_FREEOBJECTS records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREEOBJECTS]);
|
||||
(void) printf("\tTotal DRR_WRITE records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE]);
|
||||
(void) printf("\tTotal DRR_WRITE_BYREF records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE_BYREF]);
|
||||
(void) printf("\tTotal DRR_WRITE_EMBEDDED records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE_EMBEDDED]);
|
||||
(void) printf("\tTotal DRR_FREE records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREE]);
|
||||
(void) printf("\tTotal DRR_SPILL records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_SPILL]);
|
||||
(void) printf("\tTotal records = %lld\n",
|
||||
(u_longlong_t)total_records);
|
||||
(void) printf("\tTotal payload size = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_payload_size, (u_longlong_t)total_payload_size);
|
||||
(void) printf("\tTotal header overhead = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_overhead_size,
|
||||
(u_longlong_t)total_overhead_size);
|
||||
(void) printf("\tTotal write size = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_write_size, (u_longlong_t)total_write_size);
|
||||
(void) printf("\tTotal stream length = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_stream_len, (u_longlong_t)total_stream_len);
|
||||
return (0);
|
||||
|
||||
+8
-10
@@ -1,13 +1,9 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
# Get rid of compiler warning for unchecked truncating snprintfs on gcc 7.1.1
|
||||
AM_CFLAGS += $(NO_FORMAT_TRUNCATION)
|
||||
|
||||
# Includes kernel code, generate warnings for large stack frames
|
||||
AM_CFLAGS += $(FRAME_LARGER_THAN)
|
||||
|
||||
# Unconditionally enable ASSERTs
|
||||
AM_CPPFLAGS += -DDEBUG -UNDEBUG
|
||||
# -Wnoformat-truncation to get rid of compiler warning for unchecked
|
||||
# truncating snprintfs on gcc 7.1.1.
|
||||
AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN) $(NO_FORMAT_TRUNCATION)
|
||||
AM_CPPFLAGS += -DDEBUG
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
@@ -20,7 +16,9 @@ ztest_SOURCES = \
|
||||
|
||||
ztest_LDADD = \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la
|
||||
$(top_builddir)/lib/libuutil/libuutil.la \
|
||||
$(top_builddir)/lib/libzpool/libzpool.la \
|
||||
$(top_builddir)/lib/libzfs/libzfs.la \
|
||||
$(top_builddir)/lib/libzfs_core/libzfs_core.la
|
||||
|
||||
ztest_LDADD += -lm
|
||||
ztest_LDFLAGS = -pthread
|
||||
|
||||
+496
-1273
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
dist_bin_SCRIPTS = zvol_wait
|
||||
@@ -1,112 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
count_zvols() {
|
||||
if [ -z "$zvols" ]; then
|
||||
echo 0
|
||||
else
|
||||
echo "$zvols" | wc -l
|
||||
fi
|
||||
}
|
||||
|
||||
filter_out_zvols_with_links() {
|
||||
while read -r zvol; do
|
||||
if [ ! -L "/dev/zvol/$zvol" ]; then
|
||||
echo "$zvol"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
filter_out_deleted_zvols() {
|
||||
while read -r zvol; do
|
||||
if zfs list "$zvol" >/dev/null 2>&1; then
|
||||
echo "$zvol"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
list_zvols() {
|
||||
zfs list -t volume -H -o name,volmode,receive_resume_token |
|
||||
while read -r zvol_line; do
|
||||
name=$(echo "$zvol_line" | awk '{print $1}')
|
||||
volmode=$(echo "$zvol_line" | awk '{print $2}')
|
||||
token=$(echo "$zvol_line" | awk '{print $3}')
|
||||
#
|
||||
# /dev links are not created for zvols with volmode = "none".
|
||||
#
|
||||
[ "$volmode" = "none" ] && continue
|
||||
#
|
||||
# We also also ignore partially received zvols if it is
|
||||
# not an incremental receive, as those won't even have a block
|
||||
# device minor node created yet.
|
||||
#
|
||||
if [ "$token" != "-" ]; then
|
||||
#
|
||||
# Incremental receives create an invisible clone that
|
||||
# is not automatically displayed by zfs list.
|
||||
#
|
||||
if ! zfs list "$name/%recv" >/dev/null 2>&1; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
echo "$name"
|
||||
done
|
||||
}
|
||||
|
||||
zvols=$(list_zvols)
|
||||
zvols_count=$(count_zvols)
|
||||
if [ "$zvols_count" -eq 0 ]; then
|
||||
echo "No zvols found, nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Testing $zvols_count zvol links"
|
||||
|
||||
outer_loop=0
|
||||
while [ "$outer_loop" -lt 20 ]; do
|
||||
outer_loop=$((outer_loop + 1))
|
||||
|
||||
old_zvols_count=$(count_zvols)
|
||||
|
||||
inner_loop=0
|
||||
while [ "$inner_loop" -lt 30 ]; do
|
||||
inner_loop=$((inner_loop + 1))
|
||||
|
||||
zvols="$(echo "$zvols" | filter_out_zvols_with_links)"
|
||||
|
||||
zvols_count=$(count_zvols)
|
||||
if [ "$zvols_count" -eq 0 ]; then
|
||||
echo "All zvol links are now present."
|
||||
exit 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Still waiting on $zvols_count zvol links ..."
|
||||
#
|
||||
# Although zvols should normally not be deleted at boot time,
|
||||
# if that is the case then their links will be missing and
|
||||
# we would stall.
|
||||
#
|
||||
if [ "$old_zvols_count" -eq "$zvols_count" ]; then
|
||||
echo "No progress since last loop."
|
||||
echo "Checking if any zvols were deleted."
|
||||
|
||||
zvols=$(echo "$zvols" | filter_out_deleted_zvols)
|
||||
zvols_count=$(count_zvols)
|
||||
|
||||
if [ "$old_zvols_count" -ne "$zvols_count" ]; then
|
||||
echo "$((old_zvols_count - zvols_count)) zvol(s) deleted."
|
||||
fi
|
||||
|
||||
if [ "$zvols_count" -ne 0 ]; then
|
||||
echo "Remaining zvols:"
|
||||
echo "$zvols"
|
||||
else
|
||||
echo "All zvol links are now present."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Timed out waiting on zvol links"
|
||||
exit 1
|
||||
+8
-20
@@ -1,30 +1,18 @@
|
||||
#
|
||||
# Default build rules for all user space components, every Makefile.am
|
||||
# should include these rules and override or extend them as needed.
|
||||
#
|
||||
|
||||
DEFAULT_INCLUDES = -include ${top_builddir}/zfs_config.h
|
||||
|
||||
AM_LIBTOOLFLAGS = --silent
|
||||
|
||||
AM_CFLAGS = -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing
|
||||
AM_CFLAGS += $(NO_OMIT_FRAME_POINTER)
|
||||
AM_CFLAGS += $(DEBUG_CFLAGS)
|
||||
AM_CFLAGS += $(ASAN_CFLAGS)
|
||||
AM_CFLAGS = ${DEBUG_CFLAGS} -Wall -Wstrict-prototypes
|
||||
AM_CFLAGS += ${NO_UNUSED_BUT_SET_VARIABLE}
|
||||
AM_CFLAGS += ${NO_BOOL_COMPARE}
|
||||
AM_CFLAGS += -fno-strict-aliasing
|
||||
AM_CFLAGS += -std=gnu99
|
||||
AM_CFLAGS += $(CODE_COVERAGE_CFLAGS)
|
||||
|
||||
AM_CPPFLAGS = -D_GNU_SOURCE
|
||||
AM_CPPFLAGS += -D_REENTRANT
|
||||
AM_CPPFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
AM_CPPFLAGS += -D_LARGEFILE64_SOURCE
|
||||
AM_CPPFLAGS += -DHAVE_LARGE_STACKS=1
|
||||
AM_CPPFLAGS = -D_GNU_SOURCE -D__EXTENSIONS__ -D_REENTRANT
|
||||
AM_CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS -D_FILE_OFFSET_BITS=64
|
||||
AM_CPPFLAGS += -D_LARGEFILE64_SOURCE -DHAVE_LARGE_STACKS=1
|
||||
AM_CPPFLAGS += -DTEXT_DOMAIN=\"zfs-linux-user\"
|
||||
AM_CPPFLAGS += -DLIBEXECDIR=\"$(libexecdir)\"
|
||||
AM_CPPFLAGS += -DRUNSTATEDIR=\"$(runstatedir)\"
|
||||
AM_CPPFLAGS += -DSBINDIR=\"$(sbindir)\"
|
||||
AM_CPPFLAGS += -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
AM_CPPFLAGS += $(DEBUG_CPPFLAGS)
|
||||
AM_CPPFLAGS += $(CODE_COVERAGE_CPPFLAGS)
|
||||
|
||||
AM_LDFLAGS = $(DEBUG_LDFLAGS)
|
||||
AM_LDFLAGS += $(ASAN_LDFLAGS)
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
dnl #
|
||||
dnl # Enabled -fsanitize=address if supported by gcc.
|
||||
dnl #
|
||||
dnl # LDFLAGS needs -fsanitize=address at all times so libraries compiled with
|
||||
dnl # it will be linked successfully. CFLAGS will vary by binary being built.
|
||||
dnl #
|
||||
dnl # The ASAN_OPTIONS environment variable can be used to further control
|
||||
dnl # the behavior of binaries and libraries build with -fsanitize=address.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_ASAN], [
|
||||
AC_MSG_CHECKING([whether to build with -fsanitize=address support])
|
||||
AC_ARG_ENABLE([asan],
|
||||
[AS_HELP_STRING([--enable-asan],
|
||||
[Enable -fsanitize=address support @<:@default=no@:>@])],
|
||||
[],
|
||||
[enable_asan=no])
|
||||
|
||||
AM_CONDITIONAL([ASAN_ENABLED], [test x$enable_asan = xyes])
|
||||
AC_SUBST([ASAN_ENABLED], [$enable_asan])
|
||||
AC_MSG_RESULT($enable_asan)
|
||||
|
||||
AS_IF([ test "$enable_asan" = "yes" ], [
|
||||
AC_MSG_CHECKING([whether $CC supports -fsanitize=address])
|
||||
saved_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fsanitize=address"
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_SOURCE([[ int main() { return 0; } ]])
|
||||
], [
|
||||
ASAN_CFLAGS="-fsanitize=address"
|
||||
ASAN_LDFLAGS="-fsanitize=address"
|
||||
ASAN_ZFS="_with_asan"
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
AC_MSG_ERROR([$CC does not support -fsanitize=address])
|
||||
])
|
||||
CFLAGS="$saved_cflags"
|
||||
], [
|
||||
ASAN_CFLAGS=""
|
||||
ASAN_LDFLAGS=""
|
||||
ASAN_ZFS="_without_asan"
|
||||
])
|
||||
|
||||
AC_SUBST([ASAN_CFLAGS])
|
||||
AC_SUBST([ASAN_LDFLAGS])
|
||||
AC_SUBST([ASAN_ZFS])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Check if gcc supports -Wframe-larger-than=<size> option.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_FRAME_LARGER_THAN], [
|
||||
AC_MSG_CHECKING([whether $CC supports -Wframe-larger-than=<size>])
|
||||
|
||||
saved_flags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wframe-larger-than=4096"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
|
||||
FRAME_LARGER_THAN="-Wframe-larger-than=4096"
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
FRAME_LARGER_THAN=""
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
CFLAGS="$saved_flags"
|
||||
AC_SUBST([FRAME_LARGER_THAN])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Check if gcc supports -Wno-format-truncation option.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_FORMAT_TRUNCATION], [
|
||||
AC_MSG_CHECKING([whether $CC supports -Wno-format-truncation])
|
||||
|
||||
saved_flags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wno-format-truncation"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
|
||||
NO_FORMAT_TRUNCATION=-Wno-format-truncation
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
NO_FORMAT_TRUNCATION=
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
CFLAGS="$saved_flags"
|
||||
AC_SUBST([NO_FORMAT_TRUNCATION])
|
||||
])
|
||||
|
||||
|
||||
dnl #
|
||||
dnl # Check if gcc supports -Wno-bool-compare option.
|
||||
dnl #
|
||||
dnl # We actually invoke gcc with the -Wbool-compare option
|
||||
dnl # and infer the 'no-' version does or doesn't exist based upon
|
||||
dnl # the results. This is required because when checking any of
|
||||
dnl # no- prefixed options gcc always returns success.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_BOOL_COMPARE], [
|
||||
AC_MSG_CHECKING([whether $CC supports -Wno-bool-compare])
|
||||
|
||||
saved_flags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wbool-compare"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
|
||||
NO_BOOL_COMPARE=-Wno-bool-compare
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
NO_BOOL_COMPARE=
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
CFLAGS="$saved_flags"
|
||||
AC_SUBST([NO_BOOL_COMPARE])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Check if gcc supports -Wno-unused-but-set-variable option.
|
||||
dnl #
|
||||
dnl # We actually invoke gcc with the -Wunused-but-set-variable option
|
||||
dnl # and infer the 'no-' version does or doesn't exist based upon
|
||||
dnl # the results. This is required because when checking any of
|
||||
dnl # no- prefixed options gcc always returns success.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_UNUSED_BUT_SET_VARIABLE], [
|
||||
AC_MSG_CHECKING([whether $CC supports -Wno-unused-but-set-variable])
|
||||
|
||||
saved_flags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wunused-but-set-variable"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
|
||||
NO_UNUSED_BUT_SET_VARIABLE=-Wno-unused-but-set-variable
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
NO_UNUSED_BUT_SET_VARIABLE=
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
CFLAGS="$saved_flags"
|
||||
AC_SUBST([NO_UNUSED_BUT_SET_VARIABLE])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Check if gcc supports -fno-omit-frame-pointer option.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_NO_OMIT_FRAME_POINTER], [
|
||||
AC_MSG_CHECKING([whether $CC supports -fno-omit-frame-pointer])
|
||||
|
||||
saved_flags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fno-omit-frame-pointer"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], [
|
||||
NO_OMIT_FRAME_POINTER=-fno-omit-frame-pointer
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
NO_OMIT_FRAME_POINTER=
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
CFLAGS="$saved_flags"
|
||||
AC_SUBST([NO_OMIT_FRAME_POINTER])
|
||||
])
|
||||
@@ -0,0 +1,27 @@
|
||||
dnl #
|
||||
dnl # Check if gcc supports -Wno-bool-compare option.
|
||||
dnl #
|
||||
dnl # We actually invoke gcc with the -Wbool-compare option
|
||||
dnl # and infer the 'no-' version does or doesn't exist based upon
|
||||
dnl # the results. This is required because when checking any of
|
||||
dnl # no- prefixed options gcc always returns success.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_NO_BOOL_COMPARE], [
|
||||
AC_MSG_CHECKING([for -Wno-bool-compare support])
|
||||
|
||||
saved_flags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wbool-compare"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
|
||||
[
|
||||
NO_BOOL_COMPARE=-Wno-bool-compare
|
||||
AC_MSG_RESULT([yes])
|
||||
],
|
||||
[
|
||||
NO_BOOL_COMPARE=
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
CFLAGS="$saved_flags"
|
||||
AC_SUBST([NO_BOOL_COMPARE])
|
||||
])
|
||||
@@ -0,0 +1,27 @@
|
||||
dnl #
|
||||
dnl # Check if gcc supports -Wno-unused-but-set-variable option.
|
||||
dnl #
|
||||
dnl # We actually invoke gcc with the -Wunused-but-set-variable option
|
||||
dnl # and infer the 'no-' version does or doesn't exist based upon
|
||||
dnl # the results. This is required because when checking any of
|
||||
dnl # no- prefixed options gcc always returns success.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_NO_UNUSED_BUT_SET_VARIABLE], [
|
||||
AC_MSG_CHECKING([for -Wno-unused-but-set-variable support])
|
||||
|
||||
saved_flags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wunused-but-set-variable"
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
|
||||
[
|
||||
NO_UNUSED_BUT_SET_VARIABLE=-Wno-unused-but-set-variable
|
||||
AC_MSG_RESULT([yes])
|
||||
],
|
||||
[
|
||||
NO_UNUSED_BUT_SET_VARIABLE=
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
CFLAGS="$saved_flags"
|
||||
AC_SUBST([NO_UNUSED_BUT_SET_VARIABLE])
|
||||
])
|
||||
@@ -1,66 +0,0 @@
|
||||
dnl #
|
||||
dnl # The majority of the python scripts are written to be compatible
|
||||
dnl # with Python 2.6 and Python 3.4. Therefore, they may be installed
|
||||
dnl # and used with either interpreter. This option is intended to
|
||||
dnl # to provide a method to specify the default system version, and
|
||||
dnl # set the PYTHON environment variable accordingly.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYTHON], [
|
||||
AC_ARG_WITH([python],
|
||||
AC_HELP_STRING([--with-python[=VERSION]],
|
||||
[default system python version @<:@default=check@:>@]),
|
||||
[with_python=$withval],
|
||||
[with_python=check])
|
||||
|
||||
AS_CASE([$with_python],
|
||||
[check], [AC_CHECK_PROGS([PYTHON], [python3 python2], [:])],
|
||||
[2*], [PYTHON="python${with_python}"],
|
||||
[*python2*], [PYTHON="${with_python}"],
|
||||
[3*], [PYTHON="python${with_python}"],
|
||||
[*python3*], [PYTHON="${with_python}"],
|
||||
[no], [PYTHON=":"],
|
||||
[AC_MSG_ERROR([Unknown --with-python value '$with_python'])]
|
||||
)
|
||||
|
||||
dnl #
|
||||
dnl # Minimum supported Python versions for utilities:
|
||||
dnl # Python 2.6 or Python 3.4
|
||||
dnl #
|
||||
AM_PATH_PYTHON([], [], [:])
|
||||
AS_IF([test -z "$PYTHON_VERSION"], [
|
||||
PYTHON_VERSION=$(basename $PYTHON | tr -cd 0-9.)
|
||||
])
|
||||
PYTHON_MINOR=${PYTHON_VERSION#*\.}
|
||||
|
||||
AS_CASE([$PYTHON_VERSION],
|
||||
[2.*], [
|
||||
AS_IF([test $PYTHON_MINOR -lt 6],
|
||||
[AC_MSG_ERROR("Python >= 2.6 is required")])
|
||||
],
|
||||
[3.*], [
|
||||
AS_IF([test $PYTHON_MINOR -lt 4],
|
||||
[AC_MSG_ERROR("Python >= 3.4 is required")])
|
||||
],
|
||||
[:|2|3], [],
|
||||
[PYTHON_VERSION=3]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([USING_PYTHON], [test "$PYTHON" != :])
|
||||
AM_CONDITIONAL([USING_PYTHON_2], [test "x${PYTHON_VERSION%%\.*}" = x2])
|
||||
AM_CONDITIONAL([USING_PYTHON_3], [test "x${PYTHON_VERSION%%\.*}" = x3])
|
||||
|
||||
dnl #
|
||||
dnl # Request that packages be built for a specific Python version.
|
||||
dnl #
|
||||
AS_IF([test "x$with_python" != xcheck], [
|
||||
PYTHON_PKG_VERSION=$(echo $PYTHON_VERSION | tr -d .)
|
||||
DEFINE_PYTHON_PKG_VERSION='--define "__use_python_pkg_version '${PYTHON_PKG_VERSION}'"'
|
||||
DEFINE_PYTHON_VERSION='--define "__use_python '${PYTHON}'"'
|
||||
], [
|
||||
DEFINE_PYTHON_VERSION=''
|
||||
DEFINE_PYTHON_PKG_VERSION=''
|
||||
])
|
||||
|
||||
AC_SUBST(DEFINE_PYTHON_VERSION)
|
||||
AC_SUBST(DEFINE_PYTHON_PKG_VERSION)
|
||||
])
|
||||
@@ -1,105 +0,0 @@
|
||||
dnl #
|
||||
dnl # ZFS_AC_PYTHON_MODULE(module_name, [action-if-true], [action-if-false])
|
||||
dnl #
|
||||
dnl # Checks for Python module. Freely inspired by AX_PYTHON_MODULE
|
||||
dnl # https://www.gnu.org/software/autoconf-archive/ax_python_module.html
|
||||
dnl # Required by ZFS_AC_CONFIG_ALWAYS_PYZFS.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_PYTHON_MODULE], [
|
||||
PYTHON_NAME=$(basename $PYTHON)
|
||||
AC_MSG_CHECKING([for $PYTHON_NAME module: $1])
|
||||
AS_IF([$PYTHON -c "import $1" 2>/dev/null], [
|
||||
AC_MSG_RESULT(yes)
|
||||
m4_ifvaln([$2], [$2])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
m4_ifvaln([$3], [$3])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Determines if pyzfs can be built, requires Python 2.7 or later.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
AC_ARG_ENABLE([pyzfs],
|
||||
AC_HELP_STRING([--enable-pyzfs],
|
||||
[install libzfs_core python bindings @<:@default=check@:>@]),
|
||||
[enable_pyzfs=$enableval],
|
||||
[enable_pyzfs=check])
|
||||
|
||||
dnl #
|
||||
dnl # Packages for pyzfs specifically enabled/disabled.
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" != xcheck], [
|
||||
AS_IF([test "x$enable_pyzfs" = xyes], [
|
||||
DEFINE_PYZFS='--with pyzfs'
|
||||
], [
|
||||
DEFINE_PYZFS='--without pyzfs'
|
||||
])
|
||||
], [
|
||||
AS_IF([test "$PYTHON" != :], [
|
||||
DEFINE_PYZFS=''
|
||||
], [
|
||||
enable_pyzfs=no
|
||||
DEFINE_PYZFS='--without pyzfs'
|
||||
])
|
||||
])
|
||||
AC_SUBST(DEFINE_PYZFS)
|
||||
|
||||
dnl #
|
||||
dnl # Require python-devel libraries
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
|
||||
AS_CASE([$PYTHON_VERSION],
|
||||
[3.*], [PYTHON_REQUIRED_VERSION=">= '3.4.0'"],
|
||||
[2.*], [PYTHON_REQUIRED_VERSION=">= '2.7.0'"],
|
||||
[AC_MSG_ERROR("Python $PYTHON_VERSION unknown")]
|
||||
)
|
||||
|
||||
AX_PYTHON_DEVEL([$PYTHON_REQUIRED_VERSION], [
|
||||
AS_IF([test "x$enable_pyzfs" = xyes], [
|
||||
AC_MSG_ERROR("Python $PYTHON_REQUIRED_VERSION development library is not installed")
|
||||
], [test "x$enable_pyzfs" != xno], [
|
||||
enable_pyzfs=no
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Python "setuptools" module is required to build and install pyzfs
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
|
||||
ZFS_AC_PYTHON_MODULE([setuptools], [], [
|
||||
AS_IF([test "x$enable_pyzfs" = xyes], [
|
||||
AC_MSG_ERROR("Python $PYTHON_VERSION setuptools is not installed")
|
||||
], [test "x$enable_pyzfs" != xno], [
|
||||
enable_pyzfs=no
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Python "cffi" module is required to run pyzfs
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
|
||||
ZFS_AC_PYTHON_MODULE([cffi], [], [
|
||||
AS_IF([test "x$enable_pyzfs" = xyes], [
|
||||
AC_MSG_ERROR("Python $PYTHON_VERSION cffi is not installed")
|
||||
], [test "x$enable_pyzfs" != xno], [
|
||||
enable_pyzfs=no
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Set enable_pyzfs to 'yes' if every check passed
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" = xcheck], [enable_pyzfs=yes])
|
||||
|
||||
AM_CONDITIONAL([PYZFS_ENABLED], [test "x$enable_pyzfs" = xyes])
|
||||
AC_SUBST([PYZFS_ENABLED], [$enable_pyzfs])
|
||||
AC_SUBST(pythonsitedir, [$PYTHON_SITE_PKG])
|
||||
|
||||
AC_MSG_CHECKING([whether to enable pyzfs: ])
|
||||
AC_MSG_RESULT($enable_pyzfs)
|
||||
])
|
||||
@@ -50,7 +50,7 @@
|
||||
# CODE_COVERAGE_LIBS is preferred for clarity; CODE_COVERAGE_LDFLAGS is
|
||||
# deprecated. They have the same value.
|
||||
#
|
||||
# This code was derived from Makefile.decl in GLib, originally licensed
|
||||
# This code was derived from Makefile.decl in GLib, originally licenced
|
||||
# under LGPLv2.1+.
|
||||
#
|
||||
# LICENSE
|
||||
|
||||
@@ -1,345 +0,0 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_python_devel.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_PYTHON_DEVEL([version], [action-if-not-found])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it
|
||||
# in your configure.ac.
|
||||
#
|
||||
# Note: this is a slightly modified version of the original AX_PYTHON_DEVEL
|
||||
# macro which accepts an additional [action-if-not-found] argument. This
|
||||
# allow to detect if Python development is available without aborting the
|
||||
# configure phase with an hard error in case it is not.
|
||||
#
|
||||
# This macro checks for Python and tries to get the include path to
|
||||
# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LIBS) output
|
||||
# variables. It also exports $(PYTHON_EXTRA_LIBS) and
|
||||
# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code.
|
||||
#
|
||||
# You can search for some particular version of Python by passing a
|
||||
# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please
|
||||
# note that you *have* to pass also an operator along with the version to
|
||||
# match, and pay special attention to the single quotes surrounding the
|
||||
# version number. Don't use "PYTHON_VERSION" for this: that environment
|
||||
# variable is declared as precious and thus reserved for the end-user.
|
||||
#
|
||||
# This macro should work for all versions of Python >= 2.1.0. As an end
|
||||
# user, you can disable the check for the python version by setting the
|
||||
# PYTHON_NOVERSIONCHECK environment variable to something else than the
|
||||
# empty string.
|
||||
#
|
||||
# If you need to use this macro for an older Python version, please
|
||||
# contact the authors. We're always open for feedback.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2009 Sebastian Huber <sebastian-huber@web.de>
|
||||
# Copyright (c) 2009 Alan W. Irwin
|
||||
# Copyright (c) 2009 Rafael Laboissiere <rafael@laboissiere.net>
|
||||
# Copyright (c) 2009 Andrew Collier
|
||||
# Copyright (c) 2009 Matteo Settenvini <matteo@member.fsf.org>
|
||||
# Copyright (c) 2009 Horst Knorr <hk_classes@knoda.org>
|
||||
# Copyright (c) 2013 Daniel Mullner <muellner@math.stanford.edu>
|
||||
# Copyright (c) 2018 loli10K <ezomori.nozomu@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 21
|
||||
|
||||
AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL])
|
||||
AC_DEFUN([AX_PYTHON_DEVEL],[
|
||||
#
|
||||
# Allow the use of a (user set) custom python version
|
||||
#
|
||||
AC_ARG_VAR([PYTHON_VERSION],[The installed Python
|
||||
version to use, for example '2.3'. This string
|
||||
will be appended to the Python interpreter
|
||||
canonical name.])
|
||||
|
||||
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
|
||||
if test -z "$PYTHON"; then
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
|
||||
PYTHON_VERSION=""
|
||||
])
|
||||
fi
|
||||
|
||||
#
|
||||
# Check for a version of Python >= 2.1.0
|
||||
#
|
||||
AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
|
||||
ac_supports_python_ver=`$PYTHON -c "import sys; \
|
||||
ver = sys.version.split ()[[0]]; \
|
||||
print (ver >= '2.1.0')"`
|
||||
if test "$ac_supports_python_ver" != "True"; then
|
||||
if test -z "$PYTHON_NOVERSIONCHECK"; then
|
||||
AC_MSG_RESULT([no])
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_FAILURE([
|
||||
This version of the AC@&t@_PYTHON_DEVEL macro
|
||||
doesn't work properly with versions of Python before
|
||||
2.1.0. You may need to re-run configure, setting the
|
||||
variables PYTHON_CPPFLAGS, PYTHON_LIBS, PYTHON_SITE_PKG,
|
||||
PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
|
||||
Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
|
||||
to something else than an empty string.
|
||||
])
|
||||
])
|
||||
else
|
||||
AC_MSG_RESULT([skip at user request])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
#
|
||||
# if the macro parameter ``version'' is set, honour it
|
||||
#
|
||||
if test -n "$1"; then
|
||||
AC_MSG_CHECKING([for a version of Python $1])
|
||||
ac_supports_python_ver=`$PYTHON -c "import sys; \
|
||||
ver = sys.version.split ()[[0]]; \
|
||||
print (ver $1)"`
|
||||
if test "$ac_supports_python_ver" = "True"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_ERROR([this package requires Python $1.
|
||||
If you have it installed, but it isn't the default Python
|
||||
interpreter in your system path, please pass the PYTHON_VERSION
|
||||
variable to configure. See ``configure --help'' for reference.
|
||||
])
|
||||
PYTHON_VERSION=""
|
||||
])
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Check if you have distutils, else fail
|
||||
#
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
|
||||
if test $? -eq 0; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result])
|
||||
PYTHON_VERSION=""
|
||||
])
|
||||
fi
|
||||
|
||||
#
|
||||
# Check for Python include path
|
||||
#
|
||||
AC_MSG_CHECKING([for Python include path])
|
||||
if test -z "$PYTHON_CPPFLAGS"; then
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print (distutils.sysconfig.get_python_inc ());"`
|
||||
plat_python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print (distutils.sysconfig.get_python_inc (plat_specific=1));"`
|
||||
if test -n "${python_path}"; then
|
||||
if test "${plat_python_path}" != "${python_path}"; then
|
||||
python_path="-I$python_path -I$plat_python_path"
|
||||
else
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
fi
|
||||
PYTHON_CPPFLAGS=$python_path
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_CPPFLAGS])
|
||||
AC_SUBST([PYTHON_CPPFLAGS])
|
||||
|
||||
#
|
||||
# Check for Python library path
|
||||
#
|
||||
AC_MSG_CHECKING([for Python library path])
|
||||
if test -z "$PYTHON_LIBS"; then
|
||||
# (makes two attempts to ensure we've got a version number
|
||||
# from the interpreter)
|
||||
ac_python_version=`cat<<EOD | $PYTHON -
|
||||
|
||||
# join all versioning strings, on some systems
|
||||
# major/minor numbers could be in different list elements
|
||||
from distutils.sysconfig import *
|
||||
e = get_config_var('VERSION')
|
||||
if e is not None:
|
||||
print(e)
|
||||
EOD`
|
||||
|
||||
if test -z "$ac_python_version"; then
|
||||
if test -n "$PYTHON_VERSION"; then
|
||||
ac_python_version=$PYTHON_VERSION
|
||||
else
|
||||
ac_python_version=`$PYTHON -c "import sys; \
|
||||
print (sys.version[[:3]])"`
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make the versioning information available to the compiler
|
||||
AC_DEFINE_UNQUOTED([HAVE_PYTHON], ["$ac_python_version"],
|
||||
[If available, contains the Python version number currently in use.])
|
||||
|
||||
# First, the library directory:
|
||||
ac_python_libdir=`cat<<EOD | $PYTHON -
|
||||
|
||||
# There should be only one
|
||||
import distutils.sysconfig
|
||||
e = distutils.sysconfig.get_config_var('LIBDIR')
|
||||
if e is not None:
|
||||
print (e)
|
||||
EOD`
|
||||
|
||||
# Now, for the library:
|
||||
ac_python_library=`cat<<EOD | $PYTHON -
|
||||
|
||||
import distutils.sysconfig
|
||||
c = distutils.sysconfig.get_config_vars()
|
||||
if 'LDVERSION' in c:
|
||||
print ('python'+c[['LDVERSION']])
|
||||
else:
|
||||
print ('python'+c[['VERSION']])
|
||||
EOD`
|
||||
|
||||
# This small piece shamelessly adapted from PostgreSQL python macro;
|
||||
# credits goes to momjian, I think. I'd like to put the right name
|
||||
# in the credits, if someone can point me in the right direction... ?
|
||||
#
|
||||
if test -n "$ac_python_libdir" -a -n "$ac_python_library"
|
||||
then
|
||||
# use the official shared library
|
||||
ac_python_library=`echo "$ac_python_library" | sed "s/^lib//"`
|
||||
PYTHON_LIBS="-L$ac_python_libdir -l$ac_python_library"
|
||||
else
|
||||
# old way: use libpython from python_configdir
|
||||
ac_python_libdir=`$PYTHON -c \
|
||||
"from distutils.sysconfig import get_python_lib as f; \
|
||||
import os; \
|
||||
print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
|
||||
PYTHON_LIBS="-L$ac_python_libdir -lpython$ac_python_version"
|
||||
fi
|
||||
|
||||
if test -z "PYTHON_LIBS"; then
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_ERROR([
|
||||
Cannot determine location of your Python DSO. Please check it was installed with
|
||||
dynamic libraries enabled, or try setting PYTHON_LIBS by hand.
|
||||
])
|
||||
])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_LIBS])
|
||||
AC_SUBST([PYTHON_LIBS])
|
||||
|
||||
#
|
||||
# Check for site packages
|
||||
#
|
||||
AC_MSG_CHECKING([for Python site-packages path])
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print (distutils.sysconfig.get_python_lib(0,0));"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_SITE_PKG])
|
||||
AC_SUBST([PYTHON_SITE_PKG])
|
||||
|
||||
#
|
||||
# libraries which must be linked in when embedding
|
||||
#
|
||||
AC_MSG_CHECKING(python extra libraries)
|
||||
if test -z "$PYTHON_EXTRA_LIBS"; then
|
||||
PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
print (conf('LIBS') + ' ' + conf('SYSLIBS'))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
|
||||
AC_SUBST(PYTHON_EXTRA_LIBS)
|
||||
|
||||
#
|
||||
# linking flags needed when embedding
|
||||
#
|
||||
AC_MSG_CHECKING(python extra linking flags)
|
||||
if test -z "$PYTHON_EXTRA_LDFLAGS"; then
|
||||
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
|
||||
conf = distutils.sysconfig.get_config_var; \
|
||||
print (conf('LINKFORSHARED'))"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
|
||||
AC_SUBST(PYTHON_EXTRA_LDFLAGS)
|
||||
|
||||
#
|
||||
# final check to see if everything compiles alright
|
||||
#
|
||||
AC_MSG_CHECKING([consistency of all components of python development environment])
|
||||
# save current global flags
|
||||
ac_save_LIBS="$LIBS"
|
||||
ac_save_LDFLAGS="$LDFLAGS"
|
||||
ac_save_CPPFLAGS="$CPPFLAGS"
|
||||
LIBS="$ac_save_LIBS $PYTHON_LIBS $PYTHON_EXTRA_LIBS $PYTHON_EXTRA_LIBS"
|
||||
LDFLAGS="$ac_save_LDFLAGS $PYTHON_EXTRA_LDFLAGS"
|
||||
CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
AC_LANG_PUSH([C])
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_PROGRAM([[#include <Python.h>]],
|
||||
[[Py_Initialize();]])
|
||||
],[pythonexists=yes],[pythonexists=no])
|
||||
AC_LANG_POP([C])
|
||||
# turn back to default flags
|
||||
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
LDFLAGS="$ac_save_LDFLAGS"
|
||||
|
||||
AC_MSG_RESULT([$pythonexists])
|
||||
|
||||
if test ! "x$pythonexists" = "xyes"; then
|
||||
m4_ifvaln([$2],[$2],[
|
||||
AC_MSG_FAILURE([
|
||||
Could not link test program to Python. Maybe the main Python library has been
|
||||
installed in some non-standard library path. If so, pass it to configure,
|
||||
via the LIBS environment variable.
|
||||
Example: ./configure LIBS="-L/usr/non-standard-path/python/lib"
|
||||
============================================================================
|
||||
ERROR!
|
||||
You probably have to install the development version of the Python package
|
||||
for your distribution. The exact name of this package varies among them.
|
||||
============================================================================
|
||||
])
|
||||
PYTHON_VERSION=""
|
||||
])
|
||||
fi
|
||||
|
||||
#
|
||||
# all done!
|
||||
#
|
||||
])
|
||||
@@ -1,31 +0,0 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_restore_flags.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_RESTORE_FLAGS()
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Restore common compilation flags from temporary variables
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2009 Filippo Giunchedi <filippo@esaurito.net>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 3
|
||||
|
||||
AC_DEFUN([AX_RESTORE_FLAGS], [
|
||||
CPPFLAGS="${CPPFLAGS_save}"
|
||||
CFLAGS="${CFLAGS_save}"
|
||||
CXXFLAGS="${CXXFLAGS_save}"
|
||||
OBJCFLAGS="${OBJCFLAGS_save}"
|
||||
LDFLAGS="${LDFLAGS_save}"
|
||||
LIBS="${LIBS_save}"
|
||||
])
|
||||
@@ -1,31 +0,0 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_save_flags.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_SAVE_FLAGS()
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Save common compilation flags into temporary variables
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2009 Filippo Giunchedi <filippo@esaurito.net>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 3
|
||||
|
||||
AC_DEFUN([AX_SAVE_FLAGS], [
|
||||
CPPFLAGS_save="${CPPFLAGS}"
|
||||
CFLAGS_save="${CFLAGS}"
|
||||
CXXFLAGS_save="${CXXFLAGS}"
|
||||
OBJCFLAGS_save="${OBJCFLAGS}"
|
||||
LDFLAGS_save="${LDFLAGS}"
|
||||
LIBS_save="${LIBS}"
|
||||
])
|
||||
@@ -1 +0,0 @@
|
||||
# `make distclean` deletes files with size 0. This text is to avoid that.
|
||||
+5
-6
@@ -20,7 +20,7 @@ deb-kmod: deb-local rpm-kmod
|
||||
arch=`$(RPM) -qp $${name}-kmod-$${version}.src.rpm --qf %{arch} | tail -1`; \
|
||||
debarch=`$(DPKG) --print-architecture`; \
|
||||
pkg1=kmod-$${name}*$${version}.$${arch}.rpm; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1 || exit 1; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1; \
|
||||
$(RM) $$pkg1
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ deb-dkms: deb-local rpm-dkms
|
||||
arch=`$(RPM) -qp $${name}-dkms-$${version}.src.rpm --qf %{arch} | tail -1`; \
|
||||
debarch=`$(DPKG) --print-architecture`; \
|
||||
pkg1=$${name}-dkms-$${version}.$${arch}.rpm; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1 || exit 1; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1; \
|
||||
$(RM) $$pkg1
|
||||
|
||||
deb-utils: deb-local rpm-utils
|
||||
@@ -45,9 +45,8 @@ deb-utils: deb-local rpm-utils
|
||||
pkg5=libzpool2-$${version}.$${arch}.rpm; \
|
||||
pkg6=libzfs2-devel-$${version}.$${arch}.rpm; \
|
||||
pkg7=$${name}-test-$${version}.$${arch}.rpm; \
|
||||
pkg8=$${name}-dracut-$${version}.noarch.rpm; \
|
||||
pkg8=$${name}-dracut-$${version}.$${arch}.rpm; \
|
||||
pkg9=$${name}-initramfs-$${version}.$${arch}.rpm; \
|
||||
pkg10=`ls python*-pyzfs-$${version}* | tail -1`; \
|
||||
## Arguments need to be passed to dh_shlibdeps. Alien provides no mechanism
|
||||
## to do this, so we install a shim onto the path which calls the real
|
||||
## dh_shlibdeps with the required arguments.
|
||||
@@ -63,10 +62,10 @@ deb-utils: deb-local rpm-utils
|
||||
env PATH=$${path_prepend}:$${PATH} \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch \
|
||||
$$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \
|
||||
$$pkg8 $$pkg9 $$pkg10 || exit 1; \
|
||||
$$pkg8 $$pkg9; \
|
||||
$(RM) $${path_prepend}/dh_shlibdeps; \
|
||||
rmdir $${path_prepend}; \
|
||||
$(RM) $$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \
|
||||
$$pkg8 $$pkg9 $$pkg10;
|
||||
$$pkg8 $$pkg9;
|
||||
|
||||
deb: deb-kmod deb-dkms deb-utils
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
# find_system_lib.m4 - Macros to search for a system library. -*- Autoconf -*-
|
||||
|
||||
dnl requires pkg.m4 from pkg-config
|
||||
dnl requires ax_save_flags.m4 from autoconf-archive
|
||||
dnl requires ax_restore_flags.m4 from autoconf-archive
|
||||
|
||||
dnl FIND_SYSTEM_LIBRARY(VARIABLE-PREFIX, MODULE, HEADER, HEADER-PREFIXES, LIBRARY, FUNCTIONS, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
|
||||
AC_DEFUN([FIND_SYSTEM_LIBRARY], [
|
||||
AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
|
||||
_library_found=
|
||||
|
||||
PKG_CHECK_MODULES([$1], [$2], [_library_found=1], [
|
||||
AS_IF([test -f /usr/include/[$3]], [
|
||||
AC_SUBST([$1][_CFLAGS], [])
|
||||
AC_SUBST([$1][_LIBS], ["-l[$5]]")
|
||||
_library_found=1
|
||||
],[ AS_IF([test -f /usr/local/include/[$3]], [
|
||||
AC_SUBST([$1][_CFLAGS], ["-I/usr/local/include"])
|
||||
AC_SUBST([$1][_LIBS], ["-L/usr/local -l[$5]]")
|
||||
_library_found=1
|
||||
],[dnl ELSE
|
||||
m4_foreach([prefix], [$4], [
|
||||
AS_IF([test "x$_library_found" != "x1"], [
|
||||
AS_IF([test -f [/usr/include/]prefix[/][$3]], [
|
||||
AC_SUBST([$1][_CFLAGS], ["[-I/usr/include/]prefix["]])
|
||||
AC_SUBST([$1][_LIBS], ["-l[$5]]")
|
||||
_library_found=1
|
||||
],[ AS_IF([test -f [/usr/local/include/]prefix[/][$3]], [
|
||||
AC_SUBST([$1][_CFLAGS], ["[-I/usr/local/include/]prefix["]])
|
||||
AC_SUBST([$1][_LIBS], ["-L/usr/local -l[$5]"])
|
||||
_library_found=1
|
||||
])])
|
||||
])
|
||||
])
|
||||
])])
|
||||
|
||||
AS_IF([test -z "$_library_found"], [
|
||||
AC_MSG_WARN([cannot find [$2] via pkg-config or in the standard locations])
|
||||
])
|
||||
])
|
||||
|
||||
dnl do some further sanity checks
|
||||
|
||||
AS_IF([test -n "$_library_found"], [
|
||||
AX_SAVE_FLAGS
|
||||
|
||||
CPPFLAGS="$CPPFLAGS $(echo $[$1][_CFLAGS] | sed 's/-include */-include-/g; s/^/ /; s/ [^-][^ ]*//g; s/ -[^Ii][^ ]*//g; s/-include-/-include /g; s/^ //;')"
|
||||
CFLAGS="$CFLAGS $[$1][_CFLAGS]"
|
||||
LDFLAGS="$LDFLAGS $[$1][_LIBS]"
|
||||
|
||||
AC_CHECK_HEADER([$3], [], [
|
||||
AC_MSG_WARN([header [$3] for library [$2] is not usable])
|
||||
_library_found=
|
||||
])
|
||||
|
||||
m4_foreach([func], [$6], [
|
||||
AC_CHECK_LIB([$5], func, [], [
|
||||
AC_MSG_WARN([cannot find ]func[ in library [$5]])
|
||||
_library_found=
|
||||
])
|
||||
])
|
||||
|
||||
AX_RESTORE_FLAGS
|
||||
])
|
||||
|
||||
AS_IF([test -n "$_library_found"], [
|
||||
:;$7
|
||||
],[dnl ELSE
|
||||
:;$8
|
||||
])
|
||||
])
|
||||
@@ -1,386 +0,0 @@
|
||||
# gettext.m4 serial 70 (gettext-0.20)
|
||||
dnl Copyright (C) 1995-2014, 2016, 2018 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
dnl
|
||||
dnl This file can be used in projects which are not available under
|
||||
dnl the GNU General Public License or the GNU Library General Public
|
||||
dnl License but which still want to provide support for the GNU gettext
|
||||
dnl functionality.
|
||||
dnl Please note that the actual code of the GNU gettext library is covered
|
||||
dnl by the GNU Library General Public License, and the rest of the GNU
|
||||
dnl gettext package is covered by the GNU General Public License.
|
||||
dnl They are *not* in the public domain.
|
||||
|
||||
dnl Authors:
|
||||
dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
|
||||
dnl Bruno Haible <haible@clisp.cons.org>, 2000-2006, 2008-2010.
|
||||
|
||||
dnl Macro to add for using GNU gettext.
|
||||
|
||||
dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]).
|
||||
dnl INTLSYMBOL must be one of 'external', 'use-libtool'.
|
||||
dnl INTLSYMBOL should be 'external' for packages other than GNU gettext, and
|
||||
dnl 'use-libtool' for the packages 'gettext-runtime' and 'gettext-tools'.
|
||||
dnl If INTLSYMBOL is 'use-libtool', then a libtool library
|
||||
dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static,
|
||||
dnl depending on --{enable,disable}-{shared,static} and on the presence of
|
||||
dnl AM-DISABLE-SHARED).
|
||||
dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext
|
||||
dnl implementations (in libc or libintl) without the ngettext() function
|
||||
dnl will be ignored. If NEEDSYMBOL is specified and is
|
||||
dnl 'need-formatstring-macros', then GNU gettext implementations that don't
|
||||
dnl support the ISO C 99 <inttypes.h> formatstring macros will be ignored.
|
||||
dnl INTLDIR is used to find the intl libraries. If empty,
|
||||
dnl the value '$(top_builddir)/intl/' is used.
|
||||
dnl
|
||||
dnl The result of the configuration is one of three cases:
|
||||
dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled
|
||||
dnl and used.
|
||||
dnl Catalog format: GNU --> install in $(datadir)
|
||||
dnl Catalog extension: .mo after installation, .gmo in source tree
|
||||
dnl 2) GNU gettext has been found in the system's C library.
|
||||
dnl Catalog format: GNU --> install in $(datadir)
|
||||
dnl Catalog extension: .mo after installation, .gmo in source tree
|
||||
dnl 3) No internationalization, always use English msgid.
|
||||
dnl Catalog format: none
|
||||
dnl Catalog extension: none
|
||||
dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur.
|
||||
dnl The use of .gmo is historical (it was needed to avoid overwriting the
|
||||
dnl GNU format catalogs when building on a platform with an X/Open gettext),
|
||||
dnl but we keep it in order not to force irrelevant filename changes on the
|
||||
dnl maintainers.
|
||||
dnl
|
||||
AC_DEFUN([AM_GNU_GETTEXT],
|
||||
[
|
||||
dnl Argument checking.
|
||||
ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [use-libtool], ,
|
||||
[errprint([ERROR: invalid first argument to AM_GNU_GETTEXT
|
||||
])])])])
|
||||
ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old],
|
||||
[errprint([ERROR: Use of AM_GNU_GETTEXT without [external] argument is no longer supported.
|
||||
])])
|
||||
ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], ,
|
||||
[errprint([ERROR: invalid second argument to AM_GNU_GETTEXT
|
||||
])])])])
|
||||
define([gt_included_intl],
|
||||
ifelse([$1], [external], [no], [yes]))
|
||||
gt_NEEDS_INIT
|
||||
AM_GNU_GETTEXT_NEED([$2])
|
||||
|
||||
AC_REQUIRE([AM_PO_SUBDIRS])dnl
|
||||
ifelse(gt_included_intl, yes, [
|
||||
AC_REQUIRE([AM_INTL_SUBDIR])dnl
|
||||
])
|
||||
|
||||
dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
|
||||
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||
AC_REQUIRE([AC_LIB_RPATH])
|
||||
|
||||
dnl Sometimes libintl requires libiconv, so first search for libiconv.
|
||||
dnl Ideally we would do this search only after the
|
||||
dnl if test "$USE_NLS" = "yes"; then
|
||||
dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
|
||||
dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT
|
||||
dnl the configure script would need to contain the same shell code
|
||||
dnl again, outside any 'if'. There are two solutions:
|
||||
dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'.
|
||||
dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE.
|
||||
dnl Since AC_PROVIDE_IFELSE is not documented, we avoid it.
|
||||
ifelse(gt_included_intl, yes, , [
|
||||
AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
|
||||
])
|
||||
|
||||
dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation.
|
||||
gt_INTL_MACOSX
|
||||
|
||||
dnl Set USE_NLS.
|
||||
AC_REQUIRE([AM_NLS])
|
||||
|
||||
ifelse(gt_included_intl, yes, [
|
||||
BUILD_INCLUDED_LIBINTL=no
|
||||
USE_INCLUDED_LIBINTL=no
|
||||
])
|
||||
LIBINTL=
|
||||
LTLIBINTL=
|
||||
POSUB=
|
||||
|
||||
dnl Add a version number to the cache macros.
|
||||
case " $gt_needs " in
|
||||
*" need-formatstring-macros "*) gt_api_version=3 ;;
|
||||
*" need-ngettext "*) gt_api_version=2 ;;
|
||||
*) gt_api_version=1 ;;
|
||||
esac
|
||||
gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc"
|
||||
gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl"
|
||||
|
||||
dnl If we use NLS figure out what method
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
gt_use_preinstalled_gnugettext=no
|
||||
ifelse(gt_included_intl, yes, [
|
||||
AC_MSG_CHECKING([whether included gettext is requested])
|
||||
AC_ARG_WITH([included-gettext],
|
||||
[ --with-included-gettext use the GNU gettext library included here],
|
||||
nls_cv_force_use_gnu_gettext=$withval,
|
||||
nls_cv_force_use_gnu_gettext=no)
|
||||
AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext])
|
||||
|
||||
nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
|
||||
if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
|
||||
])
|
||||
dnl User does not insist on using GNU NLS library. Figure out what
|
||||
dnl to use. If GNU gettext is available we use this. Else we have
|
||||
dnl to fall back to GNU NLS library.
|
||||
|
||||
if test $gt_api_version -ge 3; then
|
||||
gt_revision_test_code='
|
||||
#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
|
||||
#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
|
||||
#endif
|
||||
changequote(,)dnl
|
||||
typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1];
|
||||
changequote([,])dnl
|
||||
'
|
||||
else
|
||||
gt_revision_test_code=
|
||||
fi
|
||||
if test $gt_api_version -ge 2; then
|
||||
gt_expression_test_code=' + * ngettext ("", "", 0)'
|
||||
else
|
||||
gt_expression_test_code=
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc],
|
||||
[AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <libintl.h>
|
||||
#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
|
||||
extern int _nl_msg_cat_cntr;
|
||||
extern int *_nl_domain_bindings;
|
||||
#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_domain_bindings)
|
||||
#else
|
||||
#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0
|
||||
#endif
|
||||
$gt_revision_test_code
|
||||
]],
|
||||
[[
|
||||
bindtextdomain ("", "");
|
||||
return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION
|
||||
]])],
|
||||
[eval "$gt_func_gnugettext_libc=yes"],
|
||||
[eval "$gt_func_gnugettext_libc=no"])])
|
||||
|
||||
if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
|
||||
dnl Sometimes libintl requires libiconv, so first search for libiconv.
|
||||
ifelse(gt_included_intl, yes, , [
|
||||
AM_ICONV_LINK
|
||||
])
|
||||
dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL
|
||||
dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv])
|
||||
dnl because that would add "-liconv" to LIBINTL and LTLIBINTL
|
||||
dnl even if libiconv doesn't exist.
|
||||
AC_LIB_LINKFLAGS_BODY([intl])
|
||||
AC_CACHE_CHECK([for GNU gettext in libintl],
|
||||
[$gt_func_gnugettext_libintl],
|
||||
[gt_save_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $INCINTL"
|
||||
gt_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $LIBINTL"
|
||||
dnl Now see whether libintl exists and does not depend on libiconv.
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <libintl.h>
|
||||
#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
|
||||
extern int _nl_msg_cat_cntr;
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
const char *_nl_expand_alias (const char *);
|
||||
#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias (""))
|
||||
#else
|
||||
#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0
|
||||
#endif
|
||||
$gt_revision_test_code
|
||||
]],
|
||||
[[
|
||||
bindtextdomain ("", "");
|
||||
return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION
|
||||
]])],
|
||||
[eval "$gt_func_gnugettext_libintl=yes"],
|
||||
[eval "$gt_func_gnugettext_libintl=no"])
|
||||
dnl Now see whether libintl exists and depends on libiconv.
|
||||
if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then
|
||||
LIBS="$LIBS $LIBICONV"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <libintl.h>
|
||||
#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
|
||||
extern int _nl_msg_cat_cntr;
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
const char *_nl_expand_alias (const char *);
|
||||
#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias (""))
|
||||
#else
|
||||
#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0
|
||||
#endif
|
||||
$gt_revision_test_code
|
||||
]],
|
||||
[[
|
||||
bindtextdomain ("", "");
|
||||
return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION
|
||||
]])],
|
||||
[LIBINTL="$LIBINTL $LIBICONV"
|
||||
LTLIBINTL="$LTLIBINTL $LTLIBICONV"
|
||||
eval "$gt_func_gnugettext_libintl=yes"
|
||||
])
|
||||
fi
|
||||
CPPFLAGS="$gt_save_CPPFLAGS"
|
||||
LIBS="$gt_save_LIBS"])
|
||||
fi
|
||||
|
||||
dnl If an already present or preinstalled GNU gettext() is found,
|
||||
dnl use it. But if this macro is used in GNU gettext, and GNU
|
||||
dnl gettext is already preinstalled in libintl, we update this
|
||||
dnl libintl. (Cf. the install rule in intl/Makefile.in.)
|
||||
if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \
|
||||
|| { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \
|
||||
&& test "$PACKAGE" != gettext-runtime \
|
||||
&& test "$PACKAGE" != gettext-tools; }; then
|
||||
gt_use_preinstalled_gnugettext=yes
|
||||
else
|
||||
dnl Reset the values set by searching for libintl.
|
||||
LIBINTL=
|
||||
LTLIBINTL=
|
||||
INCINTL=
|
||||
fi
|
||||
|
||||
ifelse(gt_included_intl, yes, [
|
||||
if test "$gt_use_preinstalled_gnugettext" != "yes"; then
|
||||
dnl GNU gettext is not found in the C library.
|
||||
dnl Fall back on included GNU gettext library.
|
||||
nls_cv_use_gnu_gettext=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||
dnl Mark actions used to generate GNU NLS library.
|
||||
BUILD_INCLUDED_LIBINTL=yes
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.la $LIBICONV $LIBTHREAD"
|
||||
LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.la $LTLIBICONV $LTLIBTHREAD"
|
||||
LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
|
||||
fi
|
||||
|
||||
CATOBJEXT=
|
||||
if test "$gt_use_preinstalled_gnugettext" = "yes" \
|
||||
|| test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||
dnl Mark actions to use GNU gettext tools.
|
||||
CATOBJEXT=.gmo
|
||||
fi
|
||||
])
|
||||
|
||||
if test -n "$INTL_MACOSX_LIBS"; then
|
||||
if test "$gt_use_preinstalled_gnugettext" = "yes" \
|
||||
|| test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||
dnl Some extra flags are needed during linking.
|
||||
LIBINTL="$LIBINTL $INTL_MACOSX_LIBS"
|
||||
LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$gt_use_preinstalled_gnugettext" = "yes" \
|
||||
|| test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||
AC_DEFINE([ENABLE_NLS], [1],
|
||||
[Define to 1 if translation of program messages to the user's native language
|
||||
is requested.])
|
||||
else
|
||||
USE_NLS=no
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to use NLS])
|
||||
AC_MSG_RESULT([$USE_NLS])
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
AC_MSG_CHECKING([where the gettext function comes from])
|
||||
if test "$gt_use_preinstalled_gnugettext" = "yes"; then
|
||||
if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
|
||||
gt_source="external libintl"
|
||||
else
|
||||
gt_source="libc"
|
||||
fi
|
||||
else
|
||||
gt_source="included intl directory"
|
||||
fi
|
||||
AC_MSG_RESULT([$gt_source])
|
||||
fi
|
||||
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
|
||||
if test "$gt_use_preinstalled_gnugettext" = "yes"; then
|
||||
if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
|
||||
AC_MSG_CHECKING([how to link with libintl])
|
||||
AC_MSG_RESULT([$LIBINTL])
|
||||
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL])
|
||||
fi
|
||||
|
||||
dnl For backward compatibility. Some packages may be using this.
|
||||
AC_DEFINE([HAVE_GETTEXT], [1],
|
||||
[Define if the GNU gettext() function is already present or preinstalled.])
|
||||
AC_DEFINE([HAVE_DCGETTEXT], [1],
|
||||
[Define if the GNU dcgettext() function is already present or preinstalled.])
|
||||
fi
|
||||
|
||||
dnl We need to process the po/ directory.
|
||||
POSUB=po
|
||||
fi
|
||||
|
||||
ifelse(gt_included_intl, yes, [
|
||||
dnl In GNU gettext we have to set BUILD_INCLUDED_LIBINTL to 'yes'
|
||||
dnl because some of the testsuite requires it.
|
||||
BUILD_INCLUDED_LIBINTL=yes
|
||||
|
||||
dnl Make all variables we use known to autoconf.
|
||||
AC_SUBST([BUILD_INCLUDED_LIBINTL])
|
||||
AC_SUBST([USE_INCLUDED_LIBINTL])
|
||||
AC_SUBST([CATOBJEXT])
|
||||
])
|
||||
|
||||
dnl For backward compatibility. Some Makefiles may be using this.
|
||||
INTLLIBS="$LIBINTL"
|
||||
AC_SUBST([INTLLIBS])
|
||||
|
||||
dnl Make all documented variables known to autoconf.
|
||||
AC_SUBST([LIBINTL])
|
||||
AC_SUBST([LTLIBINTL])
|
||||
AC_SUBST([POSUB])
|
||||
])
|
||||
|
||||
|
||||
dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized.
|
||||
m4_define([gt_NEEDS_INIT],
|
||||
[
|
||||
m4_divert_text([DEFAULTS], [gt_needs=])
|
||||
m4_define([gt_NEEDS_INIT], [])
|
||||
])
|
||||
|
||||
|
||||
dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL])
|
||||
AC_DEFUN([AM_GNU_GETTEXT_NEED],
|
||||
[
|
||||
m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"])
|
||||
])
|
||||
|
||||
|
||||
dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version])
|
||||
AC_DEFUN([AM_GNU_GETTEXT_VERSION], [])
|
||||
|
||||
|
||||
dnl Usage: AM_GNU_GETTEXT_REQUIRE_VERSION([gettext-version])
|
||||
AC_DEFUN([AM_GNU_GETTEXT_REQUIRE_VERSION], [])
|
||||
@@ -1,644 +0,0 @@
|
||||
# host-cpu-c-abi.m4 serial 11
|
||||
dnl Copyright (C) 2002-2019 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible and Sam Steingold.
|
||||
|
||||
dnl Sets the HOST_CPU variable to the canonical name of the CPU.
|
||||
dnl Sets the HOST_CPU_C_ABI variable to the canonical name of the CPU with its
|
||||
dnl C language ABI (application binary interface).
|
||||
dnl Also defines __${HOST_CPU}__ and __${HOST_CPU_C_ABI}__ as C macros in
|
||||
dnl config.h.
|
||||
dnl
|
||||
dnl This canonical name can be used to select a particular assembly language
|
||||
dnl source file that will interoperate with C code on the given host.
|
||||
dnl
|
||||
dnl For example:
|
||||
dnl * 'i386' and 'sparc' are different canonical names, because code for i386
|
||||
dnl will not run on SPARC CPUs and vice versa. They have different
|
||||
dnl instruction sets.
|
||||
dnl * 'sparc' and 'sparc64' are different canonical names, because code for
|
||||
dnl 'sparc' and code for 'sparc64' cannot be linked together: 'sparc' code
|
||||
dnl contains 32-bit instructions, whereas 'sparc64' code contains 64-bit
|
||||
dnl instructions. A process on a SPARC CPU can be in 32-bit mode or in 64-bit
|
||||
dnl mode, but not both.
|
||||
dnl * 'mips' and 'mipsn32' are different canonical names, because they use
|
||||
dnl different argument passing and return conventions for C functions, and
|
||||
dnl although the instruction set of 'mips' is a large subset of the
|
||||
dnl instruction set of 'mipsn32'.
|
||||
dnl * 'mipsn32' and 'mips64' are different canonical names, because they use
|
||||
dnl different sizes for the C types like 'int' and 'void *', and although
|
||||
dnl the instruction sets of 'mipsn32' and 'mips64' are the same.
|
||||
dnl * The same canonical name is used for different endiannesses. You can
|
||||
dnl determine the endianness through preprocessor symbols:
|
||||
dnl - 'arm': test __ARMEL__.
|
||||
dnl - 'mips', 'mipsn32', 'mips64': test _MIPSEB vs. _MIPSEL.
|
||||
dnl - 'powerpc64': test _BIG_ENDIAN vs. _LITTLE_ENDIAN.
|
||||
dnl * The same name 'i386' is used for CPUs of type i386, i486, i586
|
||||
dnl (Pentium), AMD K7, Pentium II, Pentium IV, etc., because
|
||||
dnl - Instructions that do not exist on all of these CPUs (cmpxchg,
|
||||
dnl MMX, SSE, SSE2, 3DNow! etc.) are not frequently used. If your
|
||||
dnl assembly language source files use such instructions, you will
|
||||
dnl need to make the distinction.
|
||||
dnl - Speed of execution of the common instruction set is reasonable across
|
||||
dnl the entire family of CPUs. If you have assembly language source files
|
||||
dnl that are optimized for particular CPU types (like GNU gmp has), you
|
||||
dnl will need to make the distinction.
|
||||
dnl See <https://en.wikipedia.org/wiki/X86_instruction_listings>.
|
||||
AC_DEFUN([gl_HOST_CPU_C_ABI],
|
||||
[
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([gl_C_ASM])
|
||||
AC_CACHE_CHECK([host CPU and C ABI], [gl_cv_host_cpu_c_abi],
|
||||
[case "$host_cpu" in
|
||||
|
||||
changequote(,)dnl
|
||||
i[4567]86 )
|
||||
changequote([,])dnl
|
||||
gl_cv_host_cpu_c_abi=i386
|
||||
;;
|
||||
|
||||
x86_64 )
|
||||
# On x86_64 systems, the C compiler may be generating code in one of
|
||||
# these ABIs:
|
||||
# - 64-bit instruction set, 64-bit pointers, 64-bit 'long': x86_64.
|
||||
# - 64-bit instruction set, 64-bit pointers, 32-bit 'long': x86_64
|
||||
# with native Windows (mingw, MSVC).
|
||||
# - 64-bit instruction set, 32-bit pointers, 32-bit 'long': x86_64-x32.
|
||||
# - 32-bit instruction set, 32-bit pointers, 32-bit 'long': i386.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if (defined __x86_64__ || defined __amd64__ \
|
||||
|| defined _M_X64 || defined _M_AMD64)
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __ILP32__ || defined _ILP32
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=x86_64-x32],
|
||||
[gl_cv_host_cpu_c_abi=x86_64])],
|
||||
[gl_cv_host_cpu_c_abi=i386])
|
||||
;;
|
||||
|
||||
changequote(,)dnl
|
||||
alphaev[4-8] | alphaev56 | alphapca5[67] | alphaev6[78] )
|
||||
changequote([,])dnl
|
||||
gl_cv_host_cpu_c_abi=alpha
|
||||
;;
|
||||
|
||||
arm* | aarch64 )
|
||||
# Assume arm with EABI.
|
||||
# On arm64 systems, the C compiler may be generating code in one of
|
||||
# these ABIs:
|
||||
# - aarch64 instruction set, 64-bit pointers, 64-bit 'long': arm64.
|
||||
# - aarch64 instruction set, 32-bit pointers, 32-bit 'long': arm64-ilp32.
|
||||
# - 32-bit instruction set, 32-bit pointers, 32-bit 'long': arm or armhf.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#ifdef __aarch64__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __ILP32__ || defined _ILP32
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=arm64-ilp32],
|
||||
[gl_cv_host_cpu_c_abi=arm64])],
|
||||
[# Don't distinguish little-endian and big-endian arm, since they
|
||||
# don't require different machine code for simple operations and
|
||||
# since the user can distinguish them through the preprocessor
|
||||
# defines __ARMEL__ vs. __ARMEB__.
|
||||
# But distinguish arm which passes floating-point arguments and
|
||||
# return values in integer registers (r0, r1, ...) - this is
|
||||
# gcc -mfloat-abi=soft or gcc -mfloat-abi=softfp - from arm which
|
||||
# passes them in float registers (s0, s1, ...) and double registers
|
||||
# (d0, d1, ...) - this is gcc -mfloat-abi=hard. GCC 4.6 or newer
|
||||
# sets the preprocessor defines __ARM_PCS (for the first case) and
|
||||
# __ARM_PCS_VFP (for the second case), but older GCC does not.
|
||||
echo 'double ddd; void func (double dd) { ddd = dd; }' > conftest.c
|
||||
# Look for a reference to the register d0 in the .s file.
|
||||
AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $gl_c_asm_opt conftest.c) >/dev/null 2>&1
|
||||
if LC_ALL=C grep 'd0,' conftest.$gl_asmext >/dev/null; then
|
||||
gl_cv_host_cpu_c_abi=armhf
|
||||
else
|
||||
gl_cv_host_cpu_c_abi=arm
|
||||
fi
|
||||
rm -f conftest*
|
||||
])
|
||||
;;
|
||||
|
||||
hppa1.0 | hppa1.1 | hppa2.0* | hppa64 )
|
||||
# On hppa, the C compiler may be generating 32-bit code or 64-bit
|
||||
# code. In the latter case, it defines _LP64 and __LP64__.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#ifdef __LP64__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=hppa64],
|
||||
[gl_cv_host_cpu_c_abi=hppa])
|
||||
;;
|
||||
|
||||
ia64* )
|
||||
# On ia64 on HP-UX, the C compiler may be generating 64-bit code or
|
||||
# 32-bit code. In the latter case, it defines _ILP32.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#ifdef _ILP32
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=ia64-ilp32],
|
||||
[gl_cv_host_cpu_c_abi=ia64])
|
||||
;;
|
||||
|
||||
mips* )
|
||||
# We should also check for (_MIPS_SZPTR == 64), but gcc keeps this
|
||||
# at 32.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64)
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=mips64],
|
||||
[# In the n32 ABI, _ABIN32 is defined, _ABIO32 is not defined (but
|
||||
# may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIN32.
|
||||
# In the 32 ABI, _ABIO32 is defined, _ABIN32 is not defined (but
|
||||
# may later get defined by <sgidefs.h>), and _MIPS_SIM == _ABIO32.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if (_MIPS_SIM == _ABIN32)
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=mipsn32],
|
||||
[gl_cv_host_cpu_c_abi=mips])])
|
||||
;;
|
||||
|
||||
powerpc* )
|
||||
# Different ABIs are in use on AIX vs. Mac OS X vs. Linux,*BSD.
|
||||
# No need to distinguish them here; the caller may distinguish
|
||||
# them based on the OS.
|
||||
# On powerpc64 systems, the C compiler may still be generating
|
||||
# 32-bit code. And on powerpc-ibm-aix systems, the C compiler may
|
||||
# be generating 64-bit code.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __powerpc64__ || defined _ARCH_PPC64
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[# On powerpc64, there are two ABIs on Linux: The AIX compatible
|
||||
# one and the ELFv2 one. The latter defines _CALL_ELF=2.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined _CALL_ELF && _CALL_ELF == 2
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=powerpc64-elfv2],
|
||||
[gl_cv_host_cpu_c_abi=powerpc64])
|
||||
],
|
||||
[gl_cv_host_cpu_c_abi=powerpc])
|
||||
;;
|
||||
|
||||
rs6000 )
|
||||
gl_cv_host_cpu_c_abi=powerpc
|
||||
;;
|
||||
|
||||
riscv32 | riscv64 )
|
||||
# There are 2 architectures (with variants): rv32* and rv64*.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if __riscv_xlen == 64
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[cpu=riscv64],
|
||||
[cpu=riscv32])
|
||||
# There are 6 ABIs: ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d.
|
||||
# Size of 'long' and 'void *':
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __LP64__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[main_abi=lp64],
|
||||
[main_abi=ilp32])
|
||||
# Float ABIs:
|
||||
# __riscv_float_abi_double:
|
||||
# 'float' and 'double' are passed in floating-point registers.
|
||||
# __riscv_float_abi_single:
|
||||
# 'float' are passed in floating-point registers.
|
||||
# __riscv_float_abi_soft:
|
||||
# No values are passed in floating-point registers.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __riscv_float_abi_double
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[float_abi=d],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __riscv_float_abi_single
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[float_abi=f],
|
||||
[float_abi=''])
|
||||
])
|
||||
gl_cv_host_cpu_c_abi="${cpu}-${main_abi}${float_abi}"
|
||||
;;
|
||||
|
||||
s390* )
|
||||
# On s390x, the C compiler may be generating 64-bit (= s390x) code
|
||||
# or 31-bit (= s390) code.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __LP64__ || defined __s390x__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=s390x],
|
||||
[gl_cv_host_cpu_c_abi=s390])
|
||||
;;
|
||||
|
||||
sparc | sparc64 )
|
||||
# UltraSPARCs running Linux have `uname -m` = "sparc64", but the
|
||||
# C compiler still generates 32-bit code.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __sparcv9 || defined __arch64__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi=sparc64],
|
||||
[gl_cv_host_cpu_c_abi=sparc])
|
||||
;;
|
||||
|
||||
*)
|
||||
gl_cv_host_cpu_c_abi="$host_cpu"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
dnl In most cases, $HOST_CPU and $HOST_CPU_C_ABI are the same.
|
||||
HOST_CPU=`echo "$gl_cv_host_cpu_c_abi" | sed -e 's/-.*//'`
|
||||
HOST_CPU_C_ABI="$gl_cv_host_cpu_c_abi"
|
||||
AC_SUBST([HOST_CPU])
|
||||
AC_SUBST([HOST_CPU_C_ABI])
|
||||
|
||||
# This was
|
||||
# AC_DEFINE_UNQUOTED([__${HOST_CPU}__])
|
||||
# AC_DEFINE_UNQUOTED([__${HOST_CPU_C_ABI}__])
|
||||
# earlier, but KAI C++ 3.2d doesn't like this.
|
||||
sed -e 's/-/_/g' >> confdefs.h <<EOF
|
||||
#ifndef __${HOST_CPU}__
|
||||
#define __${HOST_CPU}__ 1
|
||||
#endif
|
||||
#ifndef __${HOST_CPU_C_ABI}__
|
||||
#define __${HOST_CPU_C_ABI}__ 1
|
||||
#endif
|
||||
EOF
|
||||
AH_TOP([/* CPU and C ABI indicator */
|
||||
#ifndef __i386__
|
||||
#undef __i386__
|
||||
#endif
|
||||
#ifndef __x86_64_x32__
|
||||
#undef __x86_64_x32__
|
||||
#endif
|
||||
#ifndef __x86_64__
|
||||
#undef __x86_64__
|
||||
#endif
|
||||
#ifndef __alpha__
|
||||
#undef __alpha__
|
||||
#endif
|
||||
#ifndef __arm__
|
||||
#undef __arm__
|
||||
#endif
|
||||
#ifndef __armhf__
|
||||
#undef __armhf__
|
||||
#endif
|
||||
#ifndef __arm64_ilp32__
|
||||
#undef __arm64_ilp32__
|
||||
#endif
|
||||
#ifndef __arm64__
|
||||
#undef __arm64__
|
||||
#endif
|
||||
#ifndef __hppa__
|
||||
#undef __hppa__
|
||||
#endif
|
||||
#ifndef __hppa64__
|
||||
#undef __hppa64__
|
||||
#endif
|
||||
#ifndef __ia64_ilp32__
|
||||
#undef __ia64_ilp32__
|
||||
#endif
|
||||
#ifndef __ia64__
|
||||
#undef __ia64__
|
||||
#endif
|
||||
#ifndef __m68k__
|
||||
#undef __m68k__
|
||||
#endif
|
||||
#ifndef __mips__
|
||||
#undef __mips__
|
||||
#endif
|
||||
#ifndef __mipsn32__
|
||||
#undef __mipsn32__
|
||||
#endif
|
||||
#ifndef __mips64__
|
||||
#undef __mips64__
|
||||
#endif
|
||||
#ifndef __powerpc__
|
||||
#undef __powerpc__
|
||||
#endif
|
||||
#ifndef __powerpc64__
|
||||
#undef __powerpc64__
|
||||
#endif
|
||||
#ifndef __powerpc64_elfv2__
|
||||
#undef __powerpc64_elfv2__
|
||||
#endif
|
||||
#ifndef __riscv32__
|
||||
#undef __riscv32__
|
||||
#endif
|
||||
#ifndef __riscv64__
|
||||
#undef __riscv64__
|
||||
#endif
|
||||
#ifndef __riscv32_ilp32__
|
||||
#undef __riscv32_ilp32__
|
||||
#endif
|
||||
#ifndef __riscv32_ilp32f__
|
||||
#undef __riscv32_ilp32f__
|
||||
#endif
|
||||
#ifndef __riscv32_ilp32d__
|
||||
#undef __riscv32_ilp32d__
|
||||
#endif
|
||||
#ifndef __riscv64_ilp32__
|
||||
#undef __riscv64_ilp32__
|
||||
#endif
|
||||
#ifndef __riscv64_ilp32f__
|
||||
#undef __riscv64_ilp32f__
|
||||
#endif
|
||||
#ifndef __riscv64_ilp32d__
|
||||
#undef __riscv64_ilp32d__
|
||||
#endif
|
||||
#ifndef __riscv64_lp64__
|
||||
#undef __riscv64_lp64__
|
||||
#endif
|
||||
#ifndef __riscv64_lp64f__
|
||||
#undef __riscv64_lp64f__
|
||||
#endif
|
||||
#ifndef __riscv64_lp64d__
|
||||
#undef __riscv64_lp64d__
|
||||
#endif
|
||||
#ifndef __s390__
|
||||
#undef __s390__
|
||||
#endif
|
||||
#ifndef __s390x__
|
||||
#undef __s390x__
|
||||
#endif
|
||||
#ifndef __sh__
|
||||
#undef __sh__
|
||||
#endif
|
||||
#ifndef __sparc__
|
||||
#undef __sparc__
|
||||
#endif
|
||||
#ifndef __sparc64__
|
||||
#undef __sparc64__
|
||||
#endif
|
||||
])
|
||||
|
||||
])
|
||||
|
||||
|
||||
dnl Sets the HOST_CPU_C_ABI_32BIT variable to 'yes' if the C language ABI
|
||||
dnl (application binary interface) is a 32-bit one, or to 'no' otherwise.
|
||||
dnl This is a simplified variant of gl_HOST_CPU_C_ABI.
|
||||
AC_DEFUN([gl_HOST_CPU_C_ABI_32BIT],
|
||||
[
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_CACHE_CHECK([32-bit host C ABI], [gl_cv_host_cpu_c_abi_32bit],
|
||||
[if test -n "$gl_cv_host_cpu_c_abi"; then
|
||||
case "$gl_cv_host_cpu_c_abi" in
|
||||
i386 | x86_64-x32 | arm | armhf | arm64-ilp32 | hppa | ia64-ilp32 | mips | mipsn32 | powerpc | riscv*-ilp32* | s390 | sparc)
|
||||
gl_cv_host_cpu_c_abi_32bit=yes ;;
|
||||
*)
|
||||
gl_cv_host_cpu_c_abi_32bit=no ;;
|
||||
esac
|
||||
else
|
||||
case "$host_cpu" in
|
||||
|
||||
changequote(,)dnl
|
||||
i[4567]86 )
|
||||
changequote([,])dnl
|
||||
gl_cv_host_cpu_c_abi_32bit=yes
|
||||
;;
|
||||
|
||||
x86_64 )
|
||||
# On x86_64 systems, the C compiler may be generating code in one of
|
||||
# these ABIs:
|
||||
# - 64-bit instruction set, 64-bit pointers, 64-bit 'long': x86_64.
|
||||
# - 64-bit instruction set, 64-bit pointers, 32-bit 'long': x86_64
|
||||
# with native Windows (mingw, MSVC).
|
||||
# - 64-bit instruction set, 32-bit pointers, 32-bit 'long': x86_64-x32.
|
||||
# - 32-bit instruction set, 32-bit pointers, 32-bit 'long': i386.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if (defined __x86_64__ || defined __amd64__ \
|
||||
|| defined _M_X64 || defined _M_AMD64) \
|
||||
&& !(defined __ILP32__ || defined _ILP32)
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
arm* | aarch64 )
|
||||
# Assume arm with EABI.
|
||||
# On arm64 systems, the C compiler may be generating code in one of
|
||||
# these ABIs:
|
||||
# - aarch64 instruction set, 64-bit pointers, 64-bit 'long': arm64.
|
||||
# - aarch64 instruction set, 32-bit pointers, 32-bit 'long': arm64-ilp32.
|
||||
# - 32-bit instruction set, 32-bit pointers, 32-bit 'long': arm or armhf.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __aarch64__ && !(defined __ILP32__ || defined _ILP32)
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
hppa1.0 | hppa1.1 | hppa2.0* | hppa64 )
|
||||
# On hppa, the C compiler may be generating 32-bit code or 64-bit
|
||||
# code. In the latter case, it defines _LP64 and __LP64__.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#ifdef __LP64__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
ia64* )
|
||||
# On ia64 on HP-UX, the C compiler may be generating 64-bit code or
|
||||
# 32-bit code. In the latter case, it defines _ILP32.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#ifdef _ILP32
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no])
|
||||
;;
|
||||
|
||||
mips* )
|
||||
# We should also check for (_MIPS_SZPTR == 64), but gcc keeps this
|
||||
# at 32.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined _MIPS_SZLONG && (_MIPS_SZLONG == 64)
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
powerpc* )
|
||||
# Different ABIs are in use on AIX vs. Mac OS X vs. Linux,*BSD.
|
||||
# No need to distinguish them here; the caller may distinguish
|
||||
# them based on the OS.
|
||||
# On powerpc64 systems, the C compiler may still be generating
|
||||
# 32-bit code. And on powerpc-ibm-aix systems, the C compiler may
|
||||
# be generating 64-bit code.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __powerpc64__ || defined _ARCH_PPC64
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
rs6000 )
|
||||
gl_cv_host_cpu_c_abi_32bit=yes
|
||||
;;
|
||||
|
||||
riscv32 | riscv64 )
|
||||
# There are 6 ABIs: ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d.
|
||||
# Size of 'long' and 'void *':
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __LP64__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
s390* )
|
||||
# On s390x, the C compiler may be generating 64-bit (= s390x) code
|
||||
# or 31-bit (= s390) code.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __LP64__ || defined __s390x__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
sparc | sparc64 )
|
||||
# UltraSPARCs running Linux have `uname -m` = "sparc64", but the
|
||||
# C compiler still generates 32-bit code.
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[[#if defined __sparcv9 || defined __arch64__
|
||||
int ok;
|
||||
#else
|
||||
error fail
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_host_cpu_c_abi_32bit=no],
|
||||
[gl_cv_host_cpu_c_abi_32bit=yes])
|
||||
;;
|
||||
|
||||
*)
|
||||
gl_cv_host_cpu_c_abi_32bit=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
])
|
||||
|
||||
HOST_CPU_C_ABI_32BIT="$gl_cv_host_cpu_c_abi_32bit"
|
||||
])
|
||||
-287
@@ -1,287 +0,0 @@
|
||||
# iconv.m4 serial 21
|
||||
dnl Copyright (C) 2000-2002, 2007-2014, 2016-2019 Free Software Foundation,
|
||||
dnl Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
|
||||
[
|
||||
dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
|
||||
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||
AC_REQUIRE([AC_LIB_RPATH])
|
||||
|
||||
dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
|
||||
dnl accordingly.
|
||||
AC_LIB_LINKFLAGS_BODY([iconv])
|
||||
])
|
||||
|
||||
AC_DEFUN([AM_ICONV_LINK],
|
||||
[
|
||||
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||
dnl those with the standalone portable GNU libiconv installed).
|
||||
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
|
||||
|
||||
dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
|
||||
dnl accordingly.
|
||||
AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
|
||||
|
||||
dnl Add $INCICONV to CPPFLAGS before performing the following checks,
|
||||
dnl because if the user has installed libiconv and not disabled its use
|
||||
dnl via --without-libiconv-prefix, he wants to use it. The first
|
||||
dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed.
|
||||
am_save_CPPFLAGS="$CPPFLAGS"
|
||||
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
|
||||
|
||||
AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
|
||||
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||
am_cv_lib_iconv=no
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
]],
|
||||
[[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);]])],
|
||||
[am_cv_func_iconv=yes])
|
||||
if test "$am_cv_func_iconv" != yes; then
|
||||
am_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $LIBICONV"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
]],
|
||||
[[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);]])],
|
||||
[am_cv_lib_iconv=yes]
|
||||
[am_cv_func_iconv=yes])
|
||||
LIBS="$am_save_LIBS"
|
||||
fi
|
||||
])
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
|
||||
dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11,
|
||||
dnl Solaris 10.
|
||||
am_save_LIBS="$LIBS"
|
||||
if test $am_cv_lib_iconv = yes; then
|
||||
LIBS="$LIBS $LIBICONV"
|
||||
fi
|
||||
am_cv_func_iconv_works=no
|
||||
for ac_iconv_const in '' 'const'; do
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <iconv.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef ICONV_CONST
|
||||
# define ICONV_CONST $ac_iconv_const
|
||||
#endif
|
||||
]],
|
||||
[[int result = 0;
|
||||
/* Test against AIX 5.1 bug: Failures are not distinguishable from successful
|
||||
returns. */
|
||||
{
|
||||
iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
|
||||
if (cd_utf8_to_88591 != (iconv_t)(-1))
|
||||
{
|
||||
static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */
|
||||
char buf[10];
|
||||
ICONV_CONST char *inptr = input;
|
||||
size_t inbytesleft = strlen (input);
|
||||
char *outptr = buf;
|
||||
size_t outbytesleft = sizeof (buf);
|
||||
size_t res = iconv (cd_utf8_to_88591,
|
||||
&inptr, &inbytesleft,
|
||||
&outptr, &outbytesleft);
|
||||
if (res == 0)
|
||||
result |= 1;
|
||||
iconv_close (cd_utf8_to_88591);
|
||||
}
|
||||
}
|
||||
/* Test against Solaris 10 bug: Failures are not distinguishable from
|
||||
successful returns. */
|
||||
{
|
||||
iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
|
||||
if (cd_ascii_to_88591 != (iconv_t)(-1))
|
||||
{
|
||||
static ICONV_CONST char input[] = "\263";
|
||||
char buf[10];
|
||||
ICONV_CONST char *inptr = input;
|
||||
size_t inbytesleft = strlen (input);
|
||||
char *outptr = buf;
|
||||
size_t outbytesleft = sizeof (buf);
|
||||
size_t res = iconv (cd_ascii_to_88591,
|
||||
&inptr, &inbytesleft,
|
||||
&outptr, &outbytesleft);
|
||||
if (res == 0)
|
||||
result |= 2;
|
||||
iconv_close (cd_ascii_to_88591);
|
||||
}
|
||||
}
|
||||
/* Test against AIX 6.1..7.1 bug: Buffer overrun. */
|
||||
{
|
||||
iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
|
||||
if (cd_88591_to_utf8 != (iconv_t)(-1))
|
||||
{
|
||||
static ICONV_CONST char input[] = "\304";
|
||||
static char buf[2] = { (char)0xDE, (char)0xAD };
|
||||
ICONV_CONST char *inptr = input;
|
||||
size_t inbytesleft = 1;
|
||||
char *outptr = buf;
|
||||
size_t outbytesleft = 1;
|
||||
size_t res = iconv (cd_88591_to_utf8,
|
||||
&inptr, &inbytesleft,
|
||||
&outptr, &outbytesleft);
|
||||
if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
|
||||
result |= 4;
|
||||
iconv_close (cd_88591_to_utf8);
|
||||
}
|
||||
}
|
||||
#if 0 /* This bug could be worked around by the caller. */
|
||||
/* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
|
||||
{
|
||||
iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
|
||||
if (cd_88591_to_utf8 != (iconv_t)(-1))
|
||||
{
|
||||
static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
|
||||
char buf[50];
|
||||
ICONV_CONST char *inptr = input;
|
||||
size_t inbytesleft = strlen (input);
|
||||
char *outptr = buf;
|
||||
size_t outbytesleft = sizeof (buf);
|
||||
size_t res = iconv (cd_88591_to_utf8,
|
||||
&inptr, &inbytesleft,
|
||||
&outptr, &outbytesleft);
|
||||
if ((int)res > 0)
|
||||
result |= 8;
|
||||
iconv_close (cd_88591_to_utf8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
|
||||
provided. */
|
||||
{
|
||||
/* Try standardized names. */
|
||||
iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
|
||||
/* Try IRIX, OSF/1 names. */
|
||||
iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
|
||||
/* Try AIX names. */
|
||||
iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
|
||||
/* Try HP-UX names. */
|
||||
iconv_t cd4 = iconv_open ("utf8", "eucJP");
|
||||
if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
|
||||
&& cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
|
||||
result |= 16;
|
||||
if (cd1 != (iconv_t)(-1))
|
||||
iconv_close (cd1);
|
||||
if (cd2 != (iconv_t)(-1))
|
||||
iconv_close (cd2);
|
||||
if (cd3 != (iconv_t)(-1))
|
||||
iconv_close (cd3);
|
||||
if (cd4 != (iconv_t)(-1))
|
||||
iconv_close (cd4);
|
||||
}
|
||||
return result;
|
||||
]])],
|
||||
[am_cv_func_iconv_works=yes], ,
|
||||
[case "$host_os" in
|
||||
aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
|
||||
*) am_cv_func_iconv_works="guessing yes" ;;
|
||||
esac])
|
||||
test "$am_cv_func_iconv_works" = no || break
|
||||
done
|
||||
LIBS="$am_save_LIBS"
|
||||
])
|
||||
case "$am_cv_func_iconv_works" in
|
||||
*no) am_func_iconv=no am_cv_lib_iconv=no ;;
|
||||
*) am_func_iconv=yes ;;
|
||||
esac
|
||||
else
|
||||
am_func_iconv=no am_cv_lib_iconv=no
|
||||
fi
|
||||
if test "$am_func_iconv" = yes; then
|
||||
AC_DEFINE([HAVE_ICONV], [1],
|
||||
[Define if you have the iconv() function and it works.])
|
||||
fi
|
||||
if test "$am_cv_lib_iconv" = yes; then
|
||||
AC_MSG_CHECKING([how to link with libiconv])
|
||||
AC_MSG_RESULT([$LIBICONV])
|
||||
else
|
||||
dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
|
||||
dnl either.
|
||||
CPPFLAGS="$am_save_CPPFLAGS"
|
||||
LIBICONV=
|
||||
LTLIBICONV=
|
||||
fi
|
||||
AC_SUBST([LIBICONV])
|
||||
AC_SUBST([LTLIBICONV])
|
||||
])
|
||||
|
||||
dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
|
||||
dnl avoid warnings like
|
||||
dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
|
||||
dnl This is tricky because of the way 'aclocal' is implemented:
|
||||
dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
|
||||
dnl Otherwise aclocal's initial scan pass would miss the macro definition.
|
||||
dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
|
||||
dnl Otherwise aclocal would emit many "Use of uninitialized value $1"
|
||||
dnl warnings.
|
||||
m4_define([gl_iconv_AC_DEFUN],
|
||||
m4_version_prereq([2.64],
|
||||
[[AC_DEFUN_ONCE(
|
||||
[$1], [$2])]],
|
||||
[m4_ifdef([gl_00GNULIB],
|
||||
[[AC_DEFUN_ONCE(
|
||||
[$1], [$2])]],
|
||||
[[AC_DEFUN(
|
||||
[$1], [$2])]])]))
|
||||
gl_iconv_AC_DEFUN([AM_ICONV],
|
||||
[
|
||||
AM_ICONV_LINK
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL([am_cv_proto_iconv], [
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
]],
|
||||
[[]])],
|
||||
[am_cv_proto_iconv_arg1=""],
|
||||
[am_cv_proto_iconv_arg1="const"])
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([$am_cv_proto_iconv])
|
||||
else
|
||||
dnl When compiling GNU libiconv on a system that does not have iconv yet,
|
||||
dnl pick the POSIX compliant declaration without 'const'.
|
||||
am_cv_proto_iconv_arg1=""
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
|
||||
m4_ifdef([gl_ICONV_H_DEFAULTS],
|
||||
[AC_REQUIRE([gl_ICONV_H_DEFAULTS])
|
||||
if test -n "$am_cv_proto_iconv_arg1"; then
|
||||
ICONV_CONST="const"
|
||||
fi
|
||||
])
|
||||
])
|
||||
@@ -1,72 +0,0 @@
|
||||
# intlmacosx.m4 serial 6 (gettext-0.20)
|
||||
dnl Copyright (C) 2004-2014, 2016, 2019 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
dnl
|
||||
dnl This file can be used in projects which are not available under
|
||||
dnl the GNU General Public License or the GNU Library General Public
|
||||
dnl License but which still want to provide support for the GNU gettext
|
||||
dnl functionality.
|
||||
dnl Please note that the actual code of the GNU gettext library is covered
|
||||
dnl by the GNU Library General Public License, and the rest of the GNU
|
||||
dnl gettext package is covered by the GNU General Public License.
|
||||
dnl They are *not* in the public domain.
|
||||
|
||||
dnl Checks for special options needed on Mac OS X.
|
||||
dnl Defines INTL_MACOSX_LIBS.
|
||||
AC_DEFUN([gt_INTL_MACOSX],
|
||||
[
|
||||
dnl Check for API introduced in Mac OS X 10.4.
|
||||
AC_CACHE_CHECK([for CFPreferencesCopyAppValue],
|
||||
[gt_cv_func_CFPreferencesCopyAppValue],
|
||||
[gt_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <CoreFoundation/CFPreferences.h>]],
|
||||
[[CFPreferencesCopyAppValue(NULL, NULL)]])],
|
||||
[gt_cv_func_CFPreferencesCopyAppValue=yes],
|
||||
[gt_cv_func_CFPreferencesCopyAppValue=no])
|
||||
LIBS="$gt_save_LIBS"])
|
||||
if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then
|
||||
AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1],
|
||||
[Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework.])
|
||||
fi
|
||||
dnl Check for API introduced in Mac OS X 10.5.
|
||||
AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent],
|
||||
[gt_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <CoreFoundation/CFLocale.h>]],
|
||||
[[CFLocaleCopyCurrent();]])],
|
||||
[gt_cv_func_CFLocaleCopyCurrent=yes],
|
||||
[gt_cv_func_CFLocaleCopyCurrent=no])
|
||||
LIBS="$gt_save_LIBS"])
|
||||
if test $gt_cv_func_CFLocaleCopyCurrent = yes; then
|
||||
AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1],
|
||||
[Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework.])
|
||||
fi
|
||||
AC_CACHE_CHECK([for CFLocaleCopyPreferredLanguages], [gt_cv_func_CFLocaleCopyPreferredLanguages],
|
||||
[gt_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <CoreFoundation/CFLocale.h>]],
|
||||
[[CFLocaleCopyPreferredLanguages();]])],
|
||||
[gt_cv_func_CFLocaleCopyPreferredLanguages=yes],
|
||||
[gt_cv_func_CFLocaleCopyPreferredLanguages=no])
|
||||
LIBS="$gt_save_LIBS"])
|
||||
if test $gt_cv_func_CFLocaleCopyPreferredLanguages = yes; then
|
||||
AC_DEFINE([HAVE_CFLOCALECOPYPREFERREDLANGUAGES], [1],
|
||||
[Define to 1 if you have the Mac OS X function CFLocaleCopyPreferredLanguages in the CoreFoundation framework.])
|
||||
fi
|
||||
INTL_MACOSX_LIBS=
|
||||
if test $gt_cv_func_CFPreferencesCopyAppValue = yes \
|
||||
|| test $gt_cv_func_CFLocaleCopyCurrent = yes \
|
||||
|| test $gt_cv_func_CFLocaleCopyPreferredLanguages = yes; then
|
||||
INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
|
||||
fi
|
||||
AC_SUBST([INTL_MACOSX_LIBS])
|
||||
])
|
||||
@@ -4,23 +4,17 @@ dnl #
|
||||
dnl # - access_ok(type, addr, size)
|
||||
dnl # + access_ok(addr, size)
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE], [
|
||||
ZFS_LINUX_TEST_SRC([access_ok_type], [
|
||||
#include <linux/uaccess.h>
|
||||
],[
|
||||
const void __user __attribute__((unused)) *addr =
|
||||
(void *) 0xdeadbeef;
|
||||
unsigned long __attribute__((unused)) size = 1;
|
||||
int error __attribute__((unused)) = access_ok(0, addr, size);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_ACCESS_OK_TYPE], [
|
||||
AC_MSG_CHECKING([whether access_ok() has 'type' parameter])
|
||||
ZFS_LINUX_TEST_RESULT([access_ok_type], [
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/uaccess.h>
|
||||
],[
|
||||
const void __user __attribute__((unused)) *addr = (void *) 0xdeadbeef;
|
||||
unsigned long __attribute__((unused)) size = 1;
|
||||
int error __attribute__((unused)) = access_ok(0, addr, size);
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_ACCESS_OK_TYPE, 1,
|
||||
[kernel has access_ok with 'type' parameter])
|
||||
AC_DEFINE(HAVE_ACCESS_OK_TYPE, 1, [kernel has access_ok with 'type' parameter])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
+83
-174
@@ -3,26 +3,32 @@ dnl # Check if posix_acl_release can be used from a ZFS_META_LICENSED
|
||||
dnl # module. The is_owner_or_cap macro was replaced by
|
||||
dnl # inode_owner_or_capable
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_RELEASE], [
|
||||
ZFS_LINUX_TEST_SRC([posix_acl_release], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_RELEASE], [
|
||||
AC_MSG_CHECKING([whether posix_acl_release() is available])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/cred.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
], [
|
||||
struct posix_acl *tmp = posix_acl_alloc(1, 0);
|
||||
],[
|
||||
struct posix_acl* tmp = posix_acl_alloc(1, 0);
|
||||
posix_acl_release(tmp);
|
||||
], [], [$ZFS_META_LICENSE])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_RELEASE], [
|
||||
AC_MSG_CHECKING([whether posix_acl_release() is available])
|
||||
ZFS_LINUX_TEST_RESULT([posix_acl_release], [
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_POSIX_ACL_RELEASE, 1,
|
||||
[posix_acl_release() is available])
|
||||
|
||||
AC_MSG_CHECKING([whether posix_acl_release() is GPL-only])
|
||||
ZFS_LINUX_TEST_RESULT([posix_acl_release_license], [
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/module.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
|
||||
MODULE_LICENSE("$ZFS_META_LICENSE");
|
||||
],[
|
||||
struct posix_acl* tmp = posix_acl_alloc(1, 0);
|
||||
posix_acl_release(tmp);
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
@@ -40,25 +46,24 @@ dnl # set_cached_acl() and forget_cached_acl() changed from inline to
|
||||
dnl # EXPORT_SYMBOL. In the former case, they may not be usable because of
|
||||
dnl # posix_acl_release. In the latter case, we can always use them.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_CACHED_ACL_USABLE], [
|
||||
ZFS_LINUX_TEST_SRC([set_cached_acl], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE], [
|
||||
AC_MSG_CHECKING([whether set_cached_acl() is usable])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/module.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
], [
|
||||
|
||||
MODULE_LICENSE("$ZFS_META_LICENSE");
|
||||
],[
|
||||
struct inode *ip = NULL;
|
||||
struct posix_acl *acl = posix_acl_alloc(1, 0);
|
||||
set_cached_acl(ip, ACL_TYPE_ACCESS, acl);
|
||||
forget_cached_acl(ip, ACL_TYPE_ACCESS);
|
||||
], [], [$ZFS_META_LICENSE])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE], [
|
||||
AC_MSG_CHECKING([whether set_cached_acl() is usable])
|
||||
ZFS_LINUX_TEST_RESULT([set_cached_acl_license], [
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SET_CACHED_ACL_USABLE, 1,
|
||||
[set_cached_acl() is usable])
|
||||
[posix_acl_release() is usable])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
@@ -72,25 +77,14 @@ dnl #
|
||||
dnl # 3.14 API change,
|
||||
dnl # posix_acl_chmod() is changed to __posix_acl_chmod()
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_CHMOD], [
|
||||
ZFS_LINUX_TEST_SRC([posix_acl_chmod], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
|
||||
AC_MSG_CHECKING([whether posix_acl_chmod exists])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
],[
|
||||
posix_acl_chmod(NULL, 0, 0)
|
||||
])
|
||||
|
||||
ZFS_LINUX_TEST_SRC([__posix_acl_chmod], [
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
],[
|
||||
__posix_acl_chmod(NULL, 0, 0)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
|
||||
AC_MSG_CHECKING([whether posix_acl_chmod exists])
|
||||
ZFS_LINUX_TEST_RESULT([posix_acl_chmod], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_POSIX_ACL_CHMOD, 1, [posix_acl_chmod() exists])
|
||||
],[
|
||||
@@ -98,10 +92,14 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_CHMOD], [
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether __posix_acl_chmod exists])
|
||||
ZFS_LINUX_TEST_RESULT([__posix_acl_chmod], [
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
],[
|
||||
__posix_acl_chmod(NULL, 0, 0)
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE___POSIX_ACL_CHMOD, 1,
|
||||
[__posix_acl_chmod() exists])
|
||||
AC_DEFINE(HAVE___POSIX_ACL_CHMOD, 1, [__posix_acl_chmod() exists])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
@@ -111,22 +109,18 @@ dnl #
|
||||
dnl # 3.1 API change,
|
||||
dnl # posix_acl_equiv_mode now wants an umode_t* instead of a mode_t*
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
|
||||
ZFS_LINUX_TEST_SRC([posix_acl_equiv_mode], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
|
||||
AC_MSG_CHECKING([whether posix_acl_equiv_mode() wants umode_t])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
],[
|
||||
umode_t tmp;
|
||||
posix_acl_equiv_mode(NULL,&tmp);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
|
||||
AC_MSG_CHECKING([whether posix_acl_equiv_mode() wants umode_t])
|
||||
ZFS_LINUX_TEST_RESULT([posix_acl_equiv_mode], [
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_POSIX_ACL_EQUIV_MODE_UMODE_T, 1,
|
||||
[posix_acl_equiv_mode wants umode_t*])
|
||||
[ posix_acl_equiv_mode wants umode_t*])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
@@ -136,8 +130,9 @@ dnl #
|
||||
dnl # 4.8 API change,
|
||||
dnl # The function posix_acl_valid now must be passed a namespace.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS], [
|
||||
ZFS_LINUX_TEST_SRC([posix_acl_valid_with_ns], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
|
||||
AC_MSG_CHECKING([whether posix_acl_valid() wants user namespace])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
],[
|
||||
@@ -146,12 +141,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS], [
|
||||
int error;
|
||||
|
||||
error = posix_acl_valid(user_ns, acl);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS], [
|
||||
AC_MSG_CHECKING([whether posix_acl_valid() wants user namespace])
|
||||
ZFS_LINUX_TEST_RESULT([posix_acl_valid_with_ns], [
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_POSIX_ACL_VALID_WITH_NS, 1,
|
||||
[posix_acl_valid() wants user namespace])
|
||||
@@ -165,8 +155,9 @@ dnl # 2.6.27 API change,
|
||||
dnl # Check if inode_operations contains the function permission
|
||||
dnl # and expects the nameidata structure to have been removed.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_permission], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
|
||||
AC_MSG_CHECKING([whether iops->permission() exists])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
|
||||
int permission_fn(struct inode *inode, int mask) { return 0; }
|
||||
@@ -175,12 +166,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION], [
|
||||
iops __attribute__ ((unused)) = {
|
||||
.permission = permission_fn,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION], [
|
||||
AC_MSG_CHECKING([whether iops->permission() exists])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_permission], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_PERMISSION, 1, [iops->permission() exists])
|
||||
],[
|
||||
@@ -193,8 +180,9 @@ dnl # 2.6.26 API change,
|
||||
dnl # Check if inode_operations contains the function permission
|
||||
dnl # and expects the nameidata structure to be passed.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_permission_with_nameidata], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
|
||||
AC_MSG_CHECKING([whether iops->permission() wants nameidata])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
@@ -205,12 +193,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
|
||||
iops __attribute__ ((unused)) = {
|
||||
.permission = permission_fn,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA], [
|
||||
AC_MSG_CHECKING([whether iops->permission() wants nameidata])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_permission_with_nameidata], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_PERMISSION, 1, [iops->permission() exists])
|
||||
AC_DEFINE(HAVE_PERMISSION_WITH_NAMEIDATA, 1,
|
||||
@@ -224,8 +208,9 @@ dnl #
|
||||
dnl # 2.6.32 API change,
|
||||
dnl # Check if inode_operations contains the function check_acl
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_check_acl], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
|
||||
AC_MSG_CHECKING([whether iops->check_acl() exists])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
|
||||
int check_acl_fn(struct inode *inode, int mask) { return 0; }
|
||||
@@ -234,12 +219,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL], [
|
||||
iops __attribute__ ((unused)) = {
|
||||
.check_acl = check_acl_fn,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL], [
|
||||
AC_MSG_CHECKING([whether iops->check_acl() exists])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_check_acl], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_CHECK_ACL, 1, [iops->check_acl() exists])
|
||||
],[
|
||||
@@ -251,8 +232,9 @@ dnl #
|
||||
dnl # 2.6.38 API change,
|
||||
dnl # The function check_acl gained a new parameter: flags
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_check_acl_with_flags], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
|
||||
AC_MSG_CHECKING([whether iops->check_acl() wants flags])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
|
||||
int check_acl_fn(struct inode *inode, int mask,
|
||||
@@ -262,12 +244,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
|
||||
iops __attribute__ ((unused)) = {
|
||||
.check_acl = check_acl_fn,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS], [
|
||||
AC_MSG_CHECKING([whether iops->check_acl() wants flags])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_check_acl_with_flags], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_CHECK_ACL, 1, [iops->check_acl() exists])
|
||||
AC_DEFINE(HAVE_CHECK_ACL_WITH_FLAGS, 1,
|
||||
@@ -281,8 +259,9 @@ dnl #
|
||||
dnl # 3.1 API change,
|
||||
dnl # Check if inode_operations contains the function get_acl
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_get_acl], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
|
||||
AC_MSG_CHECKING([whether iops->get_acl() exists])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
|
||||
struct posix_acl *get_acl_fn(struct inode *inode, int type)
|
||||
@@ -292,12 +271,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL], [
|
||||
iops __attribute__ ((unused)) = {
|
||||
.get_acl = get_acl_fn,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL], [
|
||||
AC_MSG_CHECKING([whether iops->get_acl() exists])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_get_acl], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_GET_ACL, 1, [iops->get_acl() exists])
|
||||
],[
|
||||
@@ -309,23 +284,20 @@ dnl #
|
||||
dnl # 3.14 API change,
|
||||
dnl # Check if inode_operations contains the function set_acl
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL], [
|
||||
ZFS_LINUX_TEST_SRC([inode_operations_set_acl], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
|
||||
AC_MSG_CHECKING([whether iops->set_acl() exists])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
|
||||
int set_acl_fn(struct inode *inode, struct posix_acl *acl,
|
||||
int type) { return 0; }
|
||||
int set_acl_fn(struct inode *inode, struct posix_acl *acl, int type)
|
||||
{ return 0; }
|
||||
|
||||
static const struct inode_operations
|
||||
iops __attribute__ ((unused)) = {
|
||||
.set_acl = set_acl_fn,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
|
||||
AC_MSG_CHECKING([whether iops->set_acl() exists])
|
||||
ZFS_LINUX_TEST_RESULT([inode_operations_set_acl], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SET_ACL, 1, [iops->set_acl() exists])
|
||||
],[
|
||||
@@ -339,79 +311,16 @@ dnl # The kernel get_acl will now check cache before calling i_op->get_acl and
|
||||
dnl # do set_cached_acl after that, so i_op->get_acl don't need to do that
|
||||
dnl # anymore.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_GET_ACL_HANDLE_CACHE], [
|
||||
ZFS_LINUX_TEST_SRC([get_acl_handle_cache], [
|
||||
#include <linux/fs.h>
|
||||
],[
|
||||
void *sentinel __attribute__ ((unused)) =
|
||||
uncached_acl_sentinel(NULL);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE], [
|
||||
AC_MSG_CHECKING([whether uncached_acl_sentinel() exists])
|
||||
ZFS_LINUX_TEST_RESULT([get_acl_handle_cache], [
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
],[
|
||||
void *sentinel __attribute__ ((unused)) = uncached_acl_sentinel(NULL);
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_KERNEL_GET_ACL_HANDLE_CACHE, 1,
|
||||
[uncached_acl_sentinel() exists])
|
||||
AC_DEFINE(HAVE_KERNEL_GET_ACL_HANDLE_CACHE, 1, [uncached_acl_sentinel() exists])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 4.16 kernel: check if struct posix_acl acl.a_refcount is a refcount_t.
|
||||
dnl # It's an atomic_t on older kernels.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL_HAS_REFCOUNT], [
|
||||
ZFS_LINUX_TEST_SRC([acl_refcount], [
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/posix_acl.h>
|
||||
],[
|
||||
struct posix_acl acl;
|
||||
refcount_t *r __attribute__ ((unused)) = &acl.a_refcount;
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_ACL_HAS_REFCOUNT], [
|
||||
AC_MSG_CHECKING([whether posix_acl has refcount_t])
|
||||
ZFS_LINUX_TEST_RESULT([acl_refcount], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_ACL_REFCOUNT, 1, [posix_acl has refcount_t])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL], [
|
||||
ZFS_AC_KERNEL_SRC_POSIX_ACL_RELEASE
|
||||
ZFS_AC_KERNEL_SRC_SET_CACHED_ACL_USABLE
|
||||
ZFS_AC_KERNEL_SRC_POSIX_ACL_CHMOD
|
||||
ZFS_AC_KERNEL_SRC_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
|
||||
ZFS_AC_KERNEL_SRC_POSIX_ACL_VALID_WITH_NS
|
||||
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION
|
||||
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
|
||||
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL
|
||||
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
|
||||
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL
|
||||
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL
|
||||
ZFS_AC_KERNEL_SRC_GET_ACL_HANDLE_CACHE
|
||||
ZFS_AC_KERNEL_SRC_ACL_HAS_REFCOUNT
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_ACL], [
|
||||
ZFS_AC_KERNEL_POSIX_ACL_RELEASE
|
||||
ZFS_AC_KERNEL_SET_CACHED_ACL_USABLE
|
||||
ZFS_AC_KERNEL_POSIX_ACL_CHMOD
|
||||
ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
|
||||
ZFS_AC_KERNEL_POSIX_ACL_VALID_WITH_NS
|
||||
ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION
|
||||
ZFS_AC_KERNEL_INODE_OPERATIONS_PERMISSION_WITH_NAMEIDATA
|
||||
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL
|
||||
ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
|
||||
ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
|
||||
ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
|
||||
ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
|
||||
ZFS_AC_KERNEL_ACL_HAS_REFCOUNT
|
||||
])
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
dnl #
|
||||
dnl # Linux 4.9-rc5+ ABI, removal of the .aio_fsync field
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_AIO_FSYNC], [
|
||||
ZFS_LINUX_TEST_SRC([aio_fsync], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_AIO_FSYNC], [
|
||||
AC_MSG_CHECKING([whether fops->aio_fsync() exists])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/fs.h>
|
||||
|
||||
static const struct file_operations
|
||||
fops __attribute__ ((unused)) = {
|
||||
.aio_fsync = NULL,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_AIO_FSYNC], [
|
||||
AC_MSG_CHECKING([whether fops->aio_fsync() exists])
|
||||
ZFS_LINUX_TEST_RESULT([aio_fsync], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_FILE_AIO_FSYNC, 1, [fops->aio_fsync() exists])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
@@ -5,19 +5,16 @@ dnl # solution to handling automounts. Prior to this cifs/nfs clients
|
||||
dnl # which required automount support would abuse the follow_link()
|
||||
dnl # operation on directories for this purpose.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_AUTOMOUNT], [
|
||||
ZFS_LINUX_TEST_SRC([dentry_operations_d_automount], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_AUTOMOUNT], [
|
||||
AC_MSG_CHECKING([whether dops->d_automount() exists])
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/dcache.h>
|
||||
struct vfsmount *d_automount(struct path *p) { return NULL; }
|
||||
struct dentry_operations dops __attribute__ ((unused)) = {
|
||||
.d_automount = d_automount,
|
||||
};
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_AUTOMOUNT], [
|
||||
AC_MSG_CHECKING([whether dops->d_automount() exists])
|
||||
ZFS_LINUX_TEST_RESULT([dentry_operations_d_automount], [
|
||||
],[
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_AUTOMOUNT, 1, [dops->automount() exists])
|
||||
],[
|
||||
|
||||
@@ -5,22 +5,21 @@ dnl # it has been true for a while that there was no strict 1:1 mapping
|
||||
dnl # between physical sector size and logical block size this change makes
|
||||
dnl # it explicit.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_LOGICAL_BLOCK_SIZE], [
|
||||
ZFS_LINUX_TEST_SRC([bdev_logical_block_size], [
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE], [
|
||||
AC_MSG_CHECKING([whether bdev_logical_block_size() is available])
|
||||
tmp_flags="$EXTRA_KCFLAGS"
|
||||
EXTRA_KCFLAGS="${NO_UNUSED_BUT_SET_VARIABLE}"
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/blkdev.h>
|
||||
],[
|
||||
struct block_device *bdev = NULL;
|
||||
bdev_logical_block_size(bdev);
|
||||
], [$NO_UNUSED_BUT_SET_VARIABLE])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BDEV_LOGICAL_BLOCK_SIZE], [
|
||||
AC_MSG_CHECKING([whether bdev_logical_block_size() is available])
|
||||
ZFS_LINUX_TEST_RESULT([bdev_logical_block_size], [
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_BDEV_LOGICAL_BLOCK_SIZE, 1,
|
||||
[bdev_logical_block_size() is available])
|
||||
[bdev_logical_block_size() is available])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
EXTRA_KCFLAGS="$tmp_flags"
|
||||
])
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user