common.nbd's nbd_server_set_tcp_port() tries to find a free port, and then uses it for the whole test run. However, this is racy because even if the port was free at the beginning, there is no guarantee it will continue to be available. Therefore, 233 currently cannot reliably be run concurrently with other NBD TCP tests. This patch addresses the problem by dropping nbd_server_set_tcp_port(), and instead finding a new port every time nbd_server_start_tcp_socket() is invoked. For this, we run qemu-nbd with --fork and on error evaluate the output to see whether it contains "Address already in use". If so, we try the next port. On success, we still want to continually redirect the output from qemu-nbd to stderr. To achieve both, we redirect qemu-nbd's stderr to a FIFO that we then open in bash. If the parent process exits with status 0 (which means that the server has started successfully), we launch a background cat process that copies the FIFO to stderr. On failure, we read the whole content into a variable and then evaluate it. While at it, use --fork in nbd_server_start_unix_socket(), too. Doing so allows us to drop nbd_server_wait_for_*_socket(). Note that the reason common.nbd did not use --fork before is that qemu-nbd did not have --pid-file. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20190508211820.17851-6-mreitz@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com>
100 lines
2.8 KiB
Bash
100 lines
2.8 KiB
Bash
#!/usr/bin/env bash
|
|
# -*- shell-script-mode -*-
|
|
#
|
|
# Helpers for NBD server related config
|
|
#
|
|
# Copyright (C) 2018 Red Hat, Inc.
|
|
#
|
|
# 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 2 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 <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
nbd_unix_socket="${TEST_DIR}/qemu-nbd.sock"
|
|
nbd_tcp_addr="127.0.0.1"
|
|
nbd_pid_file="${TEST_DIR}/qemu-nbd.pid"
|
|
nbd_stderr_fifo="${TEST_DIR}/qemu-nbd.fifo"
|
|
|
|
# If bash version is >= 4.1, this will be overwritten by a dynamically
|
|
# assigned file descriptor value.
|
|
nbd_fifo_fd=10
|
|
|
|
nbd_server_stop()
|
|
{
|
|
local NBD_PID
|
|
if [ -f "$nbd_pid_file" ]; then
|
|
read NBD_PID < "$nbd_pid_file"
|
|
rm -f "$nbd_pid_file"
|
|
if [ -n "$NBD_PID" ]; then
|
|
kill "$NBD_PID"
|
|
fi
|
|
fi
|
|
rm -f "$nbd_unix_socket" "$nbd_stderr_fifo"
|
|
}
|
|
|
|
nbd_server_start_unix_socket()
|
|
{
|
|
nbd_server_stop
|
|
$QEMU_NBD -v -t -k "$nbd_unix_socket" --fork "$@"
|
|
}
|
|
|
|
nbd_server_start_tcp_socket()
|
|
{
|
|
nbd_server_stop
|
|
|
|
mkfifo "$nbd_stderr_fifo"
|
|
for ((port = 10809; port <= 10909; port++))
|
|
do
|
|
# Redirect stderr to FIFO, so we can later decide whether we
|
|
# want to read it or to redirect it to our stderr, depending
|
|
# on whether the command fails or not
|
|
$QEMU_NBD -v -t -b $nbd_tcp_addr -p $port --fork "$@" \
|
|
2> "$nbd_stderr_fifo" &
|
|
|
|
# Taken from common.qemu
|
|
if [[ "${BASH_VERSINFO[0]}" -ge "5" ||
|
|
("${BASH_VERSINFO[0]}" -ge "4" && "${BASH_VERSINFO[1]}" -ge "1") ]]
|
|
then
|
|
exec {nbd_fifo_fd}<"$nbd_stderr_fifo"
|
|
else
|
|
let _nbd_fifo_fd++
|
|
eval "exec ${_nbd_fifo_fd}<'$nbd_stderr_fifo'"
|
|
fi
|
|
wait $!
|
|
|
|
if test $? == 0
|
|
then
|
|
# Success, redirect qemu-nbd's stderr to our stderr
|
|
nbd_tcp_port=$port
|
|
(cat <&$nbd_fifo_fd >&2) &
|
|
eval "exec $nbd_fifo_fd>&-"
|
|
return
|
|
fi
|
|
|
|
# Failure, read the output
|
|
output=$(cat <&$nbd_fifo_fd)
|
|
eval "exec $nbd_fifo_fd>&-"
|
|
|
|
if ! echo "$output" | grep -q "Address already in use"
|
|
then
|
|
# Unknown error, print it
|
|
echo "$output" >&2
|
|
rm -f "$nbd_stderr_fifo"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
echo "Cannot find free TCP port for nbd in range 10809-10909"
|
|
rm -f "$nbd_stderr_fifo"
|
|
exit 1
|
|
}
|