mirror of
https://github.com/systemd/systemd.git
synced 2025-03-13 00:58:27 +03:00
job: Don't mark as redundant if deps are relevant
In the steps given in #13850, the resulting graph looks like: C (Anchor) -> B -> A Since B is inactive, it will be flagged as redundant and removed from the transaction, causing A to get garbage collected. The proposed fix is to not mark nodes as redundant if doing so causes a relevant node to be garbage collected. Fixes #13850
This commit is contained in:
parent
dc5737470e
commit
097537f07a
@ -383,25 +383,62 @@ JobType job_type_lookup_merge(JobType a, JobType b) {
|
||||
return job_merging_table[(a - 1) * a / 2 + b];
|
||||
}
|
||||
|
||||
bool job_type_is_redundant(JobType a, UnitActiveState b) {
|
||||
switch (a) {
|
||||
bool job_later_link_matters(Job *j, JobType type, unsigned generation) {
|
||||
JobDependency *l;
|
||||
|
||||
assert(j);
|
||||
|
||||
j->generation = generation;
|
||||
|
||||
LIST_FOREACH(subject, l, j->subject_list) {
|
||||
UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID;
|
||||
|
||||
/* Have we seen this before? */
|
||||
if (l->object->generation == generation)
|
||||
continue;
|
||||
|
||||
state = unit_active_state(l->object->unit);
|
||||
switch (type) {
|
||||
|
||||
case JOB_START:
|
||||
return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) ||
|
||||
job_later_link_matters(l->object, type, generation);
|
||||
|
||||
case JOB_STOP:
|
||||
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) ||
|
||||
job_later_link_matters(l->object, type, generation);
|
||||
|
||||
default:
|
||||
assert_not_reached("Invalid job type");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool job_is_redundant(Job *j, unsigned generation) {
|
||||
|
||||
assert(j);
|
||||
|
||||
UnitActiveState state = unit_active_state(j->unit);
|
||||
switch (j->type) {
|
||||
|
||||
case JOB_START:
|
||||
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
|
||||
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING) && !job_later_link_matters(j, JOB_START, generation);
|
||||
|
||||
case JOB_STOP:
|
||||
return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED);
|
||||
return IN_SET(state, UNIT_INACTIVE, UNIT_FAILED) && !job_later_link_matters(j, JOB_STOP, generation);
|
||||
|
||||
case JOB_VERIFY_ACTIVE:
|
||||
return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING);
|
||||
return IN_SET(state, UNIT_ACTIVE, UNIT_RELOADING);
|
||||
|
||||
case JOB_RELOAD:
|
||||
return
|
||||
b == UNIT_RELOADING;
|
||||
state == UNIT_RELOADING;
|
||||
|
||||
case JOB_RESTART:
|
||||
return
|
||||
b == UNIT_ACTIVATING;
|
||||
state == UNIT_ACTIVATING;
|
||||
|
||||
case JOB_NOP:
|
||||
return true;
|
||||
|
@ -196,7 +196,8 @@ _pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
|
||||
return a == job_type_lookup_merge(a, b);
|
||||
}
|
||||
|
||||
bool job_type_is_redundant(JobType a, UnitActiveState b) _pure_;
|
||||
bool job_later_link_matters(Job *j, JobType type, unsigned generation);
|
||||
bool job_is_redundant(Job *j, unsigned generation);
|
||||
|
||||
/* Collapses a state-dependent job type into a simpler type by observing
|
||||
* the state of the unit which it is going to be applied to. */
|
||||
|
@ -279,7 +279,7 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void transaction_drop_redundant(Transaction *tr) {
|
||||
static void transaction_drop_redundant(Transaction *tr, unsigned generation) {
|
||||
bool again;
|
||||
|
||||
/* Goes through the transaction and removes all jobs of the units whose jobs are all noops. If not
|
||||
@ -299,7 +299,7 @@ static void transaction_drop_redundant(Transaction *tr) {
|
||||
|
||||
LIST_FOREACH(transaction, k, j)
|
||||
if (tr->anchor_job == k ||
|
||||
!job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
|
||||
!job_is_redundant(k, generation) ||
|
||||
(k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type))) {
|
||||
keep = true;
|
||||
break;
|
||||
@ -730,7 +730,7 @@ int transaction_activate(
|
||||
transaction_minimize_impact(tr);
|
||||
|
||||
/* Third step: Drop redundant jobs */
|
||||
transaction_drop_redundant(tr);
|
||||
transaction_drop_redundant(tr, generation++);
|
||||
|
||||
for (;;) {
|
||||
/* Fourth step: Let's remove unneeded jobs that might
|
||||
@ -772,7 +772,7 @@ int transaction_activate(
|
||||
}
|
||||
|
||||
/* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
|
||||
transaction_drop_redundant(tr);
|
||||
transaction_drop_redundant(tr, generation++);
|
||||
|
||||
/* Ninth step: check whether we can actually apply this */
|
||||
r = transaction_is_destructive(tr, mode, e);
|
||||
|
Loading…
x
Reference in New Issue
Block a user