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);
}
next prev 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).