From: Ilya Dryomov Date: Thu, 24 Oct 2019 15:35:23 +0000 (+0200) Subject: krbd: retry on an empty list from udev_enumerate_scan_devices() X-Git-Tag: v12.2.13~28^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=9cf994a5bbd27f0df31eaf4cfb063bcca63dc613;p=ceph.git krbd: retry on an empty list from udev_enumerate_scan_devices() systemd 219 doesn't have the issue that is worked around in the previous commit, but has a different one: udev_enumerate_scan_devices() always succeeds, but sometimes returns an empty list when the device is actually there. This happens rarely and at random so I haven't been able to get to the bottom of it yet, but it looks like another similar race condition in libudev. Since an empty list is expected if the device isn't there, retry just twice with a small sleep in-between. This appears to be enough: I got 7 occurrences per 600000 "rbd unmap" invocations, all of which needed a single retry: rbd: udev enumerate missed a device, tries = 1 Signed-off-by: Ilya Dryomov (cherry picked from commit bd37a72e0ec783a1ba91e63e8d96f0bc06007060) Conflicts: src/krbd.cc [ krbd_spec not in luminous ] --- diff --git a/src/krbd.cc b/src/krbd.cc index a2230b4a2a6e5..ef07929828e87 100644 --- a/src/krbd.cc +++ b/src/krbd.cc @@ -716,13 +716,25 @@ static int unmap_image(struct krbd_ctx *ctx, const char *devnode, wholedevno = sb.st_rdev; } - r = devno_to_krbd_id(ctx->udev, wholedevno, &id); - if (r < 0) { - if (r == -ENOENT) { - cerr << "rbd: '" << devnode << "' is not an rbd device" << std::endl; - r = -EINVAL; + for (int tries = 0; ; tries++) { + r = devno_to_krbd_id(ctx->udev, wholedevno, &id); + if (r == -ENOENT && tries < 2) { + usleep(250 * 1000); + } else { + if (r < 0) { + if (r == -ENOENT) { + std::cerr << "rbd: '" << devnode << "' is not an rbd device" + << std::endl; + r = -EINVAL; + } + return r; + } + if (tries) { + std::cerr << "rbd: udev enumerate missed a device, tries = " << tries + << std::endl; + } + break; } - return r; } return do_unmap(ctx->udev, wholedevno, build_unmap_buf(id, options)); @@ -739,14 +751,25 @@ static int unmap_image(struct krbd_ctx *ctx, const char *pool, if (!snap) snap = "-"; - r = spec_to_devno_and_krbd_id(ctx->udev, pool, image, snap, &devno, &id); - if (r < 0) { - if (r == -ENOENT) { - cerr << "rbd: " << pool << "/" << image << "@" << snap - << ": not a mapped image or snapshot" << std::endl; - r = -EINVAL; + for (int tries = 0; ; tries++) { + r = spec_to_devno_and_krbd_id(ctx->udev, pool, image, snap, &devno, &id); + if (r == -ENOENT && tries < 2) { + usleep(250 * 1000); + } else { + if (r < 0) { + if (r == -ENOENT) { + std::cerr << "rbd: " << pool << "/" << image << "@" << snap + << ": not a mapped image or snapshot" << std::endl; + r = -EINVAL; + } + return r; + } + if (tries) { + std::cerr << "rbd: udev enumerate missed a device, tries = " << tries + << std::endl; + } + break; } - return r; } return do_unmap(ctx->udev, devno, build_unmap_buf(id, options));