linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Hannes Reinecke <hare@suse.de>
To: linux-hotplug@vger.kernel.org
Subject: Re: [PATCH] use uevents in udevd
Date: Fri, 14 Jan 2005 11:22:36 +0000	[thread overview]
Message-ID: <41E7AB7C.1080509@suse.de> (raw)
In-Reply-To: <41E79D7A.2060607@suse.de>

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

Kay Sievers wrote:
> On Fri, 2005-01-14 at 11:22 +0100, Hannes Reinecke wrote:
> 
>>Hi all,
>>
>>this patch adds the capabilities to read uevents directly from the 
>>kernel socket (CONFIG_KOBJECT_UEVENT=y).
> 
> 
> Heh, I just split up the message handling in udevd last week to possibly
> plug in a second source of events. Nice work!
> 
> Shouldn't we ignore events with a SEQNUM from udevsend, if we get the
> first one from the uevent?
> 
Indeed we should. I fixed the patch accordingly.
(Hopefully correct; the list is scanned backwards, right?)

> 
>>The old behaviour is left in place, as with this we can still send 
>>events manually.
> 
> 
> ./drivers/input/input.c
> ./drivers/pnp/pnpbios/core.c
> ./drivers/s390/crypto/z90main.c
> 
> are still "broken" from that view. They bypass the driver core and don't
> send any uevent.
> 
Oh s**t. Still?

Time to lean on Vojtech to fix the input layer.
Martin promised that z90main will be fixed, so no worries about that 
one. Will have to check pnpbios.

> 
>>And I've added a command-line option '-d' to start udevd as a daemon.
> 
> 
> It is already running, right? We should read /sys/kernel/hotplug_seqnum
> and initialize the next expected event number too, if the self-daemonize
> is needed.
> 
Well, no. At least not necessarily.
And doesn't matter anyway as it will exit if another daemon is already 
running.
-> There can be only one <-

How does this expected event number thingie work?
If we're presetting the expected number, what will happen to events 
which might be fed from udevsend after startup of udevd?
Especially interesting if the udevinitd approach is used ...

> 
>>Now we can do
>>/sbin/udevd -p
> 
> 
> -p? :)
> 
:-)
-ENOCOFFEE

Cheers,

Hannes
-- 
Dr. Hannes Reinecke			hare@suse.de
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de

[-- Attachment #2: udevd-uevent.patch --]
[-- Type: text/x-patch, Size: 7073 bytes --]

===== udevd.c 1.59 vs edited =====
--- 1.59/udevd.c	2005-01-04 21:37:50 +01:00
+++ edited/udevd.c	2005-01-14 12:21:25 +01:00
@@ -35,6 +35,7 @@
 #include <fcntl.h>
 #include <sys/sysinfo.h>
 #include <sys/stat.h>
+#include <linux/netlink.h>
 
 #include "list.h"
 #include "udev.h"
@@ -43,8 +44,14 @@
 #include "udevd.h"
 #include "logging.h"
 
+/* Older header files do not define this */
+#ifndef NETLINK_KOBJECT_UEVENT
+#define NETLINK_KOBJECT_UEVENT 15
+#endif
+
 /* global variables*/
 static int udevsendsock;
+static int ueventsock;
 
 static int pipefds[2];
 static long startup_time;
@@ -110,6 +117,11 @@
 
 	/* sort message by sequence number into list */
 	list_for_each_entry_reverse(loop_msg, &msg_list, list)
+		if (loop_msg->seqnum == msg->seqnum) {
+			dbg("duplicate message seq %llu, ignoring", 
+			    msg->seqnum);
+			return;
+		}
 		if (loop_msg->seqnum < msg->seqnum)
 			break;
 
@@ -376,6 +388,83 @@
 	return msg;
 }
 
+#define UEVENT_BUFFER_SIZE		1024
+#define OBJECT_SIZE			512
+
+/* receive the kernel user event message and do some sanity checks */
+static struct hotplug_msg *get_uevent_msg(void)
+{
+	struct hotplug_msg *msg;
+	int bufpos;
+	int i;
+	ssize_t size;
+	char *pos;
+	static char buffer[UEVENT_BUFFER_SIZE + OBJECT_SIZE];
+
+	size = recv(ueventsock, &buffer, sizeof(buffer),0);
+	if (size <  0) {
+		if (errno != EINTR)
+			dbg("unable to receive udevsend message");
+		return NULL;
+	}
+
+	if ((size_t)size > sizeof(buffer)-1)
+	    size = sizeof(buffer)-1;
+	
+	buffer[size] = '\0';
+
+	dbg("uevent_size=%i", size);
+	msg = malloc(sizeof(struct hotplug_msg) + size);
+	if (msg == NULL)
+		return NULL;
+
+	memset(msg, 0x00, sizeof(struct hotplug_msg) + size);
+
+	/* copy environment buffer and reconstruct envp */
+	memcpy(msg->envbuf, buffer, size);
+
+	/* save start of payload */
+	bufpos = strlen(buffer) + 1;
+
+	/* action string */
+	msg->action = msg->envbuf;
+	pos = strchr(msg->envbuf, '@');
+	if (!pos) {
+		free(msg);
+		return NULL;
+	}
+	pos[0] = '\0';
+
+	/* sysfs path */
+	msg->devpath = &pos[1];
+
+
+	for (i = 0; (bufpos < size) && (i < HOTPLUG_NUM_ENVP-2); i++) {
+		int keylen;
+		char *key;
+
+		key = &msg->envbuf[bufpos];
+		keylen = strlen(key);
+		msg->envp[i] = key;
+		bufpos += keylen + 1;
+		dbg("add '%s' to msg.envp[%i]", msg->envp[i], i);
+
+		/* remember some keys for further processing */
+		if (strncmp(key, "SUBSYSTEM=", 10) == 0)
+			msg->subsystem = &key[10];
+
+		if (strncmp(key, "SEQNUM=", 7) == 0)
+			msg->seqnum = strtoull(&key[7], NULL, 10);
+
+		if (strncmp(key, "PHYSDEVPATH=", 12) == 0)
+			msg->physdevpath = &key[12];
+	}
+	msg->envp[i++] = "UDEVD_EVENT=1";
+	msg->envp[i] = NULL;
+
+	return msg;
+}
+
 static void asmlinkage sig_handler(int signum)
 {
 	int rc;
@@ -453,17 +542,114 @@
 	}
 }
 
+static int init_udevsend_socket(void)
+{
+	struct sockaddr_un saddr;
+	socklen_t addrlen;
+	const int feature_on = 1;
+	int retval;
+
+	memset(&saddr, 0x00, sizeof(saddr));
+	saddr.sun_family = AF_LOCAL;
+	/* 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;
+
+	udevsendsock = socket(AF_LOCAL, SOCK_DGRAM, 0);
+	if (udevsendsock == -1) {
+		dbg("error getting socket, %s", strerror(errno));
+		return -1;
+	}
+
+	/* the bind takes care of ensuring only one copy running */
+	retval = bind(udevsendsock, (struct sockaddr *) &saddr, addrlen);
+	if (retval < 0) {
+		dbg("bind failed, %s", strerror(errno));
+		close(udevsendsock);
+		return -1;
+	}
+
+	/* enable receiving of the sender credentials */
+	setsockopt(udevsendsock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
+
+	return 0;
+}
+
+static int init_uevent_socket(void)
+{
+	struct sockaddr_nl snl;
+	int retval;
+
+	memset(&snl, 0x00, sizeof(struct sockaddr_nl));
+	snl.nl_family = AF_NETLINK;
+	snl.nl_pid = getpid();
+	snl.nl_groups = 0xffffffff;
+
+	ueventsock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+	if (ueventsock == -1) {
+		dbg("error getting socket, %s", strerror(errno));
+		return -1;
+	}
+
+	retval = bind(ueventsock, (struct sockaddr *) &snl,
+		      sizeof(struct sockaddr_nl));
+	if (retval < 0) {
+		dbg("bind failed, %s", strerror(errno));
+		close(ueventsock);
+		ueventsock = -1;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int start_daemon(char *pathname)
+{
+	pid_t pid;
+	pid_t child_pid;
+	char *const argv[] = { "udevd", NULL };
+	char *const envp[] = { "UDEVD_DAEMON=1", NULL };
+
+	pid = fork();
+	switch (pid) {
+	case 0:
+		/* helper child */
+		child_pid = fork();
+		switch (child_pid) {
+		case 0:
+			/* daemon with empty environment */
+			execve(pathname, argv, envp);
+			dbg("exec of daemon failed");
+			_exit(1);
+		case -1:
+			dbg("fork of daemon failed");
+			return -1;
+		default:
+			exit(0);
+		}
+		break;
+	case -1:
+		dbg("fork of helper failed");
+		return -1;
+	default:
+		waitpid(pid, NULL, 0);
+	}
+	return 0;
+}
+
 int main(int argc, char *argv[], char *envp[])
 {
 	struct sysinfo info;
 	int maxsockplus;
-	struct sockaddr_un saddr;
-	socklen_t addrlen;
 	int retval, fd;
-	const int feature_on = 1;
 	struct sigaction act;
 	fd_set readfds;
 
+	if (argc > 1 && strncmp(argv[1],"-d",2)) {
+		retval = start_daemon(argv[0]);
+		return retval;
+	}
+
 	logging_init("udevd");
 	dbg("version %s", UDEV_VERSION);
 
@@ -529,29 +715,19 @@
 	sigaction(SIGALRM, &act, NULL);
 	sigaction(SIGCHLD, &act, NULL);
 
-	memset(&saddr, 0x00, sizeof(saddr));
-	saddr.sun_family = AF_LOCAL;
-	/* 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;
-
-	udevsendsock = socket(AF_LOCAL, SOCK_DGRAM, 0);
-	if (udevsendsock == -1) {
-		dbg("error getting socket, exit");
-		goto exit;
+	if (init_uevent_socket() < 0) {
+		dbg("uevent socket not available");
 	}
 
-	/* the bind takes care of ensuring only one copy running */
-	retval = bind(udevsendsock, (struct sockaddr *) &saddr, addrlen);
-	if (retval < 0) {
-		dbg("bind failed, exit");
-		close(udevsendsock);
+	if (init_udevsend_socket() < 0) {
+		if (errno == EADDRINUSE)
+			dbg("another udevd is running, exit");
+		else
+			dbg("error initialising udevsend socket: %s",
+			    strerror(errno));
 		goto exit;
 	}
 
-	/* enable receiving of the sender credentials */
-	setsockopt(udevsendsock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
-
 	/* possible override of udev binary, used for testing */
 	udev_bin = getenv("UDEV_BIN");
 	if (udev_bin != NULL)
@@ -565,6 +741,8 @@
 
 	FD_ZERO(&readfds);
 	FD_SET(udevsendsock, &readfds);
+	if (ueventsock != -1)
+		FD_SET(ueventsock, &readfds);
 	FD_SET(pipefds[0], &readfds);
 	maxsockplus = udevsendsock+1;
 	while (1) {
@@ -581,6 +759,12 @@
 
 		if (FD_ISSET(udevsendsock, &workreadfds)) {
 			msg = get_udevsend_msg();
+			if (msg)
+				msg_queue_insert(msg);
+		}
+
+		if (FD_ISSET(ueventsock, &workreadfds)) {
+			msg = get_uevent_msg();
 			if (msg)
 				msg_queue_insert(msg);
 		}

  parent reply	other threads:[~2005-01-14 11:22 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-14 10:22 [PATCH] use uevents in udevd Hannes Reinecke
2005-01-14 10:40 ` Marco d'Itri
2005-01-14 10:55 ` Hannes Reinecke
2005-01-14 10:55 ` Kay Sievers
2005-01-14 11:00 ` Marco d'Itri
2005-01-14 11:22 ` Hannes Reinecke [this message]
2005-01-14 11:26 ` Hannes Reinecke
2005-01-14 11:37 ` Marco d'Itri
2005-01-14 12:11 ` Kay Sievers
2005-01-14 12:43 ` Kay Sievers
2005-01-14 13:01 ` Arnd Bergmann
2005-01-14 13:01 ` Hannes Reinecke
2005-01-14 13:08 ` Kay Sievers
2005-01-14 13:11 ` Arnd Bergmann
2005-01-14 13:12 ` Kay Sievers
2005-01-14 13:23 ` Hannes Reinecke
2005-01-14 13:35 ` Kay Sievers
2005-01-14 16:08 ` Hannes Reinecke
2005-01-16 16:27 ` Kay Sievers

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=41E7AB7C.1080509@suse.de \
    --to=hare@suse.de \
    --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).