diff --git a/0024-RH-libudev-monitor.patch b/0024-RH-libudev-monitor.patch new file mode 100644 index 0000000..b092779 --- /dev/null +++ b/0024-RH-libudev-monitor.patch @@ -0,0 +1,205 @@ +--- + libmultipath/Makefile | 2 + libmultipath/uevent.c | 151 ++++++++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 134 insertions(+), 19 deletions(-) + +Index: multipath-tools-120123/libmultipath/Makefile +=================================================================== +--- multipath-tools-120123.orig/libmultipath/Makefile ++++ multipath-tools-120123/libmultipath/Makefile +@@ -7,7 +7,7 @@ include ../Makefile.inc + SONAME=0 + DEVLIB = libmultipath.so + LIBS = $(DEVLIB).$(SONAME) +-LIBDEPS = -lpthread -ldl -ldevmapper ++LIBDEPS = -lpthread -ldl -ldevmapper -ludev + + OBJS = memory.o parser.o vector.o devmapper.o callout.o \ + hwtable.o blacklist.o util.o dmparser.o config.o \ +Index: multipath-tools-120123/libmultipath/uevent.c +=================================================================== +--- multipath-tools-120123.orig/libmultipath/uevent.c ++++ multipath-tools-120123/libmultipath/uevent.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + + #include "memory.h" +@@ -161,7 +162,7 @@ int uevent_dispatch(int (*uev_trigger)(s + return 0; + } + +-int uevent_listen(void) ++int failback_listen(void) + { + int sock; + struct sockaddr_nl snl; +@@ -173,20 +174,6 @@ int uevent_listen(void) + int rcvszsz = sizeof(rcvsz); + unsigned int *prcvszsz = (unsigned int *)&rcvszsz; + const int feature_on = 1; +- +- /* +- * Queue uevents for service by dedicated thread so that the uevent +- * listening thread does not block on multipathd locks (vecs->lock) +- * thereby not getting to empty the socket's receive buffer queue +- * often enough. +- */ +- INIT_LIST_HEAD(&uevq); +- +- pthread_mutex_init(uevq_lockp, NULL); +- pthread_cond_init(uev_condp, NULL); +- +- pthread_cleanup_push(uevq_stop, NULL); +- + /* + * First check whether we have a udev socket + */ +@@ -382,13 +369,141 @@ int uevent_listen(void) + + exit: + close(sock); ++ return 1; ++} + +- pthread_cleanup_pop(1); ++int uevent_listen(void) ++{ ++ int err; ++ struct udev *udev = NULL; ++ struct udev_monitor *monitor = NULL; ++ int fd, socket_flags; ++ int need_failback = 0; ++ /* ++ * Queue uevents for service by dedicated thread so that the uevent ++ * listening thread does not block on multipathd locks (vecs->lock) ++ * thereby not getting to empty the socket's receive buffer queue ++ * often enough. ++ */ ++ INIT_LIST_HEAD(&uevq); ++ ++ pthread_mutex_init(uevq_lockp, NULL); ++ pthread_cond_init(uev_condp, NULL); ++ pthread_cleanup_push(uevq_stop, NULL); ++ ++ udev = udev_new(); ++ if (!udev) { ++ condlog(2, "failed to create udev context"); ++ need_failback = 1; ++ goto out; ++ } ++ monitor = udev_monitor_new_from_netlink(udev, "udev"); ++ if (!monitor) { ++ condlog(2, "failed to create udev monitor"); ++ need_failback = 1; ++ goto out; ++ } ++ if (udev_monitor_set_receive_buffer_size(monitor, 128 * 1024 * 1024)) ++ condlog(2, "failed to increase buffer size"); ++ fd = udev_monitor_get_fd(monitor); ++ socket_flags = fcntl(fd, F_GETFL); ++ if (socket_flags < 0) { ++ condlog(2, "failed to get monitor socket flags : %s", ++ strerror(errno)); ++ need_failback = 1; ++ goto out; ++ } ++ if (fcntl(fd, F_SETFL, socket_flags & ~O_NONBLOCK) < 0) { ++ condlog(2, "failed to set monitor socket flags : %s", ++ strerror(errno)); ++ need_failback = 1; ++ goto out; ++ } ++ err = udev_monitor_filter_add_match_subsystem_devtype(monitor, "block", ++ NULL); ++ if (err) ++ condlog(2, "failed to create filter : %s\n", strerror(-err)); ++ err = udev_monitor_enable_receiving(monitor); ++ if (err) { ++ condlog(2, "failed to enable receiving : %s\n", strerror(-err)); ++ need_failback = 1; ++ goto out; ++ } ++ while (1) { ++ int i = 0; ++ char *pos, *end; ++ struct uevent *uev; ++ struct udev_device *dev; ++ struct udev_list_entry *list_entry; ++ ++ dev = udev_monitor_receive_device(monitor); ++ if (!dev) { ++ condlog(0, "failed getting udev device"); ++ continue; ++ } + ++ uev = alloc_uevent(); ++ if (!uev) { ++ condlog(1, "lost uevent, oom"); ++ continue; ++ } ++ pos = uev->buffer; ++ end = pos + HOTPLUG_BUFFER_SIZE + OBJECT_SIZE - 1; ++ udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev)) { ++ const char *name, *value; ++ int bytes; ++ ++ name = udev_list_entry_get_name(list_entry); ++ value = udev_list_entry_get_value(list_entry); ++ bytes = snprintf(pos, end - pos, "%s=%s", name, ++ value); ++ if (pos + bytes >= end) { ++ condlog(2, "buffer overflow for uevent"); ++ break; ++ } ++ uev->envp[i] = pos; ++ pos += bytes; ++ *pos = '\0'; ++ pos++; ++ if (strcmp(name, "DEVPATH") == 0) ++ uev->devpath = uev->envp[i] + 8; ++ if (strcmp(name, "ACTION") == 0) ++ uev->action = uev->envp[i] + 7; ++ i++; ++ if (i == HOTPLUG_NUM_ENVP - 1) ++ break; ++ } ++ udev_device_unref(dev); ++ uev->envp[i] = NULL; ++ ++ condlog(3, "uevent '%s' from '%s'", uev->action, uev->devpath); ++ uev->kernel = strrchr(uev->devpath, '/'); ++ if (uev->kernel) ++ uev->kernel++; ++ ++ /* print payload environment */ ++ for (i = 0; uev->envp[i] != NULL; i++) ++ condlog(5, "%s", uev->envp[i]); ++ ++ /* ++ * Queue uevent and poke service pthread. ++ */ ++ pthread_mutex_lock(uevq_lockp); ++ list_add_tail(&uev->node, &uevq); ++ pthread_cond_signal(uev_condp); ++ pthread_mutex_unlock(uevq_lockp); ++ } ++out: ++ if (monitor) ++ udev_monitor_unref(monitor); ++ if (udev) ++ udev_unref(udev); ++ if (need_failback) ++ err = failback_listen(); ++ pthread_cleanup_pop(1); + pthread_mutex_destroy(uevq_lockp); + pthread_cond_destroy(uev_condp); +- +- return 1; ++ return err; + } + + extern int diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 59570ef..e7817cf 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,7 +1,7 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath Version: 0.4.9 -Release: 22%{?dist} +Release: 23%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -31,6 +31,7 @@ Patch0020: 0020-RH-dont-remove-map-twice.patch Patch0021: 0021-RH-validate-guid-partitions.patch Patch0022: 0022-RH-adjust-messages.patch Patch0023: 0023-RH-manpage-update.patch +Patch0024: 0024-RH-libudev-monitor.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -106,6 +107,7 @@ kpartx manages partition creation and removal for device-mapper devices. %patch0021 -p1 %patch0022 -p1 %patch0023 -p1 +%patch0024 -p1 cp %{SOURCE1} . %build @@ -196,6 +198,9 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/kpartx.8.gz %changelog +* Mon Apr 30 2012 Benjamin Marzinski 0.4.9-23 +- Add 0024-RH-libudev-monitor.patch + * Fri Feb 10 2012 Benjamin Marzinski 0.4.9-22 - Add 0012-RH-update-on-show-topology.patch - Add 0013-RH-manpage-update.patch