From 06cc6afa047deb56318ce424804bb04c4f690b30 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Nov 2015 14:03:13 +0100 Subject: core: generate nice error messages for auxiliary transient units, too Let's move the validation checks into the loop that sets up the main and auxiliary transient units, so that we can generate pretty error messages for all units a transient unit transaction generates, not just for the main unit. --- src/core/dbus-manager.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core/dbus-manager.c') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 67e4e8b218..51ee5817eb 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -644,6 +644,7 @@ static int transient_unit_from_message( Unit **unit, sd_bus_error *error) { + UnitType t; Unit *u; int r; @@ -651,6 +652,13 @@ static int transient_unit_from_message( assert(message); assert(name); + t = unit_name_to_type(name); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name or type."); + + if (!unit_vtable[t]->can_transient) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t)); + r = manager_load_unit(m, name, NULL, error, &u); if (r < 0) return r; @@ -735,7 +743,6 @@ static int method_start_transient_unit(sd_bus_message *message, void *userdata, const char *name, *smode; Manager *m = userdata; JobMode mode; - UnitType t; Unit *u; int r; @@ -750,13 +757,6 @@ static int method_start_transient_unit(sd_bus_message *message, void *userdata, if (r < 0) return r; - t = unit_name_to_type(name); - if (t < 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type."); - - if (!unit_vtable[t]->can_transient) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t)); - mode = job_mode_from_string(smode); if (mode < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode); -- cgit v1.2.3-54-g00ecf From 0f13f3bd7918b84955eaa0ceeea0f964877a93f7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Nov 2015 14:04:40 +0100 Subject: core: move check whether a unit is suitable to become transient into unit.c Lets introduce unit_is_pristine() that verifies whether a unit is suitable to become a transient unit, by checking that it is no referenced yet and has no data on disk assigned. --- src/core/dbus-manager.c | 14 +------------- src/core/unit.c | 20 ++++++++++++++++++++ src/core/unit.h | 2 ++ 3 files changed, 23 insertions(+), 13 deletions(-) (limited to 'src/core/dbus-manager.c') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 51ee5817eb..693d93f3fe 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -663,19 +663,7 @@ static int transient_unit_from_message( if (r < 0) return r; - /* Check if the unit already exists or is already referenced, - * in a number of different ways. Note that to cater for unit - * types such as slice, we are generally fine with units that - * are marked UNIT_LOADED even even though nothing was - * actually loaded, as those unit types don't require a file - * on disk to validly load. */ - - if (!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) || - u->fragment_path || - u->source_path || - !strv_isempty(u->dropin_paths) || - u->refs || - set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0) + if (!unit_is_pristine(u)) return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name); /* OK, the unit failed to load and is unreferenced, now let's diff --git a/src/core/unit.c b/src/core/unit.c index d199d87bf8..7809bfd754 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3704,3 +3704,23 @@ int unit_fail_if_symlink(Unit *u, const char* where) { return -ELOOP; } + +bool unit_is_pristine(Unit *u) { + assert(u); + + /* Check if the unit already exists or is already referenced, + * in a number of different ways. Note that to cater for unit + * types such as slice, we are generally fine with units that + * are marked UNIT_LOADED even even though nothing was + * actually loaded, as those unit types don't require a file + * on disk to validly load. */ + + return !(!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) || + u->fragment_path || + u->source_path || + !strv_isempty(u->dropin_paths) || + u->refs || + set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0 || + u->job || + u->merged_into); +} diff --git a/src/core/unit.h b/src/core/unit.h index bcf41d2348..a69d624fad 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -586,6 +586,8 @@ int unit_require_mounts_for(Unit *u, const char *path); bool unit_type_supported(UnitType t); +bool unit_is_pristine(Unit *u); + static inline bool unit_supported(Unit *u) { return unit_type_supported(u->type); } -- cgit v1.2.3-54-g00ecf From 97329d201064dcfb839a66e5933623f03d87eae6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Nov 2015 14:07:38 +0100 Subject: core: dispatch load queue each time we set up a transient units manager_load_unit() will dispatch the load queue anyway, but let's make sure we also dispatch it immediately, after truning a unit into a transient one and loading the properties from the message. That way the know about the validity of the unit before we begin processing the next auxiliary unit. --- src/core/dbus-manager.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'src/core/dbus-manager.c') diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 693d93f3fe..4d730290b2 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -677,6 +677,9 @@ static int transient_unit_from_message( if (r < 0) return r; + /* Now load the missing bits of the unit we just created */ + manager_dispatch_load_queue(m); + *unit = u; return 0; @@ -687,8 +690,6 @@ static int transient_aux_units_from_message( sd_bus_message *message, sd_bus_error *error) { - Unit *u; - char *name = NULL; int r; assert(m); @@ -699,20 +700,17 @@ static int transient_aux_units_from_message( return r; while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) { + const char *name = NULL; + Unit *u; + r = sd_bus_message_read(message, "s", &name); if (r < 0) return r; r = transient_unit_from_message(m, message, name, &u, error); - if (r < 0 && r != -EEXIST) + if (r < 0) return r; - if (r != -EEXIST) { - r = unit_load(u); - if (r < 0) - return r; - } - r = sd_bus_message_exit_container(message); if (r < 0) return r; @@ -763,13 +761,6 @@ static int method_start_transient_unit(sd_bus_message *message, void *userdata, if (r < 0) return r; - /* And load this stub fully */ - r = unit_load(u); - if (r < 0) - return r; - - manager_dispatch_load_queue(m); - /* Finally, start it */ return bus_unit_queue_job(message, u, JOB_START, mode, false, error); } -- cgit v1.2.3-54-g00ecf