chiark / gitweb /
unit: When stopping due to BindsTo=, log which unit caused it
[elogind.git] / src / core / transaction.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <unistd.h>
23 #include <fcntl.h>
24
25 #include "bus-common-errors.h"
26 #include "bus-error.h"
27 #include "transaction.h"
28
29 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
30
31 static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) {
32         assert(tr);
33         assert(j);
34
35         /* Deletes one job from the transaction */
36
37         transaction_unlink_job(tr, j, delete_dependencies);
38
39         job_free(j);
40 }
41
42 static void transaction_delete_unit(Transaction *tr, Unit *u) {
43         Job *j;
44
45         /* Deletes all jobs associated with a certain unit from the
46          * transaction */
47
48         while ((j = hashmap_get(tr->jobs, u)))
49                 transaction_delete_job(tr, j, true);
50 }
51
52 void transaction_abort(Transaction *tr) {
53         Job *j;
54
55         assert(tr);
56
57         while ((j = hashmap_first(tr->jobs)))
58                 transaction_delete_job(tr, j, false);
59
60         assert(hashmap_isempty(tr->jobs));
61 }
62
63 static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) {
64         JobDependency *l;
65
66         /* A recursive sweep through the graph that marks all units
67          * that matter to the anchor job, i.e. are directly or
68          * indirectly a dependency of the anchor job via paths that
69          * are fully marked as mattering. */
70
71         j->matters_to_anchor = true;
72         j->generation = generation;
73
74         LIST_FOREACH(subject, l, j->subject_list) {
75
76                 /* This link does not matter */
77                 if (!l->matters)
78                         continue;
79
80                 /* This unit has already been marked */
81                 if (l->object->generation == generation)
82                         continue;
83
84                 transaction_find_jobs_that_matter_to_anchor(l->object, generation);
85         }
86 }
87
88 static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other, JobType t) {
89         JobDependency *l, *last;
90
91         assert(j);
92         assert(other);
93         assert(j->unit == other->unit);
94         assert(!j->installed);
95
96         /* Merges 'other' into 'j' and then deletes 'other'. */
97
98         j->type = t;
99         j->state = JOB_WAITING;
100         j->override = j->override || other->override;
101         j->irreversible = j->irreversible || other->irreversible;
102
103         j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor;
104
105         /* Patch us in as new owner of the JobDependency objects */
106         last = NULL;
107         LIST_FOREACH(subject, l, other->subject_list) {
108                 assert(l->subject == other);
109                 l->subject = j;
110                 last = l;
111         }
112
113         /* Merge both lists */
114         if (last) {
115                 last->subject_next = j->subject_list;
116                 if (j->subject_list)
117                         j->subject_list->subject_prev = last;
118                 j->subject_list = other->subject_list;
119         }
120
121         /* Patch us in as new owner of the JobDependency objects */
122         last = NULL;
123         LIST_FOREACH(object, l, other->object_list) {
124                 assert(l->object == other);
125                 l->object = j;
126                 last = l;
127         }
128
129         /* Merge both lists */
130         if (last) {
131                 last->object_next = j->object_list;
132                 if (j->object_list)
133                         j->object_list->object_prev = last;
134                 j->object_list = other->object_list;
135         }
136
137         /* Kill the other job */
138         other->subject_list = NULL;
139         other->object_list = NULL;
140         transaction_delete_job(tr, other, true);
141 }
142
143 _pure_ static bool job_is_conflicted_by(Job *j) {
144         JobDependency *l;
145
146         assert(j);
147
148         /* Returns true if this job is pulled in by a least one
149          * ConflictedBy dependency. */
150
151         LIST_FOREACH(object, l, j->object_list)
152                 if (l->conflicts)
153                         return true;
154
155         return false;
156 }
157
158 static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
159         Job *k;
160
161         assert(j);
162
163         /* Tries to delete one item in the linked list
164          * j->transaction_next->transaction_next->... that conflicts
165          * with another one, in an attempt to make an inconsistent
166          * transaction work. */
167
168         /* We rely here on the fact that if a merged with b does not
169          * merge with c, either a or b merge with c neither */
170         LIST_FOREACH(transaction, j, j)
171                 LIST_FOREACH(transaction, k, j->transaction_next) {
172                         Job *d;
173
174                         /* Is this one mergeable? Then skip it */
175                         if (job_type_is_mergeable(j->type, k->type))
176                                 continue;
177
178                         /* Ok, we found two that conflict, let's see if we can
179                          * drop one of them */
180                         if (!j->matters_to_anchor && !k->matters_to_anchor) {
181
182                                 /* Both jobs don't matter, so let's
183                                  * find the one that is smarter to
184                                  * remove. Let's think positive and
185                                  * rather remove stops then starts --
186                                  * except if something is being
187                                  * stopped because it is conflicted by
188                                  * another unit in which case we
189                                  * rather remove the start. */
190
191                                 log_unit_debug(j->unit->id,
192                                                "Looking at job %s/%s conflicted_by=%s",
193                                                j->unit->id, job_type_to_string(j->type),
194                                                yes_no(j->type == JOB_STOP && job_is_conflicted_by(j)));
195                                 log_unit_debug(k->unit->id,
196                                                "Looking at job %s/%s conflicted_by=%s",
197                                                k->unit->id, job_type_to_string(k->type),
198                                                yes_no(k->type == JOB_STOP && job_is_conflicted_by(k)));
199
200                                 if (j->type == JOB_STOP) {
201
202                                         if (job_is_conflicted_by(j))
203                                                 d = k;
204                                         else
205                                                 d = j;
206
207                                 } else if (k->type == JOB_STOP) {
208
209                                         if (job_is_conflicted_by(k))
210                                                 d = j;
211                                         else
212                                                 d = k;
213                                 } else
214                                         d = j;
215
216                         } else if (!j->matters_to_anchor)
217                                 d = j;
218                         else if (!k->matters_to_anchor)
219                                 d = k;
220                         else
221                                 return -ENOEXEC;
222
223                         /* Ok, we can drop one, so let's do so. */
224                         log_unit_debug(d->unit->id,
225                                        "Fixing conflicting jobs %s/%s,%s/%s by deleting job %s/%s",
226                                        j->unit->id, job_type_to_string(j->type),
227                                        k->unit->id, job_type_to_string(k->type),
228                                        d->unit->id, job_type_to_string(d->type));
229                         transaction_delete_job(tr, d, true);
230                         return 0;
231                 }
232
233         return -EINVAL;
234 }
235
236 static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
237         Job *j;
238         Iterator i;
239         int r;
240
241         assert(tr);
242
243         /* First step, check whether any of the jobs for one specific
244          * task conflict. If so, try to drop one of them. */
245         HASHMAP_FOREACH(j, tr->jobs, i) {
246                 JobType t;
247                 Job *k;
248
249                 t = j->type;
250                 LIST_FOREACH(transaction, k, j->transaction_next) {
251                         if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0)
252                                 continue;
253
254                         /* OK, we could not merge all jobs for this
255                          * action. Let's see if we can get rid of one
256                          * of them */
257
258                         r = delete_one_unmergeable_job(tr, j);
259                         if (r >= 0)
260                                 /* Ok, we managed to drop one, now
261                                  * let's ask our callers to call us
262                                  * again after garbage collecting */
263                                 return -EAGAIN;
264
265                         /* We couldn't merge anything. Failure */
266                         return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING,
267                                                  "Transaction contains conflicting jobs '%s' and '%s' for %s. "
268                                                  "Probably contradicting requirement dependencies configured.",
269                                                  job_type_to_string(t),
270                                                  job_type_to_string(k->type),
271                                                  k->unit->id);
272                 }
273         }
274
275         /* Second step, merge the jobs. */
276         HASHMAP_FOREACH(j, tr->jobs, i) {
277                 JobType t = j->type;
278                 Job *k;
279
280                 /* Merge all transaction jobs for j->unit */
281                 LIST_FOREACH(transaction, k, j->transaction_next)
282                         assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0);
283
284                 while ((k = j->transaction_next)) {
285                         if (tr->anchor_job == k) {
286                                 transaction_merge_and_delete_job(tr, k, j, t);
287                                 j = k;
288                         } else
289                                 transaction_merge_and_delete_job(tr, j, k, t);
290                 }
291
292                 assert(!j->transaction_next);
293                 assert(!j->transaction_prev);
294         }
295
296         return 0;
297 }
298
299 static void transaction_drop_redundant(Transaction *tr) {
300         Job *j;
301         Iterator i;
302
303         /* Goes through the transaction and removes all jobs of the units
304          * whose jobs are all noops. If not all of a unit's jobs are
305          * redundant, they are kept. */
306
307         assert(tr);
308
309 rescan:
310         HASHMAP_FOREACH(j, tr->jobs, i) {
311                 Job *k;
312
313                 LIST_FOREACH(transaction, k, j) {
314
315                         if (tr->anchor_job == k ||
316                             !job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
317                             (k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type)))
318                                 goto next_unit;
319                 }
320
321                 /* log_debug("Found redundant job %s/%s, dropping.", j->unit->id, job_type_to_string(j->type)); */
322                 transaction_delete_job(tr, j, false);
323                 goto rescan;
324         next_unit:;
325         }
326 }
327
328 _pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
329         assert(u);
330         assert(!j->transaction_prev);
331
332         /* Checks whether at least one of the jobs for this unit
333          * matters to the anchor. */
334
335         LIST_FOREACH(transaction, j, j)
336                 if (j->matters_to_anchor)
337                         return true;
338
339         return false;
340 }
341
342 static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) {
343         Iterator i;
344         Unit *u;
345         int r;
346
347         assert(tr);
348         assert(j);
349         assert(!j->transaction_prev);
350
351         /* Does a recursive sweep through the ordering graph, looking
352          * for a cycle. If we find a cycle we try to break it. */
353
354         /* Have we seen this before? */
355         if (j->generation == generation) {
356                 Job *k, *delete;
357
358                 /* If the marker is NULL we have been here already and
359                  * decided the job was loop-free from here. Hence
360                  * shortcut things and return right-away. */
361                 if (!j->marker)
362                         return 0;
363
364                 /* So, the marker is not NULL and we already have been
365                  * here. We have a cycle. Let's try to break it. We go
366                  * backwards in our path and try to find a suitable
367                  * job to remove. We use the marker to find our way
368                  * back, since smart how we are we stored our way back
369                  * in there. */
370                 log_unit_warning(j->unit->id,
371                                  "Found ordering cycle on %s/%s",
372                                  j->unit->id, job_type_to_string(j->type));
373
374                 delete = NULL;
375                 for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) {
376
377                         /* logging for j not k here here to provide consistent narrative */
378                         log_unit_warning(j->unit->id,
379                                          "Found dependency on %s/%s",
380                                          k->unit->id, job_type_to_string(k->type));
381
382                         if (!delete && hashmap_get(tr->jobs, k->unit) &&
383                             !unit_matters_to_anchor(k->unit, k)) {
384                                 /* Ok, we can drop this one, so let's
385                                  * do so. */
386                                 delete = k;
387                         }
388
389                         /* Check if this in fact was the beginning of
390                          * the cycle */
391                         if (k == j)
392                                 break;
393                 }
394
395
396                 if (delete) {
397                         /* logging for j not k here here to provide consistent narrative */
398                         log_unit_warning(j->unit->id,
399                                          "Breaking ordering cycle by deleting job %s/%s",
400                                          delete->unit->id, job_type_to_string(delete->type));
401                         log_unit_error(delete->unit->id,
402                                        "Job %s/%s deleted to break ordering cycle starting with %s/%s",
403                                        delete->unit->id, job_type_to_string(delete->type),
404                                        j->unit->id, job_type_to_string(j->type));
405                         unit_status_printf(delete->unit, ANSI_HIGHLIGHT_RED_ON " SKIP " ANSI_HIGHLIGHT_OFF,
406                                            "Ordering cycle found, skipping %s");
407                         transaction_delete_unit(tr, delete->unit);
408                         return -EAGAIN;
409                 }
410
411                 log_error("Unable to break cycle");
412
413                 return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
414                                          "Transaction order is cyclic. See system logs for details.");
415         }
416
417         /* Make the marker point to where we come from, so that we can
418          * find our way backwards if we want to break a cycle. We use
419          * a special marker for the beginning: we point to
420          * ourselves. */
421         j->marker = from ? from : j;
422         j->generation = generation;
423
424         /* We assume that the dependencies are bidirectional, and
425          * hence can ignore UNIT_AFTER */
426         SET_FOREACH(u, j->unit->dependencies[UNIT_BEFORE], i) {
427                 Job *o;
428
429                 /* Is there a job for this unit? */
430                 o = hashmap_get(tr->jobs, u);
431                 if (!o) {
432                         /* Ok, there is no job for this in the
433                          * transaction, but maybe there is already one
434                          * running? */
435                         o = u->job;
436                         if (!o)
437                                 continue;
438                 }
439
440                 r = transaction_verify_order_one(tr, o, j, generation, e);
441                 if (r < 0)
442                         return r;
443         }
444
445         /* Ok, let's backtrack, and remember that this entry is not on
446          * our path anymore. */
447         j->marker = NULL;
448
449         return 0;
450 }
451
452 static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) {
453         Job *j;
454         int r;
455         Iterator i;
456         unsigned g;
457
458         assert(tr);
459         assert(generation);
460
461         /* Check if the ordering graph is cyclic. If it is, try to fix
462          * that up by dropping one of the jobs. */
463
464         g = (*generation)++;
465
466         HASHMAP_FOREACH(j, tr->jobs, i)
467                 if ((r = transaction_verify_order_one(tr, j, NULL, g, e)) < 0)
468                         return r;
469
470         return 0;
471 }
472
473 static void transaction_collect_garbage(Transaction *tr) {
474         Iterator i;
475         Job *j;
476
477         assert(tr);
478
479         /* Drop jobs that are not required by any other job */
480
481 rescan:
482         HASHMAP_FOREACH(j, tr->jobs, i) {
483                 if (tr->anchor_job == j || j->object_list) {
484                         /* log_debug("Keeping job %s/%s because of %s/%s", */
485                         /*           j->unit->id, job_type_to_string(j->type), */
486                         /*           j->object_list->subject ? j->object_list->subject->unit->id : "root", */
487                         /*           j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); */
488                         continue;
489                 }
490
491                 /* log_debug("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); */
492                 transaction_delete_job(tr, j, true);
493                 goto rescan;
494         }
495 }
496
497 static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) {
498         Iterator i;
499         Job *j;
500
501         assert(tr);
502
503         /* Checks whether applying this transaction means that
504          * existing jobs would be replaced */
505
506         HASHMAP_FOREACH(j, tr->jobs, i) {
507
508                 /* Assume merged */
509                 assert(!j->transaction_prev);
510                 assert(!j->transaction_next);
511
512                 if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
513                     job_type_is_conflicting(j->unit->job->type, j->type))
514                         return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,
515                                                  "Transaction is destructive.");
516         }
517
518         return 0;
519 }
520
521 static void transaction_minimize_impact(Transaction *tr) {
522         Job *j;
523         Iterator i;
524
525         assert(tr);
526
527         /* Drops all unnecessary jobs that reverse already active jobs
528          * or that stop a running service. */
529
530 rescan:
531         HASHMAP_FOREACH(j, tr->jobs, i) {
532                 LIST_FOREACH(transaction, j, j) {
533                         bool stops_running_service, changes_existing_job;
534
535                         /* If it matters, we shouldn't drop it */
536                         if (j->matters_to_anchor)
537                                 continue;
538
539                         /* Would this stop a running service?
540                          * Would this change an existing job?
541                          * If so, let's drop this entry */
542
543                         stops_running_service =
544                                 j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit));
545
546                         changes_existing_job =
547                                 j->unit->job &&
548                                 job_type_is_conflicting(j->type, j->unit->job->type);
549
550                         if (!stops_running_service && !changes_existing_job)
551                                 continue;
552
553                         if (stops_running_service)
554                                 log_unit_debug(j->unit->id,
555                                                "%s/%s would stop a running service.",
556                                                j->unit->id, job_type_to_string(j->type));
557
558                         if (changes_existing_job)
559                                 log_unit_debug(j->unit->id,
560                                                "%s/%s would change existing job.",
561                                                j->unit->id, job_type_to_string(j->type));
562
563                         /* Ok, let's get rid of this */
564                         log_unit_debug(j->unit->id,
565                                        "Deleting %s/%s to minimize impact.",
566                                        j->unit->id, job_type_to_string(j->type));
567
568                         transaction_delete_job(tr, j, true);
569                         goto rescan;
570                 }
571         }
572 }
573
574 static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
575         Iterator i;
576         Job *j;
577         int r;
578
579         /* Moves the transaction jobs to the set of active jobs */
580
581         if (mode == JOB_ISOLATE || mode == JOB_FLUSH) {
582
583                 /* When isolating first kill all installed jobs which
584                  * aren't part of the new transaction */
585                 HASHMAP_FOREACH(j, m->jobs, i) {
586                         assert(j->installed);
587
588                         if (hashmap_get(tr->jobs, j->unit))
589                                 continue;
590
591                         /* Not invalidating recursively. Avoids triggering
592                          * OnFailure= actions of dependent jobs. Also avoids
593                          * invalidating our iterator. */
594                         job_finish_and_invalidate(j, JOB_CANCELED, false);
595                 }
596         }
597
598         HASHMAP_FOREACH(j, tr->jobs, i) {
599                 /* Assume merged */
600                 assert(!j->transaction_prev);
601                 assert(!j->transaction_next);
602
603                 r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j);
604                 if (r < 0)
605                         goto rollback;
606         }
607
608         while ((j = hashmap_steal_first(tr->jobs))) {
609                 Job *installed_job;
610
611                 /* Clean the job dependencies */
612                 transaction_unlink_job(tr, j, false);
613
614                 installed_job = job_install(j);
615                 if (installed_job != j) {
616                         /* j has been merged into a previously installed job */
617                         if (tr->anchor_job == j)
618                                 tr->anchor_job = installed_job;
619                         hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
620                         job_free(j);
621                         j = installed_job;
622                 }
623
624                 job_add_to_run_queue(j);
625                 job_add_to_dbus_queue(j);
626                 job_start_timer(j);
627                 job_shutdown_magic(j);
628         }
629
630         return 0;
631
632 rollback:
633
634         HASHMAP_FOREACH(j, tr->jobs, i)
635                 hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
636
637         return r;
638 }
639
640 int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) {
641         Iterator i;
642         Job *j;
643         int r;
644         unsigned generation = 1;
645
646         assert(tr);
647
648         /* This applies the changes recorded in tr->jobs to
649          * the actual list of jobs, if possible. */
650
651         /* Reset the generation counter of all installed jobs. The detection of cycles
652          * looks at installed jobs. If they had a non-zero generation from some previous
653          * walk of the graph, the algorithm would break. */
654         HASHMAP_FOREACH(j, m->jobs, i)
655                 j->generation = 0;
656
657         /* First step: figure out which jobs matter */
658         transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++);
659
660         /* Second step: Try not to stop any running services if
661          * we don't have to. Don't try to reverse running
662          * jobs if we don't have to. */
663         if (mode == JOB_FAIL)
664                 transaction_minimize_impact(tr);
665
666         /* Third step: Drop redundant jobs */
667         transaction_drop_redundant(tr);
668
669         for (;;) {
670                 /* Fourth step: Let's remove unneeded jobs that might
671                  * be lurking. */
672                 if (mode != JOB_ISOLATE)
673                         transaction_collect_garbage(tr);
674
675                 /* Fifth step: verify order makes sense and correct
676                  * cycles if necessary and possible */
677                 r = transaction_verify_order(tr, &generation, e);
678                 if (r >= 0)
679                         break;
680
681                 if (r != -EAGAIN) {
682                         log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r));
683                         return r;
684                 }
685
686                 /* Let's see if the resulting transaction ordering
687                  * graph is still cyclic... */
688         }
689
690         for (;;) {
691                 /* Sixth step: let's drop unmergeable entries if
692                  * necessary and possible, merge entries we can
693                  * merge */
694                 r = transaction_merge_jobs(tr, e);
695                 if (r >= 0)
696                         break;
697
698                 if (r != -EAGAIN) {
699                         log_warning("Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r));
700                         return r;
701                 }
702
703                 /* Seventh step: an entry got dropped, let's garbage
704                  * collect its dependencies. */
705                 if (mode != JOB_ISOLATE)
706                         transaction_collect_garbage(tr);
707
708                 /* Let's see if the resulting transaction still has
709                  * unmergeable entries ... */
710         }
711
712         /* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
713         transaction_drop_redundant(tr);
714
715         /* Ninth step: check whether we can actually apply this */
716         r = transaction_is_destructive(tr, mode, e);
717         if (r < 0) {
718                 log_notice("Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
719                 return r;
720         }
721
722         /* Tenth step: apply changes */
723         r = transaction_apply(tr, m, mode);
724         if (r < 0)
725                 return log_warning_errno(r, "Failed to apply transaction: %m");
726
727         assert(hashmap_isempty(tr->jobs));
728
729         if (!hashmap_isempty(m->jobs)) {
730                 /* Are there any jobs now? Then make sure we have the
731                  * idle pipe around. We don't really care too much
732                  * whether this works or not, as the idle pipe is a
733                  * feature for cosmetics, not actually useful for
734                  * anything beyond that. */
735
736                 if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 &&
737                     m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) {
738                         pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
739                         pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC);
740                 }
741         }
742
743         return 0;
744 }
745
746 static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool override, bool *is_new) {
747         Job *j, *f;
748
749         assert(tr);
750         assert(unit);
751
752         /* Looks for an existing prospective job and returns that. If
753          * it doesn't exist it is created and added to the prospective
754          * jobs list. */
755
756         f = hashmap_get(tr->jobs, unit);
757
758         LIST_FOREACH(transaction, j, f) {
759                 assert(j->unit == unit);
760
761                 if (j->type == type) {
762                         if (is_new)
763                                 *is_new = false;
764                         return j;
765                 }
766         }
767
768         j = job_new(unit, type);
769         if (!j)
770                 return NULL;
771
772         j->generation = 0;
773         j->marker = NULL;
774         j->matters_to_anchor = false;
775         j->override = override;
776         j->irreversible = tr->irreversible;
777
778         LIST_PREPEND(transaction, f, j);
779
780         if (hashmap_replace(tr->jobs, unit, f) < 0) {
781                 LIST_REMOVE(transaction, f, j);
782                 job_free(j);
783                 return NULL;
784         }
785
786         if (is_new)
787                 *is_new = true;
788
789         /* log_debug("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); */
790
791         return j;
792 }
793
794 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) {
795         assert(tr);
796         assert(j);
797
798         if (j->transaction_prev)
799                 j->transaction_prev->transaction_next = j->transaction_next;
800         else if (j->transaction_next)
801                 hashmap_replace(tr->jobs, j->unit, j->transaction_next);
802         else
803                 hashmap_remove_value(tr->jobs, j->unit, j);
804
805         if (j->transaction_next)
806                 j->transaction_next->transaction_prev = j->transaction_prev;
807
808         j->transaction_prev = j->transaction_next = NULL;
809
810         while (j->subject_list)
811                 job_dependency_free(j->subject_list);
812
813         while (j->object_list) {
814                 Job *other = j->object_list->matters ? j->object_list->subject : NULL;
815
816                 job_dependency_free(j->object_list);
817
818                 if (other && delete_dependencies) {
819                         log_unit_debug(other->unit->id,
820                                        "Deleting job %s/%s as dependency of job %s/%s",
821                                        other->unit->id, job_type_to_string(other->type),
822                                        j->unit->id, job_type_to_string(j->type));
823                         transaction_delete_job(tr, other, delete_dependencies);
824                 }
825         }
826 }
827
828 int transaction_add_job_and_dependencies(
829                 Transaction *tr,
830                 JobType type,
831                 Unit *unit,
832                 Job *by,
833                 bool matters,
834                 bool override,
835                 bool conflicts,
836                 bool ignore_requirements,
837                 bool ignore_order,
838                 sd_bus_error *e) {
839         Job *ret;
840         Iterator i;
841         Unit *dep;
842         int r;
843         bool is_new;
844
845         assert(tr);
846         assert(type < _JOB_TYPE_MAX);
847         assert(type < _JOB_TYPE_MAX_IN_TRANSACTION);
848         assert(unit);
849
850         /* log_debug("Pulling in %s/%s from %s/%s", */
851         /*           unit->id, job_type_to_string(type), */
852         /*           by ? by->unit->id : "NA", */
853         /*           by ? job_type_to_string(by->type) : "NA"); */
854
855         if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_MASKED))
856                 return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
857                                          "Unit %s is not loaded properly.", unit->id);
858
859         if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
860                 if (unit->load_error == -ENOENT || unit->manager->test_run)
861                         return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
862                                                  "Unit %s failed to load: %s.",
863                                                  unit->id,
864                                                  strerror(-unit->load_error));
865                 else
866                         return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
867                                                  "Unit %s failed to load: %s. "
868                                                  "See system logs and 'systemctl status %s' for details.",
869                                                  unit->id,
870                                                  strerror(-unit->load_error),
871                                                  unit->id);
872         }
873
874         if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND)
875                 return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
876                                          "Unit %s failed to load: %s.",
877                                          unit->id, strerror(-unit->load_error));
878
879         if (type != JOB_STOP && unit->load_state == UNIT_MASKED)
880                 return sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED,
881                                          "Unit %s is masked.", unit->id);
882
883         if (!unit_job_is_applicable(unit, type))
884                 return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
885                                          "Job type %s is not applicable for unit %s.",
886                                          job_type_to_string(type), unit->id);
887
888
889         /* First add the job. */
890         ret = transaction_add_one_job(tr, type, unit, override, &is_new);
891         if (!ret)
892                 return -ENOMEM;
893
894         ret->ignore_order = ret->ignore_order || ignore_order;
895
896         /* Then, add a link to the job. */
897         if (by) {
898                 if (!job_dependency_new(by, ret, matters, conflicts))
899                         return -ENOMEM;
900         } else {
901                 /* If the job has no parent job, it is the anchor job. */
902                 assert(!tr->anchor_job);
903                 tr->anchor_job = ret;
904         }
905
906         if (is_new && !ignore_requirements && type != JOB_NOP) {
907                 Set *following;
908
909                 /* If we are following some other unit, make sure we
910                  * add all dependencies of everybody following. */
911                 if (unit_following_set(ret->unit, &following) > 0) {
912                         SET_FOREACH(dep, following, i) {
913                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, override, false, false, ignore_order, e);
914                                 if (r < 0) {
915                                         log_unit_warning(dep->id,
916                                                          "Cannot add dependency job for unit %s, ignoring: %s",
917                                                          dep->id, bus_error_message(e, r));
918
919                                         if (e)
920                                                 sd_bus_error_free(e);
921                                 }
922                         }
923
924                         set_free(following);
925                 }
926
927                 /* Finally, recursively add in all dependencies. */
928                 if (type == JOB_START || type == JOB_RESTART) {
929                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
930                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
931                                 if (r < 0) {
932                                         if (r != -EBADR)
933                                                 goto fail;
934
935                                         if (e)
936                                                 sd_bus_error_free(e);
937                                 }
938                         }
939
940                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
941                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e);
942                                 if (r < 0) {
943                                         if (r != -EBADR)
944                                                 goto fail;
945
946                                         if (e)
947                                                 sd_bus_error_free(e);
948                                 }
949                         }
950
951                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES_OVERRIDABLE], i) {
952                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, !override, override, false, false, ignore_order, e);
953                                 if (r < 0) {
954                                         log_unit_full(dep->id,
955                                                       r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
956                                                       "Cannot add dependency job for unit %s, ignoring: %s",
957                                                       dep->id, bus_error_message(e, r));
958
959                                         if (e)
960                                                 sd_bus_error_free(e);
961                                 }
962                         }
963
964                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
965                                 r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, false, ignore_order, e);
966                                 if (r < 0) {
967                                         log_unit_full(dep->id,
968                                                       r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
969                                                       "Cannot add dependency job for unit %s, ignoring: %s",
970                                                       dep->id, bus_error_message(e, r));
971
972                                         if (e)
973                                                 sd_bus_error_free(e);
974                                 }
975                         }
976
977                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
978                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, override, false, false, ignore_order, e);
979                                 if (r < 0) {
980                                         if (r != -EBADR)
981                                                 goto fail;
982
983                                         if (e)
984                                                 sd_bus_error_free(e);
985                                 }
986                         }
987
988                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE_OVERRIDABLE], i) {
989                                 r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, !override, override, false, false, ignore_order, e);
990                                 if (r < 0) {
991                                         log_unit_full(dep->id,
992                                                       r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING,
993                                                       "Cannot add dependency job for unit %s, ignoring: %s",
994                                                       dep->id, bus_error_message(e, r));
995
996                                         if (e)
997                                                 sd_bus_error_free(e);
998                                 }
999                         }
1000
1001                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
1002                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, override, true, false, ignore_order, e);
1003                                 if (r < 0) {
1004                                         if (r != -EBADR)
1005                                                 goto fail;
1006
1007                                         if (e)
1008                                                 sd_bus_error_free(e);
1009                                 }
1010                         }
1011
1012                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) {
1013                                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, override, false, false, ignore_order, e);
1014                                 if (r < 0) {
1015                                         log_unit_warning(dep->id,
1016                                                          "Cannot add dependency job for unit %s, ignoring: %s",
1017                                                          dep->id, bus_error_message(e, r));
1018
1019                                         if (e)
1020                                                 sd_bus_error_free(e);
1021                                 }
1022                         }
1023
1024                 }
1025
1026                 if (type == JOB_STOP || type == JOB_RESTART) {
1027
1028                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRED_BY], i) {
1029                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1030                                 if (r < 0) {
1031                                         if (r != -EBADR)
1032                                                 goto fail;
1033
1034                                         if (e)
1035                                                 sd_bus_error_free(e);
1036                                 }
1037                         }
1038
1039                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_BOUND_BY], i) {
1040                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1041                                 if (r < 0) {
1042                                         if (r != -EBADR)
1043                                                 goto fail;
1044
1045                                         if (e)
1046                                                 sd_bus_error_free(e);
1047                                 }
1048                         }
1049
1050                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONSISTS_OF], i) {
1051                                 r = transaction_add_job_and_dependencies(tr, type, dep, ret, true, override, false, false, ignore_order, e);
1052                                 if (r < 0) {
1053                                         if (r != -EBADR)
1054                                                 goto fail;
1055
1056                                         if (e)
1057                                                 sd_bus_error_free(e);
1058                                 }
1059                         }
1060
1061                 }
1062
1063                 if (type == JOB_RELOAD) {
1064
1065                         SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
1066                                 r = transaction_add_job_and_dependencies(tr, JOB_RELOAD, dep, ret, false, override, false, false, ignore_order, e);
1067                                 if (r < 0) {
1068                                         log_unit_warning(dep->id,
1069                                                          "Cannot add dependency reload job for unit %s, ignoring: %s",
1070                                                          dep->id, bus_error_message(e, r));
1071
1072                                         if (e)
1073                                                 sd_bus_error_free(e);
1074                                 }
1075                         }
1076                 }
1077
1078                 /* JOB_VERIFY_STARTED require no dependency handling */
1079         }
1080
1081         return 0;
1082
1083 fail:
1084         return r;
1085 }
1086
1087 int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
1088         Iterator i;
1089         Unit *u;
1090         char *k;
1091         int r;
1092
1093         assert(tr);
1094         assert(m);
1095
1096         HASHMAP_FOREACH_KEY(u, k, m->units, i) {
1097
1098                 /* ignore aliases */
1099                 if (u->id != k)
1100                         continue;
1101
1102                 if (u->ignore_on_isolate)
1103                         continue;
1104
1105                 /* No need to stop inactive jobs */
1106                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job)
1107                         continue;
1108
1109                 /* Is there already something listed for this? */
1110                 if (hashmap_get(tr->jobs, u))
1111                         continue;
1112
1113                 r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, false, NULL);
1114                 if (r < 0)
1115                         log_unit_warning(u->id,
1116                                          "Cannot add isolate job for unit %s, ignoring: %s",
1117                                          u->id, strerror(-r));
1118         }
1119
1120         return 0;
1121 }
1122
1123 Transaction *transaction_new(bool irreversible) {
1124         Transaction *tr;
1125
1126         tr = new0(Transaction, 1);
1127         if (!tr)
1128                 return NULL;
1129
1130         tr->jobs = hashmap_new(NULL);
1131         if (!tr->jobs) {
1132                 free(tr);
1133                 return NULL;
1134         }
1135
1136         tr->irreversible = irreversible;
1137
1138         return tr;
1139 }
1140
1141 void transaction_free(Transaction *tr) {
1142         assert(hashmap_isempty(tr->jobs));
1143         hashmap_free(tr->jobs);
1144         free(tr);
1145 }