-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zpool: allow sharing of spare device among pools #7999
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
tests/zfs-tests/tests/functional/fault/auto_spare_shared.ksh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
#!/bin/ksh -p | ||
# | ||
# CDDL HEADER START | ||
# | ||
# This file and its contents are supplied under the terms of the | ||
# Common Development and Distribution License ("CDDL"), version 1.0. | ||
# You may only use this file in accordance with the terms of version | ||
# 1.0 of the CDDL. | ||
# | ||
# A full copy of the text of the CDDL should have accompanied this | ||
# source. A copy of the CDDL is also available via the Internet at | ||
# http://www.illumos.org/license/CDDL. | ||
# | ||
# CDDL HEADER END | ||
# | ||
|
||
# | ||
# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved. | ||
# | ||
|
||
. $STF_SUITE/include/libtest.shlib | ||
. $STF_SUITE/include/math.shlib | ||
. $STF_SUITE/tests/functional/fault/fault.cfg | ||
|
||
# | ||
# DESCRIPTION: | ||
# Spare devices (both files and disks) can be shared among different ZFS pools. | ||
# | ||
# STRATEGY: | ||
# 1. Create two pools | ||
# 2. Add the same spare device to different pools | ||
# 3. Inject IO errors with a zinject error handler | ||
# 4. Start a scrub | ||
# 5. Verify the ZED kicks in a hot spare and check pool/device status | ||
# 6. Clear the fault | ||
# 7. Verify the hot spare is available and check pool/device status | ||
# | ||
|
||
verify_runnable "both" | ||
|
||
if is_linux; then | ||
# Add one 512b spare device (4Kn would generate IO errors on replace) | ||
# NOTE: must be larger than other "file" vdevs and minimum SPA devsize: | ||
# add 32m of fudge | ||
load_scsi_debug $(($SPA_MINDEVSIZE/1024/1024+32)) 1 1 1 '512b' | ||
else | ||
log_unsupported "scsi debug module unsupported" | ||
fi | ||
|
||
function cleanup | ||
{ | ||
log_must zinject -c all | ||
destroy_pool $TESTPOOL | ||
destroy_pool $TESTPOOL1 | ||
unload_scsi_debug | ||
rm -f $SAFE_FILEDEVPOOL1 $SAFE_FILEDEVPOOL2 $FAIL_FILEDEVPOOL1 \ | ||
$FAIL_FILEDEVPOOL2 $SPARE_FILEDEV | ||
} | ||
|
||
log_assert "Spare devices can be shared among different ZFS pools" | ||
log_onexit cleanup | ||
|
||
# Clear events from previous runs | ||
zed_events_drain | ||
|
||
SAFE_FILEDEVPOOL1="$TEST_BASE_DIR/file-safe-dev1" | ||
FAIL_FILEDEVPOOL1="$TEST_BASE_DIR/file-fail-dev1" | ||
SAFE_FILEDEVPOOL2="$TEST_BASE_DIR/file-safe-dev2" | ||
FAIL_FILEDEVPOOL2="$TEST_BASE_DIR/file-fail-dev2" | ||
SPARE_FILEDEV="$TEST_BASE_DIR/file-spare-dev" | ||
SPARE_DISKDEV="$(get_debug_device)" | ||
|
||
for vdev in $SAFE_FILEDEVPOOL1 $SAFE_FILEDEVPOOL2 $FAIL_FILEDEVPOOL1 \ | ||
$FAIL_FILEDEVPOOL2 $SPARE_FILEDEV; do | ||
log_must truncate -s $SPA_MINDEVSIZE $vdev | ||
done | ||
|
||
for spare in $SPARE_FILEDEV $SPARE_DISKDEV; do | ||
# 1. Create two pools | ||
log_must zpool create -f $TESTPOOL mirror $SAFE_FILEDEVPOOL1 $FAIL_FILEDEVPOOL1 | ||
log_must zpool create -f $TESTPOOL1 mirror $SAFE_FILEDEVPOOL2 $FAIL_FILEDEVPOOL2 | ||
|
||
# 2. Add the same spare device to different pools | ||
log_must_busy zpool add $TESTPOOL spare $spare | ||
log_must_busy zpool add $TESTPOOL1 spare $spare | ||
log_must wait_hotspare_state $TESTPOOL $spare "AVAIL" | ||
log_must wait_hotspare_state $TESTPOOL1 $spare "AVAIL" | ||
|
||
# 3. Inject IO errors with a zinject error handler | ||
log_must zinject -d $FAIL_FILEDEVPOOL1 -e io -T all -f 100 $TESTPOOL | ||
log_must zinject -d $FAIL_FILEDEVPOOL2 -e io -T all -f 100 $TESTPOOL1 | ||
|
||
# 4. Start a scrub | ||
log_must zpool scrub $TESTPOOL | ||
log_must zpool scrub $TESTPOOL1 | ||
|
||
# 5. Verify the ZED kicks in a hot spare and check pool/device status | ||
log_note "Wait for ZED to auto-spare" | ||
log_must wait_vdev_state $TESTPOOL $FAIL_FILEDEVPOOL1 "FAULTED" 60 | ||
log_must wait_vdev_state $TESTPOOL $spare "ONLINE" 60 | ||
log_must wait_hotspare_state $TESTPOOL $spare "INUSE" | ||
log_must check_state $TESTPOOL "" "DEGRADED" | ||
|
||
# 6. Clear the fault | ||
log_must zinject -c all | ||
log_must zpool clear $TESTPOOL $FAIL_FILEDEVPOOL1 | ||
|
||
# 7. Verify the hot spare is available and check pool/device status | ||
log_must wait_vdev_state $TESTPOOL $FAIL_FILEDEVPOOL1 "ONLINE" 60 | ||
log_must wait_hotspare_state $TESTPOOL $spare "AVAIL" | ||
log_must is_pool_resilvered $TESTPOOL | ||
log_must check_state $TESTPOOL "" "ONLINE" | ||
|
||
# Cleanup | ||
destroy_pool $TESTPOOL | ||
destroy_pool $TESTPOOL1 | ||
done | ||
|
||
log_pass "Spare devices can be shared among different ZFS pools" |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to fix the spurious failures. I reproduced the issue on my CentOS7 home builder. Sometimes the spare cannot be added to the second pool ("testpool1"):
The error is coming from
zpool_label_disk()
. We are (erroneously) trying to label the spare device which cannot be opened withO_EXCL
:We should not be trying to label this device since it's already attached as a spare to "testpool". The underlying issue is we cannot find a valid label on this spare device (
zpool_read_label()
returns an empty config): this leads us to believe this device is not a valid (and "inuse") spare:Trying to read the first label with
dd
shows the data being all zeroes:Ultimately using O_DIRECT let us read the real label:
Sorry for the long text; i spent hours debugging the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense, the label would have been written in the kernel which would by pass the buffer cache. Passing O_DIRECT ensures we get the blocks from the disk and never a potentially stale cached version.