1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-30 06:25:37 +03:00

udev: move several functions

No functional chage.
This commit is contained in:
Yu Watanabe 2021-06-17 15:14:59 +09:00
parent e0d61dac33
commit 419ec63135

View File

@ -132,8 +132,6 @@ typedef struct Event {
LIST_FIELDS(Event, event);
} Event;
static void event_queue_cleanup(Manager *manager, EventState match_state);
typedef enum WorkerState {
WORKER_UNDEF,
WORKER_RUNNING,
@ -179,6 +177,17 @@ static void event_free(Event *event) {
free(event);
}
static void event_queue_cleanup(Manager *manager, EventState match_state) {
Event *event, *tmp;
LIST_FOREACH_SAFE(event, event, tmp, manager->events) {
if (match_state != EVENT_UNDEF && match_state != event->state)
continue;
event_free(event);
}
}
static Worker *worker_free(Worker *worker) {
if (!worker)
return NULL;
@ -195,87 +204,6 @@ static Worker *worker_free(Worker *worker) {
DEFINE_TRIVIAL_CLEANUP_FUNC(Worker*, worker_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(worker_hash_op, void, trivial_hash_func, trivial_compare_func, Worker, worker_free);
static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) {
_cleanup_(worker_freep) Worker *worker = NULL;
int r;
assert(ret);
assert(manager);
assert(worker_monitor);
assert(pid > 1);
/* close monitor, but keep address around */
device_monitor_disconnect(worker_monitor);
worker = new(Worker, 1);
if (!worker)
return -ENOMEM;
*worker = (Worker) {
.manager = manager,
.monitor = sd_device_monitor_ref(worker_monitor),
.pid = pid,
};
r = hashmap_ensure_put(&manager->workers, &worker_hash_op, PID_TO_PTR(pid), worker);
if (r < 0)
return r;
*ret = TAKE_PTR(worker);
return 0;
}
static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
Event *event = userdata;
assert(event);
assert(event->worker);
kill_and_sigcont(event->worker->pid, arg_timeout_signal);
event->worker->state = WORKER_KILLED;
log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed", event->worker->pid, event->seqnum);
return 1;
}
static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
Event *event = userdata;
assert(event);
assert(event->worker);
log_device_warning(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" is taking a long time", event->worker->pid, event->seqnum);
return 1;
}
static void worker_attach_event(Worker *worker, Event *event) {
sd_event *e;
assert(worker);
assert(worker->manager);
assert(event);
assert(!event->worker);
assert(!worker->event);
worker->state = WORKER_RUNNING;
worker->event = event;
event->state = EVENT_RUNNING;
event->worker = worker;
e = worker->manager->event;
(void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC,
udev_warn_timeout(arg_event_timeout_usec), USEC_PER_SEC,
on_event_timeout_warning, event);
(void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
arg_event_timeout_usec, USEC_PER_SEC,
on_event_timeout, event);
}
static void manager_clear_for_worker(Manager *manager) {
assert(manager);
@ -317,6 +245,107 @@ static Manager* manager_free(Manager *manager) {
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) {
_cleanup_(worker_freep) Worker *worker = NULL;
int r;
assert(ret);
assert(manager);
assert(worker_monitor);
assert(pid > 1);
/* close monitor, but keep address around */
device_monitor_disconnect(worker_monitor);
worker = new(Worker, 1);
if (!worker)
return -ENOMEM;
*worker = (Worker) {
.manager = manager,
.monitor = sd_device_monitor_ref(worker_monitor),
.pid = pid,
};
r = hashmap_ensure_put(&manager->workers, &worker_hash_op, PID_TO_PTR(pid), worker);
if (r < 0)
return r;
*ret = TAKE_PTR(worker);
return 0;
}
static void manager_kill_workers(Manager *manager, bool force) {
Worker *worker;
assert(manager);
HASHMAP_FOREACH(worker, manager->workers) {
if (worker->state == WORKER_KILLED)
continue;
if (worker->state == WORKER_RUNNING && !force) {
worker->state = WORKER_KILLING;
continue;
}
worker->state = WORKER_KILLED;
(void) kill(worker->pid, SIGTERM);
}
}
static void manager_exit(Manager *manager) {
assert(manager);
manager->exit = true;
sd_notify(false,
"STOPPING=1\n"
"STATUS=Starting shutdown...");
/* close sources of new events and discard buffered events */
manager->ctrl = udev_ctrl_unref(manager->ctrl);
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
manager->inotify_fd = safe_close(manager->inotify_fd);
manager->monitor = sd_device_monitor_unref(manager->monitor);
/* discard queued events and kill workers */
event_queue_cleanup(manager, EVENT_QUEUED);
manager_kill_workers(manager, true);
}
/* reload requested, HUP signal received, rules changed, builtin changed */
static void manager_reload(Manager *manager) {
assert(manager);
sd_notify(false,
"RELOADING=1\n"
"STATUS=Flushing configuration...");
manager_kill_workers(manager, false);
manager->rules = udev_rules_free(manager->rules);
udev_builtin_exit();
sd_notifyf(false,
"READY=1\n"
"STATUS=Processing with %u children at max", arg_children_max);
}
static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userdata) {
Manager *manager = userdata;
assert(manager);
log_debug("Cleanup idle workers");
manager_kill_workers(manager, false);
return 1;
}
static int worker_send_message(int fd) {
WorkerMessage message = {};
@ -594,6 +623,56 @@ static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device
return 0;
}
static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
Event *event = userdata;
assert(event);
assert(event->worker);
kill_and_sigcont(event->worker->pid, arg_timeout_signal);
event->worker->state = WORKER_KILLED;
log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed", event->worker->pid, event->seqnum);
return 1;
}
static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) {
Event *event = userdata;
assert(event);
assert(event->worker);
log_device_warning(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" is taking a long time", event->worker->pid, event->seqnum);
return 1;
}
static void worker_attach_event(Worker *worker, Event *event) {
sd_event *e;
assert(worker);
assert(worker->manager);
assert(event);
assert(!event->worker);
assert(!worker->event);
worker->state = WORKER_RUNNING;
worker->event = event;
event->state = EVENT_RUNNING;
event->worker = worker;
e = worker->manager->event;
(void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC,
udev_warn_timeout(arg_event_timeout_usec), USEC_PER_SEC,
on_event_timeout_warning, event);
(void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC,
arg_event_timeout_usec, USEC_PER_SEC,
on_event_timeout, event);
}
static int worker_spawn(Manager *manager, Event *event) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *worker_monitor = NULL;
Worker *worker;
@ -686,76 +765,6 @@ static void event_run(Manager *manager, Event *event) {
worker_spawn(manager, event);
}
static int event_queue_insert(Manager *manager, sd_device *dev) {
_cleanup_(sd_device_unrefp) sd_device *clone = NULL;
Event *event;
uint64_t seqnum;
int r;
assert(manager);
assert(dev);
/* only one process can add events to the queue */
assert(manager->pid == getpid_cached());
/* We only accepts devices received by device monitor. */
r = sd_device_get_seqnum(dev, &seqnum);
if (r < 0)
return r;
/* Save original device to restore the state on failures. */
r = device_shallow_clone(dev, &clone);
if (r < 0)
return r;
r = device_copy_properties(clone, dev);
if (r < 0)
return r;
event = new(Event, 1);
if (!event)
return -ENOMEM;
*event = (Event) {
.manager = manager,
.dev = sd_device_ref(dev),
.dev_kernel = TAKE_PTR(clone),
.seqnum = seqnum,
.state = EVENT_QUEUED,
};
if (LIST_IS_EMPTY(manager->events)) {
r = touch("/run/udev/queue");
if (r < 0)
log_warning_errno(r, "Failed to touch /run/udev/queue: %m");
}
LIST_APPEND(event, manager->events, event);
log_device_uevent(dev, "Device is queued");
return 0;
}
static void manager_kill_workers(Manager *manager, bool force) {
Worker *worker;
assert(manager);
HASHMAP_FOREACH(worker, manager->workers) {
if (worker->state == WORKER_KILLED)
continue;
if (worker->state == WORKER_RUNNING && !force) {
worker->state = WORKER_KILLING;
continue;
}
worker->state = WORKER_KILLED;
(void) kill(worker->pid, SIGTERM);
}
}
/* lookup event for identical, parent, child device */
static int is_device_busy(Manager *manager, Event *event) {
const char *subsystem, *devpath, *devpath_old = NULL;
@ -867,57 +876,6 @@ set_delaying_seqnum:
return true;
}
static void manager_exit(Manager *manager) {
assert(manager);
manager->exit = true;
sd_notify(false,
"STOPPING=1\n"
"STATUS=Starting shutdown...");
/* close sources of new events and discard buffered events */
manager->ctrl = udev_ctrl_unref(manager->ctrl);
manager->inotify_event = sd_event_source_unref(manager->inotify_event);
manager->inotify_fd = safe_close(manager->inotify_fd);
manager->monitor = sd_device_monitor_unref(manager->monitor);
/* discard queued events and kill workers */
event_queue_cleanup(manager, EVENT_QUEUED);
manager_kill_workers(manager, true);
}
/* reload requested, HUP signal received, rules changed, builtin changed */
static void manager_reload(Manager *manager) {
assert(manager);
sd_notify(false,
"RELOADING=1\n"
"STATUS=Flushing configuration...");
manager_kill_workers(manager, false);
manager->rules = udev_rules_free(manager->rules);
udev_builtin_exit();
sd_notifyf(false,
"READY=1\n"
"STATUS=Processing with %u children at max", arg_children_max);
}
static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userdata) {
Manager *manager = userdata;
assert(manager);
log_debug("Cleanup idle workers");
manager_kill_workers(manager, false);
return 1;
}
static void event_queue_start(Manager *manager) {
Event *event;
usec_t usec;
@ -966,15 +924,77 @@ static void event_queue_start(Manager *manager) {
}
}
static void event_queue_cleanup(Manager *manager, EventState match_state) {
Event *event, *tmp;
static int event_queue_insert(Manager *manager, sd_device *dev) {
_cleanup_(sd_device_unrefp) sd_device *clone = NULL;
Event *event;
uint64_t seqnum;
int r;
LIST_FOREACH_SAFE(event, event, tmp, manager->events) {
if (match_state != EVENT_UNDEF && match_state != event->state)
continue;
assert(manager);
assert(dev);
event_free(event);
/* only one process can add events to the queue */
assert(manager->pid == getpid_cached());
/* We only accepts devices received by device monitor. */
r = sd_device_get_seqnum(dev, &seqnum);
if (r < 0)
return r;
/* Save original device to restore the state on failures. */
r = device_shallow_clone(dev, &clone);
if (r < 0)
return r;
r = device_copy_properties(clone, dev);
if (r < 0)
return r;
event = new(Event, 1);
if (!event)
return -ENOMEM;
*event = (Event) {
.manager = manager,
.dev = sd_device_ref(dev),
.dev_kernel = TAKE_PTR(clone),
.seqnum = seqnum,
.state = EVENT_QUEUED,
};
if (LIST_IS_EMPTY(manager->events)) {
r = touch("/run/udev/queue");
if (r < 0)
log_warning_errno(r, "Failed to touch /run/udev/queue: %m");
}
LIST_APPEND(event, manager->events, event);
log_device_uevent(dev, "Device is queued");
return 0;
}
static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
Manager *manager = userdata;
int r;
assert(manager);
DEVICE_TRACE_POINT(kernel_uevent_received, dev);
device_ensure_usec_initialized(dev, NULL);
r = event_queue_insert(manager, dev);
if (r < 0) {
log_device_error_errno(dev, r, "Failed to insert device into event queue: %m");
return 1;
}
/* we have fresh events, try to schedule them */
event_queue_start(manager);
return 1;
}
static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
@ -1044,28 +1064,6 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat
return 1;
}
static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
Manager *manager = userdata;
int r;
assert(manager);
DEVICE_TRACE_POINT(kernel_uevent_received, dev);
device_ensure_usec_initialized(dev, NULL);
r = event_queue_insert(manager, dev);
if (r < 0) {
log_device_error_errno(dev, r, "Failed to insert device into event queue: %m");
return 1;
}
/* we have fresh events, try to schedule them */
event_queue_start(manager);
return 1;
}
/* receive the udevd message from userspace */
static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrlMessageValue *value, void *userdata) {
Manager *manager = userdata;