homectl: add support for configuring tmpfs limits

This commit is contained in:
Lennart Poettering
2025-01-10 15:31:44 +01:00
parent b1c95fb2e9
commit 2b2aebf4dd
2 changed files with 73 additions and 0 deletions

View File

@@ -758,6 +758,22 @@
<xi:include href="version-info.xml" xpointer="v245"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--tmp-limit=<replaceable>BYTES</replaceable></option></term>
<term><option>--tmp-limit=<replaceable>PERCENT</replaceable></option></term>
<term><option>--dev-shm-limit=<replaceable>BYTES</replaceable></option></term>
<term><option>--dev-shm-limit=<replaceable>PERCENT</replaceable></option></term>
<listitem><para>Controls the per-user quota on <filename>/tmp/</filename> and
<filename>/dev/shm/</filename> that is applied when the user logs in. Takes either an absolute value
in bytes (with the usual K, M, G, T suffixes to the base of 1024), or a percentage. In the latter
case the limit is applied relative to the size of the respective file system. This limit is only
applied if the relevant file system is <literal>tmpfs</literal> and has no effect otherwise. Note
that if these options are not used, a default quota might still be enforced (typically 80%.)</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--storage=<replaceable>STORAGE</replaceable></option></term>

View File

@@ -2830,6 +2830,9 @@ static int help(int argc, char *argv[], void *userdata) {
" --memory-max=BYTES Set maximum memory limit\n"
" --cpu-weight=WEIGHT Set CPU weight\n"
" --io-weight=WEIGHT Set IO weight\n"
" --tmp-limit=BYTES|PERCENT Set limit on /tmp/\n"
" --dev-shm-limit=BYTES|PERCENT\n"
" Set limit on /dev/shm/\n"
"\n%4$sStorage User Record Properties:%5$s\n"
" --storage=STORAGE Storage type to use (luks, fscrypt, directory,\n"
" subvolume, cifs)\n"
@@ -2978,6 +2981,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_PROMPT_NEW_USER,
ARG_AVATAR,
ARG_LOGIN_BACKGROUND,
ARG_TMP_LIMIT,
ARG_DEV_SHM_LIMIT,
};
static const struct option options[] = {
@@ -3078,6 +3083,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "blob", required_argument, NULL, 'b' },
{ "avatar", required_argument, NULL, ARG_AVATAR },
{ "login-background", required_argument, NULL, ARG_LOGIN_BACKGROUND },
{ "tmp-limit", required_argument, NULL, ARG_TMP_LIMIT },
{ "dev-shm-limit", required_argument, NULL, ARG_DEV_SHM_LIMIT },
{}
};
@@ -4511,6 +4518,56 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case ARG_TMP_LIMIT:
case ARG_DEV_SHM_LIMIT: {
const char *field =
c == ARG_TMP_LIMIT ? "tmpLimit" :
c == ARG_DEV_SHM_LIMIT ? "devShmLimit" : NULL;
const char *field_scale =
c == ARG_TMP_LIMIT ? "tmpLimitScale" :
c == ARG_DEV_SHM_LIMIT ? "devShmLimitScale" : NULL;
assert(field);
assert(field_scale);
if (isempty(optarg)) {
r = drop_from_identity(field);
if (r < 0)
return r;
r = drop_from_identity(field_scale);
if (r < 0)
return r;
break;
}
r = parse_permyriad(optarg);
if (r < 0) {
uint64_t u;
r = parse_size(optarg, 1024, &u);
if (r < 0)
return log_error_errno(r, "Failed to parse %s/%s parameter: %s", field, field_scale, optarg);
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field, u);
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field);
r = drop_from_identity(field_scale);
if (r < 0)
return r;
} else {
r = sd_json_variant_set_field_unsigned(&arg_identity_extra, field_scale, UINT32_SCALE_FROM_PERMYRIAD(r));
if (r < 0)
return log_error_errno(r, "Failed to set %s field: %m", field_scale);
r = drop_from_identity(field);
if (r < 0)
return r;
}
break;
}
case '?':
return -EINVAL;