summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-11-14 23:47:53 +0100
committerLennart Poettering <lennart@poettering.net>2010-11-14 23:48:21 +0100
commit6210e7fc31e14159627144f7409eadd3ce0d72b9 (patch)
treeb4510ab2477bdb0fa1df3dbefa91f1b01846c451 /src
parent9381a72403f622f66294ab10315240a4c4fd71cd (diff)
manager: always pull 'following' units into transaction
Diffstat (limited to 'src')
-rw-r--r--src/device.c34
-rw-r--r--src/list.h3
-rw-r--r--src/manager.c16
-rw-r--r--src/swap.c34
-rw-r--r--src/unit.c12
-rw-r--r--src/unit.h5
6 files changed, 104 insertions, 0 deletions
diff --git a/src/device.c b/src/device.c
index 7b73110120..7cb4ff699e 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 3cf18f1547..2bec8c9e73 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 932441c2de..32cd642213 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 ddda9e1a31..6de79280c9 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 ee1dc85d50..b3a8210a57 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 796aee5b5c..b260dd5b98 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);