mirror of
https://github.com/systemd/systemd
synced 2024-10-15 12:34:37 +00:00
core, systemctl: add support for irreversible jobs
Add a new job mode: replace-irreversibly. Jobs enqueued using this mode cannot be implicitly canceled by later enqueued conflicting jobs. They can however still be canceled with an explicit "systemctl cancel" call.
This commit is contained in:
parent
b7cf6049a3
commit
23ade460e5
|
@ -170,6 +170,17 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--irreversible</option></term>
|
||||
|
||||
<listitem>
|
||||
<para>Mark this transaction's jobs as irreversible. This prevents
|
||||
future conflicting transactions from replacing these jobs.
|
||||
The jobs can still be cancelled using the <command>cancel</command>
|
||||
command.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--ignore-dependencies</option></term>
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ static void job_merge_into_installed(Job *j, Job *other) {
|
|||
assert(other->type == JOB_NOP);
|
||||
|
||||
j->override = j->override || other->override;
|
||||
j->irreversible = j->irreversible || other->irreversible;
|
||||
j->ignore_order = j->ignore_order || other->ignore_order;
|
||||
}
|
||||
|
||||
|
@ -294,11 +295,13 @@ void job_dump(Job *j, FILE*f, const char *prefix) {
|
|||
"%s-> Job %u:\n"
|
||||
"%s\tAction: %s -> %s\n"
|
||||
"%s\tState: %s\n"
|
||||
"%s\tForced: %s\n",
|
||||
"%s\tForced: %s\n"
|
||||
"%s\tIrreversible: %s\n",
|
||||
prefix, j->id,
|
||||
prefix, j->unit->id, job_type_to_string(j->type),
|
||||
prefix, job_state_to_string(j->state),
|
||||
prefix, yes_no(j->override));
|
||||
prefix, yes_no(j->override),
|
||||
prefix, yes_no(j->irreversible));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -947,6 +950,7 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
|
|||
fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
|
||||
fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
|
||||
fprintf(f, "job-override=%s\n", yes_no(j->override));
|
||||
fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
|
||||
fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
|
||||
fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
|
||||
/* Cannot save bus clients. Just note the fact that we're losing
|
||||
|
@ -1014,6 +1018,12 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) {
|
|||
log_debug("Failed to parse job override flag %s", v);
|
||||
else
|
||||
j->override = j->override || b;
|
||||
} else if (streq(l, "job-irreversible")) {
|
||||
int b = parse_boolean(v);
|
||||
if (b < 0)
|
||||
log_debug("Failed to parse job irreversible flag %s", v);
|
||||
else
|
||||
j->irreversible = j->irreversible || b;
|
||||
} else if (streq(l, "job-sent-dbus-new-signal")) {
|
||||
int b = parse_boolean(v);
|
||||
if (b < 0)
|
||||
|
@ -1110,6 +1120,7 @@ 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_IRREVERSIBLY] = "replace-irreversibly",
|
||||
[JOB_ISOLATE] = "isolate",
|
||||
[JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
|
||||
[JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
|
||||
|
|
|
@ -83,6 +83,7 @@ enum JobState {
|
|||
enum JobMode {
|
||||
JOB_FAIL, /* Fail if a conflicting job is already queued */
|
||||
JOB_REPLACE, /* Replace an existing conflicting job */
|
||||
JOB_REPLACE_IRREVERSIBLY, /* Like JOB_REPLACE + produce irreversible jobs */
|
||||
JOB_ISOLATE, /* Start a unit, and stop all others */
|
||||
JOB_IGNORE_DEPENDENCIES, /* Ignore both requirement and ordering dependencies */
|
||||
JOB_IGNORE_REQUIREMENTS, /* Ignore requirement dependencies */
|
||||
|
@ -161,6 +162,7 @@ struct Job {
|
|||
bool sent_dbus_new_signal:1;
|
||||
bool ignore_order:1;
|
||||
bool forgot_bus_clients:1;
|
||||
bool irreversible:1;
|
||||
};
|
||||
|
||||
JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name);
|
||||
|
|
|
@ -766,7 +766,7 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove
|
|||
|
||||
job_type_collapse(&type, unit);
|
||||
|
||||
tr = transaction_new();
|
||||
tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY);
|
||||
if (!tr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
|
|||
j->type = t;
|
||||
j->state = JOB_WAITING;
|
||||
j->override = j->override || other->override;
|
||||
j->irreversible = j->irreversible || other->irreversible;
|
||||
|
||||
j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor;
|
||||
|
||||
|
@ -488,7 +489,7 @@ rescan:
|
|||
}
|
||||
}
|
||||
|
||||
static int transaction_is_destructive(Transaction *tr, DBusError *e) {
|
||||
static int transaction_is_destructive(Transaction *tr, JobMode mode, DBusError *e) {
|
||||
Iterator i;
|
||||
Job *j;
|
||||
|
||||
|
@ -503,7 +504,7 @@ static int transaction_is_destructive(Transaction *tr, DBusError *e) {
|
|||
assert(!j->transaction_prev);
|
||||
assert(!j->transaction_next);
|
||||
|
||||
if (j->unit->job &&
|
||||
if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
|
||||
!job_type_is_superset(j->type, j->unit->job->type)) {
|
||||
|
||||
dbus_set_error(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive.");
|
||||
|
@ -709,12 +710,10 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
|
|||
transaction_drop_redundant(tr);
|
||||
|
||||
/* Ninth step: check whether we can actually apply this */
|
||||
if (mode == JOB_FAIL) {
|
||||
r = transaction_is_destructive(tr, e);
|
||||
if (r < 0) {
|
||||
log_notice("Requested transaction contradicts existing jobs: %s", bus_error(e, r));
|
||||
return r;
|
||||
}
|
||||
r = transaction_is_destructive(tr, mode, e);
|
||||
if (r < 0) {
|
||||
log_notice("Requested transaction contradicts existing jobs: %s", bus_error(e, r));
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Tenth step: apply changes */
|
||||
|
@ -770,6 +769,7 @@ static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, b
|
|||
j->marker = NULL;
|
||||
j->matters_to_anchor = false;
|
||||
j->override = override;
|
||||
j->irreversible = tr->irreversible;
|
||||
|
||||
LIST_PREPEND(Job, transaction, f, j);
|
||||
|
||||
|
@ -1106,7 +1106,7 @@ int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Transaction *transaction_new(void) {
|
||||
Transaction *transaction_new(bool irreversible) {
|
||||
Transaction *tr;
|
||||
|
||||
tr = new0(Transaction, 1);
|
||||
|
@ -1119,6 +1119,8 @@ Transaction *transaction_new(void) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
tr->irreversible = irreversible;
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,10 @@ struct Transaction {
|
|||
/* Jobs to be added */
|
||||
Hashmap *jobs; /* Unit object => Job object list 1:1 */
|
||||
Job *anchor_job; /* the job the user asked for */
|
||||
bool irreversible;
|
||||
};
|
||||
|
||||
Transaction *transaction_new(void);
|
||||
Transaction *transaction_new(bool irreversible);
|
||||
void transaction_free(Transaction *tr);
|
||||
|
||||
int transaction_add_job_and_dependencies(
|
||||
|
|
|
@ -4306,6 +4306,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||
|
||||
enum {
|
||||
ARG_FAIL = 0x100,
|
||||
ARG_IRREVERSIBLE,
|
||||
ARG_IGNORE_DEPENDENCIES,
|
||||
ARG_VERSION,
|
||||
ARG_USER,
|
||||
|
@ -4334,6 +4335,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||
{ "failed", no_argument, NULL, ARG_FAILED },
|
||||
{ "full", no_argument, NULL, ARG_FULL },
|
||||
{ "fail", no_argument, NULL, ARG_FAIL },
|
||||
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
|
||||
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
|
||||
{ "ignore-inhibitors", no_argument, NULL, 'i' },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
|
@ -4433,6 +4435,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||
arg_job_mode = "fail";
|
||||
break;
|
||||
|
||||
case ARG_IRREVERSIBLE:
|
||||
arg_job_mode = "replace-irreversibly";
|
||||
break;
|
||||
|
||||
case ARG_IGNORE_DEPENDENCIES:
|
||||
arg_job_mode = "ignore-dependencies";
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue