linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: some timings with/without hotplug scripts and udev
Date: Tue, 16 Mar 2004 22:33:00 +0000	[thread overview]
Message-ID: <20040316223300.GA8086@vrfy.org> (raw)
In-Reply-To: <20040316090613.A31508@beaverton.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 975 bytes --]

On Tue, Mar 16, 2004 at 09:06:13AM -0800, Patrick Mansfield wrote:
> Times running without hotplug scripts, hotplug scripts without udev, and
> with udev using 512 scsi_debug LUNs.
> 
> insmod was really this:
> 
> 	modprobe scsi_debug num_tgts=32 max_luns=16 delay=0
> 
> No hotplug scripts means using /bin/true for the kernel hotplug.
> 
> 			insmod		rmmod
> no hotplug scripts	0:05.46		0:04.63
> hotplug no udev		0:30.95		0:26.40
> udev w/glibc current	0:40.84		0:36.20
> 
> So hotplug scripts take about 25 seconds, and udev adds about 10 seconds
> on top of that.

Are you running udevsend/udevd in the test?

Any chance to run the same test with the applied patch, which lets
udevsend wait until the real udev comes back?

I'm interested if this takes much longer. If we ensure that udevsend is
the first program that runs by /sbin/hotplug, we can be sure to know any
node name and attribute in any of the following scripts.


again, much thanks for the numbers,
Kay


[-- Attachment #2: 90-udevsend-wait.patch --]
[-- Type: text/plain, Size: 6847 bytes --]

===== udevd.c 1.23 vs edited =====
--- 1.23/udevd.c	Wed Mar  3 22:05:10 2004
+++ edited/udevd.c	Fri Mar 12 15:49:10 2004
@@ -222,6 +222,15 @@
 	}
 }
 
+static void send_ack_msg(int sock, struct hotplug_msg *msg)
+{
+	int retval;
+	dbg("sending ack msg for seq %i", msg->seqnum);
+	retval = sendto(sock, msg, sizeof(struct hotplug_msg), 0, (struct sockaddr*) &msg->addr, msg->addrlen);
+	if (retval == -1)
+		dbg("error sending ack msg");
+}
+
 /* receive the msg, do some basic sanity checks, and queue it */
 static void handle_msg(int sock)
 {
@@ -232,6 +241,7 @@
 	struct iovec iov;
 	struct ucred *cred;
 	char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+	struct sockaddr_un addr;
 
 	msg = msg_create();
 	if (msg == NULL) {
@@ -247,29 +257,39 @@
 	smsg.msg_iovlen = 1;
 	smsg.msg_control = cred_msg;
 	smsg.msg_controllen = sizeof(cred_msg);
+	smsg.msg_name = &addr;
+	smsg.msg_namelen = sizeof(addr);
 
 	retval = recvmsg(sock, &smsg, 0);
 	if (retval <  0) {
 		if (errno != EINTR)
 			dbg("unable to receive message");
-		return;
+		goto skip;
 	}
+
+	if (retval != sizeof(struct hotplug_msg)) {
+		dbg("wrong message size");
+		goto skip;
+	}
+
 	cmsg = CMSG_FIRSTHDR(&smsg);
 	cred = (struct ucred *) CMSG_DATA(cmsg);
+	memcpy(&msg->addr, smsg.msg_name, smsg.msg_namelen);
+	msg->addrlen = smsg.msg_namelen;
+
+	if (strncmp(msg->magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
+		dbg("message magic '%s' doesn't match, ignore it", msg->magic);
+		goto skip;
+	}
 
 	if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
 		dbg("no sender credentials received, message ignored");
-		goto skip;
+		goto refuse;
 	}
 
 	if (cred->uid != 0) {
 		dbg("sender uid=%i, message ignored", cred->uid);
-		goto skip;
-	}
-
-	if (strncmp(msg->magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
-		dbg("message magic '%s' doesn't match, ignore it", msg->magic);
-		goto skip;
+		goto refuse;
 	}
 
 	/* if no seqnum is given, we move straight to exec queue */
@@ -281,6 +301,10 @@
 	}
 	return;
 
+refuse:
+	msg->rc = EMSG_REFUSED;
+	send_ack_msg(sock, msg);
+
 skip:
 	free(msg);
 	return;
@@ -304,7 +328,7 @@
 	}
 }
 
-static void udev_done(int pid)
+static void udev_done(int pid, int rc, int sock)
 {
 	/* find msg associated with pid and delete it */
 	struct hotplug_msg *msg;
@@ -312,6 +336,9 @@
 	list_for_each_entry(msg, &running_list, list) {
 		if (msg->pid == pid) {
 			dbg("<== exec seq %d came back", msg->seqnum);
+			msg->rc = rc;
+			send_ack_msg(sock, msg);
+
 			run_queue_delete(msg);
 			return;
 		}
@@ -326,6 +353,8 @@
 	int retval;
 	const int on = 1;
 	struct sigaction act;
+	int status;
+	int rc;
 
 	init_logging("udevd");
 	dbg("version %s", UDEV_VERSION);
@@ -381,10 +410,16 @@
 			children_waiting = 0;
 			/* reap all dead children */
 			while(1) {
-				int pid = waitpid(-1, 0, WNOHANG);
+				int pid = waitpid(-1, &status, WNOHANG);
 				if ((pid == -1) || (pid == 0))
 					break;
-				udev_done(pid);
+
+				if (WIFEXITED(status))
+					rc = WEXITSTATUS(status);
+				else
+					rc = 0;
+
+				udev_done(pid, rc, ssock);
 			}
 		}
 	}
===== udevd.h 1.8 vs edited =====
--- 1.8/udevd.h	Thu Feb 26 04:09:18 2004
+++ edited/udevd.h	Fri Mar 12 16:09:17 2004
@@ -25,16 +25,26 @@
 #include "list.h"
 
 #define UDEV_MAGIC			"udevd_" UDEV_VERSION
-#define EVENT_TIMEOUT_SEC		5
 #define UDEVSEND_CONNECT_RETRY		20 /* x 100 millisec */
 #define UDEVD_SOCK_PATH			"udevd"
 
+#define EVENT_TIMEOUT_SEC		5
+#define ACK_TIMEOUT_SEC			(EVENT_TIMEOUT_SEC + 5)
+
+#define ETIMEOUT_RCV_ACK		16
+#define EMSG_REFUSED			17
+#define EMSG_SEND			18
+
+
 struct hotplug_msg {
-	char magic[20];
 	struct list_head list;
 	pid_t pid;
-	int seqnum;
 	time_t queue_time;
+	struct sockaddr_un addr;
+	socklen_t addrlen;
+	char magic[20];
+	int seqnum;
+	int rc;
 	char action[ACTION_SIZE];
 	char devpath[DEVPATH_SIZE];
 	char subsystem[SUBSYSTEM_SIZE];
===== udevsend.c 1.27 vs edited =====
--- 1.27/udevsend.c	Wed Mar  3 22:07:05 2004
+++ edited/udevsend.c	Fri Mar 12 16:05:43 2004
@@ -22,6 +22,7 @@
  *
  */
 
+#include <sys/select.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
@@ -95,6 +96,7 @@
 	default:
 		wait(NULL);
 	}
+
 	return 0;
 }
 
@@ -106,7 +108,7 @@
 	char *subsystem;
 	char *seqnum;
 	int seq;
-	int retval = 1;
+	int retval;
 	int size;
 	int loop;
 	struct timespec tspec;
@@ -114,6 +116,7 @@
 	struct sockaddr_un saddr;
 	socklen_t addrlen;
 	int started_daemon = 0;
+	int rc = EMSG_SEND;
 
 #ifdef DEBUG
 	init_logging("udevsend");
@@ -156,6 +159,14 @@
 
 	memset(&saddr, 0x00, sizeof(saddr));
 	saddr.sun_family = AF_LOCAL;
+	sprintf(&saddr.sun_path[1], "%d", getpid());
+	addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
+	
+	if (bind(sock, (struct sockaddr*)&saddr, addrlen) < 0) {
+		dbg("error binding socket");
+		goto exit;
+	}
+		
 	/* use abstract namespace for socket path */
 	strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
 	addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
@@ -164,11 +175,54 @@
 
 	/* If we can't send, try to start daemon and resend message */
 	loop = UDEVSEND_CONNECT_RETRY;
+
 	while (loop--) {
+		dbg("sending message for seq %i", msg.seqnum);
 		retval = sendto(sock, &msg, size, 0, (struct sockaddr *)&saddr, addrlen);
 		if (retval != -1) {
-			retval = 0;
-			goto close_and_exit;
+			/* wait for ack */
+			fd_set rdset;
+			int count;
+			struct timeval tv = {ACK_TIMEOUT_SEC, 0};
+
+			while(1) {
+				FD_ZERO(&rdset);
+				FD_SET(sock, &rdset);
+				count = select(sock+1, &rdset, NULL, NULL, &tv);
+				if (count == 0) {
+					dbg("timeout waiting for ack msg");
+					rc = ETIMEOUT_RCV_ACK;
+					goto close_and_exit;
+					
+				}
+
+				if (FD_ISSET(sock, &rdset)) {
+					struct hotplug_msg ack;
+
+					retval = recv(sock, &ack, sizeof(ack), MSG_DONTWAIT);
+					if (retval <= 0) {
+						dbg("no ack msg received");
+						continue;
+					}
+
+					if (strncmp(ack.magic, msg.magic, sizeof(UDEV_MAGIC)) != 0 ) {
+						dbg("wrong ack msg magic '%s'", ack.magic);
+						continue;
+					}
+
+					if (ack.rc == EMSG_REFUSED) {
+						dbg("seq %i is refused", ack.seqnum);
+						rc = EMSG_REFUSED;
+						goto close_and_exit;
+					}
+
+					if (ack.seqnum == msg.seqnum) {
+						dbg("seq %i returned with %i", ack.seqnum, ack.rc);
+						rc = ack.rc;
+						goto close_and_exit;
+					}
+				}
+			}
 		}
 		
 		if (errno != ECONNREFUSED) {
@@ -179,11 +233,10 @@
 		if (!started_daemon) {
 			dbg("connect failed, try starting daemon...");
 			retval = start_daemon();
-			if (retval) {
+			if (retval != 0) {
 				dbg("error starting daemon");
 				goto exit;
 			}
-			
 			dbg("daemon started");
 			started_daemon = 1;
 		} else {
@@ -193,9 +246,9 @@
 			nanosleep(&tspec, NULL);
 		}
 	}
-	
+
 close_and_exit:
 	close(sock);
 exit:
-	return retval;
+	return rc;
 }

  reply	other threads:[~2004-03-16 22:33 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-03-16 17:06 some timings with/without hotplug scripts and udev Patrick Mansfield
2004-03-16 22:33 ` Kay Sievers [this message]
2004-03-17  1:41 ` Patrick Mansfield

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040316223300.GA8086@vrfy.org \
    --to=kay.sievers@vrfy.org \
    --cc=linux-hotplug@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).