From d02c6f546167d5f076a8940470db3a75ff12e814 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 26 Jan 2019 00:27:26 +0900 Subject: [PATCH] udev-ctrl: use sd_event and introduce udev_ctrl_start() Now the new callback function get enum udev_ctrl_msg_type. So, this commit also drops udev_ctrl_connection and udev_ctrl_msg. --- src/udev/udev-ctrl.c | 380 +++++++++++++++++++++++---------------------------- src/udev/udev-ctrl.h | 47 ++++--- src/udev/udevd.c | 101 ++++++-------- 3 files changed, 241 insertions(+), 287 deletions(-) diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index 7d8ff6d..7b0a556 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -17,6 +17,8 @@ #include #include +#include "sd-event.h" + #include "alloc-util.h" #include "fd-util.h" #include "format-util.h" @@ -29,48 +31,27 @@ /* wire protocol magic must match */ #define UDEV_CTRL_MAGIC 0xdead1dea -enum udev_ctrl_msg_type { - UDEV_CTRL_UNKNOWN, - UDEV_CTRL_SET_LOG_LEVEL, - UDEV_CTRL_STOP_EXEC_QUEUE, - UDEV_CTRL_START_EXEC_QUEUE, - UDEV_CTRL_RELOAD, - UDEV_CTRL_SET_ENV, - UDEV_CTRL_SET_CHILDREN_MAX, - UDEV_CTRL_PING, - UDEV_CTRL_EXIT, -}; - struct udev_ctrl_msg_wire { char version[16]; unsigned magic; enum udev_ctrl_msg_type type; - union { - int intval; - char buf[256]; - }; -}; - -struct udev_ctrl_msg { - unsigned n_ref; - struct udev_ctrl_connection *conn; - struct udev_ctrl_msg_wire ctrl_msg_wire; + union udev_ctrl_msg_value value; }; struct udev_ctrl { unsigned n_ref; int sock; + int sock_connect; union sockaddr_union saddr; socklen_t addrlen; - bool bound; - bool cleanup_socket; - bool connected; -}; - -struct udev_ctrl_connection { - unsigned n_ref; - struct udev_ctrl *uctrl; - int sock; + bool bound:1; + bool cleanup_socket:1; + bool connected:1; + sd_event *event; + sd_event_source *event_source; + sd_event_source *event_source_connect; + udev_ctrl_handler_t callback; + void *userdata; }; int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd) { @@ -141,15 +122,27 @@ int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) { return 0; } +static void udev_ctrl_disconnect(struct udev_ctrl *uctrl) { + if (!uctrl) + return; + + uctrl->event_source_connect = sd_event_source_unref(uctrl->event_source_connect); + uctrl->sock_connect = safe_close(uctrl->sock_connect); +} + static struct udev_ctrl *udev_ctrl_free(struct udev_ctrl *uctrl) { assert(uctrl); + udev_ctrl_disconnect(uctrl); + + sd_event_source_unref(uctrl->event_source); safe_close(uctrl->sock); + + sd_event_unref(uctrl->event); return mfree(uctrl); } -DEFINE_PRIVATE_TRIVIAL_REF_FUNC(struct udev_ctrl, udev_ctrl); -DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free); +DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free); int udev_ctrl_cleanup(struct udev_ctrl *uctrl) { if (!uctrl) @@ -159,62 +152,172 @@ int udev_ctrl_cleanup(struct udev_ctrl *uctrl) { return 0; } -int udev_ctrl_get_fd(struct udev_ctrl *uctrl) { - if (!uctrl) - return -EINVAL; - return uctrl->sock; +int udev_ctrl_attach_event(struct udev_ctrl *uctrl, sd_event *event) { + int r; + + assert_return(uctrl, -EINVAL); + assert_return(!uctrl->event, -EBUSY); + + if (event) + uctrl->event = sd_event_ref(event); + else { + r = sd_event_default(&uctrl->event); + if (r < 0) + return r; + } + + return 0; } -struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) { - struct udev_ctrl_connection *conn; - struct ucred ucred = {}; +sd_event_source *udev_ctrl_get_event_source(struct udev_ctrl *uctrl) { + assert(uctrl); + + return uctrl->event_source; +} + +static void udev_ctrl_disconnect_and_listen_again(struct udev_ctrl *uctrl) { + udev_ctrl_disconnect(uctrl); + udev_ctrl_unref(uctrl); + (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_ON); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl *, udev_ctrl_disconnect_and_listen_again); + +static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(udev_ctrl_disconnect_and_listen_againp) struct udev_ctrl *uctrl = NULL; + struct udev_ctrl_msg_wire msg_wire; + struct iovec iov = IOVEC_MAKE(&msg_wire, sizeof(struct udev_ctrl_msg_wire)); + char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; + struct msghdr smsg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cred_msg, + .msg_controllen = sizeof(cred_msg), + }; + struct cmsghdr *cmsg; + struct ucred *cred; + ssize_t size; + + assert(userdata); + + /* When UDEV_CTRL_EXIT is received, manager unref udev_ctrl object. + * To avoid the object freed, let's increment the refcount. */ + uctrl = udev_ctrl_ref(userdata); + + size = next_datagram_size_fd(fd); + if (size < 0) + return log_error_errno(size, "Failed to get size of message: %m"); + if (size == 0) + return 0; /* Client disconnects? */ + + size = recvmsg(fd, &smsg, 0); + if (size < 0) { + if (errno != EINTR) + return log_error_errno(errno, "Failed to receive ctrl message: %m"); + + return 0; + } + + cmsg_close_all(&smsg); + + cmsg = CMSG_FIRSTHDR(&smsg); + + if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { + log_error("No sender credentials received, ignoring message"); + return 0; + } + + cred = (struct ucred *) CMSG_DATA(cmsg); + + if (cred->uid != 0) { + log_error("Invalid sender uid "UID_FMT", ignoring message", cred->uid); + return 0; + } + + if (msg_wire.magic != UDEV_CTRL_MAGIC) { + log_error("Message magic 0x%08x doesn't match, ignoring message", msg_wire.magic); + return 0; + } + + if (uctrl->callback) + (void) uctrl->callback(uctrl, msg_wire.type, &msg_wire.value, uctrl->userdata); + + return 0; +} + +static int udev_ctrl_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + struct udev_ctrl *uctrl = userdata; + _cleanup_close_ int sock = -1; + struct ucred ucred; int r; - conn = new(struct udev_ctrl_connection, 1); - if (!conn) - return NULL; - conn->n_ref = 1; - conn->uctrl = uctrl; + assert(uctrl); - conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); - if (conn->sock < 0) { + sock = accept4(fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); + if (sock < 0) { if (errno != EINTR) - log_error_errno(errno, "Failed to receive ctrl connection: %m"); - goto err; + log_error_errno(errno, "Failed to accept ctrl connection: %m"); + return 0; } /* check peer credential of connection */ - r = getpeercred(conn->sock, &ucred); + r = getpeercred(sock, &ucred); if (r < 0) { log_error_errno(r, "Failed to receive credentials of ctrl connection: %m"); - goto err; + return 0; } + if (ucred.uid > 0) { - log_error("Sender uid="UID_FMT", message ignored", ucred.uid); - goto err; + log_error("Invalid sender uid "UID_FMT", closing connection", ucred.uid); + return 0; } /* enable receiving of the sender credentials in the messages */ - r = setsockopt_int(conn->sock, SOL_SOCKET, SO_PASSCRED, true); + r = setsockopt_int(sock, SOL_SOCKET, SO_PASSCRED, true); if (r < 0) - log_warning_errno(r, "Failed to set SO_PASSCRED: %m"); + log_warning_errno(r, "Failed to set SO_PASSCRED, ignoring: %m"); - udev_ctrl_ref(uctrl); - return conn; -err: - safe_close(conn->sock); - return mfree(conn); -} + r = sd_event_add_io(uctrl->event, &uctrl->event_source_connect, sock, EPOLLIN, udev_ctrl_connection_event_handler, uctrl); + if (r < 0) { + log_error_errno(r, "Failed to create event source for udev control connection: %m"); + return 0; + } + + (void) sd_event_source_set_description(uctrl->event_source_connect, "udev-ctrl-connection"); -static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_connection *conn) { - assert(conn); + /* Do not accept multiple connection. */ + (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_OFF); - safe_close(conn->sock); - udev_ctrl_unref(conn->uctrl); - return mfree(conn); + uctrl->sock_connect = TAKE_FD(sock); + return 0; } -DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free); +int udev_ctrl_start(struct udev_ctrl *uctrl, udev_ctrl_handler_t callback, void *userdata) { + int r; + + assert(uctrl); + + if (!uctrl->event) { + r = udev_ctrl_attach_event(uctrl, NULL); + if (r < 0) + return r; + } + + r = udev_ctrl_enable_receiving(uctrl); + if (r < 0) + return r; + + uctrl->callback = callback; + uctrl->userdata = userdata; + + r = sd_event_add_io(uctrl->event, &uctrl->event_source, uctrl->sock, EPOLLIN, udev_ctrl_event_handler, uctrl); + if (r < 0) + return r; + + (void) sd_event_source_set_description(uctrl->event_source, "udev-ctrl"); + + return 0; +} static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, usec_t timeout) { struct udev_ctrl_msg_wire ctrl_msg_wire = { @@ -224,9 +327,9 @@ static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int }; if (buf) - strscpy(ctrl_msg_wire.buf, sizeof(ctrl_msg_wire.buf), buf); + strscpy(ctrl_msg_wire.value.buf, sizeof(ctrl_msg_wire.value.buf), buf); else - ctrl_msg_wire.intval = intval; + ctrl_msg_wire.value.intval = intval; if (!uctrl->connected) { if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) @@ -289,142 +392,3 @@ int udev_ctrl_send_ping(struct udev_ctrl *uctrl, usec_t timeout) { int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout) { return ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL, timeout); } - -struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) { - struct udev_ctrl_msg *uctrl_msg; - ssize_t size; - struct cmsghdr *cmsg; - struct iovec iov; - char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; - struct msghdr smsg = { - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = cred_msg, - .msg_controllen = sizeof(cred_msg), - }; - struct ucred *cred; - - uctrl_msg = new0(struct udev_ctrl_msg, 1); - if (!uctrl_msg) - return NULL; - uctrl_msg->n_ref = 1; - uctrl_msg->conn = conn; - udev_ctrl_connection_ref(conn); - - /* wait for the incoming message */ - for (;;) { - struct pollfd pfd[1]; - int r; - - pfd[0].fd = conn->sock; - pfd[0].events = POLLIN; - - r = poll(pfd, 1, 10000); - if (r < 0) { - if (errno == EINTR) - continue; - goto err; - } else if (r == 0) { - log_error("Timeout waiting for ctrl message"); - goto err; - } else { - if (!(pfd[0].revents & POLLIN)) { - log_error("Invalid ctrl connection: %m"); - goto err; - } - } - - break; - } - - iov = IOVEC_MAKE(&uctrl_msg->ctrl_msg_wire, sizeof(struct udev_ctrl_msg_wire)); - - size = recvmsg(conn->sock, &smsg, 0); - if (size < 0) { - log_error_errno(errno, "Failed to receive ctrl message: %m"); - goto err; - } - - cmsg_close_all(&smsg); - - cmsg = CMSG_FIRSTHDR(&smsg); - - if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { - log_error("No sender credentials received, ignoring message"); - goto err; - } - - cred = (struct ucred *) CMSG_DATA(cmsg); - - if (cred->uid != 0) { - log_error("Sender uid="UID_FMT", ignoring message", cred->uid); - goto err; - } - - if (uctrl_msg->ctrl_msg_wire.magic != UDEV_CTRL_MAGIC) { - log_error("Message magic 0x%08x doesn't match, ignoring", uctrl_msg->ctrl_msg_wire.magic); - goto err; - } - - return uctrl_msg; -err: - udev_ctrl_msg_unref(uctrl_msg); - return NULL; -} - -static struct udev_ctrl_msg *udev_ctrl_msg_free(struct udev_ctrl_msg *ctrl_msg) { - assert(ctrl_msg); - - udev_ctrl_connection_unref(ctrl_msg->conn); - return mfree(ctrl_msg); -} - -DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl_msg, udev_ctrl_msg, udev_ctrl_msg_free); - -int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL) - return ctrl_msg->ctrl_msg_wire.intval; - return -1; -} - -int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_STOP_EXEC_QUEUE) - return 1; - return -1; -} - -int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_START_EXEC_QUEUE) - return 1; - return -1; -} - -int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_RELOAD) - return 1; - return -1; -} - -const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_ENV) - return ctrl_msg->ctrl_msg_wire.buf; - return NULL; -} - -int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_CHILDREN_MAX) - return ctrl_msg->ctrl_msg_wire.intval; - return -1; -} - -int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_PING) - return 1; - return -1; -} - -int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg) { - if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_EXIT) - return 1; - return -1; -} diff --git a/src/udev/udev-ctrl.h b/src/udev/udev-ctrl.h index 7ea0de4..4e8c00b 100644 --- a/src/udev/udev-ctrl.h +++ b/src/udev/udev-ctrl.h @@ -1,20 +1,46 @@ /* SPDX-License-Identifier: GPL-2.0+ */ #pragma once +#include "sd-event.h" + #include "macro.h" #include "time-util.h" struct udev_ctrl; +enum udev_ctrl_msg_type { + UDEV_CTRL_UNKNOWN, + UDEV_CTRL_SET_LOG_LEVEL, + UDEV_CTRL_STOP_EXEC_QUEUE, + UDEV_CTRL_START_EXEC_QUEUE, + UDEV_CTRL_RELOAD, + UDEV_CTRL_SET_ENV, + UDEV_CTRL_SET_CHILDREN_MAX, + UDEV_CTRL_PING, + UDEV_CTRL_EXIT, +}; + +union udev_ctrl_msg_value { + int intval; + char buf[256]; +}; + +typedef int (*udev_ctrl_handler_t)(struct udev_ctrl *udev_ctrl, enum udev_ctrl_msg_type type, + const union udev_ctrl_msg_value *value, void *userdata); + int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd); static inline int udev_ctrl_new(struct udev_ctrl **ret) { return udev_ctrl_new_from_fd(ret, -1); } int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl); +struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl); struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl); int udev_ctrl_cleanup(struct udev_ctrl *uctrl); -int udev_ctrl_get_fd(struct udev_ctrl *uctrl); +int udev_ctrl_attach_event(struct udev_ctrl *uctrl, sd_event *event); +int udev_ctrl_start(struct udev_ctrl *uctrl, udev_ctrl_handler_t callback, void *userdata); +sd_event_source *udev_ctrl_get_event_source(struct udev_ctrl *uctrl); + int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, usec_t timeout); int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, usec_t timeout); int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl, usec_t timeout); @@ -24,23 +50,4 @@ int udev_ctrl_send_exit(struct udev_ctrl *uctrl, usec_t timeout); int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key, usec_t timeout); int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count, usec_t timeout); -struct udev_ctrl_connection; -struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl); -struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn); -struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn); - -struct udev_ctrl_msg; -struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn); -struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_stop_exec_queue(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_start_exec_queue(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_reload(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_ping(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_exit(struct udev_ctrl_msg *ctrl_msg); -const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg); -int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg); - DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref); -DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_connection*, udev_ctrl_connection_unref); -DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index d1a0b9b..2e31994 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -89,11 +89,9 @@ typedef struct Manager { sd_device_monitor *monitor; struct udev_ctrl *ctrl; - struct udev_ctrl_connection *ctrl_conn_blocking; int fd_inotify; int worker_watch[2]; - sd_event_source *ctrl_event; sd_event_source *inotify_event; sd_event_source *kill_workers_event; @@ -277,7 +275,6 @@ static void worker_attach_event(struct worker *worker, struct event *event) { static void manager_clear_for_worker(Manager *manager) { assert(manager); - manager->ctrl_event = sd_event_source_unref(manager->ctrl_event); manager->inotify_event = sd_event_source_unref(manager->inotify_event); manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event); @@ -287,7 +284,6 @@ static void manager_clear_for_worker(Manager *manager) { event_queue_cleanup(manager, EVENT_UNDEF); manager->monitor = sd_device_monitor_unref(manager->monitor); - manager->ctrl_conn_blocking = udev_ctrl_connection_unref(manager->ctrl_conn_blocking); manager->ctrl = udev_ctrl_unref(manager->ctrl); manager->worker_watch[READ_END] = safe_close(manager->worker_watch[READ_END]); @@ -797,7 +793,6 @@ static void manager_exit(Manager *manager) { "STATUS=Starting shutdown..."); /* close sources of new events and discard buffered events */ - manager->ctrl_event = sd_event_source_unref(manager->ctrl_event); manager->ctrl = udev_ctrl_unref(manager->ctrl); manager->inotify_event = sd_event_source_unref(manager->inotify_event); @@ -997,59 +992,44 @@ static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata) } /* receive the udevd message from userspace */ -static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userdata) { +static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, const union udev_ctrl_msg_value *value, void *userdata) { Manager *manager = userdata; - _cleanup_(udev_ctrl_connection_unrefp) struct udev_ctrl_connection *ctrl_conn = NULL; - _cleanup_(udev_ctrl_msg_unrefp) struct udev_ctrl_msg *ctrl_msg = NULL; - const char *str; - int i, r; + int r; + assert(value); assert(manager); - ctrl_conn = udev_ctrl_get_connection(manager->ctrl); - if (!ctrl_conn) - return 1; - - ctrl_msg = udev_ctrl_receive_msg(ctrl_conn); - if (!ctrl_msg) - return 1; - - i = udev_ctrl_get_set_log_level(ctrl_msg); - if (i >= 0) { - log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", i); - log_set_max_level_realm(LOG_REALM_UDEV, i); - log_set_max_level_realm(LOG_REALM_SYSTEMD, i); + switch (type) { + case UDEV_CTRL_SET_LOG_LEVEL: + log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", value->intval); + log_set_max_level_realm(LOG_REALM_UDEV, value->intval); + log_set_max_level_realm(LOG_REALM_SYSTEMD, value->intval); manager_kill_workers(manager); - } - - if (udev_ctrl_get_stop_exec_queue(ctrl_msg) > 0) { + break; + case UDEV_CTRL_STOP_EXEC_QUEUE: log_debug("Received udev control message (STOP_EXEC_QUEUE)"); manager->stop_exec_queue = true; - } - - if (udev_ctrl_get_start_exec_queue(ctrl_msg) > 0) { + break; + case UDEV_CTRL_START_EXEC_QUEUE: log_debug("Received udev control message (START_EXEC_QUEUE)"); manager->stop_exec_queue = false; event_queue_start(manager); - } - - if (udev_ctrl_get_reload(ctrl_msg) > 0) { + break; + case UDEV_CTRL_RELOAD: log_debug("Received udev control message (RELOAD)"); manager_reload(manager); - } - - str = udev_ctrl_get_set_env(ctrl_msg); - if (str) { + break; + case UDEV_CTRL_SET_ENV: { _cleanup_free_ char *key = NULL, *val = NULL, *old_key = NULL, *old_val = NULL; - char *eq; + const char *eq; - eq = strchr(str, '='); + eq = strchr(value->buf, '='); if (!eq) { - log_error("Invalid key format '%s'", str); + log_error("Invalid key format '%s'", value->buf); return 1; } - key = strndup(str, eq - str); + key = strndup(value->buf, eq - value->buf); if (!key) { log_oom(); return 1; @@ -1090,27 +1070,30 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd key = val = NULL; manager_kill_workers(manager); + break; } + case UDEV_CTRL_SET_CHILDREN_MAX: + if (value->intval <= 0) { + log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval); + return 0; + } - i = udev_ctrl_get_set_children_max(ctrl_msg); - if (i >= 0) { - log_debug("Receivd udev control message (SET_MAX_CHILDREN), setting children_max=%i", i); - arg_children_max = i; + log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval); + arg_children_max = value->intval; (void) sd_notifyf(false, "READY=1\n" "STATUS=Processing with %u children at max", arg_children_max); - } - - if (udev_ctrl_get_ping(ctrl_msg) > 0) + break; + case UDEV_CTRL_PING: log_debug("Received udev control message (PING)"); - - if (udev_ctrl_get_exit(ctrl_msg) > 0) { + break; + case UDEV_CTRL_EXIT: log_debug("Received udev control message (EXIT)"); manager_exit(manager); - /* keep reference to block the client until we exit - TODO: deal with several blocking exit requests */ - manager->ctrl_conn_blocking = udev_ctrl_connection_ref(ctrl_conn); + break; + default: + log_debug("Received unknown udev control message, ignoring"); } return 1; @@ -1617,7 +1600,7 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg } static int main_loop(Manager *manager) { - int fd_worker, fd_ctrl, r; + int fd_worker, r; /* unnamed socket from workers to the main daemon */ r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch); @@ -1664,19 +1647,19 @@ static int main_loop(Manager *manager) { if (r < 0) return log_error_errno(r, "Failed to create watchdog event source: %m"); - fd_ctrl = udev_ctrl_get_fd(manager->ctrl); - if (fd_ctrl < 0) - return log_error_errno(fd_ctrl, "Failed to get udev control socket fd: %m"); + r = udev_ctrl_attach_event(manager->ctrl, manager->event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to udev control: %m"); - r = sd_event_add_io(manager->event, &manager->ctrl_event, fd_ctrl, EPOLLIN, on_ctrl_msg, manager); + r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager); if (r < 0) - return log_error_errno(r, "Failed to create udev control event source: %m"); + return log_error_errno(r, "Failed to start device monitor: %m"); /* This needs to be after the inotify and uevent handling, to make sure * that the ping is send back after fully processing the pending uevents * (including the synthetic ones we may create due to inotify events). */ - r = sd_event_source_set_priority(manager->ctrl_event, SD_EVENT_PRIORITY_IDLE); + r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE); if (r < 0) return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m"); -- 2.7.4