summaryrefslogtreecommitdiff
path: root/udev/lib
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2009-06-04 01:44:04 +0200
committerKay Sievers <kay.sievers@vrfy.org>2009-06-04 01:44:04 +0200
commit1e03b754aef576a5cb75f01b1805cdc1f9cc292f (patch)
tree04fed54897345b57cfef598c3fe5eb00b93e53f8 /udev/lib
parentb61f48a0e8a4ad264bc0e904ea8bf3b054d5f562 (diff)
udevd: convert to event worker processes
Event processes now get re-used after they handled an event. This reduces pressure on the CPU significantly because cloned event processes no longer cause page faults in the main daemon. After the events have settled, the no longer needed worker processes get killed.
Diffstat (limited to 'udev/lib')
-rw-r--r--udev/lib/libudev-monitor.c74
-rw-r--r--udev/lib/libudev-private.h5
2 files changed, 63 insertions, 16 deletions
diff --git a/udev/lib/libudev-monitor.c b/udev/lib/libudev-monitor.c
index 395a4d27e1..33a0605492 100644
--- a/udev/lib/libudev-monitor.c
+++ b/udev/lib/libudev-monitor.c
@@ -32,15 +32,17 @@ struct udev_monitor {
int refcount;
int sock;
struct sockaddr_nl snl;
- struct sockaddr_nl snl_peer;
+ struct sockaddr_nl snl_trusted_sender;
+ struct sockaddr_nl snl_destination;
struct sockaddr_un sun;
socklen_t addrlen;
struct udev_list_node filter_subsystem_list;
};
enum udev_monitor_netlink_group {
- UDEV_MONITOR_KERNEL = 1,
- UDEV_MONITOR_UDEV = 2,
+ UDEV_MONITOR_NONE,
+ UDEV_MONITOR_KERNEL,
+ UDEV_MONITOR_UDEV,
};
#define UDEV_MONITOR_MAGIC 0xcafe1dea
@@ -171,11 +173,11 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char
return NULL;
if (name == NULL)
- return NULL;
- if (strcmp(name, "kernel") == 0)
- group = UDEV_MONITOR_KERNEL;
+ group = UDEV_MONITOR_NONE;
else if (strcmp(name, "udev") == 0)
group = UDEV_MONITOR_UDEV;
+ else if (strcmp(name, "kernel") == 0)
+ group = UDEV_MONITOR_KERNEL;
else
return NULL;
@@ -193,8 +195,10 @@ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char
udev_monitor->snl.nl_family = AF_NETLINK;
udev_monitor->snl.nl_groups = group;
- udev_monitor->snl_peer.nl_family = AF_NETLINK;
- udev_monitor->snl_peer.nl_groups = UDEV_MONITOR_UDEV;
+
+ /* default destination for sending */
+ udev_monitor->snl_destination.nl_family = AF_NETLINK;
+ udev_monitor->snl_destination.nl_groups = UDEV_MONITOR_UDEV;
dbg(udev, "monitor %p created with NETLINK_KOBJECT_UEVENT (%u)\n", udev_monitor, group);
return udev_monitor;
@@ -281,6 +285,12 @@ int udev_monitor_filter_update(struct udev_monitor *udev_monitor)
return err;
}
+int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender)
+{
+ udev_monitor->snl_trusted_sender.nl_pid = sender->snl.nl_pid;
+ return 0;
+}
+
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
{
int err;
@@ -293,6 +303,19 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
udev_monitor_filter_update(udev_monitor);
err = bind(udev_monitor->sock,
(struct sockaddr *)&udev_monitor->snl, sizeof(struct sockaddr_nl));
+ if (err == 0) {
+ struct sockaddr_nl snl;
+ socklen_t addrlen;
+
+ /*
+ * get the address the kernel has assigned us
+ * it is usually, but not neccessarily the pid
+ */
+ addrlen = sizeof(struct sockaddr_nl);
+ err = getsockname(udev_monitor->sock, (struct sockaddr *)&snl, &addrlen);
+ if (err == 0)
+ udev_monitor->snl.nl_pid = snl.nl_pid;
+ }
} else {
return -EINVAL;
}
@@ -314,6 +337,15 @@ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int
return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size));
}
+int udev_monitor_disconnect(struct udev_monitor *udev_monitor)
+{
+ int err;
+
+ err = close(udev_monitor->sock);
+ udev_monitor->sock = -1;
+ return err;
+}
+
/**
* udev_monitor_ref:
* @udev_monitor: udev monitor
@@ -478,10 +510,13 @@ retry:
if (udev_monitor->snl.nl_family != 0) {
if (snl.nl_groups == 0) {
- info(udev_monitor->udev, "unicast netlink message ignored\n");
- return NULL;
- }
- if (snl.nl_groups == UDEV_MONITOR_KERNEL) {
+ /* unicast message, check if we trust the sender */
+ if (udev_monitor->snl_trusted_sender.nl_pid == 0 ||
+ snl.nl_pid != udev_monitor->snl_trusted_sender.nl_pid) {
+ info(udev_monitor->udev, "unicast netlink message ignored\n");
+ return NULL;
+ }
+ } else if (snl.nl_groups == UDEV_MONITOR_KERNEL) {
if (snl.nl_pid > 0) {
info(udev_monitor->udev, "multicast kernel netlink message from pid %d ignored\n", snl.nl_pid);
return NULL;
@@ -621,7 +656,8 @@ retry:
return udev_device;
}
-int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_device *udev_device)
+int udev_monitor_send_device(struct udev_monitor *udev_monitor,
+ struct udev_monitor *destination, struct udev_device *udev_device)
{
struct msghdr smsg;
struct iovec iov[2];
@@ -683,8 +719,16 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_devi
memset(&smsg, 0x00, sizeof(struct msghdr));
smsg.msg_iov = iov;
smsg.msg_iovlen = 2;
- /* no destination besides the muticast group, we will always get ECONNREFUSED */
- smsg.msg_name = &udev_monitor->snl_peer;
+ /*
+ * Use custom address for target, or the default one.
+ *
+ * If we send to a muticast group, we will get
+ * ECONNREFUSED, which is expected.
+ */
+ if (destination != NULL)
+ smsg.msg_name = &destination->snl;
+ else
+ smsg.msg_name = &udev_monitor->snl_destination;
smsg.msg_namelen = sizeof(struct sockaddr_nl);
} else {
return -1;
diff --git a/udev/lib/libudev-private.h b/udev/lib/libudev-private.h
index dc02a842b8..5512341e9e 100644
--- a/udev/lib/libudev-private.h
+++ b/udev/lib/libudev-private.h
@@ -86,7 +86,10 @@ int udev_device_delete_db(struct udev_device *udev_device);
int udev_device_rename_db(struct udev_device *udev_device, const char *devpath);
/* libudev-monitor - netlink/unix socket communication */
-int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_device *udev_device);
+int udev_monitor_disconnect(struct udev_monitor *udev_monitor);
+int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender);
+int udev_monitor_send_device(struct udev_monitor *udev_monitor,
+ struct udev_monitor *destination, struct udev_device *udev_device);
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
/* libudev-ctrl - daemon runtime setup */