Skip to contentSkip to conversation

use uevents in udevd

PATCH In review Hannes Reinecke 4 participants 19 messages Jan 14, 2005 – Jan 16, 2005

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 use uevents in udevd

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

Signature · 4 lines
Dr. Hannes Reinecke			[email protected]
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de

===== udevd.c 1.59 vs edited =====

udevd.c +200 -21
@@ -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);
 		}
#1 lore raw
Quoted 1 line · Hannes Reinecke

Comments welcome.

Nice work.
How can the init scripts determine if support for uevents is available?

Signature · 2 lines
ciao,
Marco
#2 lore raw
In reply to Hannes Reinecke
Quoted 8 lines · Marco d'Itri
Quoted 1 line · Hannes Reinecke

Comments welcome.

Nice work.
How can the init scripts determine if support for uevents is available?

Good question. Asked myself the same one just now.
I couldn't figure out whether this information is exported from the kernel directly, so that leaves two possibilities:

- check /proc/config.gz for CONFIG_KOBJECT_UEVENT (if /proc/config.gz is available)
- use a program to check for it (like the attached one).

HTH,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke			[email protected]
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de

/*
* uevent_check.c - check for uevent socket
*
* based on uevent_listen.c
*
* Copyright (C) 2004 Kay Sievers <[email protected]>
* Copyright (C) 2004 Hannes Reinecke <[email protected]> *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/user.h>
#include <asm/types.h>
#include <linux/netlink.h>

int main(int argc, char *argv[])

{
	int sock;
	struct sockaddr_nl snl;
	int retval;

	if (getuid() != 0) {
		fprintf(stderr,"need to be root, exit\n");
		exit(0);
	}

	memset(&snl, 0x00, sizeof(struct sockaddr_nl));
	snl.nl_family = AF_NETLINK;
	snl.nl_pid = getpid();
	snl.nl_groups = 0xffffffff;

	sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
	if (sock == -1) {
		fprintf(stderr,"error getting socket, exit\n");
		exit(1);
	}

	retval = bind(sock, (struct sockaddr *) &snl,
		      sizeof(struct sockaddr_nl));
	if (retval < 0) {
		fprintf("bind failed, exit\n");
		exit(1);
	}
	fprintf(stderr,"uevent socket available");
	exit(0);
}
#3 lore raw
In reply to Hannes Reinecke
Quoted 4 lines · Hannes Reinecke

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?

Quoted 2 lines

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.

Quoted 1 line

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.

Quoted 2 lines

Now we can do
/sbin/udevd -p

-p? :)

Quoted 1 line

echo -n "" > /proc/sys/kernel/hotplug

This will break the complete input layer until now! :(

Quoted 2 lines

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

Thanks,
Kay

-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

#4 lore raw
In reply to Hannes Reinecke
Quoted 2 lines · Hannes Reinecke

- check /proc/config.gz for CONFIG_KOBJECT_UEVENT
(if /proc/config.gz is available)

Not acceptable for a distribution script.

Quoted 1 line

- use a program to check for it (like the attached one).

It's yet another binary to install in the initrd etc... What about integrating it in udevd? It could exit with a specific error value if uevents are not available, and most of the code is already there.

Signature · 2 lines
ciao,
Marco
#5 lore raw
In reply to Hannes Reinecke
Quoted 4 lines · Kay Sievers
Quoted 2 lines · Hannes Reinecke

Hi all,

Quoted 9 lines
Quoted 1 line

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?)

Quoted 11 lines
Quoted 2 lines

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.

Quoted 8 lines
Quoted 2 lines

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 ...

Quoted 7 lines
Quoted 3 lines

Now we can do
/sbin/udevd -p

-p? :)

:-)
-ENOCOFFEE

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke			[email protected]
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de

===== udevd.c 1.59 vs edited =====

udevd.c +205 -21
@@ -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);
 		}
#6 lore raw
In reply to Hannes Reinecke
Quoted 9 lines · Marco d'Itri
Quoted 2 lines · Hannes Reinecke

- check /proc/config.gz for CONFIG_KOBJECT_UEVENT
(if /proc/config.gz is available)

Not acceptable for a distribution script.

Yeah, I know.

Quoted 6 lines
Quoted 1 line

- use a program to check for it (like the attached one).

It's yet another binary to install in the initrd etc... What about integrating it in udevd? It could exit with a specific error value if uevents are not available, and most of the code is already there.

Well, the main point of the udevd patch is that it's backwards compatible. So it'll start regardless whether uevent sockets are available or not.
And it's not a clever idea to use udevsend for this task, either, as we will have to use it to feed manual events to udevd.
So just exiting udevsend with an error code if uevent sockets are available it IMHO not possible.

But I might be convinced otherwise.

And yes, I also don't like the 'yet another binary' idea.

Cheers,

Hannes

Signature · 14 lines
Dr. Hannes Reinecke			[email protected]
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de


-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
#7 lore raw
In reply to Hannes Reinecke
Quoted 3 lines · Hannes Reinecke

Well, the main point of the udevd patch is that it's backwards compatible. So it'll start regardless whether uevent sockets are available or not.

But I did understand that you have to start it with -d to use uevents, so where is the compatibility?

Signature · 2 lines
ciao,
Marco
#8 lore raw
In reply to Hannes Reinecke
Quoted 7 lines · Hannes Reinecke
Quoted 4 lines · Kay Sievers

On Fri, 2005-01-14 at 11:22 +0100, Hannes Reinecke wrote:
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?)

We can't be sure that the message coming in from netlink is still in the queue. I think we should just set a flag with the first valid netlink message we receive and skip all udevsend messages with a SEQNUM set from that on.

Quoted 16 lines
Quoted 7 lines

./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.

Quoted 3 lines
Quoted 1 line

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

Quoted 8 lines
Quoted 4 lines

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 <-

I mean: Why do you want to start it manually? The fist event will do this normally. But you are right, if one want's to start it, it's better than ./udevd&.

Quoted 1 line

How does this expected event number thingie work?

The daemon has a state which event is the next expected. If we get something different from the expected number we will wait until a timeout.

If you kill it and restart it or just start it by hand, we have a good chance to set the correct next_expected number from the kernel.

Quoted 2 lines

If we're presetting the expected number, what will happen to events which might be fed from udevsend after startup of udevd?

It's slippery yes, but initializing it may be slightly better than not to read it. :) It's not really important anymore as the next version of udev will have a special startup event timout of 2sec. But the current one has a 10sec timeout which e.g. breaks the firmware loader which also has a 10sec timeout. :)

Quoted 1 line

Especially interesting if the udevinitd approach is used ...

In this case we need to do more special handling when we receive the queue from initramfs, so we can handle that, right?

Thanks,
Kay

-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

#9 lore raw
In reply to Hannes Reinecke
Quoted 9 lines · Hannes Reinecke
Quoted 8 lines · Marco d'Itri
Quoted 1 line · Hannes Reinecke

Comments welcome.

Nice work.
How can the init scripts determine if support for uevents is available?

Quoted 7 lines

Good question. Asked myself the same one just now.
I couldn't figure out whether this information is exported from the kernel directly, so that leaves two possibilities:

- check /proc/config.gz for CONFIG_KOBJECT_UEVENT (if /proc/config.gz is available)
- use a program to check for it (like the attached one).

Did you try the program on a kernel without uevents. I think you can bind successful to all the 32 netlink sockets even without a "sender".

Thanks,
Kay

-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

#10 lore raw
In reply to Hannes Reinecke
Quoted 2 lines · Hannes Reinecke

Martin promised that z90main will be fixed, so no worries about that one. Will have to check pnpbios.

I think z90crypt is clean already, because Z90CRYPT_USE_HOTPLUG is never defined anyway. The option is only there because the source used to be kept in sync with the 2.4 version.

	Arnd <><
#11 lore raw
In reply to Hannes Reinecke
Quoted 18 lines · Kay Sievers
Quoted 16 lines · Hannes Reinecke
Quoted 9 lines · Marco d'Itri
Quoted 1 line · Hannes Reinecke

Comments welcome.

Nice work.
How can the init scripts determine if support for uevents is available?

Good question. Asked myself the same one just now.
I couldn't figure out whether this information is exported from the kernel directly, so that leaves two possibilities:

Quoted 8 lines
Quoted 3 lines

- check /proc/config.gz for CONFIG_KOBJECT_UEVENT (if /proc/config.gz is available)
- use a program to check for it (like the attached one).

Did you try the program on a kernel without uevents. I think you can bind successful to all the 32 netlink sockets even without a "sender".

Great. You are correct.

What now?

Scanning /proc/config.gz is ugly.

Cheers,

Hannes

Signature · 14 lines
Dr. Hannes Reinecke			[email protected]
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de


-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
#12 lore raw
In reply to Hannes Reinecke
Quoted 28 lines · Hannes Reinecke
Quoted 18 lines · Kay Sievers
Quoted 16 lines · Hannes Reinecke
Quoted 9 lines · Marco d'Itri
Quoted 1 line · Hannes Reinecke

Comments welcome.

Nice work.
How can the init scripts determine if support for uevents is available?

Good question. Asked myself the same one just now.
I couldn't figure out whether this information is exported from the kernel directly, so that leaves two possibilities:

Quoted 8 lines
Quoted 3 lines

- check /proc/config.gz for CONFIG_KOBJECT_UEVENT (if /proc/config.gz is available)
- use a program to check for it (like the attached one).

Did you try the program on a kernel without uevents. I think you can bind successful to all the 32 netlink sockets even without a "sender".

Quoted 5 lines

Great. You are correct.

What now?

Scanning /proc/config.gz is ugly.

We don't need to know that in advance it if we turn the other source of events off if we get the first add/remove event from netlink. But yes, we should think about exporting it somewhere.

Kay

-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

#13 lore raw
In reply to Hannes Reinecke
Quoted 10 lines · Kay Sievers
Quoted 7 lines · Arnd Bergmann
Quoted 2 lines · Hannes Reinecke

Martin promised that z90main will be fixed, so no worries about that one. Will have to check pnpbios.

I think z90crypt is clean already, because Z90CRYPT_USE_HOTPLUG is never defined anyway. The option is only there because the source used to be kept in sync with the 2.4 version.

So how about using the right ifdef's then instead of this obfuscation.

If I were maintaining that file, I'd simply throw out all the dead code.

Quoted 1 line

And don't you want udev support for that device?

AFAICS, it works fine with udev because it uses a miscdevice now, or am I missing something?

	Arnd <><
#14 lore raw
In reply to Hannes Reinecke
Quoted 7 lines · Arnd Bergmann
Quoted 2 lines · Hannes Reinecke

Martin promised that z90main will be fixed, so no worries about that one. Will have to check pnpbios.

I think z90crypt is clean already, because Z90CRYPT_USE_HOTPLUG is never defined anyway. The option is only there because the source used to be kept in sync with the 2.4 version.

So how about using the right ifdef's then instead of this obfuscation. And don't you want udev support for that device?

Thanks,
Kay

-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

#15 lore raw
In reply to Hannes Reinecke
Quoted 10 lines · Marco d'Itri
Quoted 3 lines · Hannes Reinecke

Well, the main point of the udevd patch is that it's backwards compatible. So it'll start regardless whether uevent sockets are available or not.

But I did understand that you have to start it with -d to use uevents, so where is the compatibility?

You only need to start it with '-d' if the udevd is not started by other means (eg. udevsend).

udevd will read from netlink sockets if they are available, '-d' doesn't affect that.

Cheers,

Hannes

Signature · 14 lines
Dr. Hannes Reinecke			[email protected]
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de


-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
#16 lore raw
In reply to Hannes Reinecke
Quoted 9 lines · Arnd Bergmann
Quoted 8 lines · Kay Sievers
Quoted 7 lines · Arnd Bergmann
Quoted 2 lines · Hannes Reinecke

Martin promised that z90main will be fixed, so no worries about that one. Will have to check pnpbios.

I think z90crypt is clean already, because Z90CRYPT_USE_HOTPLUG is never defined anyway. The option is only there because the source used to be kept in sync with the 2.4 version.

So it should not hurt if we make hotplug_path private sometimes after the input layer is converted. Good to know!

Quoted 3 lines
Quoted 1 line

So how about using the right ifdef's then instead of this obfuscation.

If I were maintaining that file, I'd simply throw out all the dead code.

Ah, ok.

Quoted 4 lines
Quoted 1 line

And don't you want udev support for that device?

AFAICS, it works fine with udev because it uses a miscdevice now, or am I missing something?

Yes, you are right.

Thanks,
Kay

-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

#17 lore raw
In reply to Hannes Reinecke
Quoted 12 lines · Kay Sievers
Quoted 10 lines · Hannes Reinecke
Quoted 7 lines · Kay Sievers

./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.

Quoted 6 lines
Quoted 5 lines

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.

Actually, the latest version from -mm already fixes the input layer somewhat. At least all input devices have now a proper device and driver, although the lower level things (bus devices etc.) are still a bit messed up. And the automatic module loading is questionable.

So we have some hope here.

Cheers,

Hannes

Signature · 14 lines
Dr. Hannes Reinecke			[email protected]
SuSE Linux AG				S390 & zSeries
Maxfeldstraße 5				+49 911 74053 688
90409 Nürnberg				http://www.suse.de


-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
#18 lore raw
In reply to Hannes Reinecke
Quoted 7 lines · Hannes Reinecke

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

I've added a simpler version of the -d option along with the separation of the socket initialization to my tree. I did not add the uevent event handling, cause we shouldn't do that until the input layer is ready.

Thanks,
Kay

-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek. It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel