1#!/bin/bash 2# 3# Test NBD client unexpected disconnect 4# 5# Copyright Red Hat, Inc. 2014 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20 21# creator 22owner=stefanha@redhat.com 23 24seq=`basename $0` 25echo "QA output created by $seq" 26 27here=`pwd` 28tmp=/tmp/$$ 29status=1 # failure is the default! 30 31# get standard environment, filters and checks 32. ./common.env 33. ./common.rc 34. ./common.filter 35 36_supported_fmt generic 37_supported_proto nbd 38_supported_os Linux 39 40# Pick a TCP port based on our pid. This way multiple instances of this test 41# can run in parallel without conflicting. 42choose_tcp_port() { 43 echo $((($$ % 31744) + 1024)) # 1024 <= port < 32768 44} 45 46wait_for_tcp_port() { 47 while ! (netstat --tcp --listening --numeric | \ 48 grep "$1.*0.0.0.0:\*.*LISTEN") 2>&1 >/dev/null; do 49 sleep 0.1 50 done 51} 52 53filter_nbd() { 54 # nbd.c error messages contain function names and line numbers that are prone 55 # to change. Message ordering depends on timing between send and receive 56 # callbacks sometimes, making them unreliable. 57 # 58 # Filter out the TCP port number since this changes between runs. 59 sed -e 's#^nbd.c:.*##g' \ 60 -e 's#nbd:127.0.0.1:[^:]*:#nbd:127.0.0.1:PORT:#g' 61} 62 63check_disconnect() { 64 event=$1 65 when=$2 66 negotiation=$3 67 echo "=== Check disconnect $when $event ===" 68 echo 69 70 port=$(choose_tcp_port) 71 72 cat > "$TEST_DIR/nbd-fault-injector.conf" <<EOF 73[inject-error] 74event=$event 75when=$when 76EOF 77 78 if [ "$negotiation" = "--classic-negotiation" ]; then 79 extra_args=--classic-negotiation 80 nbd_url="nbd:127.0.0.1:$port" 81 else 82 nbd_url="nbd:127.0.0.1:$port:exportname=foo" 83 fi 84 85 $PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" 2>&1 >/dev/null & 86 wait_for_tcp_port "127.0.0.1:$port" 87 $QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | filter_nbd 88 89 echo 90} 91 92for event in neg1 "export" neg2 request reply data; do 93 for when in before after; do 94 check_disconnect "$event" "$when" 95 done 96 97 # Also inject short replies from the NBD server 98 case "$event" in 99 neg1) 100 for when in 8 16; do 101 check_disconnect "$event" "$when" 102 done 103 ;; 104 "export") 105 for when in 4 12 16; do 106 check_disconnect "$event" "$when" 107 done 108 ;; 109 neg2) 110 for when in 8 10; do 111 check_disconnect "$event" "$when" 112 done 113 ;; 114 reply) 115 for when in 4 8; do 116 check_disconnect "$event" "$when" 117 done 118 ;; 119 esac 120done 121 122# Also check classic negotiation without export information 123for when in before 8 16 24 28 after; do 124 check_disconnect "neg-classic" "$when" --classic-negotiation 125done 126 127# success, all done 128echo "*** done" 129rm -f $seq.full 130status=0 131