From: Ilya Dryomov Date: Wed, 25 Jun 2014 16:23:44 +0000 (+0400) Subject: krbd: rework the unmap retry loop X-Git-Tag: v0.84~169^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e4737907d24a3d0fbfd1bfb05ef792cd83a125ce;p=ceph.git krbd: rework the unmap retry loop 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 --- diff --git a/src/krbd.cc b/src/krbd.cc index 441355fa78091..04f4004754298 100644 --- a/src/krbd.cc +++ b/src/krbd.cc @@ -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; }