]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-nbd: make unmap/detach wait for rbd-nbd process to terminate
authorMykola Golub <mgolub@suse.com>
Sun, 4 Oct 2020 17:41:53 +0000 (18:41 +0100)
committerMykola Golub <mgolub@suse.com>
Tue, 13 Oct 2020 17:32:50 +0000 (18:32 +0100)
Signed-off-by: Mykola Golub <mgolub@suse.com>
qa/workunits/rbd/rbd-nbd.sh
src/tools/rbd_nbd/rbd-nbd.cc

index fce36921214154734d7cef93d983ca15e0a33889..879094dc92bbf3bcb248ecdbce11162653ee7361 100755 (executable)
@@ -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}
+    rbd-nbd list-mapped | expect_false grep "^${pid}\\b" || return 1
+    ps -C rbd-nbd | expect_false grep "^${pid}\\b" || return 1
 
-    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
+    # 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
index 13ae55fe88b9a1cca42d7d35198972213104d79e..80737de19b5b14c6f15ceb4f7717c887d20a3304 100644 (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,