core: clean up errors for live mounting

* Use SD_BUS_ERROR_NOT_SUPPORTED where appropriate
* Use Service object in service_can_live_mount()
* Include errno in bus error message
This commit is contained in:
Mike Yuan
2024-10-22 19:52:24 +02:00
parent f5b0e4f92e
commit f19afb2177
3 changed files with 38 additions and 55 deletions
+28 -44
View File
@@ -5167,7 +5167,8 @@ static int service_can_clean(Unit *u, ExecCleanMask *ret) {
return 0;
}
static int service_live_mount(Unit *u,
static int service_live_mount(
Unit *u,
const char *src,
const char *dst,
sd_bus_message *message,
@@ -5175,9 +5176,8 @@ static int service_live_mount(Unit *u,
const MountOptions *options,
sd_bus_error *error) {
_cleanup_(pidref_done) PidRef worker = PIDREF_NULL;
Service *s = ASSERT_PTR(SERVICE(u));
const char *propagate_directory;
_cleanup_(pidref_done) PidRef worker = PIDREF_NULL;
int r;
assert(u);
@@ -5188,7 +5188,7 @@ static int service_live_mount(Unit *u,
assert(!s->mount_request);
if (s->state != SERVICE_RUNNING || !pidref_is_set(&s->main_pid)) {
log_unit_warning(u, "Service is not running, cannot live mount");
log_unit_warning(u, "Service is not running, cannot live mount.");
return sd_bus_error_setf(
error,
BUS_ERROR_UNIT_INACTIVE,
@@ -5199,7 +5199,7 @@ static int service_live_mount(Unit *u,
}
if (mount_point_is_credentials(u->manager->prefix[EXEC_DIRECTORY_RUNTIME], dst)) {
log_unit_warning(u, "Refusing to live mount over credential mount '%s'", dst);
log_unit_warning(u, "Refusing to live mount over credential mount '%s'.", dst);
return sd_bus_error_setf(
error,
SD_BUS_ERROR_INVALID_ARGS,
@@ -5210,7 +5210,7 @@ static int service_live_mount(Unit *u,
}
if (path_startswith_strv(dst, s->exec_context.inaccessible_paths)) {
log_unit_warning(u, "%s is not accessible to this unit, cannot live mount", dst);
log_unit_warning(u, "%s is not accessible to this unit, cannot live mount.", dst);
return sd_bus_error_setf(
error,
SD_BUS_ERROR_INVALID_ARGS,
@@ -5227,18 +5227,14 @@ static int service_live_mount(Unit *u,
r = service_arm_timer(s, /* relative= */ true, s->timeout_start_usec);
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to install timer: %m");
sd_bus_error_set_errnof(
error,
r,
"Live mounting '%s' on '%s' for unit '%s' cannot be scheduled: failed to install timer",
src,
dst,
u->id);
log_unit_error_errno(u, r, "Failed to install timer: %m");
sd_bus_error_set_errnof(error, r,
"Live mounting '%s' on '%s' for unit '%s': failed to install timer: %m",
src, dst, u->id);
goto fail;
}
propagate_directory = strjoina("/run/systemd/propagate/", u->id);
const char *propagate_directory = strjoina("/run/systemd/propagate/", u->id);
/* Given we are running from PID1, avoid doing potentially heavy I/O operations like opening images
* directly, and instead fork a worker process. We record the D-Bus message, so that we can reply
@@ -5246,19 +5242,12 @@ static int service_live_mount(Unit *u,
* resource is available (or the operation failed) once they receive the response. */
r = unit_fork_helper_process(u, "(sd-mount-in-ns)", /* into_cgroup= */ false, &worker);
if (r < 0) {
log_unit_warning_errno(
u,
r,
"Failed to fork process to mount '%s' on '%s' in unit's namespace: %m",
src,
dst);
sd_bus_error_set_errnof(
error,
r,
"Live mounting '%s' on '%s' for unit '%s' cannot be scheduled: failed to fork process",
src,
dst,
u->id);
log_unit_error_errno(u, r,
"Failed to fork process to mount '%s' on '%s' in unit's namespace: %m",
src, dst);
sd_bus_error_set_errnof(error, r,
"Live mounting '%s' on '%s' for unit '%s': failed to fork off helper process into namespace: %m",
src, dst, u->id);
goto fail;
}
if (r == 0) {
@@ -5279,26 +5268,21 @@ static int service_live_mount(Unit *u,
src, dst,
flags);
if (r < 0)
log_unit_warning_errno(
u,
r,
"Failed to mount '%s' on '%s' in unit's namespace: %m",
src,
dst);
log_unit_error_errno(u, r,
"Failed to mount '%s' on '%s' in unit's namespace: %m",
src, dst);
else
log_unit_debug(u, "Mounted '%s' on '%s' in unit's namespace", src, dst);
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
r = unit_watch_pidref(u, &worker, /* exclusive= */ true);
if (r < 0) {
sd_bus_error_set_errnof(
error,
r,
"Live mounting '%s' on '%s' for unit '%s' failed: failed to watch worker process",
src,
dst,
u->id);
log_unit_warning_errno(u, r, "Failed to watch live mount helper process: %m");
sd_bus_error_set_errnof(error, r,
"Live mounting '%s' on '%s' for unit '%s': failed to watch live mount helper process: %m",
src, dst, u->id);
goto fail;
}
@@ -5313,11 +5297,11 @@ fail:
return r;
}
static int service_can_live_mount(const Unit *u, sd_bus_error *error) {
assert(u);
static int service_can_live_mount(Unit *u, sd_bus_error *error) {
Service *s = ASSERT_PTR(SERVICE(u));
/* Ensure that the unit runs in a private mount namespace */
if (!exec_needs_mount_namespace(unit_get_exec_context(u), /* params= */ NULL, unit_get_exec_runtime(u)))
if (!exec_needs_mount_namespace(&s->exec_context, /* params= */ NULL, s->exec_runtime))
return sd_bus_error_setf(
error,
SD_BUS_ERROR_INVALID_ARGS,
+7 -8
View File
@@ -6397,22 +6397,21 @@ Condition *unit_find_failed_condition(Unit *u) {
return failed_trigger && !has_succeeded_trigger ? failed_trigger : NULL;
}
int unit_can_live_mount(const Unit *u, sd_bus_error *error) {
int unit_can_live_mount(Unit *u, sd_bus_error *error) {
assert(u);
if (!UNIT_VTABLE(u)->live_mount)
return sd_bus_error_setf(
error,
SD_BUS_ERROR_INVALID_ARGS,
"Live mounting not supported for unit type '%s' of unit '%s'.",
unit_type_to_string(u->type),
u->id);
SD_BUS_ERROR_NOT_SUPPORTED,
"Live mounting not supported by unit type '%s'",
unit_type_to_string(u->type));
if (u->load_state != UNIT_LOADED)
return sd_bus_error_setf(
error,
BUS_ERROR_NO_SUCH_UNIT,
"Unit '%s' not loaded, cannot live mount.",
"Unit '%s' not loaded, cannot live mount",
u->id);
if (!UNIT_VTABLE(u)->can_live_mount)
@@ -6434,7 +6433,7 @@ int unit_live_mount(
assert(UNIT_VTABLE(u)->live_mount);
if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
log_unit_debug(u, "Unit not active");
log_unit_debug(u, "Unit not active, cannot perform live mount.");
return sd_bus_error_setf(
error,
BUS_ERROR_UNIT_INACTIVE,
@@ -6445,7 +6444,7 @@ int unit_live_mount(
}
if (unit_active_state(u) == UNIT_REFRESHING) {
log_unit_debug(u, "Unit already live mounting");
log_unit_debug(u, "Unit already live mounting, refusing further requests.");
return sd_bus_error_setf(
error,
BUS_ERROR_UNIT_BUSY,
+3 -3
View File
@@ -587,7 +587,7 @@ typedef struct UnitVTable {
/* Add a bind/image mount into the unit namespace while it is running. */
int (*live_mount)(Unit *u, const char *src, const char *dst, sd_bus_message *message, MountInNamespaceFlags flags, const MountOptions *options, sd_bus_error *error);
int (*can_live_mount)(const Unit *u, sd_bus_error *error);
int (*can_live_mount)(Unit *u, sd_bus_error *error);
/* Serialize state and file descriptors that should be carried over into the new
* instance after reexecution. */
@@ -650,7 +650,7 @@ typedef struct UnitVTable {
int (*bus_commit_properties)(Unit *u);
/* Return the unit this unit is following */
Unit *(*following)(Unit *u);
Unit* (*following)(Unit *u);
/* Return the set of units that are following each other */
int (*following_set)(Unit *u, Set **s);
@@ -1047,7 +1047,7 @@ void unit_next_freezer_state(Unit *u, FreezerAction action, FreezerState *ret_ne
void unit_set_freezer_state(Unit *u, FreezerState state);
void unit_freezer_complete(Unit *u, FreezerState kernel_state);
int unit_can_live_mount(const Unit *u, sd_bus_error *error);
int unit_can_live_mount(Unit *u, sd_bus_error *error);
int unit_live_mount(Unit *u, const char *src, const char *dst, sd_bus_message *message, MountInNamespaceFlags flags, const MountOptions *options, sd_bus_error *error);
Condition *unit_find_failed_condition(Unit *u);