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