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