1
0
mirror of https://github.com/systemd/systemd synced 2025-09-28 00:04:47 +02:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Yu Watanabe
414cbc3c73
Merge pull request #9864 from ximion/master
localed: Run locale-gen if available to generate missing locale
2021-01-14 00:20:04 +09:00
Yu Watanabe
cb2ae9f8b9
Merge pull request #18170 from OnkelUlla/udev_introduce_TxQueueLen=_setting
udev: introduce TxQueueLength= setting
2021-01-14 00:19:29 +09:00
Felix Stupp
4327574fc1 Added option --check-inhibitors for non-tty usage
As described in #2680, systemctl did ignore inhibitors if it is not
attached to a tty to allow scripts to ignore inhibitors automatically.
This pull request preserves this behavior but allows scripts to
explicit check inhibitors if required.

The new parameter '--check-inhibitors=yes' enables this feature.
The old parameter '-i'/'--ignore-inhibitors' was deprecated in favor
of '--check-inhibitors=no', the default behaviour can be specified
with '--check-inhibitors=auto'.
The new parameter is also described in the documentations and shell
completions found here.
2021-01-13 16:07:36 +01:00
Ulrich Ölmann
ef4a91a7e8 udev: introduce TxQueueLength= setting
Enable udev to set the transmit queue length of a device via a new directive to
be used in link files. The kernel stores this parameter as an unsigned 32 bit
integer. As typical values currently range in the order of 10 to a few 10,000
packets reduce the domain of valid values for this directive to 0..4294967294
and take the excluded 4294967295 == UINT32_MAX to indicate that the directive
is unset.
2021-01-13 06:41:06 +01:00
Ulrich Ölmann
42e15a6f1a link-config: amend log message for failed application of settings
This has been forgotten in pull request #17628 ("udev: Add support to
configure Generic Segment Offload"), see [1].

[1] https://github.com/systemd/systemd/pull/17628
2021-01-13 06:26:28 +01:00
Matthias Klumpp
8f20232fcb localed: Run locale-gen if available to generate missing locale
This change improves integration with distributions using locale-gen to
generate missing locale on-demand, like Debian-based distributions
(Debian/Ubuntu/PureOS/Tanglu/...) and Arch Linux.
We only ever enable new locales for generation, and never disable them.
Furthermore, we only generate UTF-8 locale.

This feature is only used if explicitly enabled at compile-time, and
will also be inert at runtime if the locale-gen binary is missing.
2021-01-12 23:15:12 +01:00
Matthias Klumpp
bd47b0dac4 Add helper for case-independent string equality checks 2021-01-12 22:53:53 +01:00
20 changed files with 418 additions and 34 deletions

View File

@ -1849,17 +1849,34 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</varlistentry>
<varlistentry>
<term><option>-i</option></term>
<term><option>--ignore-inhibitors</option></term>
<term><option>--check-inhibitors=</option></term>
<listitem>
<para>When system shutdown or a sleep state is requested, ignore inhibitor locks. Applications can establish
inhibitor locks to avoid that certain important operations (such as CD burning or suchlike) are interrupted
by system shutdown or a sleep state. Any user may take these locks and privileged users may override these
locks. If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged) and a
list of active locks is printed. However, if <option>--ignore-inhibitors</option> is specified, the
established locks are ignored and not shown, and the operation attempted anyway, possibly requiring
additional privileges.</para>
<para>When system shutdown or sleep state is request, this option controls how to deal with
inhibitor locks. It takes one of <literal>auto</literal>, <literal>yes</literal> or
<literal>no</literal>. Defaults to <literal>auto</literal>, which will behave like
<literal>yes</literal> for interactive invocations (i.e. from a TTY) and <literal>no</literal>
for non-interactive invocations.
<literal>yes</literal> will let the request respect inhibitor locks.
<literal>no</literal> will let the request ignore inhibitor locks.
</para>
<para>Applications can establish inhibitor locks to avoid that certain important operations
(such as CD burning or suchlike) are interrupted by system shutdown or a sleep state. Any user may
take these locks and privileged users may override these locks.
If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged)
and a list of active locks is printed.
However, if <literal>no</literal> is specified or <literal>auto</literal> is specified on a
non-interactive requests, the established locks are ignored and not shown, and the operation
attempted anyway, possibly requiring additional privileges.
May be overriden by <option>--force</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-i</option></term>
<listitem>
<para>Shortcut for <option>--check-inhibitors=no</option>.</para>
</listitem>
</varlistentry>

View File

@ -409,6 +409,13 @@
be ignored.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TxQueueLength=</varname></term>
<listitem>
<para>Specifies the transmit queue length of the device in number of packets. An unsigned integer
in the range 0..4294967294. When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>MTUBytes=</varname></term>
<listitem>

View File

@ -832,6 +832,14 @@ if default_locale == ''
endif
conf.set_quoted('SYSTEMD_DEFAULT_LOCALE', default_locale)
localegen_path = get_option('localegen-path')
have = false
if localegen_path != ''
conf.set_quoted('LOCALEGEN_PATH', localegen_path)
have = true
endif
conf.set10('HAVE_LOCALEGEN', have)
conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
service_watchdog = get_option('service-watchdog')

View File

@ -240,6 +240,8 @@ option('gshadow', type : 'boolean',
description : 'support for shadow group')
option('default-locale', type : 'string', value : '',
description : 'default locale used when /etc/locale.conf does not exist')
option('localegen-path', type : 'string', value : '',
description : 'absolute path to the locale-gen binary in case the system is using locale-gen')
option('service-watchdog', type : 'string', value : '3min',
description : 'default watchdog setting for systemd services')

View File

@ -125,9 +125,9 @@ _systemctl () {
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --now
--quiet -q --system --user --version --runtime --recursive -r --firmware-setup
--show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait'
--show-types --plain --failed --value --fail --dry-run --wait'
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root
--preset-mode -n --lines -o --output -M --machine --message --timestamp'
--preset-mode -n --lines -o --output -M --machine --message --timestamp --check-inhibitors'
)
if __contains_word "--user" ${COMP_WORDS[*]}; then
@ -179,6 +179,9 @@ _systemctl () {
--timestamp)
comps='pretty us µs utc us+utc µs+utc'
;;
--check-inhibitors)
comps='auto yes no'
;;
esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0

View File

@ -443,6 +443,13 @@ done
_values -s , "${_styles[@]}"
}
(( $+functions[_systemctl_check_inhibitors] )) ||
_systemctl_check_inhibitors() {
local -a _modes
_modes=(auto yes no)
_values -s , "${_modes[@]}"
}
# Build arguments for "systemctl" to be used in completion.
local -a _modes; _modes=("--user" "--system")
# Use the last mode (they are exclusive and the last one is used).
@ -460,7 +467,7 @@ _arguments -s \
'--before[Show units ordered before]' \
{-l,--full}"[Don't ellipsize unit names on output]" \
'--show-types[When showing sockets, show socket type]' \
{-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
'--check-inhibitors[Specify if inhibitors should be checked]:mode:_systemctl_check_inhibitors' \
{-q,--quiet}'[Suppress output]' \
'--no-block[Do not wait until operation finished]' \
'--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \

View File

@ -33,6 +33,10 @@ static inline bool streq_ptr(const char *a, const char *b) {
return strcmp_ptr(a, b) == 0;
}
static inline bool strcaseeq_ptr(const char *a, const char *b) {
return strcasecmp_ptr(a, b) == 0;
}
static inline char* strstr_ptr(const char *haystack, const char *needle) {
if (!haystack || !needle)
return NULL;

View File

@ -57,16 +57,15 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
return 0;
}
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
const struct ether_addr *mac, uint32_t mtu,
uint32_t gso_max_size, size_t gso_max_segments) {
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r;
assert(rtnl);
assert(ifindex > 0);
if (!alias && !mac && mtu == 0 && gso_max_size == 0 && gso_max_segments == 0)
if (!alias && !mac && txqueuelen == UINT32_MAX && mtu == 0 && gso_max_size == 0 && gso_max_segments == 0)
return 0;
if (!*rtnl) {
@ -91,6 +90,12 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
return r;
}
if (txqueuelen < UINT32_MAX) {
r = sd_netlink_message_append_u32(message, IFLA_TXQLEN, txqueuelen);
if (r < 0)
return r;
}
if (mtu != 0) {
r = sd_netlink_message_append_u32(message, IFLA_MTU, mtu);
if (r < 0)

View File

@ -70,8 +70,8 @@ static inline bool rtnl_message_type_is_mdb(uint16_t type) {
}
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu,
uint32_t gso_max_size, size_t gso_max_segments);
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments);
int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret);
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names);

View File

@ -6,18 +6,21 @@
#include <unistd.h>
#include "bus-polkit.h"
#include "copy.h"
#include "env-file-label.h"
#include "env-file.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio-label.h"
#include "fileio.h"
#include "fs-util.h"
#include "kbd-util.h"
#include "keymap-util.h"
#include "locale-util.h"
#include "macro.h"
#include "mkdir.h"
#include "nulstr-util.h"
#include "process-util.h"
#include "string-util.h"
#include "strv.h"
#include "tmpfile-util.h"
@ -780,3 +783,211 @@ int x11_convert_to_vconsole(Context *c) {
return modified;
}
bool locale_gen_check_available(void) {
#if HAVE_LOCALEGEN
if (access(LOCALEGEN_PATH, X_OK) < 0) {
if (errno != ENOENT)
log_warning_errno(errno, "Unable to determine whether " LOCALEGEN_PATH " exists and is executable, assuming it is not: %m");
return false;
}
if (access("/etc/locale.gen", F_OK) < 0) {
if (errno != ENOENT)
log_warning_errno(errno, "Unable to determine whether /etc/locale.gen exists, assuming it does not: %m");
return false;
}
return true;
#else
return false;
#endif
}
#if HAVE_LOCALEGEN
static bool locale_encoding_is_utf8_or_unspecified(const char *locale) {
const char *c = strchr(locale, '.');
return !c || strcaseeq(c, ".UTF-8") || strcasestr(locale, ".UTF-8@");
}
static int locale_gen_locale_supported(const char *locale_entry) {
/* Returns an error valus <= 0 if the locale-gen entry is invalid or unsupported,
* 1 in case the locale entry is valid, and -EOPNOTSUPP specifically in case
* the distributor has not provided us with a SUPPORTED file to check
* locale for validity. */
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(locale_entry);
/* Locale templates without country code are never supported */
if (!strstr(locale_entry, "_"))
return -EINVAL;
f = fopen("/usr/share/i18n/SUPPORTED", "re");
if (!f) {
if (errno == ENOENT)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Unable to check validity of locale entry %s: /usr/share/i18n/SUPPORTED does not exist",
locale_entry);
return -errno;
}
for (;;) {
_cleanup_free_ char *line = NULL;
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return log_debug_errno(r, "Failed to read /usr/share/i18n/SUPPORTED: %m");
if (r == 0)
return 0;
line = strstrip(line);
if (strcaseeq_ptr(line, locale_entry))
return 1;
}
}
#endif
int locale_gen_enable_locale(const char *locale) {
#if HAVE_LOCALEGEN
_cleanup_fclose_ FILE *fr = NULL, *fw = NULL;
_cleanup_(unlink_and_freep) char *temp_path = NULL;
_cleanup_free_ char *locale_entry = NULL;
bool locale_enabled = false, first_line = false;
bool write_new = false;
int r;
if (isempty(locale))
return 0;
if (locale_encoding_is_utf8_or_unspecified(locale)) {
locale_entry = strjoin(locale, " UTF-8");
if (!locale_entry)
return -ENOMEM;
} else
return -ENOEXEC; /* We do not process non-UTF-8 locale */
r = locale_gen_locale_supported(locale_entry);
if (r == 0)
return -EINVAL;
if (r < 0 && r != -EOPNOTSUPP)
return r;
fr = fopen("/etc/locale.gen", "re");
if (!fr) {
if (errno != ENOENT)
return -errno;
write_new = true;
}
r = fopen_temporary("/etc/locale.gen", &fw, &temp_path);
if (r < 0)
return r;
if (write_new)
(void) fchmod(fileno(fw), 0644);
else {
/* apply mode & xattrs of the original file to new file */
r = copy_access(fileno(fr), fileno(fw));
if (r < 0)
return r;
r = copy_xattr(fileno(fr), fileno(fw));
if (r < 0)
return r;
}
if (!write_new) {
/* The config file ends with a line break, which we do not want to include before potentially appending a new locale
* instead of uncommenting an existing line. By prepending linebreaks, we can avoid buffering this file but can still write
* a nice config file without empty lines */
first_line = true;
for (;;) {
_cleanup_free_ char *line = NULL;
char *line_locale;
r = read_line(fr, LONG_LINE_MAX, &line);
if (r < 0)
return r;
if (r == 0)
break;
if (locale_enabled) {
/* Just complete writing the file if the new locale was already enabled */
if (!first_line)
fputc('\n', fw);
fputs(line, fw);
first_line = false;
continue;
}
line = strstrip(line);
if (isempty(line)) {
fputc('\n', fw);
first_line = false;
continue;
}
line_locale = line;
if (line_locale[0] == '#')
line_locale = strstrip(line_locale + 1);
else if (strcaseeq_ptr(line_locale, locale_entry))
return 0; /* the file already had our locale activated, so skip updating it */
if (strcaseeq_ptr(line_locale, locale_entry)) {
/* Uncomment existing line for new locale */
if (!first_line)
fputc('\n', fw);
fputs(locale_entry, fw);
locale_enabled = true;
first_line = false;
continue;
}
/* The line was not for the locale we want to enable, just copy it */
if (!first_line)
fputc('\n', fw);
fputs(line, fw);
first_line = false;
}
}
/* Add locale to enable to the end of the file if it was not found as commented line */
if (!locale_enabled) {
if (!write_new)
fputc('\n', fw);
fputs(locale_entry, fw);
}
fputc('\n', fw);
r = fflush_sync_and_check(fw);
if (r < 0)
return r;
if (rename(temp_path, "/etc/locale.gen") < 0)
return -errno;
temp_path = mfree(temp_path);
return 0;
#else
return -EOPNOTSUPP;
#endif
}
int locale_gen_run(void) {
#if HAVE_LOCALEGEN
pid_t pid;
int r;
r = safe_fork("(sd-localegen)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, &pid);
if (r < 0)
return r;
if (r == 0) {
execl(LOCALEGEN_PATH, LOCALEGEN_PATH, NULL);
_exit(EXIT_FAILURE);
}
return 0;
#else
return -EOPNOTSUPP;
#endif
}

View File

@ -42,3 +42,7 @@ int x11_convert_to_vconsole(Context *c);
int x11_write_data(Context *c);
void locale_simplify(char *locale[_VARIABLE_LC_MAX]);
int locale_write_data(Context *c, char ***settings);
bool locale_gen_check_available(void);
int locale_gen_enable_locale(const char *locale);
int locale_gen_run(void);

View File

@ -26,6 +26,9 @@
#include "verbs.h"
#include "virt.h"
/* Enough time for locale-gen to finish server-side (in case it is in use) */
#define LOCALE_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE)
static PagerFlags arg_pager_flags = 0;
static bool arg_ask_password = true;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
@ -176,7 +179,8 @@ static int set_locale(int argc, char **argv, void *userdata) {
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, NULL);
/* We use a longer timeout for the method call in case localed is running locale-gen */
r = sd_bus_call(bus, m, LOCALE_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL);
if (r < 0)
return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));

View File

@ -262,6 +262,7 @@ static int property_get_xkb(
static int process_locale_list_item(
const char *assignment,
char *new_locale[static _VARIABLE_LC_MAX],
bool use_localegen,
sd_bus_error *error) {
assert(assignment);
@ -283,7 +284,7 @@ static int process_locale_list_item(
if (!locale_is_valid(e))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s is not valid, refusing.", e);
if (locale_is_installed(e) <= 0)
if (!use_localegen && locale_is_installed(e) <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s not installed, refusing.", e);
if (new_locale[p])
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale variable %s set twice, refusing.", name);
@ -298,6 +299,47 @@ static int process_locale_list_item(
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale assignment %s not valid, refusing.", assignment);
}
static int locale_gen_process_locale(char *new_locale[static _VARIABLE_LC_MAX],
sd_bus_error *error) {
int r;
assert(new_locale);
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
if (p == VARIABLE_LANGUAGE)
continue;
if (isempty(new_locale[p]))
continue;
if (locale_is_installed(new_locale[p]))
continue;
r = locale_gen_enable_locale(new_locale[p]);
if (r == -ENOEXEC) {
log_error_errno(r, "Refused to enable locale for generation: %m");
return sd_bus_error_setf(error,
SD_BUS_ERROR_INVALID_ARGS,
"Specified locale is not installed and non-UTF-8 locale will not be auto-generated: %s",
new_locale[p]);
} else if (r == -EINVAL) {
log_error_errno(r, "Failed to enable invalid locale %s for generation.", new_locale[p]);
return sd_bus_error_setf(error,
SD_BUS_ERROR_INVALID_ARGS,
"Can not enable locale generation for invalid locale: %s",
new_locale[p]);
} else if (r < 0) {
log_error_errno(r, "Failed to enable locale for generation: %m");
return sd_bus_error_set_errnof(error, r, "Failed to enable locale generation: %m");
}
r = locale_gen_run();
if (r < 0) {
log_error_errno(r, "Failed to generate locale: %m");
return sd_bus_error_set_errnof(error, r, "Failed to generate locale: %m");
}
}
return 0;
}
static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) {
_cleanup_(locale_variables_freep) char *new_locale[_VARIABLE_LC_MAX] = {};
_cleanup_strv_free_ char **settings = NULL, **l = NULL;
@ -305,6 +347,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
bool modified = false;
int interactive, r;
char **i;
bool use_localegen;
assert(m);
assert(c);
@ -317,11 +360,13 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
if (r < 0)
return r;
use_localegen = locale_gen_check_available();
/* If single locale without variable name is provided, then we assume it is LANG=. */
if (strv_length(l) == 1 && !strchr(l[0], '=')) {
if (!locale_is_valid(l[0]))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid locale specification: %s", l[0]);
if (locale_is_installed(l[0]) <= 0)
if (!use_localegen && locale_is_installed(l[0]) <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified locale is not installed: %s", l[0]);
new_locale[VARIABLE_LANG] = strdup(l[0]);
@ -333,7 +378,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
/* Check whether a variable is valid */
STRV_FOREACH(i, l) {
r = process_locale_list_item(*i, new_locale, error);
r = process_locale_list_item(*i, new_locale, use_localegen, error);
if (r < 0)
return r;
}
@ -392,9 +437,17 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
/* Generate locale in case it is missing and the system is using locale-gen */
if (use_localegen) {
r = locale_gen_process_locale(new_locale, error);
if (r < 0)
return r;
}
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
free_and_replace(c->locale[p], new_locale[p]);
/* Write locale configuration */
r = locale_write_data(c, &settings);
if (r < 0) {
log_error_errno(r, "Failed to set locale: %m");

View File

@ -96,17 +96,19 @@ int logind_check_inhibitors(enum action a) {
char **s;
int r;
if (arg_ignore_inhibitors || arg_force > 0)
if (arg_check_inhibitors == 0 || arg_force > 0)
return 0;
if (arg_when > 0)
return 0;
if (geteuid() == 0)
return 0;
if (arg_check_inhibitors < 0) {
if (geteuid() == 0)
return 0;
if (!on_tty())
return 0;
if (!on_tty())
return 0;
}
if (arg_transport != BUS_TRANSPORT_LOCAL)
return 0;

View File

@ -74,7 +74,7 @@ bool arg_no_wall = false;
bool arg_no_reload = false;
bool arg_value = false;
bool arg_show_types = false;
bool arg_ignore_inhibitors = false;
int arg_check_inhibitors = -1;
bool arg_dry_run = false;
bool arg_quiet = false;
bool arg_full = false;
@ -241,7 +241,10 @@ static int systemctl_help(void) {
" -T --show-transaction When enqueuing a unit job, show full transaction\n"
" --show-types When showing sockets, explicitly show their type\n"
" --value When showing properties, only print the value\n"
" -i --ignore-inhibitors When shutting down or sleeping, ignore inhibitors\n"
" --check-inhibitors=MODE\n"
" Specify if checking inhibitors before shutting down,\n"
" sleeping or hibernating\n"
" -i Shortcut for --check-inhibitors=no\n"
" --kill-who=WHO Whom to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
" --what=RESOURCES Which types of resources to remove\n"
@ -364,6 +367,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_REVERSE,
ARG_AFTER,
ARG_BEFORE,
ARG_CHECK_INHIBITORS,
ARG_DRY_RUN,
ARG_SHOW_TYPES,
ARG_IRREVERSIBLE,
@ -415,7 +419,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
{ "ignore-inhibitors", no_argument, NULL, 'i' },
{ "ignore-inhibitors", no_argument, NULL, 'i' }, /* compatibility only */
{ "check-inhibitors", required_argument, NULL, ARG_CHECK_INHIBITORS },
{ "value", no_argument, NULL, ARG_VALUE },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
@ -716,7 +721,18 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case 'i':
arg_ignore_inhibitors = true;
arg_check_inhibitors = 0;
break;
case ARG_CHECK_INHIBITORS:
if (streq(optarg, "auto"))
arg_check_inhibitors = -1;
else {
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --check-inhibitors= argument: %s", optarg);
arg_check_inhibitors = r;
}
break;
case ARG_PLAIN:

View File

@ -59,7 +59,7 @@ extern bool arg_no_wall;
extern bool arg_no_reload;
extern bool arg_value;
extern bool arg_show_types;
extern bool arg_ignore_inhibitors;
extern int arg_check_inhibitors;
extern bool arg_dry_run;
extern bool arg_quiet;
extern bool arg_full;

View File

@ -40,6 +40,7 @@ Link.Name, config_parse_ifname, 0,
Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(link_config, alternative_names)
Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(link_config, alternative_names_policy)
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
Link.TxQueueLength, config_parse_txqueuelen, 0, offsetof(link_config, txqueuelen)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(link_config, speed)
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)

View File

@ -150,6 +150,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
.rx_flow_control = -1,
.tx_flow_control = -1,
.autoneg_flow_control = -1,
.txqueuelen = UINT32_MAX,
};
for (i = 0; i < ELEMENTSOF(link->features); i++)
@ -426,9 +427,11 @@ static int link_config_apply_rtnl_settings(sd_netlink **rtnl, const link_config
} else
mac = config->mac;
r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->mtu, config->gso_max_size, config->gso_max_segments);
r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->txqueuelen, config->mtu,
config->gso_max_size, config->gso_max_segments);
if (r < 0)
log_device_warning_errno(device, r, "Could not set Alias=, MACAddress= or MTU=, ignoring: %m");
log_device_warning_errno(device, r, "Could not set Alias=, MACAddress=, TxQueueLength=, MTU=, "
"GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, ignoring: %m");
return 0;
}
@ -701,6 +704,40 @@ int config_parse_ifalias(
return 0;
}
int config_parse_txqueuelen(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint32_t k, *v = data;
int r;
if (isempty(rvalue)) {
*v = UINT32_MAX;
return 0;
}
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
return 0;
}
if (k == UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
return 0;
}
*v = k;
return 0;
}
static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
[MAC_ADDRESS_POLICY_PERSISTENT] = "persistent",
[MAC_ADDRESS_POLICY_RANDOM] = "random",

View File

@ -46,6 +46,7 @@ struct link_config {
char *name;
char **alternative_names;
char *alias;
uint32_t txqueuelen;
uint32_t mtu;
uint32_t gso_max_segments;
size_t gso_max_size;
@ -90,6 +91,7 @@ MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_txqueuelen);
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_alternative_names_policy);

View File

@ -20,6 +20,7 @@ Name=
AlternativeNamesPolicy=
AlternativeName=
Alias=
TxQueueLength=
MTUBytes=
BitsPerSecond=
Duplex=