unit.c 53.1 KB
Newer Older
Lennart Poettering's avatar
Lennart Poettering committed
1
2
/*-*- Mode: C; c-basic-offset: 8 -*-*/

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***
  This file is part of systemd.

  Copyright 2010 Lennart Poettering

  systemd is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  systemd is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

Lennart Poettering's avatar
Lennart Poettering committed
22
23
24
25
26
27
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/poll.h>
28
29
#include <stdlib.h>
#include <unistd.h>
Lennart Poettering's avatar
Lennart Poettering committed
30
31
32
33
34
35
36
37

#include "set.h"
#include "unit.h"
#include "macro.h"
#include "strv.h"
#include "load-fragment.h"
#include "load-dropin.h"
#include "log.h"
38
39
#include "unit-name.h"
#include "specifier.h"
40
#include "dbus-unit.h"
Lennart Poettering's avatar
Lennart Poettering committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
        [UNIT_SERVICE] = &service_vtable,
        [UNIT_TIMER] = &timer_vtable,
        [UNIT_SOCKET] = &socket_vtable,
        [UNIT_TARGET] = &target_vtable,
        [UNIT_DEVICE] = &device_vtable,
        [UNIT_MOUNT] = &mount_vtable,
        [UNIT_AUTOMOUNT] = &automount_vtable,
        [UNIT_SNAPSHOT] = &snapshot_vtable
};

Unit *unit_new(Manager *m) {
        Unit *u;

        assert(m);

        if (!(u = new0(Unit, 1)))
                return NULL;

        if (!(u->meta.names = set_new(string_hash_func, string_compare_func))) {
                free(u);
                return NULL;
        }

        u->meta.manager = m;
        u->meta.type = _UNIT_TYPE_INVALID;

        return u;
}

72
73
74
75
76
77
78
bool unit_has_name(Unit *u, const char *name) {
        assert(u);
        assert(name);

        return !!set_get(u->meta.names, (char*) name);
}

Lennart Poettering's avatar
Lennart Poettering committed
79
80
int unit_add_name(Unit *u, const char *text) {
        UnitType t;
81
        char *s = NULL, *i = NULL;
Lennart Poettering's avatar
Lennart Poettering committed
82
83
84
85
86
        int r;

        assert(u);
        assert(text);

87
88
89
        if (unit_name_is_template(text)) {
                if (!u->meta.instance)
                        return -EINVAL;
Lennart Poettering's avatar
Lennart Poettering committed
90

91
92
93
                s = unit_name_replace_instance(text, u->meta.instance);
        } else
                s = strdup(text);
Lennart Poettering's avatar
Lennart Poettering committed
94

95
96
        if (!s)
                return -ENOMEM;
Lennart Poettering's avatar
Lennart Poettering committed
97

98
99
100
101
        if (!unit_name_is_valid(s)) {
                r = -EINVAL;
                goto fail;
        }
102

103
        assert_se((t = unit_name_to_type(s)) >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
104

105
106
107
108
        if (u->meta.type != _UNIT_TYPE_INVALID && t != u->meta.type) {
                r = -EINVAL;
                goto fail;
        }
Lennart Poettering's avatar
Lennart Poettering committed
109

110
111
        if ((r = unit_name_to_instance(s, &i)) < 0)
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
112

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
        if (i && unit_vtable[t]->no_instances)
                goto fail;

        if (u->meta.type != _UNIT_TYPE_INVALID && !streq_ptr(u->meta.instance, i)) {
                r = -EINVAL;
                goto fail;
        }

        if (unit_vtable[t]->no_alias &&
            !set_isempty(u->meta.names) &&
            !set_get(u->meta.names, s)) {
                r = -EEXIST;
                goto fail;
        }

128
129
130
131
132
        if (hashmap_size(u->meta.manager->units) >= MANAGER_MAX_NAMES) {
                r = -E2BIG;
                goto fail;
        }

133
134
135
136
        if ((r = set_put(u->meta.names, s)) < 0) {
                if (r == -EEXIST)
                        r = 0;
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
137
138
139
140
        }

        if ((r = hashmap_put(u->meta.manager->units, s, u)) < 0) {
                set_remove(u->meta.names, s);
141
                goto fail;
Lennart Poettering's avatar
Lennart Poettering committed
142
143
        }

144
        if (u->meta.type == _UNIT_TYPE_INVALID) {
Lennart Poettering's avatar
Lennart Poettering committed
145

146
                u->meta.type = t;
147
148
149
150
                u->meta.id = s;
                u->meta.instance = i;

                LIST_PREPEND(Meta, units_per_type, u->meta.manager->units_per_type[t], &u->meta);
151
152
153

                if (UNIT_VTABLE(u)->init)
                        UNIT_VTABLE(u)->init(u);
154
155
        } else
                free(i);
Lennart Poettering's avatar
Lennart Poettering committed
156

157
        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
158
        return 0;
159
160
161
162
163
164

fail:
        free(s);
        free(i);

        return r;
Lennart Poettering's avatar
Lennart Poettering committed
165
166
}

167
int unit_choose_id(Unit *u, const char *name) {
168
        char *s, *t = NULL;
169
170
171
172

        assert(u);
        assert(name);

173
174
175
176
177
178
179
180
181
182
183
        if (unit_name_is_template(name)) {

                if (!u->meta.instance)
                        return -EINVAL;

                if (!(t = unit_name_replace_instance(name, u->meta.instance)))
                        return -ENOMEM;

                name = t;
        }

184
        /* Selects one of the names of this unit as the id */
185
186
        s = set_get(u->meta.names, (char*) name);
        free(t);
187

188
        if (!s)
189
190
191
                return -ENOENT;

        u->meta.id = s;
192
        unit_add_to_dbus_queue(u);
193

194
195
196
        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
197
198
199
200
201
202
203
204
205
206
int unit_set_description(Unit *u, const char *description) {
        char *s;

        assert(u);

        if (!(s = strdup(description)))
                return -ENOMEM;

        free(u->meta.description);
        u->meta.description = s;
207
208

        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
209
210
211
        return 0;
}

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
bool unit_check_gc(Unit *u) {
        assert(u);

        if (UNIT_VTABLE(u)->no_gc)
                return true;

        if (u->meta.job)
                return true;

        if (unit_active_state(u) != UNIT_INACTIVE)
                return true;

        if (UNIT_VTABLE(u)->check_gc)
                if (UNIT_VTABLE(u)->check_gc(u))
                        return true;

        return false;
}

Lennart Poettering's avatar
Lennart Poettering committed
231
232
void unit_add_to_load_queue(Unit *u) {
        assert(u);
233
        assert(u->meta.type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
234
235
236
237
238
239
240
241

        if (u->meta.load_state != UNIT_STUB || u->meta.in_load_queue)
                return;

        LIST_PREPEND(Meta, load_queue, u->meta.manager->load_queue, &u->meta);
        u->meta.in_load_queue = true;
}

242
243
244
245
246
247
248
249
250
251
void unit_add_to_cleanup_queue(Unit *u) {
        assert(u);

        if (u->meta.in_cleanup_queue)
                return;

        LIST_PREPEND(Meta, cleanup_queue, u->meta.manager->cleanup_queue, &u->meta);
        u->meta.in_cleanup_queue = true;
}

252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
void unit_add_to_gc_queue(Unit *u) {
        assert(u);

        if (u->meta.in_gc_queue || u->meta.in_cleanup_queue)
                return;

        if (unit_check_gc(u))
                return;

        LIST_PREPEND(Meta, gc_queue, u->meta.manager->gc_queue, &u->meta);
        u->meta.in_gc_queue = true;

        u->meta.manager->n_in_gc_queue ++;

        if (u->meta.manager->gc_queue_timestamp <= 0)
                u->meta.manager->gc_queue_timestamp = now(CLOCK_MONOTONIC);
}

270
271
void unit_add_to_dbus_queue(Unit *u) {
        assert(u);
272
        assert(u->meta.type != _UNIT_TYPE_INVALID);
273
274
275
276
277
278
279
280

        if (u->meta.load_state == UNIT_STUB || u->meta.in_dbus_queue || set_isempty(u->meta.manager->subscribed))
                return;

        LIST_PREPEND(Meta, dbus_queue, u->meta.manager->dbus_unit_queue, &u->meta);
        u->meta.in_dbus_queue = true;
}

Lennart Poettering's avatar
Lennart Poettering committed
281
282
283
284
285
286
287
288
289
290
291
292
293
294
static void bidi_set_free(Unit *u, Set *s) {
        Iterator i;
        Unit *other;

        assert(u);

        /* Frees the set and makes sure we are dropped from the
         * inverse pointers */

        SET_FOREACH(other, s, i) {
                UnitDependency d;

                for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
                        set_remove(other->meta.dependencies[d], u);
295
296

                unit_add_to_gc_queue(other);
Lennart Poettering's avatar
Lennart Poettering committed
297
298
299
300
301
302
303
304
305
306
307
308
        }

        set_free(s);
}

void unit_free(Unit *u) {
        UnitDependency d;
        Iterator i;
        char *t;

        assert(u);

309
310
        bus_unit_send_removed_signal(u);

Lennart Poettering's avatar
Lennart Poettering committed
311
312
313
314
        /* Detach from next 'bigger' objects */
        SET_FOREACH(t, u->meta.names, i)
                hashmap_remove_value(u->meta.manager->units, t, u);

Lennart Poettering's avatar
Lennart Poettering committed
315
316
317
        if (u->meta.type != _UNIT_TYPE_INVALID)
                LIST_REMOVE(Meta, units_per_type, u->meta.manager->units_per_type[u->meta.type], &u->meta);

Lennart Poettering's avatar
Lennart Poettering committed
318
319
320
        if (u->meta.in_load_queue)
                LIST_REMOVE(Meta, load_queue, u->meta.manager->load_queue, &u->meta);

321
322
323
        if (u->meta.in_dbus_queue)
                LIST_REMOVE(Meta, dbus_queue, u->meta.manager->dbus_unit_queue, &u->meta);

324
325
326
        if (u->meta.in_cleanup_queue)
                LIST_REMOVE(Meta, cleanup_queue, u->meta.manager->cleanup_queue, &u->meta);

327
328
329
330
331
        if (u->meta.in_gc_queue) {
                LIST_REMOVE(Meta, gc_queue, u->meta.manager->gc_queue, &u->meta);
                u->meta.manager->n_in_gc_queue--;
        }

332
333
334
335
        /* Free data and next 'smaller' objects */
        if (u->meta.job)
                job_free(u->meta.job);

336
        if (u->meta.load_state != UNIT_STUB)
Lennart Poettering's avatar
Lennart Poettering committed
337
338
339
                if (UNIT_VTABLE(u)->done)
                        UNIT_VTABLE(u)->done(u);

340
        cgroup_bonding_free_list(u->meta.cgroup_bondings);
Lennart Poettering's avatar
Lennart Poettering committed
341
342
343
344
345

        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
                bidi_set_free(u, u->meta.dependencies[d]);

        free(u->meta.description);
346
        free(u->meta.fragment_path);
Lennart Poettering's avatar
Lennart Poettering committed
347
348
349
350
351

        while ((t = set_steal_first(u->meta.names)))
                free(t);
        set_free(u->meta.names);

352
353
        free(u->meta.instance);

Lennart Poettering's avatar
Lennart Poettering committed
354
355
356
357
358
359
360
361
362
363
364
365
        free(u);
}

UnitActiveState unit_active_state(Unit *u) {
        assert(u);

        if (u->meta.load_state != UNIT_LOADED)
                return UNIT_INACTIVE;

        return UNIT_VTABLE(u)->active_state(u);
}

366
367
368
369
370
371
const char* unit_sub_state_to_string(Unit *u) {
        assert(u);

        return UNIT_VTABLE(u)->sub_state_to_string(u);
}

372
373
374
static void complete_move(Set **s, Set **other) {
        assert(s);
        assert(other);
Lennart Poettering's avatar
Lennart Poettering committed
375

376
377
        if (!*other)
                return;
Lennart Poettering's avatar
Lennart Poettering committed
378
379

        if (*s)
380
381
382
383
384
385
                set_move(*s, *other);
        else {
                *s = *other;
                *other = NULL;
        }
}
Lennart Poettering's avatar
Lennart Poettering committed
386

387
388
389
static void merge_names(Unit *u, Unit *other) {
        char *t;
        Iterator i;
Lennart Poettering's avatar
Lennart Poettering committed
390

391
392
393
394
395
396
397
398
399
400
401
402
403
404
        assert(u);
        assert(other);

        complete_move(&u->meta.names, &other->meta.names);

        while ((t = set_steal_first(other->meta.names)))
                free(t);

        set_free(other->meta.names);
        other->meta.names = NULL;
        other->meta.id = NULL;

        SET_FOREACH(t, u->meta.names, i)
                assert_se(hashmap_replace(u->meta.manager->units, t, u) == 0);
Lennart Poettering's avatar
Lennart Poettering committed
405
406
}

407
408
409
static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
        Iterator i;
        Unit *back;
Lennart Poettering's avatar
Lennart Poettering committed
410
        int r;
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

        assert(u);
        assert(other);
        assert(d < _UNIT_DEPENDENCY_MAX);

        SET_FOREACH(back, other->meta.dependencies[d], i) {
                UnitDependency k;

                for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++)
                        if ((r = set_remove_and_put(back->meta.dependencies[k], other, u)) < 0) {

                                if (r == -EEXIST)
                                        set_remove(back->meta.dependencies[k], other);
                                else
                                        assert(r == -ENOENT);
                        }
        }

        complete_move(&u->meta.dependencies[d], &other->meta.dependencies[d]);

        set_free(other->meta.dependencies[d]);
        other->meta.dependencies[d] = NULL;
}

int unit_merge(Unit *u, Unit *other) {
Lennart Poettering's avatar
Lennart Poettering committed
436
437
438
439
440
        UnitDependency d;

        assert(u);
        assert(other);
        assert(u->meta.manager == other->meta.manager);
441
        assert(u->meta.type != _UNIT_TYPE_INVALID);
Lennart Poettering's avatar
Lennart Poettering committed
442

443
444
        other = unit_follow_merge(other);

445
446
447
        if (other == u)
                return 0;

448
449
450
451
        if (u->meta.type != other->meta.type)
                return -EINVAL;

        if (!streq_ptr(u->meta.instance, other->meta.instance))
Lennart Poettering's avatar
Lennart Poettering committed
452
453
                return -EINVAL;

454
455
        if (other->meta.load_state != UNIT_STUB &&
            other->meta.load_state != UNIT_FAILED)
456
                return -EEXIST;
Lennart Poettering's avatar
Lennart Poettering committed
457

458
459
460
461
462
463
        if (other->meta.job)
                return -EEXIST;

        if (unit_active_state(other) != UNIT_INACTIVE)
                return -EEXIST;

Lennart Poettering's avatar
Lennart Poettering committed
464
        /* Merge names */
465
        merge_names(u, other);
Lennart Poettering's avatar
Lennart Poettering committed
466
467
468

        /* Merge dependencies */
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
469
                merge_dependencies(u, other, d);
Lennart Poettering's avatar
Lennart Poettering committed
470

471
472
473
        other->meta.load_state = UNIT_MERGED;
        other->meta.merged_into = u;

474
475
476
477
478
479
480
        /* If there is still some data attached to the other node, we
         * don't need it anymore, and can free it. */
        if (other->meta.load_state != UNIT_STUB)
                if (UNIT_VTABLE(other)->done)
                        UNIT_VTABLE(other)->done(other);

        unit_add_to_dbus_queue(u);
481
482
483
484
485
486
487
        unit_add_to_cleanup_queue(other);

        return 0;
}

int unit_merge_by_name(Unit *u, const char *name) {
        Unit *other;
488
489
        int r;
        char *s = NULL;
490
491
492
493

        assert(u);
        assert(name);

494
495
496
497
498
499
500
501
502
503
        if (unit_name_is_template(name)) {
                if (!u->meta.instance)
                        return -EINVAL;

                if (!(s = unit_name_replace_instance(name, u->meta.instance)))
                        return -ENOMEM;

                name = s;
        }

504
        if (!(other = manager_get_unit(u->meta.manager, name)))
505
506
507
                r = unit_add_name(u, name);
        else
                r = unit_merge(u, other);
508

509
510
        free(s);
        return r;
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
}

Unit* unit_follow_merge(Unit *u) {
        assert(u);

        while (u->meta.load_state == UNIT_MERGED)
                assert_se(u = u->meta.merged_into);

        return u;
}

int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
        int r;

        assert(u);
        assert(c);

Lennart Poettering's avatar
Lennart Poettering committed
528
        if (c->std_output != EXEC_OUTPUT_KERNEL && c->std_output != EXEC_OUTPUT_SYSLOG)
529
530
531
532
533
                return 0;

        /* If syslog or kernel logging is requested, make sure our own
         * logging daemon is run first. */

534
        if ((r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
535
536
537
                return r;

        if (u->meta.manager->running_as != MANAGER_SESSION)
538
                if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_LOGGER_SOCKET, NULL, true)) < 0)
539
540
                        return r;

Lennart Poettering's avatar
Lennart Poettering committed
541
542
543
544
545
546
547
548
549
        return 0;
}

const char *unit_description(Unit *u) {
        assert(u);

        if (u->meta.description)
                return u->meta.description;

550
        return u->meta.id;
Lennart Poettering's avatar
Lennart Poettering committed
551
552
553
554
555
556
}

void unit_dump(Unit *u, FILE *f, const char *prefix) {
        char *t;
        UnitDependency d;
        Iterator i;
557
558
        char *p2;
        const char *prefix2;
559
        CGroupBonding *b;
560
        char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
Lennart Poettering's avatar
Lennart Poettering committed
561
562

        assert(u);
563
        assert(u->meta.type >= 0);
Lennart Poettering's avatar
Lennart Poettering committed
564
565
566

        if (!prefix)
                prefix = "";
567
568
        p2 = strappend(prefix, "\t");
        prefix2 = p2 ? p2 : prefix;
Lennart Poettering's avatar
Lennart Poettering committed
569
570

        fprintf(f,
571
                "%s-> Unit %s:\n"
Lennart Poettering's avatar
Lennart Poettering committed
572
                "%s\tDescription: %s\n"
573
                "%s\tInstance: %s\n"
Lennart Poettering's avatar
Lennart Poettering committed
574
                "%s\tUnit Load State: %s\n"
575
576
                "%s\tUnit Active State: %s\n"
                "%s\tActive Enter Timestamp: %s\n"
577
578
                "%s\tActive Exit Timestamp: %s\n"
                "%s\tGC Check Good: %s\n",
579
                prefix, u->meta.id,
Lennart Poettering's avatar
Lennart Poettering committed
580
                prefix, unit_description(u),
581
                prefix, strna(u->meta.instance),
582
                prefix, unit_load_state_to_string(u->meta.load_state),
583
584
                prefix, unit_active_state_to_string(unit_active_state(u)),
                prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->meta.active_enter_timestamp)),
585
586
                prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->meta.active_exit_timestamp)),
                prefix, yes_no(unit_check_gc(u)));
587

Lennart Poettering's avatar
Lennart Poettering committed
588
589
590
        SET_FOREACH(t, u->meta.names, i)
                fprintf(f, "%s\tName: %s\n", prefix, t);

591
592
593
        if (u->meta.fragment_path)
                fprintf(f, "%s\tFragment Path: %s\n", prefix, u->meta.fragment_path);

Lennart Poettering's avatar
Lennart Poettering committed
594
595
596
597
        for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
                Unit *other;

                SET_FOREACH(other, u->meta.dependencies[d], i)
598
                        fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->meta.id);
Lennart Poettering's avatar
Lennart Poettering committed
599
600
        }

601
        if (u->meta.load_state == UNIT_LOADED) {
602
603
604
605
606
607
                fprintf(f,
                        "%s\tRecursive Stop: %s\n"
                        "%s\tStop When Unneeded: %s\n",
                        prefix, yes_no(u->meta.recursive_stop),
                        prefix, yes_no(u->meta.stop_when_unneeded));

608
609
610
                LIST_FOREACH(by_unit, b, u->meta.cgroup_bondings)
                        fprintf(f, "%s\tControlGroup: %s:%s\n",
                                prefix, b->controller, b->path);
611

612
613
                if (UNIT_VTABLE(u)->dump)
                        UNIT_VTABLE(u)->dump(u, f, prefix2);
614
615
616
617

        } else if (u->meta.load_state == UNIT_MERGED)
                fprintf(f,
                        "%s\tMerged into: %s\n",
618
                        prefix, u->meta.merged_into->meta.id);
Lennart Poettering's avatar
Lennart Poettering committed
619
620
621
622

        if (u->meta.job)
                job_dump(u->meta.job, f, prefix2);

623
        free(p2);
Lennart Poettering's avatar
Lennart Poettering committed
624
625
626
}

/* Common implementation for multiple backends */
627
int unit_load_fragment_and_dropin(Unit *u) {
628
629
630
631
632
        int r;

        assert(u);

        /* Load a .service file */
633
        if ((r = unit_load_fragment(u)) < 0)
634
635
                return r;

636
        if (u->meta.load_state == UNIT_STUB)
637
638
639
640
641
642
643
644
645
646
                return -ENOENT;

        /* Load drop-in directory data */
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
                return r;

        return 0;
}

/* Common implementation for multiple backends */
647
int unit_load_fragment_and_dropin_optional(Unit *u) {
648
        int r;
Lennart Poettering's avatar
Lennart Poettering committed
649
650
651

        assert(u);

652
653
654
655
        /* Same as unit_load_fragment_and_dropin(), but whether
         * something can be loaded or not doesn't matter. */

        /* Load a .service file */
656
        if ((r = unit_load_fragment(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
657
658
                return r;

659
660
        if (u->meta.load_state == UNIT_STUB)
                u->meta.load_state = UNIT_LOADED;
661

Lennart Poettering's avatar
Lennart Poettering committed
662
        /* Load drop-in directory data */
663
        if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
664
665
                return r;

666
        return 0;
Lennart Poettering's avatar
Lennart Poettering committed
667
668
}

669
670
671
672
673
674
675
676
677
678
/* Common implementation for multiple backends */
int unit_load_nop(Unit *u) {
        assert(u);

        if (u->meta.load_state == UNIT_STUB)
                u->meta.load_state = UNIT_LOADED;

        return 0;
}

Lennart Poettering's avatar
Lennart Poettering committed
679
680
681
682
683
684
685
686
687
688
int unit_load(Unit *u) {
        int r;

        assert(u);

        if (u->meta.in_load_queue) {
                LIST_REMOVE(Meta, load_queue, u->meta.manager->load_queue, &u->meta);
                u->meta.in_load_queue = false;
        }

689
690
691
        if (u->meta.type == _UNIT_TYPE_INVALID)
                return -EINVAL;

Lennart Poettering's avatar
Lennart Poettering committed
692
693
694
        if (u->meta.load_state != UNIT_STUB)
                return 0;

695
696
        if (UNIT_VTABLE(u)->load)
                if ((r = UNIT_VTABLE(u)->load(u)) < 0)
Lennart Poettering's avatar
Lennart Poettering committed
697
                        goto fail;
698

699
        if (u->meta.load_state == UNIT_STUB) {
700
701
702
703
704
705
706
                r = -ENOENT;
                goto fail;
        }

        assert((u->meta.load_state != UNIT_MERGED) == !u->meta.merged_into);

        unit_add_to_dbus_queue(unit_follow_merge(u));
707
        unit_add_to_gc_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
708
709
710
711
712

        return 0;

fail:
        u->meta.load_state = UNIT_FAILED;
713
        unit_add_to_dbus_queue(u);
714

715
        log_error("Failed to load configuration for %s: %s", u->meta.id, strerror(-r));
716

Lennart Poettering's avatar
Lennart Poettering committed
717
718
719
720
721
722
723
724
725
726
727
728
729
        return r;
}

/* Errors:
 *         -EBADR:    This unit type does not support starting.
 *         -EALREADY: Unit is already started.
 *         -EAGAIN:   An operation is already in progress. Retry later.
 */
int unit_start(Unit *u) {
        UnitActiveState state;

        assert(u);

730
731
732
733
        /* If this is already (being) started, then this will
         * succeed. Note that this will even succeed if this unit is
         * not startable by the user. This is relied on to detect when
         * we need to wait for units and when waiting is finished. */
Lennart Poettering's avatar
Lennart Poettering committed
734
735
736
737
        state = unit_active_state(u);
        if (UNIT_IS_ACTIVE_OR_RELOADING(state))
                return -EALREADY;

738
739
740
741
        /* If it is stopped, but we cannot start it, then fail */
        if (!UNIT_VTABLE(u)->start)
                return -EBADR;

Lennart Poettering's avatar
Lennart Poettering committed
742
743
744
745
746
747
        /* We don't suppress calls to ->start() here when we are
         * already starting, to allow this request to be used as a
         * "hurry up" call, for example when the unit is in some "auto
         * restart" state where it waits for a holdoff timer to elapse
         * before it will start again. */

748
        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
        return UNIT_VTABLE(u)->start(u);
}

bool unit_can_start(Unit *u) {
        assert(u);

        return !!UNIT_VTABLE(u)->start;
}

/* Errors:
 *         -EBADR:    This unit type does not support stopping.
 *         -EALREADY: Unit is already stopped.
 *         -EAGAIN:   An operation is already in progress. Retry later.
 */
int unit_stop(Unit *u) {
        UnitActiveState state;

        assert(u);

        state = unit_active_state(u);
        if (state == UNIT_INACTIVE)
                return -EALREADY;

772
773
774
        if (!UNIT_VTABLE(u)->stop)
                return -EBADR;

775
        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
        return UNIT_VTABLE(u)->stop(u);
}

/* Errors:
 *         -EBADR:    This unit type does not support reloading.
 *         -ENOEXEC:  Unit is not started.
 *         -EAGAIN:   An operation is already in progress. Retry later.
 */
int unit_reload(Unit *u) {
        UnitActiveState state;

        assert(u);

        if (!unit_can_reload(u))
                return -EBADR;

        state = unit_active_state(u);
        if (unit_active_state(u) == UNIT_ACTIVE_RELOADING)
                return -EALREADY;

        if (unit_active_state(u) != UNIT_ACTIVE)
                return -ENOEXEC;

799
        unit_add_to_dbus_queue(u);
Lennart Poettering's avatar
Lennart Poettering committed
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
        return UNIT_VTABLE(u)->reload(u);
}

bool unit_can_reload(Unit *u) {
        assert(u);

        if (!UNIT_VTABLE(u)->reload)
                return false;

        if (!UNIT_VTABLE(u)->can_reload)
                return true;

        return UNIT_VTABLE(u)->can_reload(u);
}

815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
static void unit_check_uneeded(Unit *u) {
        Iterator i;
        Unit *other;

        assert(u);

        /* If this service shall be shut down when unneeded then do
         * so. */

        if (!u->meta.stop_when_unneeded)
                return;

        if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
                return;

        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY], i)
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                        return;

834
        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
835
836
837
838
839
840
841
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                        return;

        SET_FOREACH(other, u->meta.dependencies[UNIT_WANTED_BY], i)
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                        return;

842
        log_debug("Service %s is not needed anymore. Stopping.", u->meta.id);
843
844
845
846
847

        /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
        manager_add_job(u->meta.manager, JOB_STOP, u, JOB_FAIL, true, NULL);
}

Lennart Poettering's avatar
Lennart Poettering committed
848
849
850
851
852
853
854
855
856
857
858
static void retroactively_start_dependencies(Unit *u) {
        Iterator i;
        Unit *other;

        assert(u);
        assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)));

        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES], i)
                if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
                        manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL);

859
        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
Lennart Poettering's avatar
Lennart Poettering committed
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
                if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
                        manager_add_job(u->meta.manager, JOB_START, other, JOB_FAIL, false, NULL);

        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUISITE], i)
                if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
                        manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL);

        SET_FOREACH(other, u->meta.dependencies[UNIT_WANTS], i)
                if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
                        manager_add_job(u->meta.manager, JOB_START, other, JOB_FAIL, false, NULL);

        SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTS], i)
                if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
                        manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL);
}

static void retroactively_stop_dependencies(Unit *u) {
        Iterator i;
        Unit *other;

        assert(u);
        assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));

883
884
885
886
887
888
889
890
891
        if (u->meta.recursive_stop) {
                /* Pull down units need us recursively if enabled */
                SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY], i)
                        if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                                manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL);
        }

        /* Garbage collect services that might not be needed anymore, if enabled */
        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES], i)
Lennart Poettering's avatar
Lennart Poettering committed
892
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
893
                        unit_check_uneeded(other);
894
        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
895
896
897
898
899
900
901
902
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                        unit_check_uneeded(other);
        SET_FOREACH(other, u->meta.dependencies[UNIT_WANTS], i)
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                        unit_check_uneeded(other);
        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUISITE], i)
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                        unit_check_uneeded(other);
903
        SET_FOREACH(other, u->meta.dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
904
905
                if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
                        unit_check_uneeded(other);
Lennart Poettering's avatar
Lennart Poettering committed
906
907
908
}

void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
909
910
        bool unexpected = false;

Lennart Poettering's avatar
Lennart Poettering committed
911
912
913
914
        assert(u);
        assert(os < _UNIT_ACTIVE_STATE_MAX);
        assert(ns < _UNIT_ACTIVE_STATE_MAX);

915
916
917
918
919
920
        /* Note that this is called for all low-level state changes,
         * even if they might map to the same high-level
         * UnitActiveState! That means that ns == os is OK an expected
         * behaviour here. For example: if a mount point is remounted
         * this function will be called too and the utmp code below
         * relies on that! */
Lennart Poettering's avatar
Lennart Poettering committed
921
922
923
924
925
926
927
928
929
930
931
932
933

        if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
                u->meta.active_enter_timestamp = now(CLOCK_REALTIME);
        else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns))
                u->meta.active_exit_timestamp = now(CLOCK_REALTIME);

        if (u->meta.job) {

                if (u->meta.job->state == JOB_WAITING)

                        /* So we reached a different state for this
                         * job. Let's see if we can run it now if it
                         * failed previously due to EAGAIN. */
934
                        job_add_to_run_queue(u->meta.job);
Lennart Poettering's avatar
Lennart Poettering committed
935
936
937
938

                else {
                        assert(u->meta.job->state == JOB_RUNNING);

Lennart Poettering's avatar
Lennart Poettering committed
939
                        /* Let's check whether this state change
Lennart Poettering's avatar
Lennart Poettering committed
940
941
942
943
944
945
946
947
948
                         * constitutes a finished job, or maybe
                         * cotradicts a running job and hence needs to
                         * invalidate jobs. */

                        switch (u->meta.job->type) {

                        case JOB_START:
                        case JOB_VERIFY_ACTIVE:

949
                                if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
Lennart Poettering's avatar
Lennart Poettering committed
950
                                        job_finish_and_invalidate(u->meta.job, true);
951
952
                                else if (ns != UNIT_ACTIVATING) {
                                        unexpected = true;
Lennart Poettering's avatar
Lennart Poettering committed
953
                                        job_finish_and_invalidate(u->meta.job, false);
954
                                }
Lennart Poettering's avatar
Lennart Poettering committed
955
956
957
958
959
960

                                break;

                        case JOB_RELOAD:
                        case JOB_RELOAD_OR_START:

961
                                if (ns == UNIT_ACTIVE)
Lennart Poettering's avatar
Lennart Poettering committed
962
                                        job_finish_and_invalidate(u->meta.job, true);
963
964
                                else if (ns != UNIT_ACTIVATING && ns != UNIT_ACTIVE_RELOADING) {
                                        unexpected = true;
Lennart Poettering's avatar
Lennart Poettering committed
965
                                        job_finish_and_invalidate(u->meta.job, false);
966
                                }
Lennart Poettering's avatar
Lennart Poettering committed
967
968
969
970
971
972
973

                                break;

                        case JOB_STOP:
                        case JOB_RESTART:
                        case JOB_TRY_RESTART:

974
                                if (ns == UNIT_INACTIVE)
Lennart Poettering's avatar
Lennart Poettering committed
975
                                        job_finish_and_invalidate(u->meta.job, true);
976
977
                                else if (ns != UNIT_DEACTIVATING) {
                                        unexpected = true;
Lennart Poettering's avatar
Lennart Poettering committed
978
                                        job_finish_and_invalidate(u->meta.job, false);
979
                                }
Lennart Poettering's avatar
Lennart Poettering committed
980
981
982
983
984
985
986
987
988
989
990
991

                                break;

                        default:
                                assert_not_reached("Job type unknown");
                        }
                }
        }

        /* If this state change happened without being requested by a
         * job, then let's retroactively start or stop dependencies */

992
993
994
995
996
997
        if (unexpected) {
                if (UNIT_IS_INACTIVE_OR_DEACTIVATING(os) && UNIT_IS_ACTIVE_OR_ACTIVATING(ns))
                        retroactively_start_dependencies(u);
                else if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
                        retroactively_stop_dependencies(u);
        }
998

999
1000
        /* Some names are special */
        if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {