Compare commits
33 Commits
b11e98037c
...
57b611a5bf
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 57b611a5bf | |
Yegor Vialov | 8b8ae7959d | |
Adam Nielsen | f01994380e | |
Lennart Poettering | ed66590d15 | |
Jan Klötzke | bf76080180 | |
Lennart Poettering | 8b5616fa91 | |
Lennart Poettering | d3d0b763b4 | |
Lennart Poettering | 5a36324962 | |
Lennart Poettering | 707dc7949c | |
Yu Watanabe | a4d1bef73f | |
Maxim Fomin | 6cc27c29ad | |
YmrDtnJu | c15ab81ed9 | |
YmrDtnJu | ac2474e4ff | |
Lennart Poettering | a34a2933e9 | |
Lennart Poettering | 048b4dc2e1 | |
Lennart Poettering | 95ac523030 | |
Susant Sahani | 2153bbc81a | |
Susant Sahani | daec96821d | |
Susant Sahani | 5dfaf89b5b | |
Zbigniew Jędrzejewski-Szmek | 3a9692dd05 | |
Zbigniew Jędrzejewski-Szmek | 3ac33bc966 | |
Michal Sekletár | 2884836e3c | |
Michal Sekletár | a0d79df8e5 | |
Zbigniew Jędrzejewski-Szmek | 856e51957a | |
Zbigniew Jędrzejewski-Szmek | 138f49e452 | |
Zbigniew Jędrzejewski-Szmek | ea806175cd | |
Zbigniew Jędrzejewski-Szmek | 68b0ab5891 | |
Zbigniew Jędrzejewski-Szmek | 55825de59b | |
Zbigniew Jędrzejewski-Szmek | 3aff6c7917 | |
Zbigniew Jędrzejewski-Szmek | 31ca609f8a | |
Zbigniew Jędrzejewski-Szmek | 43874aa7bb | |
Zbigniew Jędrzejewski-Szmek | c544fc319c | |
Zbigniew Jędrzejewski-Szmek | 06134457d2 |
|
@ -12,6 +12,8 @@
|
|||
.config.args
|
||||
.gdb_history
|
||||
.deps/
|
||||
.mypy_cache/
|
||||
__pycache__/
|
||||
/*.gcda
|
||||
/*.gcno
|
||||
/*.tar.bz2
|
||||
|
@ -34,4 +36,3 @@
|
|||
/mkosi.builddir/
|
||||
/mkosi.output/
|
||||
/tags
|
||||
__pycache__/
|
||||
|
|
8
TODO
8
TODO
|
@ -19,6 +19,14 @@ Janitorial Clean-ups:
|
|||
|
||||
Features:
|
||||
|
||||
* add systemd.random_seed= on the kernel cmdline, taking some hex or base64
|
||||
encoded data. During earliest boot, credit it to entropy. This is not useful
|
||||
for general purpose systems, but certainly for testing environments in VMs
|
||||
and such, as it allows us to boot up instantly with fully initialized entropy
|
||||
pool even if RNG pass-thru is not available.
|
||||
|
||||
* Support ProtectProc= or so, using: https://patchwork.kernel.org/cover/11310197/
|
||||
|
||||
* if /usr/bin/swapoff fails due to OOM, log a friendly explanatory message about it
|
||||
|
||||
* build short web pages out of each catalog entry, build them along with man
|
||||
|
|
|
@ -312,6 +312,10 @@ sensor:modalias:platform:cros-ec-accel:dmi:*:svnGOOGLE*
|
|||
sensor:modalias:platform:cros-ec-accel:dmi:*:svnGoogle:pnCaroline*
|
||||
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
|
||||
|
||||
# Dell Inspiron Chromebook 14 2-in-1
|
||||
sensor:modalias:platform:cros-ec-accel:dmi:*svnGoogle:pnVayne*
|
||||
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1
|
||||
|
||||
#########################################
|
||||
# GP-electronic
|
||||
#########################################
|
||||
|
|
|
@ -177,6 +177,13 @@
|
|||
<option>size=</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>bitlk</option></term>
|
||||
|
||||
<listitem><para>Decrypt Bitlocker drive. Encryption parameters
|
||||
are deduced by cryptsetup from Bitlocker header.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>_netdev</option></term>
|
||||
|
||||
|
|
|
@ -273,7 +273,8 @@
|
|||
<term><varname>rd.udev.event_timeout=</varname></term>
|
||||
<term><varname>udev.timeout_signal=</varname></term>
|
||||
<term><varname>rd.udev.timeout_signal=</varname></term>
|
||||
|
||||
<term><varname>udev.blockdev_read_only</varname></term>
|
||||
<term><varname>rd.udev.blockdev_read_only</varname></term>
|
||||
<term><varname>net.ifnames=</varname></term>
|
||||
<term><varname>net.naming-scheme=</varname></term>
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-c=</option></term>
|
||||
<term><option>-c</option></term>
|
||||
<term><option>--children-max=</option></term>
|
||||
<listitem>
|
||||
<para>Limit the number of events executed in parallel.</para>
|
||||
|
@ -85,7 +85,7 @@
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-e=</option></term>
|
||||
<term><option>-e</option></term>
|
||||
<term><option>--exec-delay=</option></term>
|
||||
<listitem>
|
||||
<para>Delay the execution of <varname>RUN</varname>
|
||||
|
@ -97,7 +97,7 @@
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-t=</option></term>
|
||||
<term><option>-t</option></term>
|
||||
<term><option>--event-timeout=</option></term>
|
||||
<listitem>
|
||||
<para>Set the number of seconds to wait for events to finish. After
|
||||
|
@ -121,7 +121,7 @@
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-N=</option></term>
|
||||
<term><option>-N</option></term>
|
||||
<term><option>--resolve-names=</option></term>
|
||||
<listitem>
|
||||
<para>Specify when systemd-udevd should resolve names of users and groups.
|
||||
|
@ -140,8 +140,8 @@
|
|||
|
||||
<refsect1><title>Kernel command line</title>
|
||||
<variablelist class='kernel-commandline-options'>
|
||||
<para>Parameters starting with "rd." will be read when
|
||||
<command>systemd-udevd</command> is used in an initrd.</para>
|
||||
<para>Parameters prefixed with "rd." will be read when <command>systemd-udevd</command> is used in an
|
||||
initrd, those without will be processed both in the initrd and on the host.</para>
|
||||
<varlistentry>
|
||||
<term><varname>udev.log_priority=</varname></term>
|
||||
<term><varname>rd.udev.log_priority=</varname></term>
|
||||
|
@ -184,6 +184,22 @@
|
|||
setting in the configuration file and the one on the program command line.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>udev.blockdev_read_only</varname></term>
|
||||
<term><varname>rd.udev.blockdev_read_only</varname></term>
|
||||
<listitem>
|
||||
<para>If specified, mark all physical block devices read-only as they appear. Synthetic block
|
||||
devices (such as loopback block devices or device mapper devices) are left as they are. This is
|
||||
useful to guarantee that the contents of physical block devices remains unmodified during runtime,
|
||||
for example to implement fully stateless systems, for testing or for recovery situations where
|
||||
corrupted file systems shall not be corrupted further through accidental modification.</para>
|
||||
|
||||
<para>A block device may be marked writable again by issuing the <command>blockdev
|
||||
--setrw</command> command, see <citerefentry
|
||||
project='man-pages'><refentrytitle>blockdev</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
for details.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>net.ifnames=</varname></term>
|
||||
<listitem>
|
||||
|
|
|
@ -560,16 +560,12 @@
|
|||
|
||||
<varlistentry>
|
||||
<term><varname>TimeoutStartSec=</varname></term>
|
||||
<listitem><para>Configures the time to wait for start-up. If a
|
||||
daemon service does not signal start-up completion within the
|
||||
configured time, the service will be considered failed and
|
||||
will be shut down again. Takes a unit-less value in seconds,
|
||||
or a time span value such as "5min 20s". Pass
|
||||
<literal>infinity</literal> to disable the timeout logic. Defaults to
|
||||
<varname>DefaultTimeoutStartSec=</varname> from the manager
|
||||
configuration file, except when
|
||||
<varname>Type=oneshot</varname> is used, in which case the
|
||||
timeout is disabled by default (see
|
||||
<listitem><para>Configures the time to wait for start-up. If a daemon service does not signal start-up
|
||||
completion within the configured time, the service will be considered failed and will be shut down again. The
|
||||
precise action depends on the <varname>TimeoutStartFailureMode=</varname> option. Takes a unit-less value in
|
||||
seconds, or a time span value such as "5min 20s". Pass <literal>infinity</literal> to disable the timeout logic.
|
||||
Defaults to <varname>DefaultTimeoutStartSec=</varname> from the manager configuration file, except when
|
||||
<varname>Type=oneshot</varname> is used, in which case the timeout is disabled by default (see
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
</para>
|
||||
|
||||
|
@ -588,7 +584,8 @@
|
|||
<listitem><para>This option serves two purposes. First, it configures the time to wait for each
|
||||
<varname>ExecStop=</varname> command. If any of them times out, subsequent <varname>ExecStop=</varname> commands
|
||||
are skipped and the service will be terminated by <constant>SIGTERM</constant>. If no <varname>ExecStop=</varname>
|
||||
commands are specified, the service gets the <constant>SIGTERM</constant> immediately. Second, it configures the time
|
||||
commands are specified, the service gets the <constant>SIGTERM</constant> immediately. This default behavior
|
||||
can be changed by the <varname>TimeoutStopFailureMode=</varname> option. Second, it configures the time
|
||||
to wait for the service itself to stop. If it doesn't terminate in the specified time, it will be forcibly terminated
|
||||
by <constant>SIGKILL</constant> (see <varname>KillMode=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
|
@ -646,6 +643,28 @@
|
|||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>TimeoutStartFailureMode=</varname></term>
|
||||
<term><varname>TimeoutStopFailureMode=</varname></term>
|
||||
|
||||
<listitem><para>These options configure the action that is taken in case a daemon service does not signal
|
||||
start-up within its configured <varname>TimeoutStartSec=</varname>, respectively if it does not stop within
|
||||
<varname>TimeoutStopSec=</varname>. Takes one of <option>terminate</option>, <option>abort</option> and
|
||||
<option>kill</option>. Both options default to <option>terminate</option>.</para>
|
||||
|
||||
<para>If <option>terminate</option> is set the service will be gracefully terminated by sending the signal
|
||||
specified in <varname>KillSignal=</varname> (defaults to <constant>SIGTERM</constant>, see
|
||||
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>). If the
|
||||
service does not terminate the <varname>FinalKillSignal=</varname> is sent after
|
||||
<varname>TimeoutStopSec=</varname>. If <option>abort</option> is set, <varname>WatchdogSignal=</varname> is sent
|
||||
instead and <varname>TimeoutAbortSec=</varname> applies before sending <varname>FinalKillSignal=</varname>.
|
||||
This setting may be used to analyze services that fail to start-up or shut-down intermittently.
|
||||
By using <option>kill</option> the service is immediately terminated by sending
|
||||
<varname>FinalKillSignal=</varname> without any further timeout. This setting can be used to expedite the
|
||||
shutdown of failing services.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RuntimeMaxSec=</varname></term>
|
||||
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
# hostctl(1) completion -*- shell-script -*-
|
||||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# systemd is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
__contains_word () {
|
||||
local w word=$1; shift
|
||||
for w in "$@"; do
|
||||
[[ $w = "$word" ]] && return
|
||||
done
|
||||
}
|
||||
|
||||
__get_machines() {
|
||||
local a b
|
||||
machinectl list --full --no-legend --no-pager 2>/dev/null |
|
||||
{ while read a b; do echo " $a"; done; };
|
||||
}
|
||||
|
||||
__get_homes() {
|
||||
homectl --no-pager --no-legend list 2>/dev/null
|
||||
}
|
||||
|
||||
_homectl() {
|
||||
local i verb comps
|
||||
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
local -A OPTS=(
|
||||
[STANDALONE]='-h --help --version
|
||||
--no-pager --no-legend --no-ask-password
|
||||
-j -E -P'
|
||||
[ARG]=' -H --host
|
||||
-M --machine
|
||||
--identity
|
||||
--json
|
||||
--export-format
|
||||
-c --real-name
|
||||
--realm
|
||||
--email-address
|
||||
--location
|
||||
--icon-name
|
||||
-d --home-dir
|
||||
--uid
|
||||
-G --member-of
|
||||
--skel
|
||||
--shell
|
||||
--setenv
|
||||
--timezone
|
||||
--language
|
||||
--ssh-authorized-keys
|
||||
--pkcs11-token-uri
|
||||
--locked
|
||||
--not-before
|
||||
--not-after
|
||||
--rate-limit-interval
|
||||
--rate-limit-burst
|
||||
--password-hint
|
||||
--enforce-password-policy
|
||||
--password-change-now
|
||||
--password-change-min
|
||||
--password-change-max
|
||||
--password-change-warn
|
||||
--password-change-inactive
|
||||
--disk-size
|
||||
--access-mode
|
||||
--umask
|
||||
--nice
|
||||
--rlimit
|
||||
--tasks-max
|
||||
--memory-high
|
||||
--memory-max
|
||||
--cpu-weight
|
||||
--io-weight
|
||||
--storage
|
||||
--image-path
|
||||
--fs-type
|
||||
--luks-discard
|
||||
--luks-offline-discard
|
||||
--luks-cipher
|
||||
--luks-cipher-mode
|
||||
--luks-volume-key-size
|
||||
--luks-pbkdf-type
|
||||
--luks-pbkdf-hash-algorithm
|
||||
--luks-pbkdf-time-cost
|
||||
--luks-pbkdf-memory-cost
|
||||
--luks-pbkdf-parallel-threads
|
||||
--nosuid
|
||||
--nodev
|
||||
--noexec
|
||||
--cifs-domain
|
||||
--cifs-user-name
|
||||
--cifs-service
|
||||
--stop-delay
|
||||
--kill-processes
|
||||
--auto-login'
|
||||
)
|
||||
|
||||
if __contains_word "$prev" ${OPTS[ARG]}; then
|
||||
case $prev in
|
||||
--host|-H)
|
||||
comps=$(compgen -A hostname)
|
||||
;;
|
||||
--machine|-M)
|
||||
comps=$( __get_machines )
|
||||
;;
|
||||
--identity|--image-path)
|
||||
comps=$(compgen -A file -- "$cur" )
|
||||
compopt -o filenames
|
||||
;;
|
||||
--json)
|
||||
comps='pretty short off'
|
||||
;;
|
||||
--export-format)
|
||||
comps='full stripped minimal'
|
||||
;;
|
||||
--locked|--enforce-password-policy|--password-change-now|--luks-discard|--luks-offline-discard|--nosuid|--nodev|--noexec|--kill-processes|--auto-login)
|
||||
comps='yes no'
|
||||
;;
|
||||
-d|--home-dir|--skel)
|
||||
comps=$(compgen -A directory -- "$cur" )
|
||||
compopt -o dirnames
|
||||
;;
|
||||
-G|--member-of)
|
||||
comps=$(compgen -A group -- "$cur" )
|
||||
;;
|
||||
--shell)
|
||||
comps=$(cat /etc/shells)
|
||||
;;
|
||||
--fs-type)
|
||||
comps='ext4 xfs btrsf'
|
||||
;;
|
||||
--cifs-user-name)
|
||||
comps=$(compgen -A user -- "$cur" )
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$cur" = -* ]]; then
|
||||
COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
local -A VERBS=(
|
||||
[STANDALONE]='list lock-all'
|
||||
[CREATE]='create'
|
||||
[NAMES]='activate deactivate inspect authenticate remove lock unlock'
|
||||
[NAME]='update passwd'
|
||||
[RESIZE]='resize'
|
||||
[WITH]='with'
|
||||
)
|
||||
|
||||
for ((i=0; i < COMP_CWORD; i++)); do
|
||||
if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then
|
||||
verb=${COMP_WORDS[i]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z $verb ]]; then
|
||||
comps=${VERBS[*]}
|
||||
elif __contains_word "$verb" ${VERBS[NAME]}; then
|
||||
comps=$(__get_homes)
|
||||
elif __contains_word "$verb" ${VERBS[NAMES]}; then
|
||||
comps=$(__get_homes)
|
||||
elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[CREATE]} ${VERBS[RESIZE]}; then
|
||||
comps=$(__get_homes)
|
||||
elif __contains_word "$verb" ${VERBS[WITH]}; then
|
||||
comps=$(__get_homes)
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -F _homectl homectl
|
|
@ -72,7 +72,6 @@ _loginctl () {
|
|||
return 0
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$cur" = -* ]]; then
|
||||
COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
|
||||
return 0
|
||||
|
|
|
@ -145,12 +145,7 @@ struct hashmap_debug_info {
|
|||
/* Tracks all existing hashmaps. Get at it from gdb. See sd_dump_hashmaps.py */
|
||||
static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list);
|
||||
static pthread_mutex_t hashmap_debug_list_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#define HASHMAP_DEBUG_FIELDS struct hashmap_debug_info debug;
|
||||
|
||||
#else /* !ENABLE_DEBUG_HASHMAP */
|
||||
#define HASHMAP_DEBUG_FIELDS
|
||||
#endif /* ENABLE_DEBUG_HASHMAP */
|
||||
#endif
|
||||
|
||||
enum HashmapType {
|
||||
HASHMAP_TYPE_PLAIN,
|
||||
|
@ -212,7 +207,10 @@ struct HashmapBase {
|
|||
bool from_pool:1; /* whether was allocated from mempool */
|
||||
bool dirty:1; /* whether dirtied since last iterated_cache_get() */
|
||||
bool cached:1; /* whether this hashmap is being cached */
|
||||
HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */
|
||||
|
||||
#if ENABLE_DEBUG_HASHMAP
|
||||
struct hashmap_debug_info debug;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Specific hash types
|
||||
|
@ -254,7 +252,7 @@ struct hashmap_type_info {
|
|||
unsigned n_direct_buckets;
|
||||
};
|
||||
|
||||
static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
|
||||
static _used_ const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
|
||||
[HASHMAP_TYPE_PLAIN] = {
|
||||
.head_size = sizeof(Hashmap),
|
||||
.entry_size = sizeof(struct plain_hashmap_entry),
|
||||
|
@ -707,7 +705,7 @@ static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
|
|||
: hashmap_iterate_in_internal_order(h, i);
|
||||
}
|
||||
|
||||
bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key) {
|
||||
bool _hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key) {
|
||||
struct hashmap_base_entry *e;
|
||||
void *data;
|
||||
unsigned idx;
|
||||
|
@ -733,7 +731,7 @@ bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const v
|
|||
}
|
||||
|
||||
bool set_iterate(const Set *s, Iterator *i, void **value) {
|
||||
return internal_hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL);
|
||||
return _hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL);
|
||||
}
|
||||
|
||||
#define HASHMAP_FOREACH_IDX(idx, h, i) \
|
||||
|
@ -741,7 +739,7 @@ bool set_iterate(const Set *s, Iterator *i, void **value) {
|
|||
(idx != IDX_NIL); \
|
||||
(idx) = hashmap_iterate_entry((h), &(i)))
|
||||
|
||||
IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h) {
|
||||
IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h) {
|
||||
IteratedCache *cache;
|
||||
|
||||
assert(h);
|
||||
|
@ -809,15 +807,15 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
|
|||
return h;
|
||||
}
|
||||
|
||||
Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
Hashmap *_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
|
||||
}
|
||||
|
||||
OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
|
||||
}
|
||||
|
||||
Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
Set *_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
|
||||
}
|
||||
|
||||
|
@ -838,15 +836,15 @@ static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops
|
|||
return 0;
|
||||
}
|
||||
|
||||
int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
int _hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
|
||||
}
|
||||
|
||||
int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
|
||||
}
|
||||
|
||||
int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
|
||||
return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
|
||||
}
|
||||
|
||||
|
@ -868,16 +866,16 @@ static void hashmap_free_no_clear(HashmapBase *h) {
|
|||
free(h);
|
||||
}
|
||||
|
||||
HashmapBase *internal_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
|
||||
HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
|
||||
if (h) {
|
||||
internal_hashmap_clear(h, default_free_key, default_free_value);
|
||||
_hashmap_clear(h, default_free_key, default_free_value);
|
||||
hashmap_free_no_clear(h);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
|
||||
void _hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
|
||||
free_func_t free_key, free_value;
|
||||
if (!h)
|
||||
return;
|
||||
|
@ -891,11 +889,11 @@ void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_f
|
|||
* hash table, and only then call the destructor functions. If these destructors then try to unregister
|
||||
* themselves from our hash table a second time, the entry is already gone. */
|
||||
|
||||
while (internal_hashmap_size(h) > 0) {
|
||||
while (_hashmap_size(h) > 0) {
|
||||
void *k = NULL;
|
||||
void *v;
|
||||
|
||||
v = internal_hashmap_first_key_and_value(h, true, &k);
|
||||
v = _hashmap_first_key_and_value(h, true, &k);
|
||||
|
||||
if (free_key)
|
||||
free_key(k);
|
||||
|
@ -1301,7 +1299,7 @@ int hashmap_update(Hashmap *h, const void *key, void *value) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void *internal_hashmap_get(HashmapBase *h, const void *key) {
|
||||
void *_hashmap_get(HashmapBase *h, const void *key) {
|
||||
struct hashmap_base_entry *e;
|
||||
unsigned hash, idx;
|
||||
|
||||
|
@ -1336,7 +1334,7 @@ void *hashmap_get2(Hashmap *h, const void *key, void **key2) {
|
|||
return e->value;
|
||||
}
|
||||
|
||||
bool internal_hashmap_contains(HashmapBase *h, const void *key) {
|
||||
bool _hashmap_contains(HashmapBase *h, const void *key) {
|
||||
unsigned hash;
|
||||
|
||||
if (!h)
|
||||
|
@ -1346,7 +1344,7 @@ bool internal_hashmap_contains(HashmapBase *h, const void *key) {
|
|||
return bucket_scan(h, hash, key) != IDX_NIL;
|
||||
}
|
||||
|
||||
void *internal_hashmap_remove(HashmapBase *h, const void *key) {
|
||||
void *_hashmap_remove(HashmapBase *h, const void *key) {
|
||||
struct hashmap_base_entry *e;
|
||||
unsigned hash, idx;
|
||||
void *data;
|
||||
|
@ -1484,7 +1482,7 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_
|
|||
return 0;
|
||||
}
|
||||
|
||||
void *internal_hashmap_remove_value(HashmapBase *h, const void *key, void *value) {
|
||||
void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value) {
|
||||
struct hashmap_base_entry *e;
|
||||
unsigned hash, idx;
|
||||
|
||||
|
@ -1514,7 +1512,7 @@ static unsigned find_first_entry(HashmapBase *h) {
|
|||
return hashmap_iterate_entry(h, &i);
|
||||
}
|
||||
|
||||
void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) {
|
||||
void *_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) {
|
||||
struct hashmap_base_entry *e;
|
||||
void *key, *data;
|
||||
unsigned idx;
|
||||
|
@ -1539,21 +1537,21 @@ void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **r
|
|||
return data;
|
||||
}
|
||||
|
||||
unsigned internal_hashmap_size(HashmapBase *h) {
|
||||
unsigned _hashmap_size(HashmapBase *h) {
|
||||
if (!h)
|
||||
return 0;
|
||||
|
||||
return n_entries(h);
|
||||
}
|
||||
|
||||
unsigned internal_hashmap_buckets(HashmapBase *h) {
|
||||
unsigned _hashmap_buckets(HashmapBase *h) {
|
||||
if (!h)
|
||||
return 0;
|
||||
|
||||
return n_buckets(h);
|
||||
}
|
||||
|
||||
int internal_hashmap_merge(Hashmap *h, Hashmap *other) {
|
||||
int _hashmap_merge(Hashmap *h, Hashmap *other) {
|
||||
Iterator i;
|
||||
unsigned idx;
|
||||
|
||||
|
@ -1589,7 +1587,7 @@ int set_merge(Set *s, Set *other) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) {
|
||||
int _hashmap_reserve(HashmapBase *h, unsigned entries_add) {
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
|
@ -1607,7 +1605,7 @@ int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) {
|
|||
* Returns: 0 on success.
|
||||
* -ENOMEM on alloc failure, in which case no move has been done.
|
||||
*/
|
||||
int internal_hashmap_move(HashmapBase *h, HashmapBase *other) {
|
||||
int _hashmap_move(HashmapBase *h, HashmapBase *other) {
|
||||
struct swap_entries swap;
|
||||
struct hashmap_base_entry *e, *n;
|
||||
Iterator i;
|
||||
|
@ -1652,7 +1650,7 @@ int internal_hashmap_move(HashmapBase *h, HashmapBase *other) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
|
||||
int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
|
||||
struct swap_entries swap;
|
||||
unsigned h_hash, other_hash, idx;
|
||||
struct hashmap_base_entry *e, *n;
|
||||
|
@ -1689,7 +1687,7 @@ int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *ke
|
|||
return 0;
|
||||
}
|
||||
|
||||
HashmapBase *internal_hashmap_copy(HashmapBase *h) {
|
||||
HashmapBase *_hashmap_copy(HashmapBase *h) {
|
||||
HashmapBase *copy;
|
||||
int r;
|
||||
|
||||
|
@ -1712,14 +1710,14 @@ HashmapBase *internal_hashmap_copy(HashmapBase *h) {
|
|||
}
|
||||
|
||||
if (r < 0) {
|
||||
internal_hashmap_free(copy, false, false);
|
||||
_hashmap_free(copy, false, false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
char **internal_hashmap_get_strv(HashmapBase *h) {
|
||||
char **_hashmap_get_strv(HashmapBase *h) {
|
||||
char **sv;
|
||||
Iterator i;
|
||||
unsigned idx, n;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* will be treated as empty hashmap for all read operations. That way it is not
|
||||
* necessary to instantiate an object for each Hashmap use.
|
||||
*
|
||||
* If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap),
|
||||
* If ENABLE_DEBUG_HASHMAP is defined (by configuring with -Ddebug-extra=hashmap),
|
||||
* the implementation will:
|
||||
* - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py)
|
||||
* - perform extra checks for invalid use of iterators
|
||||
|
@ -24,10 +24,9 @@
|
|||
|
||||
typedef void* (*hashmap_destroy_t)(void *p);
|
||||
|
||||
/* The base type for all hashmap and set types. Many functions in the
|
||||
* implementation take (HashmapBase*) parameters and are run-time polymorphic,
|
||||
* though the API is not meant to be polymorphic (do not call functions
|
||||
* internal_*() directly). */
|
||||
/* The base type for all hashmap and set types. Many functions in the implementation take (HashmapBase*)
|
||||
* parameters and are run-time polymorphic, though the API is not meant to be polymorphic (do not call
|
||||
* underscore-prefixed functions directly). */
|
||||
typedef struct HashmapBase HashmapBase;
|
||||
|
||||
/* Specific hashmap/set types */
|
||||
|
@ -84,10 +83,10 @@ typedef struct {
|
|||
# define HASHMAP_DEBUG_PASS_ARGS
|
||||
#endif
|
||||
|
||||
Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
#define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
Hashmap *_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define hashmap_new(ops) _hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
#define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
#define hashmap_free_and_replace(a, b) \
|
||||
({ \
|
||||
|
@ -97,57 +96,57 @@ OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HA
|
|||
0; \
|
||||
})
|
||||
|
||||
HashmapBase *internal_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
static inline Hashmap *hashmap_free(Hashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, NULL);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL);
|
||||
}
|
||||
static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, NULL);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL);
|
||||
}
|
||||
|
||||
static inline Hashmap *hashmap_free_free(Hashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, free);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free);
|
||||
}
|
||||
static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, free);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free);
|
||||
}
|
||||
|
||||
static inline Hashmap *hashmap_free_free_key(Hashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, NULL);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL);
|
||||
}
|
||||
static inline OrderedHashmap *ordered_hashmap_free_free_key(OrderedHashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, NULL);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL);
|
||||
}
|
||||
|
||||
static inline Hashmap *hashmap_free_free_free(Hashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, free);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), free, free);
|
||||
}
|
||||
static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) {
|
||||
return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, free);
|
||||
return (void*) _hashmap_free(HASHMAP_BASE(h), free, free);
|
||||
}
|
||||
|
||||
IteratedCache *iterated_cache_free(IteratedCache *cache);
|
||||
int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries);
|
||||
|
||||
HashmapBase *internal_hashmap_copy(HashmapBase *h);
|
||||
HashmapBase *_hashmap_copy(HashmapBase *h);
|
||||
static inline Hashmap *hashmap_copy(Hashmap *h) {
|
||||
return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
|
||||
return (Hashmap*) _hashmap_copy(HASHMAP_BASE(h));
|
||||
}
|
||||
static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) {
|
||||
return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
|
||||
return (OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h));
|
||||
}
|
||||
|
||||
int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
#define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
int _hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define hashmap_ensure_allocated(h, ops) _hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
#define ordered_hashmap_ensure_allocated(h, ops) _ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h);
|
||||
IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h);
|
||||
static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) {
|
||||
return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h));
|
||||
return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h));
|
||||
}
|
||||
static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) {
|
||||
return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h));
|
||||
return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h));
|
||||
}
|
||||
|
||||
int hashmap_put(Hashmap *h, const void *key, void *value);
|
||||
|
@ -167,12 +166,12 @@ static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, vo
|
|||
return hashmap_replace(PLAIN_HASHMAP(h), key, value);
|
||||
}
|
||||
|
||||
void *internal_hashmap_get(HashmapBase *h, const void *key);
|
||||
void *_hashmap_get(HashmapBase *h, const void *key);
|
||||
static inline void *hashmap_get(Hashmap *h, const void *key) {
|
||||
return internal_hashmap_get(HASHMAP_BASE(h), key);
|
||||
return _hashmap_get(HASHMAP_BASE(h), key);
|
||||
}
|
||||
static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) {
|
||||
return internal_hashmap_get(HASHMAP_BASE(h), key);
|
||||
return _hashmap_get(HASHMAP_BASE(h), key);
|
||||
}
|
||||
|
||||
void *hashmap_get2(Hashmap *h, const void *key, void **rkey);
|
||||
|
@ -180,20 +179,20 @@ static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, voi
|
|||
return hashmap_get2(PLAIN_HASHMAP(h), key, rkey);
|
||||
}
|
||||
|
||||
bool internal_hashmap_contains(HashmapBase *h, const void *key);
|
||||
bool _hashmap_contains(HashmapBase *h, const void *key);
|
||||
static inline bool hashmap_contains(Hashmap *h, const void *key) {
|
||||
return internal_hashmap_contains(HASHMAP_BASE(h), key);
|
||||
return _hashmap_contains(HASHMAP_BASE(h), key);
|
||||
}
|
||||
static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) {
|
||||
return internal_hashmap_contains(HASHMAP_BASE(h), key);
|
||||
return _hashmap_contains(HASHMAP_BASE(h), key);
|
||||
}
|
||||
|
||||
void *internal_hashmap_remove(HashmapBase *h, const void *key);
|
||||
void *_hashmap_remove(HashmapBase *h, const void *key);
|
||||
static inline void *hashmap_remove(Hashmap *h, const void *key) {
|
||||
return internal_hashmap_remove(HASHMAP_BASE(h), key);
|
||||
return _hashmap_remove(HASHMAP_BASE(h), key);
|
||||
}
|
||||
static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) {
|
||||
return internal_hashmap_remove(HASHMAP_BASE(h), key);
|
||||
return _hashmap_remove(HASHMAP_BASE(h), key);
|
||||
}
|
||||
|
||||
void *hashmap_remove2(Hashmap *h, const void *key, void **rkey);
|
||||
|
@ -201,9 +200,9 @@ static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key,
|
|||
return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey);
|
||||
}
|
||||
|
||||
void *internal_hashmap_remove_value(HashmapBase *h, const void *key, void *value);
|
||||
void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value);
|
||||
static inline void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
|
||||
return internal_hashmap_remove_value(HASHMAP_BASE(h), key, value);
|
||||
return _hashmap_remove_value(HASHMAP_BASE(h), key, value);
|
||||
}
|
||||
|
||||
static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) {
|
||||
|
@ -222,41 +221,41 @@ static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const vo
|
|||
|
||||
/* Since merging data from a OrderedHashmap into a Hashmap or vice-versa
|
||||
* should just work, allow this by having looser type-checking here. */
|
||||
int internal_hashmap_merge(Hashmap *h, Hashmap *other);
|
||||
#define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other))
|
||||
int _hashmap_merge(Hashmap *h, Hashmap *other);
|
||||
#define hashmap_merge(h, other) _hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other))
|
||||
#define ordered_hashmap_merge(h, other) hashmap_merge(h, other)
|
||||
|
||||
int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add);
|
||||
int _hashmap_reserve(HashmapBase *h, unsigned entries_add);
|
||||
static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) {
|
||||
return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
|
||||
return _hashmap_reserve(HASHMAP_BASE(h), entries_add);
|
||||
}
|
||||
static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) {
|
||||
return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
|
||||
return _hashmap_reserve(HASHMAP_BASE(h), entries_add);
|
||||
}
|
||||
|
||||
int internal_hashmap_move(HashmapBase *h, HashmapBase *other);
|
||||
int _hashmap_move(HashmapBase *h, HashmapBase *other);
|
||||
/* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */
|
||||
static inline int hashmap_move(Hashmap *h, Hashmap *other) {
|
||||
return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
|
||||
return _hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
|
||||
}
|
||||
static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) {
|
||||
return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
|
||||
return _hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
|
||||
}
|
||||
|
||||
int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key);
|
||||
int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key);
|
||||
static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
|
||||
return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
|
||||
return _hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
|
||||
}
|
||||
static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) {
|
||||
return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
|
||||
return _hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
|
||||
}
|
||||
|
||||
unsigned internal_hashmap_size(HashmapBase *h) _pure_;
|
||||
unsigned _hashmap_size(HashmapBase *h) _pure_;
|
||||
static inline unsigned hashmap_size(Hashmap *h) {
|
||||
return internal_hashmap_size(HASHMAP_BASE(h));
|
||||
return _hashmap_size(HASHMAP_BASE(h));
|
||||
}
|
||||
static inline unsigned ordered_hashmap_size(OrderedHashmap *h) {
|
||||
return internal_hashmap_size(HASHMAP_BASE(h));
|
||||
return _hashmap_size(HASHMAP_BASE(h));
|
||||
}
|
||||
|
||||
static inline bool hashmap_isempty(Hashmap *h) {
|
||||
|
@ -266,49 +265,49 @@ static inline bool ordered_hashmap_isempty(OrderedHashmap *h) {
|
|||
return ordered_hashmap_size(h) == 0;
|
||||
}
|
||||
|
||||
unsigned internal_hashmap_buckets(HashmapBase *h) _pure_;
|
||||
unsigned _hashmap_buckets(HashmapBase *h) _pure_;
|
||||
static inline unsigned hashmap_buckets(Hashmap *h) {
|
||||
return internal_hashmap_buckets(HASHMAP_BASE(h));
|
||||
return _hashmap_buckets(HASHMAP_BASE(h));
|
||||
}
|
||||
static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
|
||||
return internal_hashmap_buckets(HASHMAP_BASE(h));
|
||||
return _hashmap_buckets(HASHMAP_BASE(h));
|
||||
}
|
||||
|
||||
bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
|
||||
bool _hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
|
||||
static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) {
|
||||
return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
|
||||
return _hashmap_iterate(HASHMAP_BASE(h), i, value, key);
|
||||
}
|
||||
static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) {
|
||||
return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
|
||||
return _hashmap_iterate(HASHMAP_BASE(h), i, value, key);
|
||||
}
|
||||
|
||||
void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
void _hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
|
||||
static inline void hashmap_clear(Hashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), NULL, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(h), NULL, NULL);
|
||||
}
|
||||
static inline void ordered_hashmap_clear(OrderedHashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), NULL, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(h), NULL, NULL);
|
||||
}
|
||||
|
||||
static inline void hashmap_clear_free(Hashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), NULL, free);
|
||||
_hashmap_clear(HASHMAP_BASE(h), NULL, free);
|
||||
}
|
||||
static inline void ordered_hashmap_clear_free(OrderedHashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), NULL, free);
|
||||
_hashmap_clear(HASHMAP_BASE(h), NULL, free);
|
||||
}
|
||||
|
||||
static inline void hashmap_clear_free_key(Hashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), free, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(h), free, NULL);
|
||||
}
|
||||
static inline void ordered_hashmap_clear_free_key(OrderedHashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), free, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(h), free, NULL);
|
||||
}
|
||||
|
||||
static inline void hashmap_clear_free_free(Hashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), free, free);
|
||||
_hashmap_clear(HASHMAP_BASE(h), free, free);
|
||||
}
|
||||
static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(h), free, free);
|
||||
_hashmap_clear(HASHMAP_BASE(h), free, free);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -322,50 +321,50 @@ static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
|
|||
* the first entry is O(1).
|
||||
*/
|
||||
|
||||
void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key);
|
||||
void *_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key);
|
||||
static inline void *hashmap_steal_first_key_and_value(Hashmap *h, void **ret) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
|
||||
}
|
||||
static inline void *ordered_hashmap_steal_first_key_and_value(OrderedHashmap *h, void **ret) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret);
|
||||
}
|
||||
static inline void *hashmap_first_key_and_value(Hashmap *h, void **ret) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
|
||||
}
|
||||
static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void **ret) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret);
|
||||
}
|
||||
|
||||
static inline void *hashmap_steal_first(Hashmap *h) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
|
||||
}
|
||||
static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL);
|
||||
}
|
||||
static inline void *hashmap_first(Hashmap *h) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
|
||||
}
|
||||
static inline void *ordered_hashmap_first(OrderedHashmap *h) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL);
|
||||
}
|
||||
|
||||
static inline void *internal_hashmap_first_key(HashmapBase *h, bool remove) {
|
||||
static inline void *_hashmap_first_key(HashmapBase *h, bool remove) {
|
||||
void *key = NULL;
|
||||
|
||||
(void) internal_hashmap_first_key_and_value(HASHMAP_BASE(h), remove, &key);
|
||||
(void) _hashmap_first_key_and_value(HASHMAP_BASE(h), remove, &key);
|
||||
return key;
|
||||
}
|
||||
static inline void *hashmap_steal_first_key(Hashmap *h) {
|
||||
return internal_hashmap_first_key(HASHMAP_BASE(h), true);
|
||||
return _hashmap_first_key(HASHMAP_BASE(h), true);
|
||||
}
|
||||
static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) {
|
||||
return internal_hashmap_first_key(HASHMAP_BASE(h), true);
|
||||
return _hashmap_first_key(HASHMAP_BASE(h), true);
|
||||
}
|
||||
static inline void *hashmap_first_key(Hashmap *h) {
|
||||
return internal_hashmap_first_key(HASHMAP_BASE(h), false);
|
||||
return _hashmap_first_key(HASHMAP_BASE(h), false);
|
||||
}
|
||||
static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
|
||||
return internal_hashmap_first_key(HASHMAP_BASE(h), false);
|
||||
return _hashmap_first_key(HASHMAP_BASE(h), false);
|
||||
}
|
||||
|
||||
#define hashmap_clear_with_destructor(_s, _f) \
|
||||
|
@ -394,12 +393,12 @@ static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
|
|||
/* no hashmap_next */
|
||||
void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
|
||||
|
||||
char **internal_hashmap_get_strv(HashmapBase *h);
|
||||
char **_hashmap_get_strv(HashmapBase *h);
|
||||
static inline char **hashmap_get_strv(Hashmap *h) {
|
||||
return internal_hashmap_get_strv(HASHMAP_BASE(h));
|
||||
return _hashmap_get_strv(HASHMAP_BASE(h));
|
||||
}
|
||||
static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
|
||||
return internal_hashmap_get_strv(HASHMAP_BASE(h));
|
||||
return _hashmap_get_strv(HASHMAP_BASE(h));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -338,6 +338,16 @@ bool fstype_is_api_vfs(const char *fstype) {
|
|||
"tracefs");
|
||||
}
|
||||
|
||||
bool fstype_is_blockdev_backed(const char *fstype) {
|
||||
const char *x;
|
||||
|
||||
x = startswith(fstype, "fuse.");
|
||||
if (x)
|
||||
fstype = x;
|
||||
|
||||
return !streq(fstype, "9p") && !fstype_is_network(fstype) && !fstype_is_api_vfs(fstype);
|
||||
}
|
||||
|
||||
bool fstype_is_ro(const char *fstype) {
|
||||
/* All Linux file systems that are necessarily read-only */
|
||||
return STR_IN_SET(fstype,
|
||||
|
|
|
@ -14,6 +14,7 @@ int path_is_mount_point(const char *path, const char *root, int flags);
|
|||
|
||||
bool fstype_is_network(const char *fstype);
|
||||
bool fstype_is_api_vfs(const char *fstype);
|
||||
bool fstype_is_blockdev_backed(const char *fstype);
|
||||
bool fstype_is_ro(const char *fsype);
|
||||
bool fstype_can_discard(const char *fstype);
|
||||
bool fstype_can_uid_gid(const char *fstype);
|
||||
|
|
|
@ -59,7 +59,7 @@ static inline void* ordered_set_steal_first(OrderedSet *s) {
|
|||
}
|
||||
|
||||
static inline char **ordered_set_get_strv(OrderedSet *s) {
|
||||
return internal_hashmap_get_strv(HASHMAP_BASE((OrderedHashmap*) s));
|
||||
return _hashmap_get_strv(HASHMAP_BASE((OrderedHashmap*) s));
|
||||
}
|
||||
|
||||
int ordered_set_consume(OrderedSet *s, void *p);
|
||||
|
|
|
@ -13,40 +13,40 @@
|
|||
0; \
|
||||
})
|
||||
|
||||
Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
Set *_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
static inline Set *set_free(Set *s) {
|
||||
return (Set*) internal_hashmap_free(HASHMAP_BASE(s), NULL, NULL);
|
||||
return (Set*) _hashmap_free(HASHMAP_BASE(s), NULL, NULL);
|
||||
}
|
||||
|
||||
static inline Set *set_free_free(Set *s) {
|
||||
return (Set*) internal_hashmap_free(HASHMAP_BASE(s), free, NULL);
|
||||
return (Set*) _hashmap_free(HASHMAP_BASE(s), free, NULL);
|
||||
}
|
||||
|
||||
/* no set_free_free_free */
|
||||
|
||||
static inline Set *set_copy(Set *s) {
|
||||
return (Set*) internal_hashmap_copy(HASHMAP_BASE(s));
|
||||
return (Set*) _hashmap_copy(HASHMAP_BASE(s));
|
||||
}
|
||||
|
||||
int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
|
||||
#define set_ensure_allocated(h, ops) _set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
||||
int set_put(Set *s, const void *key);
|
||||
/* no set_update */
|
||||
/* no set_replace */
|
||||
static inline void *set_get(const Set *s, void *key) {
|
||||
return internal_hashmap_get(HASHMAP_BASE((Set *) s), key);
|
||||
return _hashmap_get(HASHMAP_BASE((Set *) s), key);
|
||||
}
|
||||
/* no set_get2 */
|
||||
|
||||
static inline bool set_contains(const Set *s, const void *key) {
|
||||
return internal_hashmap_contains(HASHMAP_BASE((Set *) s), key);
|
||||
return _hashmap_contains(HASHMAP_BASE((Set *) s), key);
|
||||
}
|
||||
|
||||
static inline void *set_remove(Set *s, const void *key) {
|
||||
return internal_hashmap_remove(HASHMAP_BASE(s), key);
|
||||
return _hashmap_remove(HASHMAP_BASE(s), key);
|
||||
}
|
||||
|
||||
/* no set_remove2 */
|
||||
|
@ -56,19 +56,19 @@ int set_remove_and_put(Set *s, const void *old_key, const void *new_key);
|
|||
int set_merge(Set *s, Set *other);
|
||||
|
||||
static inline int set_reserve(Set *h, unsigned entries_add) {
|
||||
return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
|
||||
return _hashmap_reserve(HASHMAP_BASE(h), entries_add);
|
||||
}
|
||||
|
||||
static inline int set_move(Set *s, Set *other) {
|
||||
return internal_hashmap_move(HASHMAP_BASE(s), HASHMAP_BASE(other));
|
||||
return _hashmap_move(HASHMAP_BASE(s), HASHMAP_BASE(other));
|
||||
}
|
||||
|
||||
static inline int set_move_one(Set *s, Set *other, const void *key) {
|
||||
return internal_hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key);
|
||||
return _hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key);
|
||||
}
|
||||
|
||||
static inline unsigned set_size(const Set *s) {
|
||||
return internal_hashmap_size(HASHMAP_BASE((Set *) s));
|
||||
return _hashmap_size(HASHMAP_BASE((Set *) s));
|
||||
}
|
||||
|
||||
static inline bool set_isempty(const Set *s) {
|
||||
|
@ -76,23 +76,23 @@ static inline bool set_isempty(const Set *s) {
|
|||
}
|
||||
|
||||
static inline unsigned set_buckets(const Set *s) {
|
||||
return internal_hashmap_buckets(HASHMAP_BASE((Set *) s));
|
||||
return _hashmap_buckets(HASHMAP_BASE((Set *) s));
|
||||
}
|
||||
|
||||
bool set_iterate(const Set *s, Iterator *i, void **value);
|
||||
|
||||
static inline void set_clear(Set *s) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(s), NULL, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(s), NULL, NULL);
|
||||
}
|
||||
|
||||
static inline void set_clear_free(Set *s) {
|
||||
internal_hashmap_clear(HASHMAP_BASE(s), free, NULL);
|
||||
_hashmap_clear(HASHMAP_BASE(s), free, NULL);
|
||||
}
|
||||
|
||||
/* no set_clear_free_free */
|
||||
|
||||
static inline void *set_steal_first(Set *s) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL);
|
||||
}
|
||||
|
||||
#define set_clear_with_destructor(_s, _f) \
|
||||
|
@ -111,13 +111,13 @@ static inline void *set_steal_first(Set *s) {
|
|||
/* no set_first_key */
|
||||
|
||||
static inline void *set_first(const Set *s) {
|
||||
return internal_hashmap_first_key_and_value(HASHMAP_BASE((Set *) s), false, NULL);
|
||||
return _hashmap_first_key_and_value(HASHMAP_BASE((Set *) s), false, NULL);
|
||||
}
|
||||
|
||||
/* no set_next */
|
||||
|
||||
static inline char **set_get_strv(Set *s) {
|
||||
return internal_hashmap_get_strv(HASHMAP_BASE(s));
|
||||
return _hashmap_get_strv(HASHMAP_BASE(s));
|
||||
}
|
||||
|
||||
int set_consume(Set *s, void *value);
|
||||
|
|
|
@ -946,20 +946,20 @@ static int string_strv_hashmap_put_internal(Hashmap *h, const char *key, const c
|
|||
return 1;
|
||||
}
|
||||
|
||||
int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value) {
|
||||
int _string_strv_hashmap_put(Hashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS) {
|
||||
int r;
|
||||
|
||||
r = hashmap_ensure_allocated(h, &string_strv_hash_ops);
|
||||
r = _hashmap_ensure_allocated(h, &string_strv_hash_ops HASHMAP_DEBUG_PASS_ARGS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return string_strv_hashmap_put_internal(*h, key, value);
|
||||
}
|
||||
|
||||
int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value) {
|
||||
int _string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS) {
|
||||
int r;
|
||||
|
||||
r = ordered_hashmap_ensure_allocated(h, &string_strv_hash_ops);
|
||||
r = _ordered_hashmap_ensure_allocated(h, &string_strv_hash_ops HASHMAP_DEBUG_PASS_ARGS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -226,5 +226,7 @@ int fputstrv(FILE *f, char * const *l, const char *separator, bool *space);
|
|||
})
|
||||
|
||||
extern const struct hash_ops string_strv_hash_ops;
|
||||
int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value);
|
||||
int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value);
|
||||
int _string_strv_hashmap_put(Hashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);
|
||||
int _string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);
|
||||
#define string_strv_hashmap_put(h, k, v) _string_strv_hashmap_put(h, k, v HASHMAP_DEBUG_SRC_ARGS)
|
||||
#define string_strv_ordered_hashmap_put(h, k, v) _string_strv_ordered_hashmap_put(h, k, v HASHMAP_DEBUG_SRC_ARGS)
|
||||
|
|
|
@ -185,6 +185,7 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
|
|||
[SERVICE_STOP_SIGTERM] = "stop-sigterm",
|
||||
[SERVICE_STOP_SIGKILL] = "stop-sigkill",
|
||||
[SERVICE_STOP_POST] = "stop-post",
|
||||
[SERVICE_FINAL_WATCHDOG] = "final-watchdog",
|
||||
[SERVICE_FINAL_SIGTERM] = "final-sigterm",
|
||||
[SERVICE_FINAL_SIGKILL] = "final-sigkill",
|
||||
[SERVICE_FAILED] = "failed",
|
||||
|
|
|
@ -127,6 +127,7 @@ typedef enum ServiceState {
|
|||
SERVICE_STOP_SIGTERM,
|
||||
SERVICE_STOP_SIGKILL,
|
||||
SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG, /* In case the STOP_POST executable needs to be aborted. */
|
||||
SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */
|
||||
SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_FAILED,
|
||||
|
|
|
@ -29,6 +29,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, N
|
|||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
|
||||
static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec);
|
||||
static BUS_DEFINE_PROPERTY_GET(property_get_watchdog_usec, "t", Service, service_get_watchdog_usec);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode);
|
||||
|
||||
static int property_get_exit_status_set(
|
||||
sd_bus *bus,
|
||||
|
@ -101,6 +102,8 @@ const sd_bus_vtable bus_service_vtable[] = {
|
|||
SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec, 0, 0),
|
||||
SD_BUS_PROPERTY("TimeoutStartFailureMode", "s", property_get_timeout_failure_mode, offsetof(Service, timeout_start_failure_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TimeoutStopFailureMode", "s", property_get_timeout_failure_mode, offsetof(Service, timeout_stop_failure_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("WatchdogUSec", "t", property_get_watchdog_usec, 0, 0),
|
||||
BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
|
||||
|
@ -259,6 +262,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_fr
|
|||
static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid);
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(timeout_failure_mode, ServiceTimeoutFailureMode, service_timeout_failure_mode_from_string);
|
||||
|
||||
static int bus_service_set_transient_property(
|
||||
Service *s,
|
||||
|
@ -316,6 +320,12 @@ static int bus_service_set_transient_property(
|
|||
return r;
|
||||
}
|
||||
|
||||
if (streq(name, "TimeoutStartFailureMode"))
|
||||
return bus_set_transient_timeout_failure_mode(u, name, &s->timeout_start_failure_mode, message, flags, error);
|
||||
|
||||
if (streq(name, "TimeoutStopFailureMode"))
|
||||
return bus_set_transient_timeout_failure_mode(u, name, &s->timeout_stop_failure_mode, message, flags, error);
|
||||
|
||||
if (streq(name, "RuntimeMaxUSec"))
|
||||
return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error);
|
||||
|
||||
|
|
|
@ -322,6 +322,8 @@ Service.TimeoutSec, config_parse_service_timeout, 0,
|
|||
Service.TimeoutStartSec, config_parse_service_timeout, 0, 0
|
||||
Service.TimeoutStopSec, config_parse_sec_fix_0, 0, offsetof(Service, timeout_stop_usec)
|
||||
Service.TimeoutAbortSec, config_parse_service_timeout_abort, 0, 0
|
||||
Service.TimeoutStartFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_start_failure_mode)
|
||||
Service.TimeoutStopFailureMode, config_parse_service_timeout_failure_mode, 0, offsetof(Service, timeout_stop_failure_mode)
|
||||
Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
|
||||
Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
|
||||
m4_dnl The following five only exist for compatibility, they moved into Unit, see above
|
||||
|
|
|
@ -123,6 +123,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSys
|
|||
DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy, "Failed to parse OOM policy");
|
||||
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
|
||||
|
@ -4941,6 +4942,7 @@ void unit_dump_config_items(FILE *f) {
|
|||
{ config_parse_exec, "PATH [ARGUMENT [...]]" },
|
||||
{ config_parse_service_type, "SERVICETYPE" },
|
||||
{ config_parse_service_restart, "SERVICERESTART" },
|
||||
{ config_parse_service_timeout_failure_mode, "TIMEOUTMODE" },
|
||||
{ config_parse_kill_mode, "KILLMODE" },
|
||||
{ config_parse_signal, "SIGNAL" },
|
||||
{ config_parse_socket_listen, "SOCKET [...]" },
|
||||
|
|
|
@ -30,6 +30,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_coredump_filter);
|
|||
CONFIG_PARSER_PROTOTYPE(config_parse_exec);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_failure_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_type);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_restart);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_socket_bindtodevice);
|
||||
|
|
|
@ -56,6 +56,7 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
|
|||
[SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_POST] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_WATCHDOG] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FAILED] = UNIT_FAILED,
|
||||
|
@ -79,6 +80,7 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] =
|
|||
[SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_POST] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_WATCHDOG] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FAILED] = UNIT_FAILED,
|
||||
|
@ -857,10 +859,14 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
|
|||
fprintf(f,
|
||||
"%sRestartSec: %s\n"
|
||||
"%sTimeoutStartSec: %s\n"
|
||||
"%sTimeoutStopSec: %s\n",
|
||||
"%sTimeoutStopSec: %s\n"
|
||||
"%sTimeoutStartFailureMode: %s\n"
|
||||
"%sTimeoutStopFailureMode: %s\n",
|
||||
prefix, format_timespan(buf_restart, sizeof(buf_restart), s->restart_usec, USEC_PER_SEC),
|
||||
prefix, format_timespan(buf_start, sizeof(buf_start), s->timeout_start_usec, USEC_PER_SEC),
|
||||
prefix, format_timespan(buf_stop, sizeof(buf_stop), s->timeout_stop_usec, USEC_PER_SEC));
|
||||
prefix, format_timespan(buf_stop, sizeof(buf_stop), s->timeout_stop_usec, USEC_PER_SEC),
|
||||
prefix, service_timeout_failure_mode_to_string(s->timeout_start_failure_mode),
|
||||
prefix, service_timeout_failure_mode_to_string(s->timeout_stop_failure_mode));
|
||||
|
||||
if (s->timeout_abort_set)
|
||||
fprintf(f,
|
||||
|
@ -1072,7 +1078,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
|||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_AUTO_RESTART,
|
||||
SERVICE_CLEANING))
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
|
@ -1081,7 +1087,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
|||
SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
|
||||
service_unwatch_main_pid(s);
|
||||
s->main_command = NULL;
|
||||
}
|
||||
|
@ -1090,7 +1096,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
|||
SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_CLEANING)) {
|
||||
service_unwatch_control_pid(s);
|
||||
s->control_command = NULL;
|
||||
|
@ -1106,7 +1112,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
|||
SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) &&
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) &&
|
||||
!(state == SERVICE_DEAD && UNIT(s)->job))
|
||||
service_close_socket_fd(s);
|
||||
|
||||
|
@ -1154,6 +1160,7 @@ static usec_t service_coldplug_timeout(Service *s) {
|
|||
return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_stop_usec);
|
||||
|
||||
case SERVICE_STOP_WATCHDOG:
|
||||
case SERVICE_FINAL_WATCHDOG:
|
||||
return usec_add(UNIT(s)->state_change_timestamp.monotonic, service_timeout_abort_usec(s));
|
||||
|
||||
case SERVICE_AUTO_RESTART:
|
||||
|
@ -1187,7 +1194,7 @@ static int service_coldplug(Unit *u) {
|
|||
SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) {
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) {
|
||||
r = unit_watch_pid(UNIT(s), s->main_pid, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1199,7 +1206,7 @@ static int service_coldplug(Unit *u) {
|
|||
SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_CLEANING)) {
|
||||
r = unit_watch_pid(UNIT(s), s->control_pid, false);
|
||||
if (r < 0)
|
||||
|
@ -1859,6 +1866,7 @@ static int state_to_kill_operation(Service *s, ServiceState state) {
|
|||
switch (state) {
|
||||
|
||||
case SERVICE_STOP_WATCHDOG:
|
||||
case SERVICE_FINAL_WATCHDOG:
|
||||
return KILL_WATCHDOG;
|
||||
|
||||
case SERVICE_STOP_SIGTERM:
|
||||
|
@ -1879,7 +1887,7 @@ static int state_to_kill_operation(Service *s, ServiceState state) {
|
|||
}
|
||||
|
||||
static void service_enter_signal(Service *s, ServiceState state, ServiceResult f) {
|
||||
int r;
|
||||
int kill_operation, r;
|
||||
|
||||
assert(s);
|
||||
|
||||
|
@ -1893,10 +1901,11 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
|
|||
* died now */
|
||||
(void) unit_enqueue_rewatch_pids(UNIT(s));
|
||||
|
||||
kill_operation = state_to_kill_operation(s, state);
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(s, state),
|
||||
kill_operation,
|
||||
s->main_pid,
|
||||
s->control_pid,
|
||||
s->main_pid_alien);
|
||||
|
@ -1905,7 +1914,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
|
|||
|
||||
if (r > 0) {
|
||||
r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC),
|
||||
state == SERVICE_STOP_WATCHDOG ? service_timeout_abort_usec(s) : s->timeout_stop_usec));
|
||||
kill_operation == KILL_WATCHDOG ? service_timeout_abort_usec(s) : s->timeout_stop_usec));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -1914,7 +1923,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
|
|||
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_SUCCESS);
|
||||
else if (IN_SET(state, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL))
|
||||
service_enter_stop_post(s, SERVICE_SUCCESS);
|
||||
else if (state == SERVICE_FINAL_SIGTERM && s->kill_context.send_sigkill)
|
||||
else if (IN_SET(state, SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM) && s->kill_context.send_sigkill)
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_SUCCESS);
|
||||
else
|
||||
service_enter_dead(s, SERVICE_SUCCESS, true);
|
||||
|
@ -2444,7 +2453,7 @@ static int service_start(Unit *u) {
|
|||
* please! */
|
||||
if (IN_SET(s->state,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, SERVICE_CLEANING))
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, SERVICE_CLEANING))
|
||||
return -EAGAIN;
|
||||
|
||||
/* Already on it! */
|
||||
|
@ -2515,7 +2524,7 @@ static int service_stop(Unit *u) {
|
|||
/* Already on it */
|
||||
if (IN_SET(s->state,
|
||||
SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))
|
||||
return 0;
|
||||
|
||||
/* A restart will be scheduled or is in progress. */
|
||||
|
@ -3321,6 +3330,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
|
|||
break;
|
||||
|
||||
case SERVICE_STOP_POST:
|
||||
case SERVICE_FINAL_WATCHDOG:
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
case SERVICE_FINAL_SIGKILL:
|
||||
if (main_pid_good(s) <= 0 && control_pid_good(s) <= 0)
|
||||
|
@ -3521,6 +3531,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
|||
|
||||
break;
|
||||
|
||||
case SERVICE_FINAL_WATCHDOG:
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
case SERVICE_FINAL_SIGKILL:
|
||||
|
||||
|
@ -3674,6 +3685,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
|||
service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
|
||||
break;
|
||||
|
||||
case SERVICE_FINAL_WATCHDOG:
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
case SERVICE_FINAL_SIGKILL:
|
||||
if (main_pid_good(s) <= 0)
|
||||
|
@ -3720,13 +3732,32 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
|
|||
case SERVICE_CONDITION:
|
||||
case SERVICE_START_PRE:
|
||||
case SERVICE_START:
|
||||
log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", service_state_to_string(s->state));
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SERVICE_START_POST:
|
||||
log_unit_warning(UNIT(s), "Start-post operation timed out. Stopping.");
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
switch (s->timeout_start_failure_mode) {
|
||||
|
||||
case SERVICE_TIMEOUT_TERMINATE:
|
||||
log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", service_state_to_string(s->state));
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SERVICE_TIMEOUT_ABORT:
|
||||
log_unit_warning(UNIT(s), "%s operation timed out. Aborting.", service_state_to_string(s->state));
|
||||
service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SERVICE_TIMEOUT_KILL:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "%s operation timed out. Killing.", service_state_to_string(s->state));
|
||||
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "%s operation timed out. Skipping SIGKILL.", service_state_to_string(s->state));
|
||||
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("unknown timeout mode");
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_RUNNING:
|
||||
|
@ -3742,17 +3773,48 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
|
|||
break;
|
||||
|
||||
case SERVICE_STOP:
|
||||
log_unit_warning(UNIT(s), "Stopping timed out. Terminating.");
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
switch (s->timeout_stop_failure_mode) {
|
||||
|
||||
case SERVICE_TIMEOUT_TERMINATE:
|
||||
log_unit_warning(UNIT(s), "Stopping timed out. Terminating.");
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SERVICE_TIMEOUT_ABORT:
|
||||
log_unit_warning(UNIT(s), "Stopping timed out. Aborting.");
|
||||
service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SERVICE_TIMEOUT_KILL:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "Stopping timed out. Killing.");
|
||||
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL.");
|
||||
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("unknown timeout mode");
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_STOP_WATCHDOG:
|
||||
log_unit_warning(UNIT(s), "State 'stop-watchdog' timed out. Terminating.");
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "State 'stop-watchdog' timed out. Killing.");
|
||||
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "State 'stop-watchdog' timed out. Skipping SIGKILL.");
|
||||
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_STOP_SIGTERM:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
if (s->timeout_stop_failure_mode == SERVICE_TIMEOUT_ABORT) {
|
||||
log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Aborting.");
|
||||
service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_TIMEOUT);
|
||||
} else if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Killing.");
|
||||
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
|
@ -3772,16 +3834,52 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
|
|||
break;
|
||||
|
||||
case SERVICE_STOP_POST:
|
||||
log_unit_warning(UNIT(s), "State 'stop-post' timed out. Terminating.");
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
switch (s->timeout_stop_failure_mode) {
|
||||
|
||||
case SERVICE_TIMEOUT_TERMINATE:
|
||||
log_unit_warning(UNIT(s), "State 'stop-post' timed out. Terminating.");
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SERVICE_TIMEOUT_ABORT:
|
||||
log_unit_warning(UNIT(s), "State 'stop-post' timed out. Aborting.");
|
||||
service_enter_signal(s, SERVICE_FINAL_WATCHDOG, SERVICE_FAILURE_TIMEOUT);
|
||||
break;
|
||||
|
||||
case SERVICE_TIMEOUT_KILL:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "State 'stop-post' timed out. Killing.");
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "State 'stop-post' timed out. Skipping SIGKILL. Entering failed mode.");
|
||||
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("unknown timeout mode");
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_FINAL_WATCHDOG:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "State 'final-watchdog' timed out. Killing.");
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "State 'final-watchdog' timed out. Skipping SIGKILL. Entering failed mode.");
|
||||
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Killing.");
|
||||
if (s->timeout_stop_failure_mode == SERVICE_TIMEOUT_ABORT) {
|
||||
log_unit_warning(UNIT(s), "State 'final-sigterm' timed out. Aborting.");
|
||||
service_enter_signal(s, SERVICE_FINAL_WATCHDOG, SERVICE_FAILURE_TIMEOUT);
|
||||
} else if (s->kill_context.send_sigkill) {
|
||||
log_unit_warning(UNIT(s), "State 'final-sigterm' timed out. Killing.");
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
|
||||
} else {
|
||||
log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode.");
|
||||
log_unit_warning(UNIT(s), "State 'final-sigterm' timed out. Skipping SIGKILL. Entering failed mode.");
|
||||
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
|
||||
}
|
||||
|
||||
|
@ -4263,6 +4361,7 @@ static bool service_needs_console(Unit *u) {
|
|||
SERVICE_STOP_SIGTERM,
|
||||
SERVICE_STOP_SIGKILL,
|
||||
SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG,
|
||||
SERVICE_FINAL_SIGTERM,
|
||||
SERVICE_FINAL_SIGKILL);
|
||||
}
|
||||
|
@ -4417,6 +4516,14 @@ static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
|
|||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
|
||||
|
||||
static const char* const service_timeout_failure_mode_table[_SERVICE_TIMEOUT_FAILURE_MODE_MAX] = {
|
||||
[SERVICE_TIMEOUT_TERMINATE] = "terminate",
|
||||
[SERVICE_TIMEOUT_ABORT] = "abort",
|
||||
[SERVICE_TIMEOUT_KILL] = "kill",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_timeout_failure_mode, ServiceTimeoutFailureMode);
|
||||
|
||||
const UnitVTable service_vtable = {
|
||||
.object_size = sizeof(Service),
|
||||
.exec_context_offset = offsetof(Service, exec_context),
|
||||
|
|
|
@ -74,6 +74,14 @@ typedef enum ServiceResult {
|
|||
_SERVICE_RESULT_INVALID = -1
|
||||
} ServiceResult;
|
||||
|
||||
typedef enum ServiceTimeoutFailureMode {
|
||||
SERVICE_TIMEOUT_TERMINATE,
|
||||
SERVICE_TIMEOUT_ABORT,
|
||||
SERVICE_TIMEOUT_KILL,
|
||||
_SERVICE_TIMEOUT_FAILURE_MODE_MAX,
|
||||
_SERVICE_TIMEOUT_FAILURE_MODE_INVALID = -1
|
||||
} ServiceTimeoutFailureMode;
|
||||
|
||||
struct ServiceFDStore {
|
||||
Service *service;
|
||||
|
||||
|
@ -103,6 +111,8 @@ struct Service {
|
|||
usec_t timeout_abort_usec;
|
||||
bool timeout_abort_set;
|
||||
usec_t runtime_max_usec;
|
||||
ServiceTimeoutFailureMode timeout_start_failure_mode;
|
||||
ServiceTimeoutFailureMode timeout_stop_failure_mode;
|
||||
|
||||
dual_timestamp watchdog_timestamp;
|
||||
usec_t watchdog_usec; /* the requested watchdog timeout in the unit file */
|
||||
|
@ -228,6 +238,9 @@ NotifyState notify_state_from_string(const char *s) _pure_;
|
|||
const char* service_result_to_string(ServiceResult i) _const_;
|
||||
ServiceResult service_result_from_string(const char *s) _pure_;
|
||||
|
||||
const char* service_timeout_failure_mode_to_string(ServiceTimeoutFailureMode i) _const_;
|
||||
ServiceTimeoutFailureMode service_timeout_failure_mode_from_string(const char *s) _pure_;
|
||||
|
||||
DEFINE_CAST(SERVICE, Service);
|
||||
|
||||
#define STATUS_TEXT_MAX (16U*1024U)
|
||||
|
|
|
@ -403,7 +403,7 @@ static int slice_freezer_action(Unit *s, FreezerAction action) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int slice_freeze(Unit *s) {
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#define CRYPT_SECTOR_SIZE 512
|
||||
#define CRYPT_MAX_SECTOR_SIZE 4096
|
||||
|
||||
static const char *arg_type = NULL; /* ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT or CRYPT_PLAIN */
|
||||
static const char *arg_type = NULL; /* ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT, CRYPT_BITLK or CRYPT_PLAIN */
|
||||
static char *arg_cipher = NULL;
|
||||
static unsigned arg_key_size = 0;
|
||||
static unsigned arg_sector_size = CRYPT_SECTOR_SIZE;
|
||||
|
@ -220,6 +220,11 @@ static int parse_one_option(const char *option) {
|
|||
arg_submit_from_crypt_cpus = true;
|
||||
else if (streq(option, "luks"))
|
||||
arg_type = ANY_LUKS;
|
||||
/* since cryptsetup 2.3.0 (Feb 2020) */
|
||||
#ifdef CRYPT_BITLK
|
||||
else if (streq(option, "bitlk"))
|
||||
arg_type = CRYPT_BITLK;
|
||||
#endif
|
||||
else if (streq(option, "tcrypt"))
|
||||
arg_type = CRYPT_TCRYPT;
|
||||
else if (STR_IN_SET(option, "tcrypt-hidden", "tcrypthidden")) {
|
||||
|
@ -545,7 +550,7 @@ static int attach_tcrypt(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int attach_luks_or_plain(
|
||||
static int attach_luks_or_plain_or_bitlk(
|
||||
struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *key_file,
|
||||
|
@ -950,6 +955,15 @@ static int run(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
/* since cryptsetup 2.3.0 (Feb 2020) */
|
||||
#ifdef CRYPT_BITLK
|
||||
if (!arg_type || STR_IN_SET(arg_type, ANY_LUKS, CRYPT_BITLK)) {
|
||||
r = crypt_load(cd, CRYPT_BITLK, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load Bitlocker superblock on device %s: %m", crypt_get_device_name(cd));
|
||||
}
|
||||
#endif
|
||||
|
||||
for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) {
|
||||
_cleanup_strv_free_erase_ char **passwords = NULL;
|
||||
|
||||
|
@ -988,7 +1002,7 @@ static int run(int argc, char *argv[]) {
|
|||
if (streq_ptr(arg_type, CRYPT_TCRYPT))
|
||||
r = attach_tcrypt(cd, argv[2], key_file, key_data, key_data_size, passwords, flags);
|
||||
else
|
||||
r = attach_luks_or_plain(cd, argv[2], key_file, key_data, key_data_size, passwords, flags, until);
|
||||
r = attach_luks_or_plain_or_bitlk(cd, argv[2], key_file, key_data, key_data_size, passwords, flags, until);
|
||||
if (r >= 0)
|
||||
break;
|
||||
if (r != -EAGAIN)
|
||||
|
|
|
@ -23,8 +23,11 @@ SKIP_REMAINING=77
|
|||
usage()
|
||||
{
|
||||
echo "Usage:"
|
||||
echo " $0 add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]"
|
||||
echo " $0 remove KERNEL-VERSION"
|
||||
echo " $0 [OPTIONS...] add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]"
|
||||
echo " $0 [OPTIONS...] remove KERNEL-VERSION"
|
||||
echo "Options:"
|
||||
echo " -h,--help Print this help"
|
||||
echo " -v,--verbose Increase verbosity"
|
||||
}
|
||||
|
||||
dropindirs_sort()
|
||||
|
|
|
@ -168,6 +168,10 @@ _public_ int sd_network_link_get_address_state(int ifindex, char **state) {
|
|||
return network_link_get_string(ifindex, "ADDRESS_STATE", state);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_dhcp4_client_id_string(int ifindex, char **client_id) {
|
||||
return network_link_get_string(ifindex, "DHCP4_CLIENT_ID", client_id);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_required_for_online(int ifindex) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
int r;
|
||||
|
|
|
@ -30,6 +30,11 @@ SUBSYSTEM=="pci", ENV{ID_PCI_CLASS_FROM_DATABASE}=="Display controller", \
|
|||
ENV{DRIVER}=="", IMPORT{cmdline}="nomodeset", TAG+="seat", TAG+="master-of-seat"
|
||||
|
||||
SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat"
|
||||
|
||||
# Allow individual USB ports to be assigned to a seat
|
||||
SUBSYSTEM=="usb", ATTR{bDeviceClass}=="00", TAG+="seat"
|
||||
|
||||
# Allow USB hubs (and all downstream ports) to be assigned to a seat
|
||||
SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat"
|
||||
|
||||
# 'Plugable' USB hub, sound, network, graphics adapter
|
||||
|
|
|
@ -364,7 +364,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"At most two arguments required.");
|
||||
|
||||
if (arg_mount_type && (fstype_is_api_vfs(arg_mount_type) || fstype_is_network(arg_mount_type))) {
|
||||
if (arg_mount_type && !fstype_is_blockdev_backed(arg_mount_type)) {
|
||||
arg_mount_what = strdup(argv[optind]);
|
||||
if (!arg_mount_what)
|
||||
return log_oom();
|
||||
|
@ -1463,7 +1463,7 @@ static int run(int argc, char* argv[]) {
|
|||
if (arg_action == ACTION_UMOUNT)
|
||||
return action_umount(bus, argc, argv);
|
||||
|
||||
if ((!arg_mount_type || !fstype_is_network(arg_mount_type))
|
||||
if ((!arg_mount_type || fstype_is_blockdev_backed(arg_mount_type))
|
||||
&& !path_is_normalized(arg_mount_what)) {
|
||||
log_error("Path contains non-normalized components: %s", arg_mount_what);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1381,7 +1381,7 @@ static int link_status_one(
|
|||
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL,
|
||||
**pop3_server = NULL, **smtp_server = NULL, **lpr_server = NULL;
|
||||
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
|
||||
_cleanup_free_ char *t = NULL, *network = NULL;
|
||||
_cleanup_free_ char *t = NULL, *network = NULL, *client_id = NULL;
|
||||
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
|
||||
const char *on_color_operational, *off_color_operational,
|
||||
*on_color_setup, *off_color_setup;
|
||||
|
@ -2073,6 +2073,16 @@ static int link_status_one(
|
|||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
r = sd_network_link_get_dhcp4_client_id_string(info->ifindex, &client_id);
|
||||
if (r >= 0) {
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "DHCP4 Client ID:",
|
||||
TABLE_STRING, client_id);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
r = dump_lldp_neighbors(table, "Connected To:", info->ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
|
|
@ -4374,6 +4374,8 @@ int link_save(Link *link) {
|
|||
if (link->dhcp_lease) {
|
||||
struct in_addr address;
|
||||
const char *tz = NULL;
|
||||
size_t client_id_len;
|
||||
const void *client_id;
|
||||
|
||||
assert(link->network);
|
||||
|
||||
|
@ -4388,6 +4390,15 @@ int link_save(Link *link) {
|
|||
fputc('\n', f);
|
||||
}
|
||||
|
||||
r = sd_dhcp_lease_get_client_id(link->dhcp_lease, &client_id, &client_id_len);
|
||||
if (r >= 0) {
|
||||
_cleanup_free_ char *id = NULL;
|
||||
|
||||
r = sd_dhcp_client_id_to_string(client_id, client_id_len, &id);
|
||||
if (r >= 0)
|
||||
fprintf(f, "DHCP4_CLIENT_ID=%s\n", id);
|
||||
}
|
||||
|
||||
r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
|
|
@ -1490,7 +1490,9 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
|
|||
"NotifyAccess",
|
||||
"USBFunctionDescriptors",
|
||||
"USBFunctionStrings",
|
||||
"OOMPolicy"))
|
||||
"OOMPolicy",
|
||||
"TimeoutStartFailureMode",
|
||||
"TimeoutStopFailureMode"))
|
||||
return bus_append_string(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "PermissionsStartOnly",
|
||||
|
|
|
@ -188,6 +188,9 @@ int sd_network_link_get_carrier_bound_by(int ifindex, int **ifindexes);
|
|||
/* Get the timezone that was learnt on a specific link. */
|
||||
int sd_network_link_get_timezone(int ifindex, char **timezone);
|
||||
|
||||
/* Get DHCPv4 client id for a given link. */
|
||||
int sd_network_link_get_dhcp4_client_id_string(int ifindex, char **client_id);
|
||||
|
||||
/* Monitor object */
|
||||
typedef struct sd_network_monitor sd_network_monitor;
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ static unsigned arg_children_max = 0;
|
|||
static usec_t arg_exec_delay_usec = 0;
|
||||
static usec_t arg_event_timeout_usec = 180 * USEC_PER_SEC;
|
||||
static int arg_timeout_signal = SIGKILL;
|
||||
static bool arg_blockdev_read_only = false;
|
||||
|
||||
typedef struct Manager {
|
||||
sd_event *event;
|
||||
|
@ -383,6 +384,56 @@ static int worker_lock_block_device(sd_device *dev, int *ret_fd) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int worker_mark_block_device_read_only(sd_device *dev) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
const char *val;
|
||||
int state = 1, r;
|
||||
|
||||
assert(dev);
|
||||
|
||||
if (!arg_blockdev_read_only)
|
||||
return 0;
|
||||
|
||||
/* Do this only once, when the block device is new. If the device is later retriggered let's not
|
||||
* toggle the bit again, so that people can boot up with full read-only mode and then unset the bit
|
||||
* for specific devices only. */
|
||||
if (!device_for_action(dev, DEVICE_ACTION_ADD))
|
||||
return 0;
|
||||
|
||||
r = sd_device_get_subsystem(dev, &val);
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(dev, r, "Failed to get subsystem: %m");
|
||||
|
||||
if (!streq(val, "block"))
|
||||
return 0;
|
||||
|
||||
r = sd_device_get_sysname(dev, &val);
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(dev, r, "Failed to get sysname: %m");
|
||||
|
||||
/* Exclude synthetic devices for now, this is supposed to be a safety feature to avoid modification
|
||||
* of physical devices, and what sits on top of those doesn't really matter if we don't allow the
|
||||
* underlying block devices to recieve changes. */
|
||||
if (STARTSWITH_SET(val, "dm-", "md", "drbd", "loop", "nbd", "zram"))
|
||||
return 0;
|
||||
|
||||
r = sd_device_get_devname(dev, &val);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(dev, r, "Failed to get devname: %m");
|
||||
|
||||
fd = open(val, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
return log_device_debug_errno(dev, errno, "Failed to open '%s', ignoring: %m", val);
|
||||
|
||||
if (ioctl(fd, BLKROSET, &state) < 0)
|
||||
return log_device_warning_errno(dev, errno, "Failed to mark block device '%s' read-only: %m", val);
|
||||
|
||||
log_device_info(dev, "Successfully marked block device '%s' read-only.", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int worker_process_device(Manager *manager, sd_device *dev) {
|
||||
_cleanup_(udev_event_freep) UdevEvent *udev_event = NULL;
|
||||
_cleanup_close_ int fd_lock = -1;
|
||||
|
@ -412,6 +463,8 @@ static int worker_process_device(Manager *manager, sd_device *dev) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) worker_mark_block_device_read_only(dev);
|
||||
|
||||
/* apply rules, create node, symlinks */
|
||||
r = udev_event_execute_rules(udev_event, arg_event_timeout_usec, arg_timeout_signal, manager->properties, manager->rules);
|
||||
if (r < 0)
|
||||
|
@ -1417,15 +1470,13 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) {
|
|||
* udev.children_max=<number of workers> events are fully serialized if set to 1
|
||||
* udev.exec_delay=<number of seconds> delay execution of every executed program
|
||||
* udev.event_timeout=<number of seconds> seconds to wait before terminating an event
|
||||
* udev.blockdev_read_only<=bool> mark all block devices read-only when they appear
|
||||
*/
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||
int r = 0;
|
||||
int r;
|
||||
|
||||
assert(key);
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
if (proc_cmdline_key_streq(key, "udev.log_priority")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
|
@ -1457,14 +1508,37 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||
r = parse_sec(value, &arg_exec_delay_usec);
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "udev.timeout_signal")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
r = signal_from_string(value);
|
||||
if (r > 0)
|
||||
arg_timeout_signal = r;
|
||||
} else if (startswith(key, "udev."))
|
||||
log_warning("Unknown udev kernel command line option \"%s\", ignoring", key);
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "udev.blockdev_read_only")) {
|
||||
|
||||
if (!value)
|
||||
arg_blockdev_read_only = true;
|
||||
else {
|
||||
r = parse_boolean(value);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse udev.blockdev-read-only argument, ignoring: %s", value);
|
||||
else
|
||||
arg_blockdev_read_only = r;
|
||||
}
|
||||
|
||||
if (arg_blockdev_read_only)
|
||||
log_notice("All physical block devices will be marked read-only.");
|
||||
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
if (startswith(key, "udev."))
|
||||
log_warning("Unknown udev kernel command line option \"%s\", ignoring.", key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse \"%s=%s\", ignoring: %m", key, value);
|
||||
|
|
|
@ -246,6 +246,8 @@ test_preserve_state() {
|
|||
|
||||
echo -n " - freeze from outside: "
|
||||
echo 1 > /sys/fs/cgroup/"${slice}"/cgroup.freeze
|
||||
# Give kernel some time to freeze the slice
|
||||
sleep 1
|
||||
|
||||
# Our state should not be affected
|
||||
check_freezer_state "${slice}" "running"
|
||||
|
@ -258,6 +260,8 @@ test_preserve_state() {
|
|||
|
||||
echo -n " - thaw from outside: "
|
||||
echo 0 > /sys/fs/cgroup/"${slice}"/cgroup.freeze
|
||||
sleep 1
|
||||
|
||||
check_freezer_state "${unit}" "running"
|
||||
check_freezer_state "${slice}" "running"
|
||||
grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/cgroup.events
|
||||
|
|
|
@ -1,79 +1,77 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import gdb
|
||||
|
||||
class sd_dump_hashmaps(gdb.Command):
|
||||
"dump systemd's hashmaps"
|
||||
"dump systemd's hashmaps"
|
||||
|
||||
def __init__(self):
|
||||
super(sd_dump_hashmaps, self).__init__("sd_dump_hashmaps", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
|
||||
def __init__(self):
|
||||
super().__init__("sd_dump_hashmaps", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
d = gdb.parse_and_eval("hashmap_debug_list")
|
||||
all_entry_sizes = gdb.parse_and_eval("all_entry_sizes")
|
||||
all_direct_buckets = gdb.parse_and_eval("all_direct_buckets")
|
||||
uchar_t = gdb.lookup_type("unsigned char")
|
||||
ulong_t = gdb.lookup_type("unsigned long")
|
||||
debug_offset = gdb.parse_and_eval("(unsigned long)&((HashmapBase*)0)->debug")
|
||||
def invoke(self, arg, from_tty):
|
||||
d = gdb.parse_and_eval("hashmap_debug_list")
|
||||
hashmap_type_info = gdb.parse_and_eval("hashmap_type_info")
|
||||
uchar_t = gdb.lookup_type("unsigned char")
|
||||
ulong_t = gdb.lookup_type("unsigned long")
|
||||
debug_offset = gdb.parse_and_eval("(unsigned long)&((HashmapBase*)0)->debug")
|
||||
|
||||
print("type, hash, indirect, entries, max_entries, buckets, creator")
|
||||
while d:
|
||||
h = gdb.parse_and_eval("(HashmapBase*)((char*)%d - %d)" % (int(d.cast(ulong_t)), debug_offset))
|
||||
print("type, hash, indirect, entries, max_entries, buckets, creator")
|
||||
while d:
|
||||
h = gdb.parse_and_eval(f"(HashmapBase*)((char*){int(d.cast(ulong_t))} - {debug_offset})")
|
||||
|
||||
if h["has_indirect"]:
|
||||
storage_ptr = h["indirect"]["storage"].cast(uchar_t.pointer())
|
||||
n_entries = h["indirect"]["n_entries"]
|
||||
n_buckets = h["indirect"]["n_buckets"]
|
||||
else:
|
||||
storage_ptr = h["direct"]["storage"].cast(uchar_t.pointer())
|
||||
n_entries = h["n_direct_entries"]
|
||||
n_buckets = all_direct_buckets[int(h["type"])];
|
||||
if h["has_indirect"]:
|
||||
storage_ptr = h["indirect"]["storage"].cast(uchar_t.pointer())
|
||||
n_entries = h["indirect"]["n_entries"]
|
||||
n_buckets = h["indirect"]["n_buckets"]
|
||||
else:
|
||||
storage_ptr = h["direct"]["storage"].cast(uchar_t.pointer())
|
||||
n_entries = h["n_direct_entries"]
|
||||
n_buckets = hashmap_type_info[h["type"]]["n_direct_buckets"]
|
||||
|
||||
t = ["plain", "ordered", "set"][int(h["type"])]
|
||||
t = ["plain", "ordered", "set"][int(h["type"])]
|
||||
|
||||
print("{}, {}, {}, {}, {}, {}, {} ({}:{})".format(t, h["hash_ops"], bool(h["has_indirect"]), n_entries, d["max_entries"], n_buckets, d["func"], d["file"], d["line"]))
|
||||
print(f'{t}, {h["hash_ops"]}, {bool(h["has_indirect"])}, {n_entries}, {d["max_entries"]}, {n_buckets}, {d["func"].string()}, {d["file"].string()}:{d["line"]}')
|
||||
|
||||
if arg != "" and n_entries > 0:
|
||||
dib_raw_addr = storage_ptr + (all_entry_sizes[h["type"]] * n_buckets)
|
||||
if arg != "" and n_entries > 0:
|
||||
dib_raw_addr = storage_ptr + hashmap_type_info[h["type"]]["entry_size"] * n_buckets
|
||||
|
||||
histogram = {}
|
||||
for i in xrange(0, n_buckets):
|
||||
dib = int(dib_raw_addr[i])
|
||||
histogram[dib] = histogram.get(dib, 0) + 1
|
||||
histogram = {}
|
||||
for i in range(0, n_buckets):
|
||||
dib = int(dib_raw_addr[i])
|
||||
histogram[dib] = histogram.get(dib, 0) + 1
|
||||
|
||||
for dib in sorted(iter(histogram)):
|
||||
if dib != 255:
|
||||
print("{:>3} {:>8} {} of entries".format(dib, histogram[dib], 100.0*histogram[dib]/n_entries))
|
||||
else:
|
||||
print("{:>3} {:>8} {} of slots".format(dib, histogram[dib], 100.0*histogram[dib]/n_buckets))
|
||||
print("mean DIB of entries: {}".format(sum([dib*histogram[dib] for dib in iter(histogram) if dib != 255])*1.0/n_entries))
|
||||
for dib in sorted(histogram):
|
||||
if dib != 255:
|
||||
print(f"{dib:>3} {histogram[dib]:>8} {float(histogram[dib]/n_entries):.0%} of entries")
|
||||
else:
|
||||
print(f"{dib:>3} {histogram[dib]:>8} {float(histogram[dib]/n_buckets):.0%} of slots")
|
||||
s = sum(dib*count for (dib, count) in histogram.items() if dib != 255) / n_entries
|
||||
print(f"mean DIB of entries: {s}")
|
||||
|
||||
blocks = []
|
||||
current_len = 1
|
||||
prev = int(dib_raw_addr[0])
|
||||
for i in xrange(1, n_buckets):
|
||||
dib = int(dib_raw_addr[i])
|
||||
if (dib == 255) != (prev == 255):
|
||||
if prev != 255:
|
||||
blocks += [[i, current_len]]
|
||||
current_len = 1
|
||||
else:
|
||||
current_len += 1
|
||||
blocks = []
|
||||
current_len = 1
|
||||
prev = int(dib_raw_addr[0])
|
||||
for i in range(1, n_buckets):
|
||||
dib = int(dib_raw_addr[i])
|
||||
if (dib == 255) != (prev == 255):
|
||||
if prev != 255:
|
||||
blocks += [[i, current_len]]
|
||||
current_len = 1
|
||||
else:
|
||||
current_len += 1
|
||||
|
||||
prev = dib
|
||||
if prev != 255:
|
||||
blocks += [[i, current_len]]
|
||||
# a block may be wrapped around
|
||||
if len(blocks) > 1 and blocks[0][0] == blocks[0][1] and blocks[-1][0] == n_buckets - 1:
|
||||
blocks[0][1] += blocks[-1][1]
|
||||
blocks = blocks[0:-1]
|
||||
print("max block: {}".format(max(blocks, key=lambda a: a[1])))
|
||||
print("sum block lens: {}".format(sum(b[1] for b in blocks)))
|
||||
print("mean block len: {}".format((1.0 * sum(b[1] for b in blocks) / len(blocks))))
|
||||
prev = dib
|
||||
if prev != 255:
|
||||
blocks += [[i, current_len]]
|
||||
# a block may be wrapped around
|
||||
if len(blocks) > 1 and blocks[0][0] == blocks[0][1] and blocks[-1][0] == n_buckets - 1:
|
||||
blocks[0][1] += blocks[-1][1]
|
||||
blocks = blocks[0:-1]
|
||||
print("max block: {}".format(max(blocks, key=lambda a: a[1])))
|
||||
print("sum block lens: {}".format(sum(b[1] for b in blocks)))
|
||||
print("mean block len: {}".format(sum(b[1] for b in blocks) / len(blocks)))
|
||||
|
||||
d = d["debug_list_next"]
|
||||
d = d["debug_list_next"]
|
||||
|
||||
sd_dump_hashmaps()
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Cleanup udevd DB
|
||||
Description=Cleanup udev Database
|
||||
DefaultDependencies=no
|
||||
ConditionPathExists=/etc/initrd-release
|
||||
Conflicts=systemd-udevd.service systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udev-trigger.service systemd-udev-settle.service
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# expect a populated /dev during bootup.
|
||||
|
||||
[Unit]
|
||||
Description=udev Wait for Complete Device Initialization
|
||||
Description=Wait for udev To Complete Device Initialization
|
||||
Documentation=man:systemd-udev-settle.service(8)
|
||||
DefaultDependencies=no
|
||||
Wants=systemd-udevd.service
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=udev Coldplug all Devices
|
||||
Description=Coldplug All udev Devices
|
||||
Documentation=man:udev(7) man:systemd-udevd.service(8)
|
||||
DefaultDependencies=no
|
||||
Wants=systemd-udevd.service
|
||||
|
|
Loading…
Reference in New Issue