From c497c7a9e4db487eab4f92421a74d721d9558186 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 22 Apr 2010 02:42:59 +0200 Subject: [PATCH] manager: introduce 'isolate' job mode which kills all units but the requested one --- device.c | 1 + job.c | 3 ++- job.h | 1 + manager.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- mount.c | 1 + systemctl.vala | 17 +++++++++++++++++ unit.h | 3 +++ 7 files changed, 70 insertions(+), 5 deletions(-) diff --git a/device.c b/device.c index a65d4172..520cbdb2 100644 --- a/device.c +++ b/device.c @@ -433,6 +433,7 @@ const UnitVTable device_vtable = { .no_requires = true, .no_instances = true, .no_snapshots = true, + .no_isolate = true, .load = unit_load_fragment_and_dropin_optional, .done = device_done, diff --git a/job.c b/job.c index 3210bb42..f35c91c4 100644 --- a/job.c +++ b/job.c @@ -577,7 +577,8 @@ DEFINE_STRING_TABLE_LOOKUP(job_type, JobType); static const char* const job_mode_table[_JOB_MODE_MAX] = { [JOB_FAIL] = "fail", - [JOB_REPLACE] = "replace" + [JOB_REPLACE] = "replace", + [JOB_ISOLATE] = "isolate" }; DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode); diff --git a/job.h b/job.h index e8857eda..1ae97b75 100644 --- a/job.h +++ b/job.h @@ -65,6 +65,7 @@ enum JobState { enum JobMode { JOB_FAIL, JOB_REPLACE, + JOB_ISOLATE, _JOB_MODE_MAX, _JOB_MODE_INVALID = -1 }; diff --git a/manager.c b/manager.c index 5cb5c3d2..3ac01779 100644 --- a/manager.c +++ b/manager.c @@ -1004,7 +1004,7 @@ static void transaction_collect_garbage(Manager *m) { } while (again); } -static int transaction_is_destructive(Manager *m, JobMode mode) { +static int transaction_is_destructive(Manager *m) { Iterator i; Job *j; @@ -1083,7 +1083,7 @@ static void transaction_minimize_impact(Manager *m) { } while (again); } -static int transaction_apply(Manager *m, JobMode mode) { +static int transaction_apply(Manager *m) { Iterator i; Job *j; int r; @@ -1203,13 +1203,13 @@ static int transaction_activate(Manager *m, JobMode mode) { /* Ninth step: check whether we can actually apply this */ if (mode == JOB_FAIL) - if ((r = transaction_is_destructive(m, mode)) < 0) { + if ((r = transaction_is_destructive(m)) < 0) { log_debug("Requested transaction contradicts existing jobs: %s", strerror(-r)); goto rollback; } /* Tenth step: apply changes */ - if ((r = transaction_apply(m, mode)) < 0) { + if ((r = transaction_apply(m)) < 0) { log_debug("Failed to apply transaction: %s", strerror(-r)); goto rollback; } @@ -1383,6 +1383,38 @@ fail: return r; } +static int transaction_add_isolate_jobs(Manager *m) { + Iterator i; + Unit *u; + char *k; + int r; + + assert(m); + + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + + /* ignore aliases */ + if (u->meta.id != k) + continue; + + if (UNIT_VTABLE(u)->no_isolate) + continue; + + /* No need to stop inactive jobs */ + if (unit_active_state(u) == UNIT_INACTIVE) + continue; + + /* Is there already something listed for this? */ + if (hashmap_get(m->transaction_jobs, u)) + continue; + + if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, u, NULL, true, false, NULL)) < 0) + log_warning("Cannot add isolate job for unit %s, ignoring: %s", u->meta.id, strerror(-r)); + } + + return 0; +} + int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, Job **_ret) { int r; Job *ret; @@ -1392,6 +1424,9 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove assert(unit); assert(mode < _JOB_MODE_MAX); + if (mode == JOB_ISOLATE && type != JOB_START) + return -EINVAL; + log_debug("Trying to enqueue job %s/%s", unit->meta.id, job_type_to_string(type)); if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, &ret)) < 0) { @@ -1399,6 +1434,12 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove return r; } + if (mode == JOB_ISOLATE) + if ((r = transaction_add_isolate_jobs(m)) < 0) { + transaction_abort(m); + return r; + } + if ((r = transaction_activate(m, mode)) < 0) return r; diff --git a/mount.c b/mount.c index 15cce6f8..3cb4cf2d 100644 --- a/mount.c +++ b/mount.c @@ -1462,6 +1462,7 @@ const UnitVTable mount_vtable = { .no_alias = true, .no_instances = true, + .no_isolate = true, .init = mount_init, .load = mount_load, diff --git a/systemctl.vala b/systemctl.vala index a0237bb7..feacdb2b 100644 --- a/systemctl.vala +++ b/systemctl.vala @@ -81,6 +81,7 @@ int main (string[] args) { " cancel [JOB...] Cancel one or more jobs\n" + " start [NAME...] Start on or more units\n" + " stop [NAME...] Stop on or more units\n" + + " enter [NAME] Start one unit and stop all others\n" + " restart [NAME...] Restart on or more units\n" + " reload [NAME...] Reload on or more units\n" + " monitor Monitor unit/job changes\n" + @@ -214,6 +215,22 @@ int main (string[] args) { u.reload(mode); } + } else if (args[1] == "isolate") { + + if (args.length != 3) { + stderr.printf("Missing argument.\n"); + return 1; + } + + ObjectPath p = manager.get_unit(args[2]); + + Unit u = bus.get_object( + "org.freedesktop.systemd1", + p, + "org.freedesktop.systemd1.Unit") as Unit; + + u.start("isolate"); + } else if (args[1] == "monitor") { manager.subscribe(); diff --git a/unit.h b/unit.h index 9155b2ed..21627ef4 100644 --- a/unit.h +++ b/unit.h @@ -306,6 +306,9 @@ struct UnitVTable { /* Exclude from automatic gc */ bool no_gc:1; + + /* Exclude from isolation requests */ + bool no_isolate:1; }; extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX]; -- 2.39.5