]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
krbd: rework the unmap retry loop 2040/head
authorIlya Dryomov <ilya.dryomov@inktank.com>
Wed, 25 Jun 2014 16:23:44 +0000 (20:23 +0400)
committerIlya Dryomov <ilya.dryomov@inktank.com>
Mon, 30 Jun 2014 08:59:34 +0000 (12:59 +0400)
The retry loop in the unmap path turned out to be insufficient for
doing long fsx -K runs.  Replace it with a single retry and then call
out to 'udevadm settle' if the retry doesn't help.

Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
src/krbd.cc

index 441355fa780910ff0b0059801b3863021ae4bc8d..04f40047542984f9c546a5ab5d01e24b61cb2a9f 100644 (file)
@@ -28,6 +28,7 @@
 #include "common/errno.h"
 #include "common/Formatter.h"
 #include "common/module.h"
+#include "common/run_cmd.h"
 #include "common/safe_io.h"
 #include "common/secret.h"
 #include "common/TextTable.h"
@@ -419,18 +420,26 @@ static int do_unmap(struct udev *udev, dev_t devno, const string& id)
    * On final device close(), kernel sends a block change event, in
    * response to which udev apparently runs blkid on the device.  This
    * makes unmap fail with EBUSY, if issued right after final close().
-   * Circumvent this with a retry loop.
+   * Try to circumvent this with a retry before turning to udev.
    */
-  {
-    int tries = 0;
-
-  again:
+  for (int tries = 0; ; tries++) {
     r = sysfs_write_rbd_remove(id);
-    if (r < 0) {
-      if (r == -EBUSY && tries++ < 5) {
-        usleep(200 * 1000);
-        goto again;
+    if (r >= 0) {
+      break;
+    } else if (r == -EBUSY && tries < 2) {
+      if (!tries) {
+        usleep(250 * 1000);
+      } else {
+        /*
+         * libudev does not provide the "wait until the queue is empty"
+         * API or the sufficient amount of primitives to build it from.
+         */
+        string err = run_cmd("udevadm", "settle", "--timeout", "10", "--quiet",
+                             NULL);
+        if (!err.empty())
+          cerr << "rbd: " << err << std::endl;
       }
+    } else {
       cerr << "rbd: sysfs write failed" << std::endl;
       goto out_mon;
     }