[lvm-devel] [PATCH 3/3] udev: Use udev monitor
Bastian Blank
waldi at debian.org
Sat Jun 8 09:56:57 UTC 2013
---
libdm/libdm-common.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 92 insertions(+), 1 deletion(-)
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index d028029..fdabf80 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -26,6 +26,7 @@
#include <dirent.h>
#ifdef UDEV_SYNC_SUPPORT
+# include <poll.h>
# include <libudev.h>
#endif
@@ -64,7 +65,9 @@ static int _udev_disabled = 0;
#ifdef UDEV_SYNC_SUPPORT
static struct udev *_udev;
+static struct udev_monitor *_udev_monitor;
static int _udev_running = -1;
+static unsigned int _udev_monitor_inflight;
static int _sync_with_udev = 1;
static int _udev_checking = 1;
#endif
@@ -1992,6 +1995,55 @@ bad:
return 0;
}
+static struct udev_monitor *_get_udev_monitor(void)
+{
+ struct udev *udev = _get_udev();
+
+ if (!udev)
+ return 0;
+
+ if (!_udev_monitor) {
+ log_debug("Opening udev monitor");
+
+ _udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
+ if (!_udev_monitor)
+ goto_bad;
+
+ udev_monitor_filter_add_match_subsystem_devtype(_udev_monitor, "block", "disk");
+ udev_monitor_enable_receiving(_udev_monitor);
+ }
+
+ return _udev_monitor;
+
+bad:
+ log_error("Could not get udev monitor. Assuming udev is not running.");
+ return 0;
+}
+
+static void _close_udev_monitor(void)
+{
+ log_debug("Closing udev monitor");
+ udev_monitor_unref(_udev_monitor);
+ _udev_monitor = NULL;
+}
+
+static void _push_udev_monitor_inflight(void)
+{
+ _udev_monitor_inflight++;
+ if (_udev_monitor_inflight == 0)
+ abort();
+ _get_udev_monitor();
+}
+
+static void _pop_udev_monitor_inflight(void)
+{
+ if (_udev_monitor_inflight == 0)
+ abort();
+ _udev_monitor_inflight--;
+ if (_udev_monitor_inflight == 0)
+ _close_udev_monitor();
+}
+
static int _check_udev_is_running(void)
{
struct udev *udev;
@@ -2166,6 +2218,7 @@ int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags)
dmt->event_nr |= ~DM_UDEV_FLAGS_MASK & *cookie;
dmt->cookie_set = 1;
+ _push_udev_monitor_inflight();
log_debug_activation("Udev cookie 0x%" PRIx32 " assigned to "
"%s task(%d) with flags%s%s%s%s%s%s%s (0x%" PRIx16 ")", *cookie, _task_type_disp(dmt->type), dmt->type,
@@ -2195,10 +2248,48 @@ int dm_udev_complete(uint32_t cookie)
static int _udev_wait(uint32_t cookie)
{
+ struct udev_monitor *monitor;
+ struct pollfd p = { -1, POLLIN, 0 };
+ int r = 0;
+
if (!cookie || !dm_udev_get_sync_support())
return 1;
- return_0;
+ cookie &= ~DM_UDEV_FLAGS_MASK;
+ log_debug("Udev cookie 0x%" PRIx32 " expected", cookie);
+
+ monitor = _get_udev_monitor();
+
+ p.fd = udev_monitor_get_fd(monitor);
+
+ while (!r)
+ {
+ // TODO: timeout
+ poll(&p, 1, -1);
+
+ struct udev_device *device = udev_monitor_receive_device(monitor);
+ struct udev_list_entry *l;
+
+ udev_list_entry_foreach(l, udev_device_get_properties_list_entry(device))
+ {
+ if (strcmp("DM_COOKIE", udev_list_entry_get_name(l)) == 0)
+ {
+ const char *value = udev_list_entry_get_value(l);
+ uint32_t cookie_current = strtol(value, NULL, 10) & ~DM_UDEV_FLAGS_MASK;
+ log_debug("Udev cookie 0x%" PRIx32 " found", cookie_current);
+
+ if (cookie == cookie_current)
+ r = 1;
+ break;
+ }
+ }
+
+ udev_device_unref(device);
+ }
+
+ _pop_udev_monitor_inflight();
+
+ return r;
}
int dm_udev_wait(uint32_t cookie)
--
I have never understood the female capacity to avoid a direct answer to
any question.
-- Spock, "This Side of Paradise", stardate 3417.3
More information about the lvm-devel
mailing list