Path: blob/main/tests/sys/geom/class/multipath/misc.sh
39635 views
#!/bin/sh1# Copyright (c) 2019 Axcient2#3# Redistribution and use in source and binary forms, with or without4# modification, are permitted provided that the following conditions5# are met:6# 1. Redistributions of source code must retain the above copyright7# notice, this list of conditions and the following disclaimer.8# 2. Redistributions in binary form must reproduce the above copyright9# notice, this list of conditions and the following disclaimer in the10# documentation and/or other materials provided with the distribution.11#12# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND13# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE14# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE15# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE16# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL17# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS18# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)19# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT20# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY21# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF22# SUCH DAMAGE.23#2425. $(atf_get_srcdir)/conf.sh2627atf_test_case add cleanup28add_head()29{30atf_set "descr" "Add a new path"31atf_set "require.user" "root"32}33add_body()34{35load_gmultipath36load_dtrace3738md0=$(alloc_md)39md1=$(alloc_md)40md2=$(alloc_md)41name=$(mkname)42atf_check -s exit:0 gmultipath create "$name" ${md0} ${md1}43check_multipath_state ${md0} "OPTIMAL" "ACTIVE" "PASSIVE"4445# Add a new path46atf_check -s exit:0 gmultipath add "$name" ${md2}47check_multipath_state ${md0} "OPTIMAL" "ACTIVE" "PASSIVE" "PASSIVE"48}49add_cleanup()50{51common_cleanup52}5354atf_test_case create_A cleanup55create_A_head()56{57atf_set "descr" "Create an Active/Active multipath device"58atf_set "require.user" "root"59}60create_A_body()61{62load_gmultipath63load_dtrace6465md0=$(alloc_md)66md1=$(alloc_md)67name=$(mkname)68atf_check -s exit:0 gmultipath create -A "$name" ${md0} ${md1}69check_multipath_state "${md1} ${md0}" "OPTIMAL" "ACTIVE" "ACTIVE"70}71create_A_cleanup()72{73common_cleanup74}7576atf_test_case create_R cleanup77create_R_head()78{79atf_set "descr" "Create an Active/Read multipath device"80atf_set "require.user" "root"81}82create_R_body()83{84load_gmultipath85load_dtrace8687md0=$(alloc_md)88md1=$(alloc_md)89name=$(mkname)90atf_check -s exit:0 gmultipath create -R "$name" ${md0} ${md1}91check_multipath_state ${md0} "OPTIMAL" "ACTIVE" "READ"92}93create_R_cleanup()94{95common_cleanup96}9798atf_test_case depart_and_arrive cleanup99depart_and_arrive_head()100{101atf_set "descr" "gmultipath should remove devices that disappear, and automatically reattach labeled providers that reappear"102atf_set "require.user" "root"103}104depart_and_arrive_body()105{106load_gnop107load_gmultipath108md0=$(alloc_md)109md1=$(alloc_md)110name=$(mkname)111# We need a non-zero offset to gmultipath won't see the label when it112# tastes the md device. We only want the label to be visible on the113# gnop device.114offset=131072115atf_check gnop create -o $offset /dev/${md0}116atf_check gnop create -o $offset /dev/${md1}117atf_check -s exit:0 gmultipath label "$name" ${md0}.nop118# gmultipath is too smart to let us create a gmultipath device by label119# when the two providers aren't actually related. So we create a120# device by label with one provider, and then manually add the second.121atf_check -s exit:0 gmultipath add "$name" ${md1}.nop122NDEVS=`gmultipath list "$name" | grep -c 'md[0-9]*\.nop'`123atf_check_equal 2 $NDEVS124125# Now fail the labeled provider126atf_check -s exit:0 gnop destroy -f ${md0}.nop127# It should be automatically removed from the multipath device128NDEVS=`gmultipath list "$name" | grep -c 'md[0-9]*\.nop'`129atf_check_equal 1 $NDEVS130131# Now return the labeled provider132atf_check gnop create -o $offset /dev/${md0}133# It should be automatically restored to the multipath device. We134# don't really care which path is active.135NDEVS=`gmultipath list "$name" | grep -c 'md[0-9]*\.nop'`136atf_check_equal 2 $NDEVS137STATE=`gmultipath list "$name" | awk '/^State:/ {print $2}'`138atf_check_equal "OPTIMAL" $STATE139}140depart_and_arrive_cleanup()141{142common_cleanup143}144145146atf_test_case fail cleanup147fail_head()148{149atf_set "descr" "Manually fail a path"150atf_set "require.user" "root"151}152fail_body()153{154load_gmultipath155md0=$(alloc_md)156md1=$(alloc_md)157name=$(mkname)158atf_check -s exit:0 gmultipath create "$name" ${md0} ${md1}159check_multipath_state ${md0} "OPTIMAL" "ACTIVE" "PASSIVE"160# Manually fail the active path161atf_check -s exit:0 gmultipath fail "$name" ${md0}162check_multipath_state ${md1} "DEGRADED" "FAIL" "ACTIVE"163}164fail_cleanup()165{166common_cleanup167}168169atf_test_case fail_on_error cleanup170fail_on_error_head()171{172atf_set "descr" "An error in the provider will cause gmultipath to mark it as FAIL"173atf_set "require.user" "root"174}175fail_on_error_body()176{177load_gnop178load_gmultipath179md0=$(alloc_md)180md1=$(alloc_md)181name=$(mkname)182atf_check gnop create /dev/${md0}183atf_check gnop create /dev/${md1}184atf_check -s exit:0 gmultipath create "$name" ${md0}.nop ${md1}.nop185# The first I/O to the first path should fail, causing gmultipath to186# fail over to the second path.187atf_check gnop configure -r 100 -w 100 ${md0}.nop188atf_check -s exit:0 -o ignore -e ignore dd if=/dev/zero of=/dev/multipath/"$name" bs=4096 count=1189check_multipath_state ${md1}.nop "DEGRADED" "FAIL" "ACTIVE"190}191fail_on_error_cleanup()192{193common_cleanup194}195196atf_test_case physpath cleanup197physpath_head()198{199atf_set "descr" "gmultipath should append /mp to the underlying providers' physical path"200atf_set "require.user" "root"201}202physpath_body()203{204load_gnop205load_gmultipath206md0=$(alloc_md)207md1=$(alloc_md)208name=$(mkname)209physpath="some/physical/path"210# Create two providers with the same physical paths, mimicing how211# multipathed SAS drives appear. This is the normal way to use212# gmultipath. If the underlying providers' physical paths differ,213# then you're probably using gmultipath wrong.214atf_check gnop create -z $physpath /dev/${md0}215atf_check gnop create -z $physpath /dev/${md1}216atf_check -s exit:0 gmultipath create "$name" ${md0}.nop ${md1}.nop217gmultipath_physpath=$(diskinfo -p multipath/"$name")218atf_check_equal "$physpath/mp" "$gmultipath_physpath"219}220physpath_cleanup()221{222common_cleanup223}224225atf_test_case prefer cleanup226prefer_head()227{228atf_set "descr" "Manually select the preferred path"229atf_set "require.user" "root"230}231prefer_body()232{233load_gmultipath234load_dtrace235236md0=$(alloc_md)237md1=$(alloc_md)238md2=$(alloc_md)239name=$(mkname)240atf_check -s exit:0 gmultipath create "$name" ${md0} ${md1} ${md2}241check_multipath_state ${md0} "OPTIMAL" "ACTIVE" "PASSIVE" "PASSIVE"242243# Explicitly prefer the final path244atf_check -s exit:0 gmultipath prefer "$name" ${md2}245check_multipath_state ${md2} "OPTIMAL" "PASSIVE" "PASSIVE" "ACTIVE"246}247prefer_cleanup()248{249common_cleanup250}251252atf_test_case restore cleanup253restore_head()254{255atf_set "descr" "Manually restore a failed path"256atf_set "require.user" "root"257}258restore_body()259{260load_gmultipath261load_dtrace262263md0=$(alloc_md)264md1=$(alloc_md)265name=$(mkname)266atf_check -s exit:0 gmultipath create "$name" ${md0} ${md1}267268# Explicitly fail the first path269atf_check -s exit:0 gmultipath fail "$name" ${md0}270check_multipath_state ${md1} "DEGRADED" "FAIL" "ACTIVE"271272# Explicitly restore it273atf_check -s exit:0 gmultipath restore "$name" ${md0}274check_multipath_state ${md1} "OPTIMAL" "PASSIVE" "ACTIVE"275}276restore_cleanup()277{278common_cleanup279}280281atf_test_case restore_on_error cleanup282restore_on_error_head()283{284atf_set "descr" "A failed path should be restored if an I/O error is encountered on all other active paths"285atf_set "require.user" "root"286}287restore_on_error_body()288{289load_gnop290load_gmultipath291load_dtrace292293md0=$(alloc_md)294md1=$(alloc_md)295name=$(mkname)296atf_check gnop create /dev/${md0}297atf_check gnop create /dev/${md1}298atf_check -s exit:0 gmultipath create "$name" ${md0}.nop ${md1}.nop299# Explicitly fail the first path300atf_check -s exit:0 gmultipath fail "$name" ${md0}.nop301302# Setup the second path to fail on the next I/O303atf_check gnop configure -r 100 -w 100 ${md1}.nop304atf_check -s exit:0 -o ignore -e ignore \305dd if=/dev/zero of=/dev/multipath/"$name" bs=4096 count=1306307# Now the first path should be active, and the second should be failed308check_multipath_state ${md0}.nop "DEGRADED" "ACTIVE" "FAIL"309}310restore_on_error_cleanup()311{312common_cleanup313}314315atf_test_case rotate cleanup316rotate_head()317{318atf_set "descr" "Manually rotate the active path"319atf_set "require.user" "root"320}321rotate_body()322{323load_gmultipath324load_dtrace325326md0=$(alloc_md)327md1=$(alloc_md)328md2=$(alloc_md)329name=$(mkname)330atf_check -s exit:0 gmultipath create "$name" ${md0} ${md1} ${md2}331check_multipath_state ${md0} "OPTIMAL" "ACTIVE" "PASSIVE" "PASSIVE"332333# Explicitly rotate the paths334atf_check -s exit:0 gmultipath rotate "$name"335check_multipath_state ${md2} "OPTIMAL" "PASSIVE" "PASSIVE" "ACTIVE"336# Again337atf_check -s exit:0 gmultipath rotate "$name"338check_multipath_state ${md1} "OPTIMAL" "PASSIVE" "ACTIVE" "PASSIVE"339# Final rotation should restore original configuration340atf_check -s exit:0 gmultipath rotate "$name"341check_multipath_state ${md0} "OPTIMAL" "ACTIVE" "PASSIVE" "PASSIVE"342}343rotate_cleanup()344{345common_cleanup346}347348atf_init_test_cases()349{350atf_add_test_case add351atf_add_test_case create_A352atf_add_test_case create_R353atf_add_test_case depart_and_arrive354atf_add_test_case fail355atf_add_test_case fail_on_error356atf_add_test_case physpath357atf_add_test_case prefer358atf_add_test_case restore359atf_add_test_case restore_on_error360atf_add_test_case rotate361}362363364