All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hannes Reinecke <hare@suse.de>
To: linux-hotplug@vger.kernel.org
Subject: [PATCH] use uevents in udevd
Date: Fri, 14 Jan 2005 10:22:50 +0000	[thread overview]
Message-ID: <41E79D7A.2060607@suse.de> (raw)

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

Hi all,

this patch adds the capabilities to read uevents directly from the 
kernel socket (CONFIG_KOBJECT_UEVENT=y).
The old behaviour is left in place, as with this we can still send 
events manually.

And I've added a command-line option '-d' to start udevd as a daemon.
Now we can do

/sbin/udevd -p
echo -n "" > /proc/sys/kernel/hotplug

no need for udevsend anymore.
Plus we can finally do a load-limit for hotplug events.

Comments welcome.

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: 6743 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 11:13:51 +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;
@@ -376,6 +383,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 +537,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[] = { 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 +710,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 +736,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 +754,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);
 		}

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

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-14 10:22 Hannes Reinecke [this message]
2005-01-14 10:40 ` [PATCH] use uevents in udevd 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
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=41E79D7A.2060607@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.