mirror of
https://github.com/systemd/systemd
synced 2024-10-15 20:45:09 +00:00
service: allow freeing the fdstore via cleaning
Now that we have a potentially pinned fdstore let's add a concept for cleaning it explicitly on user requested. Let's expose this via "systemctl clean", i.e. the same way as user directories are cleaned.
This commit is contained in:
parent
b9c1883a9c
commit
4fb8f1e883
|
@ -538,12 +538,16 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||
<varname>StateDirectory=</varname>, <varname>CacheDirectory=</varname>,
|
||||
<varname>LogsDirectory=</varname> and <varname>RuntimeDirectory=</varname>, see
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. It may also be used to clear the file decriptor store as enabled via
|
||||
<varname>FileDescriptorStoreMax=</varname>, see
|
||||
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. For timer units this may be used to clear out the persistent timestamp data if
|
||||
<varname>Persistent=</varname> is used and <option>--what=state</option> is selected, see
|
||||
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>. This
|
||||
command only applies to units that use either of these settings. If <option>--what=</option> is
|
||||
not specified, both the cache and runtime data are removed (as these two types of data are
|
||||
generally redundant and reproducible on the next invocation of the unit).</para>
|
||||
not specified, the cache and runtime data as well as the file descriptor store are removed (as
|
||||
these three types of resources are generally redundant and reproducible on the next invocation of
|
||||
the unit). Note that the specified units must be stopped to invoke this operation.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
@ -2193,13 +2197,17 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
|||
|
||||
<listitem>
|
||||
<para>Select what type of per-unit resources to remove when the <command>clean</command> command is
|
||||
invoked, see below. Takes one of <constant>configuration</constant>, <constant>state</constant>,
|
||||
<constant>cache</constant>, <constant>logs</constant>, <constant>runtime</constant> to select the
|
||||
type of resource. This option may be specified more than once, in which case all specified resource
|
||||
types are removed. Also accepts the special value <constant>all</constant> as a shortcut for
|
||||
specifying all five resource types. If this option is not specified defaults to the combination of
|
||||
<constant>cache</constant> and <constant>runtime</constant>, i.e. the two kinds of resources that
|
||||
are generally considered to be redundant and can be reconstructed on next invocation.</para>
|
||||
invoked, see above. Takes one of <constant>configuration</constant>, <constant>state</constant>,
|
||||
<constant>cache</constant>, <constant>logs</constant>, <constant>runtime</constant>,
|
||||
<constant>fdstore</constant> to select the type of resource. This option may be specified more than
|
||||
once, in which case all specified resource types are removed. Also accepts the special value
|
||||
<constant>all</constant> as a shortcut for specifying all six resource types. If this option is not
|
||||
specified defaults to the combination of <constant>cache</constant>, <constant>runtime</constant>
|
||||
and <constant>fdstore</constant>, i.e. the three kinds of resources that are generally considered
|
||||
to be redundant and can be reconstructed on next invocation. Note that the explicit removal of the
|
||||
<constant>fdstore</constant> resource type is only useful if the
|
||||
<varname>FileDescriptorStorePreserve=</varname> option is enabled, since the file descriptor store
|
||||
is otherwise cleaned automatically when the unit is stopped.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
|
@ -90,6 +90,12 @@ static int property_get_can_clean(
|
|||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(mask, EXEC_CLEAN_FDSTORE)) {
|
||||
r = sd_bus_message_append(reply, "s", "fdstore");
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
|
@ -696,6 +702,7 @@ int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error
|
|||
return r;
|
||||
|
||||
for (;;) {
|
||||
ExecCleanMask m;
|
||||
const char *i;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &i);
|
||||
|
@ -704,17 +711,11 @@ int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error
|
|||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(i, "all"))
|
||||
mask |= EXEC_CLEAN_ALL;
|
||||
else {
|
||||
ExecDirectoryType t;
|
||||
|
||||
t = exec_resource_type_from_string(i);
|
||||
if (t < 0)
|
||||
m = exec_clean_mask_from_string(i);
|
||||
if (m < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i);
|
||||
|
||||
mask |= 1U << t;
|
||||
}
|
||||
mask |= m;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
|
|
|
@ -7582,6 +7582,23 @@ void exec_directory_sort(ExecDirectory *d) {
|
|||
}
|
||||
}
|
||||
|
||||
ExecCleanMask exec_clean_mask_from_string(const char *s) {
|
||||
ExecDirectoryType t;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (streq(s, "all"))
|
||||
return EXEC_CLEAN_ALL;
|
||||
if (streq(s, "fdstore"))
|
||||
return EXEC_CLEAN_FDSTORE;
|
||||
|
||||
t = exec_resource_type_from_string(s);
|
||||
if (t < 0)
|
||||
return (ExecCleanMask) t;
|
||||
|
||||
return 1U << t;
|
||||
}
|
||||
|
||||
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(exec_set_credential_hash_ops, char, string_hash_func, string_compare_func, ExecSetCredential, exec_set_credential_free);
|
||||
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(exec_load_credential_hash_ops, char, string_hash_func, string_compare_func, ExecLoadCredential, exec_load_credential_free);
|
||||
|
||||
|
|
|
@ -161,8 +161,9 @@ typedef enum ExecCleanMask {
|
|||
EXEC_CLEAN_CACHE = 1U << EXEC_DIRECTORY_CACHE,
|
||||
EXEC_CLEAN_LOGS = 1U << EXEC_DIRECTORY_LOGS,
|
||||
EXEC_CLEAN_CONFIGURATION = 1U << EXEC_DIRECTORY_CONFIGURATION,
|
||||
EXEC_CLEAN_FDSTORE = 1U << _EXEC_DIRECTORY_TYPE_MAX,
|
||||
EXEC_CLEAN_NONE = 0,
|
||||
EXEC_CLEAN_ALL = (1U << _EXEC_DIRECTORY_TYPE_MAX) - 1,
|
||||
EXEC_CLEAN_ALL = (1U << (_EXEC_DIRECTORY_TYPE_MAX+1)) - 1,
|
||||
_EXEC_CLEAN_MASK_INVALID = -EINVAL,
|
||||
} ExecCleanMask;
|
||||
|
||||
|
@ -520,6 +521,8 @@ void exec_directory_done(ExecDirectory *d);
|
|||
int exec_directory_add(ExecDirectory *d, const char *path, const char *symlink);
|
||||
void exec_directory_sort(ExecDirectory *d);
|
||||
|
||||
ExecCleanMask exec_clean_mask_from_string(const char *s);
|
||||
|
||||
extern const struct hash_ops exec_set_credential_hash_ops;
|
||||
extern const struct hash_ops exec_load_credential_hash_ops;
|
||||
|
||||
|
|
|
@ -4857,22 +4857,39 @@ static const char* service_status_text(Unit *u) {
|
|||
|
||||
static int service_clean(Unit *u, ExecCleanMask mask) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
bool may_clean_fdstore = false;
|
||||
Service *s = SERVICE(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(mask != 0);
|
||||
|
||||
if (s->state != SERVICE_DEAD)
|
||||
if (!IN_SET(s->state, SERVICE_DEAD, SERVICE_DEAD_RESOURCES_PINNED))
|
||||
return -EBUSY;
|
||||
|
||||
/* Determine if there's anything we could potentially clean */
|
||||
r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (strv_isempty(l))
|
||||
return -EUNATCH;
|
||||
if (mask & EXEC_CLEAN_FDSTORE)
|
||||
may_clean_fdstore = s->n_fd_store > 0 || s->n_fd_store_max > 0;
|
||||
|
||||
if (strv_isempty(l) && !may_clean_fdstore)
|
||||
return -EUNATCH; /* Nothing to potentially clean */
|
||||
|
||||
/* Let's clean the stuff we can clean quickly */
|
||||
if (may_clean_fdstore)
|
||||
service_release_fd_store(s);
|
||||
|
||||
/* If we are done, leave quickly */
|
||||
if (strv_isempty(l)) {
|
||||
if (s->state == SERVICE_DEAD_RESOURCES_PINNED && !s->fd_store)
|
||||
service_set_state(s, SERVICE_DEAD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We need to clean disk stuff. This is slow, hence do it out of process, and change state */
|
||||
service_unwatch_control_pid(s);
|
||||
s->clean_result = SERVICE_SUCCESS;
|
||||
s->control_command = NULL;
|
||||
|
@ -4899,10 +4916,21 @@ fail:
|
|||
|
||||
static int service_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
Service *s = SERVICE(u);
|
||||
ExecCleanMask mask = 0;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
r = exec_context_get_clean_mask(&s->exec_context, &mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (s->n_fd_store_max > 0)
|
||||
mask |= EXEC_CLEAN_FDSTORE;
|
||||
|
||||
*ret = mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
|
||||
|
|
|
@ -884,6 +884,7 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
|
|||
Timer *t = TIMER(u);
|
||||
|
||||
assert(t);
|
||||
assert(ret);
|
||||
|
||||
*ret = t->persistent ? EXEC_CLEAN_STATE : 0;
|
||||
return 0;
|
||||
|
|
|
@ -21,7 +21,7 @@ int verb_clean_or_freeze(int argc, char *argv[], void *userdata) {
|
|||
polkit_agent_open_maybe();
|
||||
|
||||
if (!arg_clean_what) {
|
||||
arg_clean_what = strv_new("cache", "runtime");
|
||||
arg_clean_what = strv_new("cache", "runtime", "fdstore");
|
||||
if (!arg_clean_what)
|
||||
return log_oom();
|
||||
}
|
||||
|
|
|
@ -937,7 +937,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
|||
"state\n"
|
||||
"cache\n"
|
||||
"logs\n"
|
||||
"configuration");
|
||||
"configuration\n"
|
||||
"fdstore");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue