[dm-devel] [PATCH 31/57] multipathd: improve uxlsnr

Hannes Reinecke hare at suse.de
Wed Apr 27 11:10:32 UTC 2016


Improve uxlsnr by adding a lock around the poll structure and
not reallocating memory for every poll, thereby significantly
speedup processing.

Signed-off-by: Hannes Reinecke <hare at suse.com>
---
 multipathd/main.c   |  6 ++--
 multipathd/uxlsnr.c | 84 +++++++++++++++++++++++++++++++----------------------
 2 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/multipathd/main.c b/multipathd/main.c
index 61b82f6..c1b94bd 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -966,8 +966,10 @@ uevqloop (void * ap)
 static void *
 uxlsnrloop (void * ap)
 {
-	if (cli_init())
+	if (cli_init()) {
+		condlog(1, "Failed to init uxsock listener");
 		return NULL;
+	}
 
 	set_handler_callback(LIST+PATHS, cli_list_paths);
 	set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt);
@@ -1278,7 +1280,7 @@ check_path (struct vectors * vecs, struct path * pp)
 		sysfs_attr_set_value(pp->udev, "uevent", "change",
 				     strlen("change"));
 		return 0;
-	} 
+	}
 
 	/*
 	 * provision a next check soonest,
diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
index e5c5d90..77efa8a 100644
--- a/multipathd/uxlsnr.c
+++ b/multipathd/uxlsnr.c
@@ -44,6 +44,8 @@ struct client {
 	int fd;
 };
 
+#define MIN_POLLS 1023
+
 LIST_HEAD(clients);
 pthread_mutex_t client_lock = PTHREAD_MUTEX_INITIALIZER;
 struct pollfd *polls;
@@ -133,6 +135,7 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
 	char *inbuf;
 	char *reply;
 	sigset_t mask;
+	int old_clients = MIN_POLLS;
 
 	ux_sock = ux_socket_listen(DEFAULT_SOCKET);
 
@@ -142,20 +145,22 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
 	}
 
 	if (!conf) {
-		condlog(1, "configuration changed");
+		condlog(1, "uxsock: configuration changed");
 		return NULL;
 	}
 
-	timeout = conf->uxsock_timeout;
-
 	pthread_cleanup_push(uxsock_cleanup, NULL);
 
-	polls = (struct pollfd *)MALLOC(0);
+	condlog(3, "uxsock: startup listener");
+	polls = (struct pollfd *)MALLOC(MIN_POLLS + 1);
+	if (!polls) {
+		condlog(0, "uxsock: failed to allocate poll fds");
+		return NULL;
+	}
 	pthread_sigmask(SIG_SETMASK, NULL, &mask);
 	sigdelset(&mask, SIGHUP);
 	sigdelset(&mask, SIGUSR1);
 	while (1) {
-		struct pollfd *new;
 		struct client *c, *tmp;
 		int i, poll_count, num_clients;
 
@@ -173,19 +178,25 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
 		list_for_each_entry(c, &clients, node) {
 			num_clients++;
 		}
-		new = REALLOC(polls, (1+num_clients) * sizeof(*polls));
-		/* If we can't allocate poliing space for the new client,
-		 * close it */
-		if (!new) {
-			if (!num_clients) {
-				condlog(1, "can't listen for new clients");
-				return NULL;
+		if (num_clients != old_clients) {
+			struct pollfd *new;
+			if (num_clients < MIN_POLLS) {
+				new = REALLOC(polls, (1 + MIN_POLLS) *
+						sizeof(struct pollfd));
+			} else {
+				new = REALLOC(polls, (1+num_clients) *
+						sizeof(struct pollfd));
 			}
-			dead_client(list_entry(clients.prev,
-					       typeof(struct client), node));
-		}
-		else
+			if (!new) {
+				pthread_mutex_unlock(&client_lock);
+				condlog(0, "%s: failed to realloc %d poll fds",
+					"uxsock", 1 + num_clients);
+				pthread_yield();
+				continue;
+			}
+			num_clients = old_clients;
 			polls = new;
+		}
 		polls[0].fd = ux_sock;
 		polls[0].events = POLLIN;
 
@@ -208,8 +219,8 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
 			}
 
 			/* something went badly wrong! */
-			condlog(0, "poll");
-			pthread_exit(NULL);
+			condlog(0, "uxsock: poll failed with %d", errno);
+			break;
 		}
 
 		if (poll_count == 0)
@@ -230,7 +241,7 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
 				}
 				pthread_mutex_unlock(&client_lock);
 				if (!c) {
-					condlog(3, "cli%d: invalid fd %d",
+					condlog(4, "cli%d: new fd %d",
 						i, polls[i].fd);
 					continue;
 				}
@@ -238,24 +249,27 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
 					start_time.tv_sec = 0;
 				if (recv_packet(c->fd, &inbuf, timeout) != 0) {
 					dead_client(c);
-				} else {
-					condlog(4, "Got request [%s]", inbuf);
-					uxsock_trigger(inbuf, &reply, &rlen,
-						       trigger_data);
-					if (reply) {
-						if (send_packet(c->fd,
-								reply) != 0) {
-							dead_client(c);
-						}
-						condlog(4, "Reply [%d bytes]",
-							rlen);
-						FREE(reply);
-						reply = NULL;
+					continue;
+				}
+				condlog(4, "cli[%d]: Got request [%s]",
+					i, inbuf);
+				uxsock_trigger(inbuf, &reply, &rlen,
+					       trigger_data);
+				if (reply) {
+					if (send_packet(c->fd,
+							reply) != 0) {
+						dead_client(c);
+					} else {
+						condlog(4, "cli[%d]: "
+							"Reply [%d bytes]",
+							i, rlen);
 					}
-					check_timeout(start_time, inbuf,
-						      timeout);
-					FREE(inbuf);
+					FREE(reply);
+					reply = NULL;
 				}
+				check_timeout(start_time, inbuf,
+					      timeout);
+				FREE(inbuf);
 			}
 		}
 
-- 
2.6.6




More information about the dm-devel mailing list