rbd-nbd: make unmap/detach wait for rbd-nbd process to terminate

Signed-off-by: Mykola Golub <mgolub@suse.com>
This commit is contained in:
Mykola Golub 2020-10-04 18:41:53 +01:00
parent 20670fab51
commit 3043d80168
2 changed files with 68 additions and 23 deletions

View File

@ -97,7 +97,7 @@ function get_pid()
PID=$(rbd-nbd --format xml list-mapped | $XMLSTARLET sel -t -v \
"//devices/device[pool='${POOL}'][namespace='${ns}'][image='${IMAGE}'][device='${DEV}']/id")
test -n "${PID}"
test -n "${PID}" || return 1
ps -p ${PID} -C rbd-nbd
}
@ -105,15 +105,13 @@ unmap_device()
{
local dev=$1
local pid=$2
_sudo rbd-nbd unmap ${dev}
for s in 0.5 1 2 4 8 16 32; do
sleep ${s}
rbd-nbd list-mapped | expect_false grep "^${pid}\\b" &&
ps -C rbd-nbd | expect_false grep "^${pid}\\b" &&
return 0
done
return 1
_sudo rbd-nbd unmap ${dev}
rbd-nbd list-mapped | expect_false grep "^${pid}\\b" || return 1
ps -C rbd-nbd | expect_false grep "^${pid}\\b" || return 1
# workaround possible race between unmap and following map
sleep 0.5
}
#
@ -320,17 +318,8 @@ DEV=`_sudo rbd-nbd map --try-netlink ${POOL}/${IMAGE}`
get_pid
_sudo mount ${DEV} ${TEMPDIR}/mnt
_sudo rbd-nbd detach ${POOL}/${IMAGE}
attached=
for i in `seq 10`; do
if _sudo rbd-nbd attach --device ${DEV} ${POOL}/${IMAGE}; then
attached=1
break
fi
rbd-nbd list-mapped
ps auxww | grep rbd-nbd
sleep 1
done
test "${attached}" = 1
expect_false get_pid
_sudo rbd-nbd attach --device ${DEV} ${POOL}/${IMAGE}
get_pid
ls ${TEMPDIR}/mnt/
dd if=${TEMPDIR}/mnt/test of=/dev/null bs=1M count=1

View File

@ -1420,6 +1420,57 @@ static void run_server(Preforker& forker, NBDServer *server, bool netlink_used)
shutdown_async_signal_handler();
}
// Eventually it should be replaced with glibc' pidfd_open
// when it is widely available.
static int
pidfd_open(pid_t pid, unsigned int)
{
std::string path = "/proc/" + stringify(pid);
int fd = open(path.c_str(), O_RDONLY);
if (fd == -1 && errno == ENOENT) {
errno = ESRCH;
}
return fd;
}
static int wait_for_terminate(int pid, int timeout)
{
int fd = pidfd_open(pid, 0);
if (fd == -1) {
if (errno == -ESRCH) {
return 0;
}
int r = -errno;
cerr << "rbd-nbd: pidfd_open(" << pid << ") failed: "
<< cpp_strerror(r) << std::endl;
return r;
}
struct pollfd poll_fds[1];
memset(poll_fds, 0, sizeof(struct pollfd));
poll_fds[0].fd = fd;
poll_fds[0].events = POLLIN;
int r = poll(poll_fds, 1, timeout * 1000);
if (r == -1) {
r = -errno;
cerr << "rbd-nbd: failed to poll rbd-nbd process: " << cpp_strerror(r)
<< std::endl;
goto done;
}
if ((poll_fds[0].revents & POLLIN) == 0) {
cerr << "rbd-nbd: waiting for process exit timed out" << std::endl;
r = -ETIMEDOUT;
}
done:
close(fd);
return r;
}
static int do_map(int argc, const char *argv[], Config *cfg, bool reconnect)
{
int r;
@ -1625,14 +1676,14 @@ close_ret:
static int do_detach(Config *cfg)
{
int r = kill(cfg->pid, SIGTERM);
if (r != 0) {
if (r == -1) {
r = -errno;
cerr << "rbd-nbd: failed to terminate " << cfg->pid << ": "
<< cpp_strerror(r) << std::endl;
return r;
}
return 0;
return wait_for_terminate(cfg->pid, cfg->timeout);
}
static int do_unmap(Config *cfg)
@ -1659,7 +1710,12 @@ static int do_unmap(Config *cfg)
}
close(nbd);
return r;
if (r < 0) {
return r;
}
return wait_for_terminate(cfg->pid, cfg->timeout);
}
static int parse_imgpath(const std::string &imgpath, Config *cfg,