2012-04-22 15:22:27 +02:00
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2012-04-24 14:28:00 +02:00
|
|
|
#include <fcntl.h>
|
2015-11-16 22:09:36 +01:00
|
|
|
#include <unistd.h>
|
2012-04-24 14:28:00 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2014-12-10 19:00:46 +01:00
|
|
|
#include "bus-common-errors.h"
|
2013-11-19 21:12:59 +01:00
|
|
|
#include "bus-error.h"
|
2015-04-10 23:15:59 +02:00
|
|
|
#include "terminal-util.h"
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "transaction.h"
|
2015-12-02 17:03:28 +01:00
|
|
|
#include "dbus-unit.h"
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
|
|
|
|
|
|
|
|
static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) {
|
|
|
|
assert(tr);
|
|
|
|
assert(j);
|
|
|
|
|
|
|
|
/* Deletes one job from the transaction */
|
|
|
|
|
|
|
|
transaction_unlink_job(tr, j, delete_dependencies);
|
|
|
|
|
2012-04-20 10:02:05 +02:00
|
|
|
job_free(j);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void transaction_delete_unit(Transaction *tr, Unit *u) {
|
|
|
|
Job *j;
|
|
|
|
|
|
|
|
/* Deletes all jobs associated with a certain unit from the
|
|
|
|
* transaction */
|
|
|
|
|
|
|
|
while ((j = hashmap_get(tr->jobs, u)))
|
|
|
|
transaction_delete_job(tr, j, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void transaction_abort(Transaction *tr) {
|
|
|
|
Job *j;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
|
|
|
|
while ((j = hashmap_first(tr->jobs)))
|
2012-04-22 10:54:58 +02:00
|
|
|
transaction_delete_job(tr, j, false);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
assert(hashmap_isempty(tr->jobs));
|
|
|
|
}
|
|
|
|
|
2012-04-20 01:20:14 +02:00
|
|
|
static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) {
|
2012-04-19 23:54:11 +02:00
|
|
|
JobDependency *l;
|
|
|
|
|
|
|
|
/* A recursive sweep through the graph that marks all units
|
|
|
|
* that matter to the anchor job, i.e. are directly or
|
|
|
|
* indirectly a dependency of the anchor job via paths that
|
|
|
|
* are fully marked as mattering. */
|
|
|
|
|
2012-04-20 01:20:14 +02:00
|
|
|
j->matters_to_anchor = true;
|
|
|
|
j->generation = generation;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-20 01:20:14 +02:00
|
|
|
LIST_FOREACH(subject, l, j->subject_list) {
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
/* This link does not matter */
|
|
|
|
if (!l->matters)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* This unit has already been marked */
|
|
|
|
if (l->object->generation == generation)
|
|
|
|
continue;
|
|
|
|
|
2012-04-20 01:20:14 +02:00
|
|
|
transaction_find_jobs_that_matter_to_anchor(l->object, generation);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other, JobType t) {
|
|
|
|
JobDependency *l, *last;
|
|
|
|
|
|
|
|
assert(j);
|
|
|
|
assert(other);
|
|
|
|
assert(j->unit == other->unit);
|
|
|
|
assert(!j->installed);
|
|
|
|
|
|
|
|
/* Merges 'other' into 'j' and then deletes 'other'. */
|
|
|
|
|
|
|
|
j->type = t;
|
|
|
|
j->state = JOB_WAITING;
|
2013-02-22 11:21:37 +01:00
|
|
|
j->irreversible = j->irreversible || other->irreversible;
|
2012-04-19 23:54:11 +02:00
|
|
|
j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor;
|
|
|
|
|
|
|
|
/* Patch us in as new owner of the JobDependency objects */
|
|
|
|
last = NULL;
|
|
|
|
LIST_FOREACH(subject, l, other->subject_list) {
|
|
|
|
assert(l->subject == other);
|
|
|
|
l->subject = j;
|
|
|
|
last = l;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Merge both lists */
|
|
|
|
if (last) {
|
|
|
|
last->subject_next = j->subject_list;
|
|
|
|
if (j->subject_list)
|
|
|
|
j->subject_list->subject_prev = last;
|
|
|
|
j->subject_list = other->subject_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Patch us in as new owner of the JobDependency objects */
|
|
|
|
last = NULL;
|
|
|
|
LIST_FOREACH(object, l, other->object_list) {
|
|
|
|
assert(l->object == other);
|
|
|
|
l->object = j;
|
|
|
|
last = l;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Merge both lists */
|
|
|
|
if (last) {
|
|
|
|
last->object_next = j->object_list;
|
|
|
|
if (j->object_list)
|
|
|
|
j->object_list->object_prev = last;
|
|
|
|
j->object_list = other->object_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Kill the other job */
|
|
|
|
other->subject_list = NULL;
|
|
|
|
other->object_list = NULL;
|
|
|
|
transaction_delete_job(tr, other, true);
|
|
|
|
}
|
|
|
|
|
2013-05-03 04:51:50 +02:00
|
|
|
_pure_ static bool job_is_conflicted_by(Job *j) {
|
2012-04-19 23:54:11 +02:00
|
|
|
JobDependency *l;
|
|
|
|
|
|
|
|
assert(j);
|
|
|
|
|
|
|
|
/* Returns true if this job is pulled in by a least one
|
|
|
|
* ConflictedBy dependency. */
|
|
|
|
|
|
|
|
LIST_FOREACH(object, l, j->object_list)
|
|
|
|
if (l->conflicts)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
|
|
|
|
Job *k;
|
|
|
|
|
|
|
|
assert(j);
|
|
|
|
|
|
|
|
/* Tries to delete one item in the linked list
|
|
|
|
* j->transaction_next->transaction_next->... that conflicts
|
|
|
|
* with another one, in an attempt to make an inconsistent
|
|
|
|
* transaction work. */
|
|
|
|
|
|
|
|
/* We rely here on the fact that if a merged with b does not
|
|
|
|
* merge with c, either a or b merge with c neither */
|
|
|
|
LIST_FOREACH(transaction, j, j)
|
|
|
|
LIST_FOREACH(transaction, k, j->transaction_next) {
|
|
|
|
Job *d;
|
|
|
|
|
|
|
|
/* Is this one mergeable? Then skip it */
|
|
|
|
if (job_type_is_mergeable(j->type, k->type))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Ok, we found two that conflict, let's see if we can
|
|
|
|
* drop one of them */
|
|
|
|
if (!j->matters_to_anchor && !k->matters_to_anchor) {
|
|
|
|
|
|
|
|
/* Both jobs don't matter, so let's
|
|
|
|
* find the one that is smarter to
|
|
|
|
* remove. Let's think positive and
|
|
|
|
* rather remove stops then starts --
|
|
|
|
* except if something is being
|
|
|
|
* stopped because it is conflicted by
|
|
|
|
* another unit in which case we
|
|
|
|
* rather remove the start. */
|
|
|
|
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_debug(j->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"Looking at job %s/%s conflicted_by=%s",
|
|
|
|
j->unit->id, job_type_to_string(j->type),
|
|
|
|
yes_no(j->type == JOB_STOP && job_is_conflicted_by(j)));
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_debug(k->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"Looking at job %s/%s conflicted_by=%s",
|
|
|
|
k->unit->id, job_type_to_string(k->type),
|
|
|
|
yes_no(k->type == JOB_STOP && job_is_conflicted_by(k)));
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
if (j->type == JOB_STOP) {
|
|
|
|
|
|
|
|
if (job_is_conflicted_by(j))
|
|
|
|
d = k;
|
|
|
|
else
|
|
|
|
d = j;
|
|
|
|
|
|
|
|
} else if (k->type == JOB_STOP) {
|
|
|
|
|
|
|
|
if (job_is_conflicted_by(k))
|
|
|
|
d = j;
|
|
|
|
else
|
|
|
|
d = k;
|
|
|
|
} else
|
|
|
|
d = j;
|
|
|
|
|
|
|
|
} else if (!j->matters_to_anchor)
|
|
|
|
d = j;
|
|
|
|
else if (!k->matters_to_anchor)
|
|
|
|
d = k;
|
|
|
|
else
|
|
|
|
return -ENOEXEC;
|
|
|
|
|
|
|
|
/* Ok, we can drop one, so let's do so. */
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_debug(d->unit,
|
2014-02-06 06:37:18 +01:00
|
|
|
"Fixing conflicting jobs %s/%s,%s/%s by deleting job %s/%s",
|
|
|
|
j->unit->id, job_type_to_string(j->type),
|
|
|
|
k->unit->id, job_type_to_string(k->type),
|
2013-01-05 18:00:35 +01:00
|
|
|
d->unit->id, job_type_to_string(d->type));
|
2012-04-19 23:54:11 +02:00
|
|
|
transaction_delete_job(tr, d, true);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
|
2012-04-19 23:54:11 +02:00
|
|
|
Job *j;
|
|
|
|
Iterator i;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
|
|
|
|
/* First step, check whether any of the jobs for one specific
|
|
|
|
* task conflict. If so, try to drop one of them. */
|
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
JobType t;
|
|
|
|
Job *k;
|
|
|
|
|
|
|
|
t = j->type;
|
|
|
|
LIST_FOREACH(transaction, k, j->transaction_next) {
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0)
|
2012-04-19 23:54:11 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* OK, we could not merge all jobs for this
|
|
|
|
* action. Let's see if we can get rid of one
|
|
|
|
* of them */
|
|
|
|
|
|
|
|
r = delete_one_unmergeable_job(tr, j);
|
|
|
|
if (r >= 0)
|
|
|
|
/* Ok, we managed to drop one, now
|
|
|
|
* let's ask our callers to call us
|
|
|
|
* again after garbage collecting */
|
|
|
|
return -EAGAIN;
|
|
|
|
|
|
|
|
/* We couldn't merge anything. Failure */
|
2014-10-31 01:32:17 +01:00
|
|
|
return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING,
|
|
|
|
"Transaction contains conflicting jobs '%s' and '%s' for %s. "
|
|
|
|
"Probably contradicting requirement dependencies configured.",
|
|
|
|
job_type_to_string(t),
|
|
|
|
job_type_to_string(k->type),
|
|
|
|
k->unit->id);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Second step, merge the jobs. */
|
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
JobType t = j->type;
|
|
|
|
Job *k;
|
|
|
|
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
/* Merge all transaction jobs for j->unit */
|
2012-04-19 23:54:11 +02:00
|
|
|
LIST_FOREACH(transaction, k, j->transaction_next)
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
while ((k = j->transaction_next)) {
|
2012-04-20 09:38:43 +02:00
|
|
|
if (tr->anchor_job == k) {
|
2012-04-19 23:54:11 +02:00
|
|
|
transaction_merge_and_delete_job(tr, k, j, t);
|
|
|
|
j = k;
|
|
|
|
} else
|
|
|
|
transaction_merge_and_delete_job(tr, j, k, t);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(!j->transaction_next);
|
|
|
|
assert(!j->transaction_prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void transaction_drop_redundant(Transaction *tr) {
|
2012-04-21 21:40:40 +02:00
|
|
|
Job *j;
|
|
|
|
Iterator i;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
/* Goes through the transaction and removes all jobs of the units
|
|
|
|
* whose jobs are all noops. If not all of a unit's jobs are
|
|
|
|
* redundant, they are kept. */
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
assert(tr);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
rescan:
|
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
Job *k;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
LIST_FOREACH(transaction, k, j) {
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
if (tr->anchor_job == k ||
|
|
|
|
!job_type_is_redundant(k->type, unit_active_state(k->unit)) ||
|
|
|
|
(k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type)))
|
|
|
|
goto next_unit;
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
/* log_debug("Found redundant job %s/%s, dropping.", j->unit->id, job_type_to_string(j->type)); */
|
|
|
|
transaction_delete_job(tr, j, false);
|
|
|
|
goto rescan;
|
|
|
|
next_unit:;
|
|
|
|
}
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
2013-05-03 04:51:50 +02:00
|
|
|
_pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
|
2012-04-19 23:54:11 +02:00
|
|
|
assert(u);
|
|
|
|
assert(!j->transaction_prev);
|
|
|
|
|
|
|
|
/* Checks whether at least one of the jobs for this unit
|
|
|
|
* matters to the anchor. */
|
|
|
|
|
|
|
|
LIST_FOREACH(transaction, j, j)
|
|
|
|
if (j->matters_to_anchor)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) {
|
2012-04-19 23:54:11 +02:00
|
|
|
Iterator i;
|
|
|
|
Unit *u;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
assert(j);
|
|
|
|
assert(!j->transaction_prev);
|
|
|
|
|
|
|
|
/* Does a recursive sweep through the ordering graph, looking
|
2013-09-15 18:15:38 +02:00
|
|
|
* for a cycle. If we find a cycle we try to break it. */
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
/* Have we seen this before? */
|
|
|
|
if (j->generation == generation) {
|
|
|
|
Job *k, *delete;
|
|
|
|
|
|
|
|
/* If the marker is NULL we have been here already and
|
|
|
|
* decided the job was loop-free from here. Hence
|
|
|
|
* shortcut things and return right-away. */
|
|
|
|
if (!j->marker)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* So, the marker is not NULL and we already have been
|
|
|
|
* here. We have a cycle. Let's try to break it. We go
|
|
|
|
* backwards in our path and try to find a suitable
|
|
|
|
* job to remove. We use the marker to find our way
|
|
|
|
* back, since smart how we are we stored our way back
|
|
|
|
* in there. */
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_warning(j->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"Found ordering cycle on %s/%s",
|
|
|
|
j->unit->id, job_type_to_string(j->type));
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
delete = NULL;
|
|
|
|
for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) {
|
|
|
|
|
2016-07-10 14:48:23 +02:00
|
|
|
/* logging for j not k here to provide consistent narrative */
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_warning(j->unit,
|
2014-11-02 18:10:42 +01:00
|
|
|
"Found dependency on %s/%s",
|
|
|
|
k->unit->id, job_type_to_string(k->type));
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2015-09-08 23:03:38 +02:00
|
|
|
if (!delete && hashmap_get(tr->jobs, k->unit) && !unit_matters_to_anchor(k->unit, k))
|
2012-04-19 23:54:11 +02:00
|
|
|
/* Ok, we can drop this one, so let's
|
|
|
|
* do so. */
|
|
|
|
delete = k;
|
|
|
|
|
|
|
|
/* Check if this in fact was the beginning of
|
|
|
|
* the cycle */
|
|
|
|
if (k == j)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (delete) {
|
2016-03-16 14:27:37 +01:00
|
|
|
const char *status;
|
2016-07-10 14:48:23 +02:00
|
|
|
/* logging for j not k here to provide consistent narrative */
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_warning(j->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"Breaking ordering cycle by deleting job %s/%s",
|
|
|
|
delete->unit->id, job_type_to_string(delete->type));
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_error(delete->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"Job %s/%s deleted to break ordering cycle starting with %s/%s",
|
|
|
|
delete->unit->id, job_type_to_string(delete->type),
|
|
|
|
j->unit->id, job_type_to_string(j->type));
|
2016-03-16 14:27:37 +01:00
|
|
|
|
|
|
|
if (log_get_show_color())
|
|
|
|
status = ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL;
|
|
|
|
else
|
|
|
|
status = " SKIP ";
|
|
|
|
|
|
|
|
unit_status_printf(delete->unit, status,
|
2013-02-27 23:31:35 +01:00
|
|
|
"Ordering cycle found, skipping %s");
|
2012-04-19 23:54:11 +02:00
|
|
|
transaction_delete_unit(tr, delete->unit);
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_error("Unable to break cycle");
|
|
|
|
|
2014-10-31 01:32:17 +01:00
|
|
|
return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
|
|
|
|
"Transaction order is cyclic. See system logs for details.");
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make the marker point to where we come from, so that we can
|
|
|
|
* find our way backwards if we want to break a cycle. We use
|
|
|
|
* a special marker for the beginning: we point to
|
|
|
|
* ourselves. */
|
|
|
|
j->marker = from ? from : j;
|
|
|
|
j->generation = generation;
|
|
|
|
|
2012-09-04 19:24:16 +02:00
|
|
|
/* We assume that the dependencies are bidirectional, and
|
2012-04-19 23:54:11 +02:00
|
|
|
* hence can ignore UNIT_AFTER */
|
|
|
|
SET_FOREACH(u, j->unit->dependencies[UNIT_BEFORE], i) {
|
|
|
|
Job *o;
|
|
|
|
|
|
|
|
/* Is there a job for this unit? */
|
|
|
|
o = hashmap_get(tr->jobs, u);
|
|
|
|
if (!o) {
|
|
|
|
/* Ok, there is no job for this in the
|
|
|
|
* transaction, but maybe there is already one
|
|
|
|
* running? */
|
|
|
|
o = u->job;
|
|
|
|
if (!o)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = transaction_verify_order_one(tr, o, j, generation, e);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ok, let's backtrack, and remember that this entry is not on
|
|
|
|
* our path anymore. */
|
|
|
|
j->marker = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) {
|
2012-04-19 23:54:11 +02:00
|
|
|
Job *j;
|
|
|
|
int r;
|
|
|
|
Iterator i;
|
|
|
|
unsigned g;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
assert(generation);
|
|
|
|
|
|
|
|
/* Check if the ordering graph is cyclic. If it is, try to fix
|
|
|
|
* that up by dropping one of the jobs. */
|
|
|
|
|
|
|
|
g = (*generation)++;
|
|
|
|
|
2015-09-08 19:14:10 +02:00
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
r = transaction_verify_order_one(tr, j, NULL, g, e);
|
|
|
|
if (r < 0)
|
2012-04-19 23:54:11 +02:00
|
|
|
return r;
|
2015-09-08 19:14:10 +02:00
|
|
|
}
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void transaction_collect_garbage(Transaction *tr) {
|
2012-04-21 21:40:40 +02:00
|
|
|
Iterator i;
|
|
|
|
Job *j;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
|
|
|
|
/* Drop jobs that are not required by any other job */
|
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
rescan:
|
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
if (tr->anchor_job == j || j->object_list) {
|
|
|
|
/* log_debug("Keeping job %s/%s because of %s/%s", */
|
|
|
|
/* j->unit->id, job_type_to_string(j->type), */
|
|
|
|
/* j->object_list->subject ? j->object_list->subject->unit->id : "root", */
|
|
|
|
/* j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); */
|
|
|
|
continue;
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
/* log_debug("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); */
|
|
|
|
transaction_delete_job(tr, j, true);
|
|
|
|
goto rescan;
|
|
|
|
}
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) {
|
2012-04-19 23:54:11 +02:00
|
|
|
Iterator i;
|
|
|
|
Job *j;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
|
|
|
|
/* Checks whether applying this transaction means that
|
|
|
|
* existing jobs would be replaced */
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
|
|
|
|
/* Assume merged */
|
|
|
|
assert(!j->transaction_prev);
|
|
|
|
assert(!j->transaction_next);
|
|
|
|
|
2013-02-22 11:21:37 +01:00
|
|
|
if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
|
2014-11-27 15:23:58 +01:00
|
|
|
job_type_is_conflicting(j->unit->job->type, j->type))
|
2014-10-31 01:32:17 +01:00
|
|
|
return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,
|
|
|
|
"Transaction is destructive.");
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void transaction_minimize_impact(Transaction *tr) {
|
2012-04-21 21:40:40 +02:00
|
|
|
Job *j;
|
|
|
|
Iterator i;
|
|
|
|
|
2012-04-19 23:54:11 +02:00
|
|
|
assert(tr);
|
|
|
|
|
|
|
|
/* Drops all unnecessary jobs that reverse already active jobs
|
|
|
|
* or that stop a running service. */
|
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
rescan:
|
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
LIST_FOREACH(transaction, j, j) {
|
|
|
|
bool stops_running_service, changes_existing_job;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
/* If it matters, we shouldn't drop it */
|
|
|
|
if (j->matters_to_anchor)
|
|
|
|
continue;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
/* Would this stop a running service?
|
|
|
|
* Would this change an existing job?
|
|
|
|
* If so, let's drop this entry */
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
stops_running_service =
|
|
|
|
j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit));
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
changes_existing_job =
|
|
|
|
j->unit->job &&
|
|
|
|
job_type_is_conflicting(j->type, j->unit->job->type);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
if (!stops_running_service && !changes_existing_job)
|
|
|
|
continue;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
if (stops_running_service)
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_debug(j->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"%s/%s would stop a running service.",
|
|
|
|
j->unit->id, job_type_to_string(j->type));
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
if (changes_existing_job)
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_debug(j->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"%s/%s would change existing job.",
|
|
|
|
j->unit->id, job_type_to_string(j->type));
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
/* Ok, let's get rid of this */
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_debug(j->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"Deleting %s/%s to minimize impact.",
|
|
|
|
j->unit->id, job_type_to_string(j->type));
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-04-21 21:40:40 +02:00
|
|
|
transaction_delete_job(tr, j, true);
|
|
|
|
goto rescan;
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
2012-04-21 21:40:40 +02:00
|
|
|
}
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
|
|
|
|
Iterator i;
|
|
|
|
Job *j;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
/* Moves the transaction jobs to the set of active jobs */
|
|
|
|
|
2013-11-26 02:13:41 +01:00
|
|
|
if (mode == JOB_ISOLATE || mode == JOB_FLUSH) {
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
/* When isolating first kill all installed jobs which
|
|
|
|
* aren't part of the new transaction */
|
|
|
|
HASHMAP_FOREACH(j, m->jobs, i) {
|
|
|
|
assert(j->installed);
|
|
|
|
|
|
|
|
if (hashmap_get(tr->jobs, j->unit))
|
|
|
|
continue;
|
|
|
|
|
2012-04-24 11:21:03 +02:00
|
|
|
/* Not invalidating recursively. Avoids triggering
|
|
|
|
* OnFailure= actions of dependent jobs. Also avoids
|
|
|
|
* invalidating our iterator. */
|
2016-05-16 17:24:51 +02:00
|
|
|
job_finish_and_invalidate(j, JOB_CANCELED, false, false);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i) {
|
|
|
|
/* Assume merged */
|
|
|
|
assert(!j->transaction_prev);
|
|
|
|
assert(!j->transaction_next);
|
|
|
|
|
|
|
|
r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j);
|
|
|
|
if (r < 0)
|
|
|
|
goto rollback;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((j = hashmap_steal_first(tr->jobs))) {
|
2012-04-20 09:38:43 +02:00
|
|
|
Job *installed_job;
|
|
|
|
|
2012-04-19 23:54:11 +02:00
|
|
|
/* Clean the job dependencies */
|
|
|
|
transaction_unlink_job(tr, j, false);
|
|
|
|
|
2012-04-20 09:38:43 +02:00
|
|
|
installed_job = job_install(j);
|
|
|
|
if (installed_job != j) {
|
|
|
|
/* j has been merged into a previously installed job */
|
|
|
|
if (tr->anchor_job == j)
|
|
|
|
tr->anchor_job = installed_job;
|
|
|
|
hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
|
|
|
|
job_free(j);
|
|
|
|
j = installed_job;
|
|
|
|
}
|
2012-04-20 02:04:01 +02:00
|
|
|
|
2012-04-19 23:54:11 +02:00
|
|
|
job_add_to_run_queue(j);
|
|
|
|
job_add_to_dbus_queue(j);
|
|
|
|
job_start_timer(j);
|
2013-01-25 22:33:33 +01:00
|
|
|
job_shutdown_magic(j);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
rollback:
|
|
|
|
|
2012-04-20 10:02:05 +02:00
|
|
|
HASHMAP_FOREACH(j, tr->jobs, i)
|
2012-04-19 23:54:11 +02:00
|
|
|
hashmap_remove(m->jobs, UINT32_TO_PTR(j->id));
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) {
|
2012-04-22 02:09:04 +02:00
|
|
|
Iterator i;
|
|
|
|
Job *j;
|
2012-04-19 23:54:11 +02:00
|
|
|
int r;
|
|
|
|
unsigned generation = 1;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
|
|
|
|
/* This applies the changes recorded in tr->jobs to
|
|
|
|
* the actual list of jobs, if possible. */
|
|
|
|
|
2012-04-22 02:09:04 +02:00
|
|
|
/* Reset the generation counter of all installed jobs. The detection of cycles
|
|
|
|
* looks at installed jobs. If they had a non-zero generation from some previous
|
|
|
|
* walk of the graph, the algorithm would break. */
|
|
|
|
HASHMAP_FOREACH(j, m->jobs, i)
|
|
|
|
j->generation = 0;
|
|
|
|
|
2012-04-19 23:54:11 +02:00
|
|
|
/* First step: figure out which jobs matter */
|
2012-04-20 01:20:14 +02:00
|
|
|
transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
/* Second step: Try not to stop any running services if
|
|
|
|
* we don't have to. Don't try to reverse running
|
|
|
|
* jobs if we don't have to. */
|
|
|
|
if (mode == JOB_FAIL)
|
|
|
|
transaction_minimize_impact(tr);
|
|
|
|
|
|
|
|
/* Third step: Drop redundant jobs */
|
|
|
|
transaction_drop_redundant(tr);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
/* Fourth step: Let's remove unneeded jobs that might
|
|
|
|
* be lurking. */
|
|
|
|
if (mode != JOB_ISOLATE)
|
|
|
|
transaction_collect_garbage(tr);
|
|
|
|
|
|
|
|
/* Fifth step: verify order makes sense and correct
|
|
|
|
* cycles if necessary and possible */
|
|
|
|
r = transaction_verify_order(tr, &generation, e);
|
|
|
|
if (r >= 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (r != -EAGAIN) {
|
2013-11-19 21:12:59 +01:00
|
|
|
log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r));
|
2012-04-19 23:54:11 +02:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Let's see if the resulting transaction ordering
|
|
|
|
* graph is still cyclic... */
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
/* Sixth step: let's drop unmergeable entries if
|
|
|
|
* necessary and possible, merge entries we can
|
|
|
|
* merge */
|
|
|
|
r = transaction_merge_jobs(tr, e);
|
|
|
|
if (r >= 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (r != -EAGAIN) {
|
2013-11-19 21:12:59 +01:00
|
|
|
log_warning("Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r));
|
2012-04-19 23:54:11 +02:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Seventh step: an entry got dropped, let's garbage
|
|
|
|
* collect its dependencies. */
|
|
|
|
if (mode != JOB_ISOLATE)
|
|
|
|
transaction_collect_garbage(tr);
|
|
|
|
|
|
|
|
/* Let's see if the resulting transaction still has
|
|
|
|
* unmergeable entries ... */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */
|
|
|
|
transaction_drop_redundant(tr);
|
|
|
|
|
|
|
|
/* Ninth step: check whether we can actually apply this */
|
2013-02-22 11:21:37 +01:00
|
|
|
r = transaction_is_destructive(tr, mode, e);
|
|
|
|
if (r < 0) {
|
2013-11-19 21:12:59 +01:00
|
|
|
log_notice("Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
|
2013-02-22 11:21:37 +01:00
|
|
|
return r;
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Tenth step: apply changes */
|
|
|
|
r = transaction_apply(tr, m, mode);
|
2014-11-28 18:23:20 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_warning_errno(r, "Failed to apply transaction: %m");
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
assert(hashmap_isempty(tr->jobs));
|
|
|
|
|
2012-04-24 14:28:00 +02:00
|
|
|
if (!hashmap_isempty(m->jobs)) {
|
|
|
|
/* Are there any jobs now? Then make sure we have the
|
|
|
|
* idle pipe around. We don't really care too much
|
|
|
|
* whether this works or not, as the idle pipe is a
|
|
|
|
* feature for cosmetics, not actually useful for
|
|
|
|
* anything beyond that. */
|
|
|
|
|
systemd: do not output status messages once gettys are running
Make Type=idle communication bidirectional: when bootup is finished,
the manager, as before, signals idling Type=idle jobs to continue.
However, if the boot takes too long, idling jobs signal the manager
that they have had enough, wait a tiny bit more, and continue, taking
ownership of the console. The manager, when signalled that Type=idle
jobs are done, makes a note and will not write to the console anymore.
This is a cosmetic issue, but quite noticable, so let's just fix it.
Based on Harald Hoyer's patch.
https://bugs.freedesktop.org/show_bug.cgi?id=54247
http://unix.stackexchange.com/questions/51805/systemd-messages-after-starting-login/
2013-07-16 03:34:57 +02:00
|
|
|
if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 &&
|
|
|
|
m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) {
|
2015-09-11 18:18:01 +02:00
|
|
|
(void) pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
|
|
|
|
(void) pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC);
|
systemd: do not output status messages once gettys are running
Make Type=idle communication bidirectional: when bootup is finished,
the manager, as before, signals idling Type=idle jobs to continue.
However, if the boot takes too long, idling jobs signal the manager
that they have had enough, wait a tiny bit more, and continue, taking
ownership of the console. The manager, when signalled that Type=idle
jobs are done, makes a note and will not write to the console anymore.
This is a cosmetic issue, but quite noticable, so let's just fix it.
Based on Harald Hoyer's patch.
https://bugs.freedesktop.org/show_bug.cgi?id=54247
http://unix.stackexchange.com/questions/51805/systemd-messages-after-starting-login/
2013-07-16 03:34:57 +02:00
|
|
|
}
|
2012-04-24 14:28:00 +02:00
|
|
|
}
|
|
|
|
|
2012-04-19 23:54:11 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-11-12 19:52:31 +01:00
|
|
|
static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool *is_new) {
|
2012-04-19 23:54:11 +02:00
|
|
|
Job *j, *f;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
assert(unit);
|
|
|
|
|
|
|
|
/* Looks for an existing prospective job and returns that. If
|
|
|
|
* it doesn't exist it is created and added to the prospective
|
|
|
|
* jobs list. */
|
|
|
|
|
|
|
|
f = hashmap_get(tr->jobs, unit);
|
|
|
|
|
|
|
|
LIST_FOREACH(transaction, j, f) {
|
|
|
|
assert(j->unit == unit);
|
|
|
|
|
|
|
|
if (j->type == type) {
|
|
|
|
if (is_new)
|
|
|
|
*is_new = false;
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-18 18:15:49 +02:00
|
|
|
j = job_new(unit, type);
|
|
|
|
if (!j)
|
|
|
|
return NULL;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
j->generation = 0;
|
|
|
|
j->marker = NULL;
|
|
|
|
j->matters_to_anchor = false;
|
2013-02-22 11:21:37 +01:00
|
|
|
j->irreversible = tr->irreversible;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2013-10-14 06:10:14 +02:00
|
|
|
LIST_PREPEND(transaction, f, j);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
if (hashmap_replace(tr->jobs, unit, f) < 0) {
|
2013-10-14 06:10:14 +02:00
|
|
|
LIST_REMOVE(transaction, f, j);
|
2012-04-19 23:54:11 +02:00
|
|
|
job_free(j);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_new)
|
|
|
|
*is_new = true;
|
|
|
|
|
|
|
|
/* log_debug("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); */
|
|
|
|
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) {
|
|
|
|
assert(tr);
|
|
|
|
assert(j);
|
|
|
|
|
|
|
|
if (j->transaction_prev)
|
|
|
|
j->transaction_prev->transaction_next = j->transaction_next;
|
|
|
|
else if (j->transaction_next)
|
|
|
|
hashmap_replace(tr->jobs, j->unit, j->transaction_next);
|
|
|
|
else
|
|
|
|
hashmap_remove_value(tr->jobs, j->unit, j);
|
|
|
|
|
|
|
|
if (j->transaction_next)
|
|
|
|
j->transaction_next->transaction_prev = j->transaction_prev;
|
|
|
|
|
|
|
|
j->transaction_prev = j->transaction_next = NULL;
|
|
|
|
|
|
|
|
while (j->subject_list)
|
2012-04-20 02:11:14 +02:00
|
|
|
job_dependency_free(j->subject_list);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
while (j->object_list) {
|
|
|
|
Job *other = j->object_list->matters ? j->object_list->subject : NULL;
|
|
|
|
|
2012-04-20 02:11:14 +02:00
|
|
|
job_dependency_free(j->object_list);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
if (other && delete_dependencies) {
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_debug(other->unit,
|
2013-01-05 18:00:35 +01:00
|
|
|
"Deleting job %s/%s as dependency of job %s/%s",
|
|
|
|
other->unit->id, job_type_to_string(other->type),
|
|
|
|
j->unit->id, job_type_to_string(j->type));
|
2012-04-19 23:54:11 +02:00
|
|
|
transaction_delete_job(tr, other, delete_dependencies);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int transaction_add_job_and_dependencies(
|
|
|
|
Transaction *tr,
|
|
|
|
JobType type,
|
|
|
|
Unit *unit,
|
|
|
|
Job *by,
|
|
|
|
bool matters,
|
|
|
|
bool conflicts,
|
|
|
|
bool ignore_requirements,
|
|
|
|
bool ignore_order,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_error *e) {
|
2012-04-19 23:54:11 +02:00
|
|
|
Job *ret;
|
|
|
|
Iterator i;
|
|
|
|
Unit *dep;
|
|
|
|
int r;
|
|
|
|
bool is_new;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
assert(type < _JOB_TYPE_MAX);
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
assert(type < _JOB_TYPE_MAX_IN_TRANSACTION);
|
2012-04-19 23:54:11 +02:00
|
|
|
assert(unit);
|
|
|
|
|
2015-04-27 20:19:02 +02:00
|
|
|
/* Before adding jobs for this unit, let's ensure that its state has been loaded
|
|
|
|
* This matters when jobs are spawned as part of coldplugging itself (see e. g. path_coldplug()).
|
|
|
|
* This way, we "recursively" coldplug units, ensuring that we do not look at state of
|
|
|
|
* not-yet-coldplugged units. */
|
2016-02-24 21:36:09 +01:00
|
|
|
if (MANAGER_IS_RELOADING(unit->manager))
|
2015-04-27 20:19:02 +02:00
|
|
|
unit_coldplug(unit);
|
|
|
|
|
2012-04-19 23:54:11 +02:00
|
|
|
/* log_debug("Pulling in %s/%s from %s/%s", */
|
|
|
|
/* unit->id, job_type_to_string(type), */
|
|
|
|
/* by ? by->unit->id : "NA", */
|
|
|
|
/* by ? job_type_to_string(by->type) : "NA"); */
|
|
|
|
|
2014-10-31 01:32:17 +01:00
|
|
|
if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_MASKED))
|
2015-05-19 18:13:22 +02:00
|
|
|
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2015-12-02 17:03:28 +01:00
|
|
|
if (type != JOB_STOP) {
|
|
|
|
r = bus_unit_check_load_state(unit, e);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
2014-10-31 01:32:17 +01:00
|
|
|
if (!unit_job_is_applicable(unit, type))
|
|
|
|
return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,
|
|
|
|
"Job type %s is not applicable for unit %s.",
|
|
|
|
job_type_to_string(type), unit->id);
|
2012-04-19 23:54:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* First add the job. */
|
2015-11-12 19:52:31 +01:00
|
|
|
ret = transaction_add_one_job(tr, type, unit, &is_new);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (!ret)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
ret->ignore_order = ret->ignore_order || ignore_order;
|
|
|
|
|
|
|
|
/* Then, add a link to the job. */
|
2012-04-20 02:11:14 +02:00
|
|
|
if (by) {
|
|
|
|
if (!job_dependency_new(by, ret, matters, conflicts))
|
|
|
|
return -ENOMEM;
|
|
|
|
} else {
|
|
|
|
/* If the job has no parent job, it is the anchor job. */
|
2012-04-20 10:33:37 +02:00
|
|
|
assert(!tr->anchor_job);
|
|
|
|
tr->anchor_job = ret;
|
2012-04-20 00:33:26 +02:00
|
|
|
}
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
|
|
|
|
if (is_new && !ignore_requirements && type != JOB_NOP) {
|
2012-04-19 23:54:11 +02:00
|
|
|
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) {
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_warning(dep, "Cannot add dependency job for, ignoring: %s", bus_error_message(e, r));
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_free(following);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally, recursively add in all dependencies. */
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
if (type == JOB_START || type == JOB_RESTART) {
|
2012-04-19 23:54:11 +02:00
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) {
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
2016-02-09 20:28:58 +01:00
|
|
|
if (r != -EBADR) /* job type not applicable */
|
2012-04-19 23:54:11 +02:00
|
|
|
goto fail;
|
|
|
|
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-13 23:34:40 +02:00
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[UNIT_BINDS_TO], i) {
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
2016-02-09 20:28:58 +01:00
|
|
|
if (r != -EBADR) /* job type not applicable */
|
2012-04-19 23:54:11 +02:00
|
|
|
goto fail;
|
|
|
|
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[UNIT_WANTS], i) {
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
2016-02-09 20:28:58 +01:00
|
|
|
/* unit masked, job type not applicable and unit not found are not considered as errors. */
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_full(dep,
|
2016-04-17 00:41:34 +02:00
|
|
|
IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING,
|
2016-01-14 09:25:18 +01:00
|
|
|
r, "Cannot add dependency job, ignoring: %s",
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
bus_error_message(e, r));
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUISITE], i) {
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, false, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
2016-02-09 20:28:58 +01:00
|
|
|
if (r != -EBADR) /* job type not applicable */
|
2012-04-19 23:54:11 +02:00
|
|
|
goto fail;
|
|
|
|
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTS], i) {
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, true, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
2016-02-09 20:28:58 +01:00
|
|
|
if (r != -EBADR) /* job type not applicable */
|
2012-04-19 23:54:11 +02:00
|
|
|
goto fail;
|
|
|
|
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) {
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, false, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_warning(dep,
|
|
|
|
"Cannot add dependency job, ignoring: %s",
|
|
|
|
bus_error_message(e, r));
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
if (type == JOB_STOP || type == JOB_RESTART) {
|
2015-05-19 17:40:50 +02:00
|
|
|
static const UnitDependency propagate_deps[] = {
|
|
|
|
UNIT_REQUIRED_BY,
|
|
|
|
UNIT_REQUISITE_OF,
|
|
|
|
UNIT_BOUND_BY,
|
|
|
|
UNIT_CONSISTS_OF,
|
|
|
|
};
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2015-05-19 18:13:22 +02:00
|
|
|
JobType ptype;
|
2015-05-19 17:40:50 +02:00
|
|
|
unsigned j;
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2015-05-19 18:13:22 +02:00
|
|
|
/* We propagate STOP as STOP, but RESTART only
|
|
|
|
* as TRY_RESTART, in order not to start
|
|
|
|
* dependencies that are not around. */
|
|
|
|
ptype = type == JOB_RESTART ? JOB_TRY_RESTART : type;
|
|
|
|
|
2015-05-19 17:40:50 +02:00
|
|
|
for (j = 0; j < ELEMENTSOF(propagate_deps); j++)
|
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[propagate_deps[j]], i) {
|
2015-05-21 20:39:23 +02:00
|
|
|
JobType nt;
|
2012-07-20 15:55:01 +02:00
|
|
|
|
2015-05-21 20:39:23 +02:00
|
|
|
nt = job_type_collapse(ptype, dep);
|
|
|
|
if (nt == JOB_NOP)
|
|
|
|
continue;
|
|
|
|
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, nt, dep, ret, true, false, false, ignore_order, e);
|
2015-05-19 17:40:50 +02:00
|
|
|
if (r < 0) {
|
2016-02-09 20:28:58 +01:00
|
|
|
if (r != -EBADR) /* job type not applicable */
|
2015-05-19 17:40:50 +02:00
|
|
|
goto fail;
|
2012-07-20 15:55:01 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_error_free(e);
|
2015-05-19 17:40:50 +02:00
|
|
|
}
|
2012-07-20 15:55:01 +02:00
|
|
|
}
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
if (type == JOB_RELOAD) {
|
2012-04-19 23:54:11 +02:00
|
|
|
|
2012-07-13 23:34:40 +02:00
|
|
|
SET_FOREACH(dep, ret->unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) {
|
2016-01-28 18:51:42 +01:00
|
|
|
JobType nt;
|
|
|
|
|
|
|
|
nt = job_type_collapse(JOB_TRY_RELOAD, dep);
|
|
|
|
if (nt == JOB_NOP)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r = transaction_add_job_and_dependencies(tr, nt, dep, ret, false, false, false, ignore_order, e);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0) {
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_warning(dep,
|
|
|
|
"Cannot add dependency reload job, ignoring: %s",
|
|
|
|
bus_error_message(e, r));
|
2015-05-19 17:56:44 +02:00
|
|
|
sd_bus_error_free(e);
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
core: add NOP jobs, job type collapsing
Two of our current job types are special:
JOB_TRY_RESTART, JOB_RELOAD_OR_START.
They differ from other job types by being sensitive to the unit active state.
They perform some action when the unit is active and some other action
otherwise. This raises a question: when exactly should the unit state be
checked to make the decision?
Currently the unit state is checked when the job becomes runnable. It's more
sensible to check the state immediately when the job is added by the user.
When the user types "systemctl try-restart foo.service", he really intends
to restart the service if it's running right now. If it isn't running right
now, the restart is pointless.
Consider the example (from Bugzilla[1]):
sleep.service takes some time to start.
hello.service has After=sleep.service.
Both services get started. Two jobs will appear:
hello.service/start waiting
sleep.service/start running
Then someone runs "systemctl try-restart hello.service".
Currently the try-restart operation will block and wait for
sleep.service/start to complete.
The correct result is to complete the try-restart operation immediately
with success, because hello.service is not running. The two original
jobs must not be disturbed by this.
To fix this we introduce two new concepts:
- a new job type: JOB_NOP
A JOB_NOP job does not do anything to the unit. It does not pull in any
dependencies. It is always immediately runnable. When installed to a unit,
it sits in a special slot (u->nop_job) where it never conflicts with
the installed job (u->job) of a different type. It never merges with jobs
of other types, but it can merge into an already installed JOB_NOP job.
- "collapsing" of job types
When a job of one of the two special types is added, the state of the unit
is checked immediately and the job type changes:
JOB_TRY_RESTART -> JOB_RESTART or JOB_NOP
JOB_RELOAD_OR_START -> JOB_RELOAD or JOB_START
Should a job type JOB_RELOAD_OR_START appear later during job merging, it
collapses immediately afterwards.
Collapsing actually makes some things simpler, because there are now fewer
job types that are allowed in the transaction.
[1] Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=753586
2012-04-25 11:58:27 +02:00
|
|
|
/* JOB_VERIFY_STARTED require no dependency handling */
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
int transaction_add_isolate_jobs(Transaction *tr, Manager *m) {
|
|
|
|
Iterator i;
|
|
|
|
Unit *u;
|
|
|
|
char *k;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(tr);
|
|
|
|
assert(m);
|
|
|
|
|
|
|
|
HASHMAP_FOREACH_KEY(u, k, m->units, i) {
|
|
|
|
|
|
|
|
/* ignore aliases */
|
|
|
|
if (u->id != k)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (u->ignore_on_isolate)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* No need to stop inactive jobs */
|
|
|
|
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Is there already something listed for this? */
|
|
|
|
if (hashmap_get(tr->jobs, u))
|
|
|
|
continue;
|
|
|
|
|
2015-11-12 19:52:31 +01:00
|
|
|
r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, NULL);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (r < 0)
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_unit_warning_errno(u, r, "Cannot add isolate job, ignoring: %m");
|
2012-04-19 23:54:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-02-22 11:21:37 +01:00
|
|
|
Transaction *transaction_new(bool irreversible) {
|
2012-04-19 23:54:11 +02:00
|
|
|
Transaction *tr;
|
|
|
|
|
|
|
|
tr = new0(Transaction, 1);
|
|
|
|
if (!tr)
|
|
|
|
return NULL;
|
|
|
|
|
2014-08-13 01:00:18 +02:00
|
|
|
tr->jobs = hashmap_new(NULL);
|
2012-04-19 23:54:11 +02:00
|
|
|
if (!tr->jobs) {
|
|
|
|
free(tr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-02-22 11:21:37 +01:00
|
|
|
tr->irreversible = irreversible;
|
|
|
|
|
2012-04-19 23:54:11 +02:00
|
|
|
return tr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void transaction_free(Transaction *tr) {
|
|
|
|
assert(hashmap_isempty(tr->jobs));
|
|
|
|
hashmap_free(tr->jobs);
|
|
|
|
free(tr);
|
|
|
|
}
|