From: Zhi Zhang Date: Thu, 11 Apr 2019 05:09:01 +0000 (+0800) Subject: krbd: fix rbd map hang due to udev return subsystem unordered X-Git-Tag: v13.2.7~134^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=2cdf09217824bcd965f5a39c96738c9736f6be2a;p=ceph.git krbd: fix rbd map hang due to udev return subsystem unordered The order of subsystem returned by udev_device_get_subsystem might not be same order as adding subsystem by udev_monitor_filter_add_match_subsystem_devtype. So if block event is returned first and rbd event is returned next, then further poll will get nothing back until timed-out. Fixes: http://tracker.ceph.com/issues/39089 Signed-off-by: Zhi Zhang (cherry picked from 42dd1eae630f31a628051049e4007175561f1939) Conflicts: src/krbd.cc --- diff --git a/src/krbd.cc b/src/krbd.cc index 9192174f7aa44..638595af1743a 100644 --- a/src/krbd.cc +++ b/src/krbd.cc @@ -184,6 +184,8 @@ static int wait_for_udev_add(struct udev_monitor *mon, const char *pool, string *pname) { struct udev_device *bus_dev = nullptr; + std::vector block_dev_vec; + int r; /* * Catch /sys/devices/rbd// and wait for the corresponding @@ -193,16 +195,16 @@ static int wait_for_udev_add(struct udev_monitor *mon, const char *pool, for (;;) { struct pollfd fds[1]; struct udev_device *dev; - int r; fds[0].fd = udev_monitor_get_fd(mon); fds[0].events = POLLIN; r = poll(fds, 1, POLL_TIMEOUT); - if (r < 0) - return -errno; - - if (r == 0) - return -ETIMEDOUT; + if (r > 0) { + r = 0; + } else { + r = (r == 0) ? -ETIMEDOUT : -errno; + break; + } dev = udev_monitor_receive_device(mon); if (!dev) @@ -211,8 +213,8 @@ static int wait_for_udev_add(struct udev_monitor *mon, const char *pool, if (strcmp(udev_device_get_action(dev), "add") != 0) goto next; - if (!bus_dev) { - if (strcmp(udev_device_get_subsystem(dev), "rbd") == 0) { + if (strcmp(udev_device_get_subsystem(dev), "rbd") == 0) { + if (!bus_dev) { const char *this_pool = udev_device_get_sysattr_value(dev, "pool"); const char *this_image = udev_device_get_sysattr_value(dev, "name"); const char *this_snap = udev_device_get_sysattr_value(dev, @@ -222,37 +224,50 @@ static int wait_for_udev_add(struct udev_monitor *mon, const char *pool, this_image && strcmp(this_image, image) == 0 && this_snap && strcmp(this_snap, snap) == 0) { bus_dev = dev; - continue; + goto check; } } - } else { - if (strcmp(udev_device_get_subsystem(dev), "block") == 0) { - const char *major = udev_device_get_sysattr_value(bus_dev, "major"); - const char *minor = udev_device_get_sysattr_value(bus_dev, "minor"); - const char *this_major = udev_device_get_property_value(dev, "MAJOR"); - const char *this_minor = udev_device_get_property_value(dev, "MINOR"); + } else if (strcmp(udev_device_get_subsystem(dev), "block") == 0) { + block_dev_vec.push_back(dev); + goto check; + } + +next: + udev_device_unref(dev); + continue; + +check: + if (bus_dev && !block_dev_vec.empty()) { + const char *major = udev_device_get_sysattr_value(bus_dev, "major"); + const char *minor = udev_device_get_sysattr_value(bus_dev, "minor"); + assert(!minor ^ have_minor_attr()); - assert(!minor ^ have_minor_attr()); + for (auto p : block_dev_vec) { + const char *this_major = udev_device_get_property_value(p, "MAJOR"); + const char *this_minor = udev_device_get_property_value(p, "MINOR"); if (strcmp(this_major, major) == 0 && (!minor || strcmp(this_minor, minor) == 0)) { string name = get_kernel_rbd_name(udev_device_get_sysname(bus_dev)); - assert(strcmp(udev_device_get_devnode(dev), name.c_str()) == 0); + assert(strcmp(udev_device_get_devnode(p), name.c_str()) == 0); *pname = name; - - udev_device_unref(dev); - udev_device_unref(bus_dev); - break; + goto done; } } } + } - next: - udev_device_unref(dev); +done: + if (bus_dev) { + udev_device_unref(bus_dev); + } + + for (auto p : block_dev_vec) { + udev_device_unref(p); } - return 0; + return r; } static int do_map(struct udev *udev, const char *pool, const char *image,