diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2009-06-04 01:44:04 +0200 |
---|---|---|
committer | Kay Sievers <kay.sievers@vrfy.org> | 2009-06-04 01:44:04 +0200 |
commit | 1e03b754aef576a5cb75f01b1805cdc1f9cc292f (patch) | |
tree | 04fed54897345b57cfef598c3fe5eb00b93e53f8 /udev/lib | |
parent | b61f48a0e8a4ad264bc0e904ea8bf3b054d5f562 (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.c | 74 | ||||
-rw-r--r-- | udev/lib/libudev-private.h | 5 |
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 */ |