chiark / gitweb /
monitor udev for device changes
[elogind.git] / manager.c
index fd219b03041f7eb5b58c19b2ef2f3750cdb655a9..e0ffe93270a4e10479dc54fb0be3851ac5a12df0 100644 (file)
--- a/manager.c
+++ b/manager.c
@@ -36,7 +36,7 @@ static int manager_setup_signals(Manager *m) {
         assert_se(sigaddset(&mask, SIGPIPE) == 0);
         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
 
-        m->signal_watch.type = WATCH_SIGNAL_FD;
+        m->signal_watch.type = WATCH_SIGNAL;
         if ((m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0)
                 return -errno;
 
@@ -56,7 +56,7 @@ Manager* manager_new(void) {
         if (!(m = new0(Manager, 1)))
                 return NULL;
 
-        m->signal_watch.fd = m->epoll_fd = -1;
+        m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = -1;
 
         if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
                 goto fail;
@@ -563,6 +563,7 @@ static void transaction_minimize_impact(Manager *m) {
 
                 HASHMAP_FOREACH(j, m->transaction_jobs, i) {
                         LIST_FOREACH(transaction, j, j) {
+                                bool stops_running_service, changes_existing_job;
 
                                 /* If it matters, we shouldn't drop it */
                                 if (j->matters_to_anchor)
@@ -571,12 +572,25 @@ static void transaction_minimize_impact(Manager *m) {
                                 /* Would this stop a running service?
                                  * Would this change an existing job?
                                  * If so, let's drop this entry */
-                                if ((j->type != JOB_STOP || UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(j->unit))) &&
-                                    (!j->unit->meta.job  || job_type_is_conflicting(j->type, j->unit->meta.job->state)))
+
+                                stops_running_service =
+                                        j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit));
+
+                                changes_existing_job =
+                                        j->unit->meta.job && job_type_is_conflicting(j->type, j->unit->meta.job->state);
+
+                                if (!stops_running_service && !changes_existing_job)
                                         continue;
 
+                                if (stops_running_service)
+                                        log_debug("%s/%s would stop a running service.", unit_id(j->unit), job_type_to_string(j->type));
+
+                                if (changes_existing_job)
+                                        log_debug("%s/%s would change existing job.", unit_id(j->unit), job_type_to_string(j->type));
+
                                 /* Ok, let's get rid of this */
-                                log_debug("Deleting %s/%s to minimize impact", unit_id(j->unit), job_type_to_string(j->type));
+                                log_debug("Deleting %s/%s to minimize impact.", unit_id(j->unit), job_type_to_string(j->type));
+
                                 transaction_delete_job(m, j);
                                 again = true;
                                 break;
@@ -1109,10 +1123,10 @@ static int process_event(Manager *m, struct epoll_event *ev, bool *quit) {
 
         switch (w->type) {
 
-        case WATCH_SIGNAL_FD:
+        case WATCH_SIGNAL:
 
                 /* An incoming signal? */
-                if (ev->events != POLLIN)
+                if (ev->events != EPOLLIN)
                         return -EINVAL;
 
                 if ((r = manager_process_signal_fd(m, quit)) < 0)
@@ -1143,6 +1157,16 @@ static int process_event(Manager *m, struct epoll_event *ev, bool *quit) {
                 break;
         }
 
+        case WATCH_MOUNT:
+                /* Some mount table change, intended for the mount subsystem */
+                mount_fd_event(m, ev->events);
+                break;
+
+        case WATCH_UDEV:
+                /* Some notification from udev, intended for the device subsystem */
+                device_fd_event(m, ev->events);
+                break;
+
         default:
                 assert_not_reached("Unknown epoll event type.");
         }