File multipath-tools-use-lists-for-uevent-processing of Package multipath-tools

From 825076f0d9c5c58223dfe0b3336f9cfb9088110e Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Wed, 25 Feb 2009 16:10:16 +0100
Subject: [PATCH] Use lists for uevent processing

We now have proper list definitions, so we might as well use them
for uevent processing. And we can clean up signalling, too;
the pthreads condition signalling is unreliable, as a condition
signal might be lost if we're in the middle of processing. So
we should rather check the queue status prior to wait for a
condition.

References: 478874

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 libmultipath/uevent.c |   59 ++++++++++++++++++++++--------------------------
 libmultipath/uevent.h |    2 +-
 2 files changed, 28 insertions(+), 33 deletions(-)

diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
index 19a71ad..86d5d11 100644
--- a/libmultipath/uevent.c
+++ b/libmultipath/uevent.c
@@ -37,15 +37,17 @@
 #include <linux/netlink.h>
 #include <pthread.h>
 #include <sys/mman.h>
+#include <errno.h>
 
 #include "memory.h"
 #include "debug.h"
+#include "list.h"
 #include "uevent.h"
 
 typedef int (uev_trigger)(struct uevent *, void * trigger_data);
 
 pthread_t uevq_thr;
-struct uevent *uevqhp, *uevqtp;
+LIST_HEAD(uevq);
 pthread_mutex_t uevq_lock, *uevq_lockp = &uevq_lock;
 pthread_mutex_t uevc_lock, *uevc_lockp = &uevc_lock;
 pthread_cond_t  uev_cond,  *uev_condp  = &uev_cond;
@@ -60,29 +62,18 @@ struct uevent * alloc_uevent (void)
 void
 service_uevq(void)
 {
-	int empty;
-	struct uevent *uev;
+	struct uevent *uev, *tmp;
 
-	do {
-		pthread_mutex_lock(uevq_lockp);
-		empty = (uevqhp == NULL);
-		if (!empty) {
-			uev = uevqhp;
-			uevqhp = uev->next;
-			if (uevqtp == uev)
-				uevqtp = uev->next;
-			pthread_mutex_unlock(uevq_lockp);
+	list_for_each_entry_safe(uev, tmp, &uevq, node) {
+		list_del_init(&uev->node);
+		pthread_mutex_unlock(uevq_lockp);
 
-			if (my_uev_trigger && my_uev_trigger(uev,
-							my_trigger_data))
-				condlog(0, "uevent trigger error");
+		if (my_uev_trigger && my_uev_trigger(uev, my_trigger_data))
+			condlog(0, "uevent trigger error");
 
-			FREE(uev);
-		}
-		else {
-			pthread_mutex_unlock(uevq_lockp);
-		}
-	} while (empty == 0);
+		FREE(uev);
+		pthread_mutex_lock(uevq_lockp);
+	}
 }
 
 /*
@@ -94,11 +85,20 @@ uevq_thread(void * et)
 	mlockall(MCL_CURRENT | MCL_FUTURE);
 
 	while (1) {
-		pthread_mutex_lock(uevc_lockp);
-		pthread_cond_wait(uev_condp, uevc_lockp);
-		pthread_mutex_unlock(uevc_lockp);
-
+		pthread_mutex_lock(uevq_lockp);
+		/*
+		 * Condition signals are unreliable,
+		 * so make sure we only wait if we have to.
+		 */
+		if (list_empty(&uevq)) {
+			pthread_mutex_unlock(uevq_lockp);
+			pthread_mutex_lock(uevc_lockp);
+			pthread_cond_wait(uev_condp, uevc_lockp);
+			pthread_mutex_unlock(uevc_lockp);
+			pthread_mutex_lock(uevq_lockp);
+		}
 		service_uevq();
+		pthread_mutex_unlock(uevq_lockp);
 	}
 }
 
@@ -125,7 +125,7 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data),
 	 * thereby not getting to empty the socket's receive buffer queue
 	 * often enough.
 	 */
-	uevqhp = uevqtp = NULL;
+	INIT_LIST_HEAD(&uevq);
 
 	pthread_mutex_init(uevq_lockp, NULL);
 	pthread_mutex_init(uevc_lockp, NULL);
@@ -274,12 +274,7 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data),
 		 * Queue uevent and poke service pthread.
 		 */
 		pthread_mutex_lock(uevq_lockp);
-		if (uevqtp)
-			uevqtp->next = uev;
-		else
-			uevqhp = uev;
-		uevqtp = uev;
-		uev->next = NULL;
+		list_add(&uev->node, &uevq);
 		pthread_mutex_unlock(uevq_lockp);
 
 		pthread_mutex_lock(uevc_lockp);
diff --git a/libmultipath/uevent.h b/libmultipath/uevent.h
index ec6450b..27f225d 100644
--- a/libmultipath/uevent.h
+++ b/libmultipath/uevent.h
@@ -11,7 +11,7 @@
 #endif
 
 struct uevent {
-	void *next;
+	struct list_head node;
 	char buffer[HOTPLUG_BUFFER_SIZE + OBJECT_SIZE];
 	char *devpath;
 	char *action;
-- 
1.6.0.2

openSUSE Build Service is sponsored by