From: Lennart Poettering Date: Sun, 14 Nov 2010 22:47:53 +0000 (+0100) Subject: manager: always pull 'following' units into transaction X-Git-Tag: v12~32 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=6210e7fc31e14159627144f7409eadd3ce0d72b9 manager: always pull 'following' units into transaction --- diff --git a/TODO b/TODO index d02dbd78e..645b075f3 100644 --- a/TODO +++ b/TODO @@ -78,12 +78,14 @@ * in the PAM module rely on loginuid to figure out XDG_RUNTIME_DIR +* automatically determine TERM= based on tty name. (TERM=linux vs. TERM=vt100-nav) + +* declare /etc/system-release cross-distro standard + Pre v12: * fsck-root.service/start gets queued twice -* pull in 'following' units in transactions - * fix hotplug transactions * plymouth agent start loop diff --git a/src/device.c b/src/device.c index 7b7311012..7cb4ff699 100644 --- a/src/device.c +++ b/src/device.c @@ -401,6 +401,39 @@ static Unit *device_following(Unit *u) { return UNIT(first); } +static int device_following_set(Unit *u, Set **_s) { + Device *d = DEVICE(u); + Device *other; + Set *s; + int r; + + assert(d); + assert(_s); + + if (!d->same_sysfs_prev && !d->same_sysfs_next) { + *_s = NULL; + return 0; + } + + if (!(s = set_new(NULL, NULL))) + return -ENOMEM; + + for (other = d->same_sysfs_next; other; other = other->same_sysfs_next) + if ((r = set_put(s, other)) < 0) + goto fail; + + for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) + if ((r = set_put(s, other)) < 0) + goto fail; + + *_s = s; + return 1; + +fail: + set_free(s); + return r; +} + static void device_shutdown(Manager *m) { assert(m); @@ -550,6 +583,7 @@ const UnitVTable device_vtable = { .bus_invalidating_properties = bus_device_invalidating_properties, .following = device_following, + .following_set = device_following_set, .enumerate = device_enumerate, .shutdown = device_shutdown diff --git a/src/list.h b/src/list.h index 3cf18f154..2bec8c9e7 100644 --- a/src/list.h +++ b/src/list.h @@ -110,6 +110,9 @@ } \ } while(false) +#define LIST_JUST_US(name,item) \ + (!(item)->name##_prev && !(item)->name##_next) \ + #define LIST_FOREACH(name,i,head) \ for ((i) = (head); (i); (i) = (i)->name##_next) diff --git a/src/manager.c b/src/manager.c index 932441c2d..32cd64221 100644 --- a/src/manager.c +++ b/src/manager.c @@ -1445,6 +1445,22 @@ static int transaction_add_job_and_dependencies( return -ENOMEM; if (is_new) { + Set *following; + + /* If we are following some other unit, make sure we + * add all dependencies of everybody following. */ + if (unit_following_set(ret->unit, &following) > 0) { + SET_FOREACH(dep, following, i) + if ((r = transaction_add_job_and_dependencies(m, type, dep, ret, false, override, false, e, NULL)) < 0) { + log_warning("Cannot add dependency job for unit %s, ignoring: %s", dep->meta.id, bus_error(e, r)); + + if (e) + dbus_error_free(e); + } + + set_free(following); + } + /* Finally, recursively add in all dependencies. */ if (type == JOB_START || type == JOB_RELOAD_OR_START) { SET_FOREACH(dep, ret->unit->meta.dependencies[UNIT_REQUIRES], i) diff --git a/src/swap.c b/src/swap.c index ddda9e1a3..6de79280c 100644 --- a/src/swap.c +++ b/src/swap.c @@ -1162,6 +1162,39 @@ static Unit *swap_following(Unit *u) { return UNIT(first); } +static int swap_following_set(Unit *u, Set **_set) { + Swap *s = SWAP(u); + Swap *other; + Set *set; + int r; + + assert(s); + assert(_set); + + if (LIST_JUST_US(same_proc_swaps, s)) { + *_set = NULL; + return 0; + } + + if (!(set = set_new(NULL, NULL))) + return -ENOMEM; + + LIST_FOREACH_AFTER(same_proc_swaps, other, s) + if ((r = set_put(set, other)) < 0) + goto fail; + + LIST_FOREACH_BEFORE(same_proc_swaps, other, s) + if ((r = set_put(set, other)) < 0) + goto fail; + + *_set = set; + return 1; + +fail: + set_free(set); + return r; +} + static void swap_shutdown(Manager *m) { assert(m); @@ -1319,6 +1352,7 @@ const UnitVTable swap_vtable = { .bus_invalidating_properties = bus_swap_invalidating_properties, .following = swap_following, + .following_set = swap_following_set, .enumerate = swap_enumerate, .shutdown = swap_shutdown diff --git a/src/unit.c b/src/unit.c index ee1dc85d5..b3a8210a5 100644 --- a/src/unit.c +++ b/src/unit.c @@ -2319,6 +2319,18 @@ int unit_kill(Unit *u, KillWho w, KillMode m, int signo, DBusError *error) { return UNIT_VTABLE(u)->kill(u, w, m, signo, error); } + +int unit_following_set(Unit *u, Set **s) { + assert(u); + assert(s); + + if (UNIT_VTABLE(u)->following_set) + return UNIT_VTABLE(u)->following_set(u, s); + + *s = NULL; + return 0; +} + static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = { [UNIT_STUB] = "stub", [UNIT_LOADED] = "loaded", diff --git a/src/unit.h b/src/unit.h index 796aee5b5..b260dd5b9 100644 --- a/src/unit.h +++ b/src/unit.h @@ -329,6 +329,9 @@ struct UnitVTable { /* Return the unit this unit is following */ Unit *(*following)(Unit *u); + /* Return the set of units that are following each other */ + int (*following_set)(Unit *u, Set **s); + /* This is called for each unit type and should be used to * enumerate existing devices and load them. However, * everything that is loaded here should still stay in @@ -508,6 +511,8 @@ bool unit_pending_active(Unit *u); int unit_add_default_target_dependency(Unit *u, Unit *target); +int unit_following_set(Unit *u, Set **s); + UnitType unit_name_to_type(const char *n); bool unit_name_is_valid(const char *n, bool template_ok);