]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #11159 from keszybz/udev-typedef
authorLennart Poettering <lennart@poettering.net>
Mon, 17 Dec 2018 15:19:10 +0000 (16:19 +0100)
committerGitHub <noreply@github.com>
Mon, 17 Dec 2018 15:19:10 +0000 (16:19 +0100)
Udev typedef and normal error reporting

68 files changed:
.mkosi/mkosi.debian
NEWS
docs/BOOT_LOADER_INTERFACE.md
hwdb/60-sensor.hwdb
hwdb/70-mouse.hwdb
man/systemd-boot.xml
man/systemd-mount.xml
man/systemd.exec.xml
man/systemd.netdev.xml
man/systemd.service.xml
man/systemd.unit.xml
shell-completion/bash/resolvectl
shell-completion/bash/systemd-nspawn
shell-completion/bash/systemd-resolve
shell-completion/bash/udevadm
src/basic/fileio.c
src/basic/in-addr-util.c
src/basic/util.h
src/core/cgroup.c
src/core/cgroup.h
src/core/dynamic-user.c
src/core/load-fragment.c
src/core/manager.h
src/core/mount.c
src/core/unit-printf.c
src/core/unit.c
src/core/unit.h
src/fstab-generator/fstab-generator.c
src/hostname/hostnamed.c
src/journal/journald-context.c
src/libsystemd-network/lldp-neighbor.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-device/device-monitor.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-resolve/test-resolve.c
src/machine/machine.c
src/machine/machined-core.c [new file with mode: 0644]
src/machine/machined.c
src/machine/machined.h
src/machine/meson.build
src/network/netdev/bond.c
src/network/netdev/bond.h
src/network/netdev/netdev-gperf.gperf
src/resolve/resolv.conf
src/resolve/resolved-dnssd.c
src/resolve/resolved-link.h
src/resolve/resolved-manager.h
src/resolve/resolved-resolv-conf.c
src/shared/install-printf.c
src/shared/install-printf.h
src/shared/install.c
src/shared/meson.build
src/shared/nscd-flush.c [new file with mode: 0644]
src/shared/nscd-flush.h [new file with mode: 0644]
src/shared/specifier.c
src/shared/specifier.h
src/sysctl/sysctl.c
src/systemd/sd-id128.h
src/test/meson.build
src/test/test-fileio.c
src/test/test-json.c
src/test/test-nscd-flush.c [new file with mode: 0644]
src/test/test-unit-file.c
src/tmpfiles/tmpfiles.c
src/udev/udevd.c
test/fuzz/fuzz-netdev-parser/directives.netdev
test/test-network/conf/25-bond-balanced-tlb.netdev [new file with mode: 0644]
test/test-network/systemd-networkd-tests.py

index 0ab9258d1e888335546dd7906934054bb83086f5..e85612bef1e50cc13cc935e29bfdfa2afa5c76be 100644 (file)
@@ -61,6 +61,6 @@ BuildPackages=
         xz-utils
 
 Packages=
-        libqrencode3
+        libqrencode4
         locales
         libidn2-0
diff --git a/NEWS b/NEWS
index 4c32d86139652d67ed646d067f75e86e6bfd65e8..ba69ec02b23acb99431a2ca3e8d638850f221253 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -173,14 +173,15 @@ CHANGES WITH 240 in spe:
         * networkd gained support for Foo-Over-UDP, ERSPAN and ISATAP
           tunnels. It also gained a new option ForceDHCPv6PDOtherInformation=
           for forcing the "Other Information" bit in IPv6 RA messages. The
-          bonding logic gained three new options AdActorSystemPriority=,
+          bonding logic gained four new options AdActorSystemPriority=,
           AdUserPortKey=, AdActorSystem= for configuring various 802.3ad
-          aspects. The tunnel logic gained a new IPv6RapidDeploymentPrefix=
-          option for configuring IPv6 Rapid Deployment. The policy rule logic
-          gained four new options IPProtocol=, SourcePort= and
-          DestinationPort=, InvertRule=. The bridge logic gained support for
-          the MulticastToUnicast= option. networkd also gained support for
-          configuring static IPv4 ARP or IPv6 neighbor entries.
+          aspects, and DynamicTransmitLoadBalancing= for enabling dynamic
+          shuffling of flows. The tunnel logic gained a new
+          IPv6RapidDeploymentPrefix= option for configuring IPv6 Rapid
+          Deployment. The policy rule logic gained four new options IPProtocol=,
+          SourcePort= and DestinationPort=, InvertRule=. The bridge logic gained
+          support for the MulticastToUnicast= option. networkd also gained
+          support for configuring static IPv4 ARP or IPv6 neighbor entries.
 
         * .preset files (as read by 'systemctl preset') may now be used to
           instantiate services.
@@ -379,6 +380,10 @@ CHANGES WITH 240 in spe:
           interface names even as systemd/udev are updated and the naming logic
           is improved.
 
+        * sd-id128.h learnt two new auxiliary helpers: sd_id128_is_allf() and
+          SD_ID128_ALLF to test if a 128bit ID is set to all 0xFF bytes, and to
+          initialize one to all 0xFF.
+
         Contributions from: afg, Alan Jenkins, Aleksei Timofeyev, Alexander
         Filippov, Alexander Kurtz, Alexey Bogdanenko, Andreas Henriksson,
         Andrew Jorgensen, Anita Zhang, apnix-uk, Arkan49, Arseny Maslennikov,
@@ -541,7 +546,7 @@ CHANGES WITH 239:
           Debian and FreeBSD resolvconf tool.
 
         * Support for suspend-then-hibernate has been added, i.e. a sleep mode
-          where the system initially suspends, and after a time-out resumes and
+          where the system initially suspends, and after a timeout resumes and
           hibernates again.
 
         * networkd's ClientIdentifier= now accepts a new option "duid-only". If
@@ -4845,7 +4850,7 @@ CHANGES WITH 217:
           /run/systemd/user directory that was already previously
           supported, but is under the control of the user.
 
-        * Job timeouts (i.e. time-outs on the time a job that is
+        * Job timeouts (i.e. timeouts on the time a job that is
           queued stays in the run queue) can now optionally result in
           immediate reboot or power-off actions (JobTimeoutAction= and
           JobTimeoutRebootArgument=). This is useful on ".target"
index e1b99be960af167712b4429ef2ec9f2b581f244a..a0c7f3997072f841fc9db57f9dd77ed02d77406f 100644 (file)
@@ -21,18 +21,18 @@ variables. All EFI variables use the vendor UUID
   ESP the boot loader was run from formatted as NUL-terminated UTF16 string, in
   normal GUID syntax.
 
-* The EFI variable `LoaderConfigTimeout` contains the boot menu time-out
+* The EFI variable `LoaderConfigTimeout` contains the boot menu timeout
   currently in use. It may be modified both by the boot loader and by the
   host. The value should be formatted as numeric, NUL-terminated, decimal
   string, in UTF-16. The time is specified in Âµs.
 
 * Similarly, the EFI variable `LoaderConfigTimeoutOneShot` contains a boot menu
-  time-out for a single following boot. It is set by the OS in order to request
+  timeout for a single following boot. It is set by the OS in order to request
   display of the boot menu on the following boot. When set overrides
   `LoaderConfigTimeout`. It is removed automatically after being read by the
   boot loader, to ensure it only takes effect a single time. This value is
   formatted the same way as `LoaderConfigTimeout`. If set to `0` the boot menu
-  time-out is turned off, and the menu is shown indefinitely.
+  timeout is turned off, and the menu is shown indefinitely.
 
 * The EFI variable `LoaderEntries` may contain a series of boot loader entry
   identifiers, one after the other, each individually NUL terminated. This may
index e18ea9544dafeddbb292d741ad8a416a1ac793d2..ebca631f59ecacb593bc2ae0e9094548bc2ddb29 100644 (file)
@@ -426,6 +426,10 @@ sensor:modalias:acpi:KIOX000A*:dmi:*:svnTECLAST:pnX98PlusII:*
 sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.011:bd11/03/2015:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnCherryTrailCR:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
+# Teclast F5
+sensor:modalias:acpi:KIOX010A*:dmi:*:svnTECLAST:pnF5:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+
 #########################################
 # Trekstor
 #########################################
index 8bf7a4225241904802b3e15063808f8f4661b62c..07364c2c64daa739fcf926002b8076d26f946f9c 100644 (file)
@@ -96,7 +96,7 @@
 #   The list may contain a single item which must be marked with an
 #   asterisk.
 #
-# Local changes to the non-default resolution of the mouse (e.g. through
+# Local changes to the non-default resolution of the mouse (e.g. through
 # third-party software) must not be entered into this file, use a local
 # hwdb instead.
 #
index e78420dd0d32f287732c7f7ed69dc21760d7f62d..44b0f61f2222f097a8828bd27eee82510483a4c4 100644 (file)
       <varlistentry>
         <term><varname>LoaderConfigTimeout</varname></term>
         <term><varname>LoaderConfigTimeoutOneShot</varname></term>
-        <listitem><para>The menu time-out in seconds. Read by the boot loader. <varname>LoaderConfigTimeout</varname>
+        <listitem><para>The menu timeout in seconds. Read by the boot loader. <varname>LoaderConfigTimeout</varname>
         is maintained persistently, while <varname>LoaderConfigTimeoutOneShot</varname> is a one-time override which is
         read once (in which case it takes precedence over <varname>LoaderConfigTimeout</varname>) and then
         removed. <varname>LoaderConfigTimeout</varname> may be manipulated with the
index 80d24ac8f5661af168930af8b680ca0dc7ef5ad6..610c97f9488721754cc7724d3d4d79237757a60e 100644 (file)
         the command line. If passed, additional metadata is read from the device to enhance the unit to create. For
         example, a descriptive string for the transient units is generated from the file system label and device
         model. Moreover if a removable block device (e.g. USB stick) is detected an automount unit instead of a regular
-        mount unit is created, with a short idle time-out, in order to ensure the file-system is placed in a clean
+        mount unit is created, with a short idle timeout, in order to ensure the file-system is placed in a clean
         state quickly after each access.</para></listitem>
       </varlistentry>
 
index 41b5d7144de1cb84098ffe8d44e88629f41bd9d4..6419bee4998448cff53178a5427b9147e447d958 100644 (file)
@@ -1793,7 +1793,13 @@ SystemCallErrorNumber=EPERM</programlisting>
         <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more
         details about named file descriptors and their ordering.</para>
 
-        <para>This setting defaults to <option>null</option>.</para></listitem>
+        <para>This setting defaults to <option>null</option>.</para>
+
+        <para>Note that services which specify <option>DefaultDependencies=no</option> and use
+        <varname>StandardInput=</varname> or <varname>StandardOutput=</varname> with
+        <option>tty</option>/<option>tty-force</option>/<option>tty-fail</option>, should specify
+        <option>After=systemd-vconsole-setup.service</option>, to make sure that the tty intialization is
+        finished before they start.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 67ccc66dd8ed09ffd17378504c23b6140453ece9..e17c1e3fbefe0db6f238199813e7ca199c735346 100644 (file)
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>DynamicTransmitLoadBalancing=</varname></term>
+        <listitem>
+          <para>Takes a boolean. Specifies if dynamic shuffling of flows is enabled. Applies only
+          for balance-tlb mode. Defaults to unset.
+          </para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>MinLinks=</varname></term>
         <listitem>
index 4c33ed0b68b5c88293e67bfefa8370924e638157..ad04efeb342ac11055a4a8ca986a3f4e4ed40d17 100644 (file)
             actual execution of the service program is delayed until all active jobs are dispatched. This may be used
             to avoid interleaving of output of shell services with the status output on the console. Note that this
             type is useful only to improve console output, it is not useful as a general unit ordering tool, and the
-            effect of this service type is subject to a 5s time-out, after which the service program is invoked
+            effect of this service type is subject to a 5s timeout, after which the service program is invoked
             anyway.</para></listitem>
           </itemizedlist>
 
index 26d215e3cc4e83616f46d519d67c06544ac3ca14..7e1b3cb7eb372a4dc8ad7f1aacce1d93a634bd46 100644 (file)
         <term><varname>JobTimeoutSec=</varname></term>
         <term><varname>JobRunningTimeoutSec=</varname></term>
 
-        <listitem><para>When a job for this unit is queued, a time-out <varname>JobTimeoutSec=</varname> may be
+        <listitem><para>When a job for this unit is queued, a timeout <varname>JobTimeoutSec=</varname> may be
         configured. Similarly, <varname>JobRunningTimeoutSec=</varname> starts counting when the queued job is actually
         started. If either time limit is reached, the job will be cancelled, the unit however will not change state or
         even enter the <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts
         <term><varname>JobTimeoutRebootArgument=</varname></term>
 
         <listitem><para><varname>JobTimeoutAction=</varname> optionally configures an additional action to take when
-        the time-out is hit, see description of <varname>JobTimeoutSec=</varname> and
+        the timeout is hit, see description of <varname>JobTimeoutSec=</varname> and
         <varname>JobRunningTimeoutSec=</varname> above. It takes the same values as
         <varname>StartLimitAction=</varname>. Defaults to <option>none</option>.
         <varname>JobTimeoutRebootArgument=</varname> configures an optional reboot string to pass to the
index 8d71f8b6138b5cf8f7318aa23e77b76d5a986bf5..f8167c63d54c8d546ae31b0cebc692604eb2b420 100644 (file)
@@ -25,8 +25,8 @@ __contains_word () {
 }
 
 __get_interfaces(){
-        { cd /sys/class/net && echo *; } | \
-        while read -d' ' -r name; do
+        local name
+        for name in $(cd /sys/class/net && ls); do
                 [[ "$name" != "lo" ]] && echo "$name"
         done
 }
index 62bb0ba6056ad3045e6adca0f447edb505a390ce..3ba2cd6ec948257bd0b619dd1fd10bd16be2d1da 100644 (file)
@@ -44,9 +44,9 @@ __get_env() {
         env | { while read a; do echo " ${a%%=*}"; done; };
 }
 
-__get_interfaces() {
-        { cd /sys/class/net && echo *; } | \
-        while read -d' ' -r name; do
+__get_interfaces(){
+        local name
+        for name in $(cd /sys/class/net && ls); do
                 [[ "$name" != "lo" ]] && echo "$name"
         done
 }
index 86b8db2cf8a9d0f26ce482bd6821e39405284d87..cd0231a6f497974ccb25b82fedd2a3e201228898 100644 (file)
@@ -24,8 +24,8 @@ __contains_word () {
 }
 
 __get_interfaces(){
-        { cd /sys/class/net && echo *; } | \
-        while read -d' ' -r name; do
+        local name
+        for name in $(cd /sys/class/net && ls); do
                 [[ "$name" != "lo" ]] && echo "$name"
         done
 }
index e5c11bf43cf85a8c46590b61f7e8091c6b8d07f0..7b33839b1e9f14b213dbf84830a67881029c9acd 100644 (file)
@@ -30,61 +30,199 @@ __get_all_sysdevs() {
         printf '%s\n' "${devs[@]%/}"
 }
 
+__get_all_devs() {
+        local i
+        for i in /dev/* /dev/*/*; do
+                echo $i
+        done
+}
+
+__get_all_device_units() {
+        systemctl list-units -t device --full --no-legend --no-pager 2>/dev/null | \
+                { while read -r a b; do echo "$a"; done; }
+}
+
 _udevadm() {
-        local i verb comps
+        local i verb comps builtin
         local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
-        local OPTS='-h --help --version --debug'
+        local -A OPTS=(
+                [COMMON]='-h --help -V --version'
+                [DEBUG]='-d --debug'
+                [INFO_STANDALONE]='-r --root -a --attribute-walk -x --export -e --export-db -c --cleanup-db'
+                [INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file'
+                [TRIGGER_STANDALONE]='-v --verbose -n --dry-run -w --settle'
+                [TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch
+                               -a --attr-match -A --attr-nomatch -p --property-match
+                               -g --tag-match -y --sysname-match --name-match -b --parent-match'
+                [SETTLE]='-t --timeout -E --exit-if-exists'
+                [CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload'
+                [CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout'
+                [MONITOR_STANDALONE]='-k --kernel -u --udev -p --property'
+                [MONITOR_ARG]='-s --subsystem-match -t --tag-match'
+                [TEST]='-a --action -N --resolve-names'
+        )
 
-        local verbs=(info trigger settle control monitor hwdb test-builtin test)
+        local verbs=(info trigger settle control monitor test-builtin test)
+        local builtins=(blkid btrfs hwdb input_id keyboard kmod net_id net_setup_link path_id usb_id uaccess)
 
         for ((i=0; i < COMP_CWORD; i++)); do
-                if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}" &&
-                 ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then
+                if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}"; then
                         verb=${COMP_WORDS[i]}
                         break
                 fi
         done
 
         if [[ -z $verb ]]; then
-                COMPREPLY=( $(compgen -W '${OPTS[*]} ${verbs[*]}' -- "$cur") )
+                if [[ "$cur" = -* ]]; then
+                        COMPREPLY=( $(compgen -W '${OPTS[COMMON]} ${OPTS[DEBUG]}' -- "$cur") )
+                else
+                        COMPREPLY=( $(compgen -W '${verbs[*]}' -- "$cur") )
+                fi
                 return 0
         fi
 
         case $verb in
                 'info')
+                        if __contains_word "$prev" ${OPTS[INFO_ARG]}; then
+                                case $prev in
+                                        -q|--query)
+                                                comps='name symlink path property all'
+                                                ;;
+                                        -p|--path)
+                                                comps=$( __get_all_sysdevs )
+                                                local IFS=$'\n'
+                                                ;;
+                                        -n|--name)
+                                                comps=$( __get_all_devs )
+                                                ;;
+                                        *)
+                                                comps=''
+                                                ;;
+                                esac
+                                COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+                                return 0
+                        fi
+
                         if [[ $cur = -* ]]; then
-                                comps='--help --query= --path= --name= --root --attribute-walk --export-db --cleanup-db'
+                                comps="${OPTS[COMMON]} ${OPTS[INFO_STANDALONE]} ${OPTS[INFO_ARG]}"
                         else
-                                comps=$( __get_all_sysdevs )
+                                comps=$( __get_all_sysdevs; __get_all_device_units )
+                                local IFS=$'\n'
                         fi
                         ;;
                 'trigger')
-                        comps='--help --verbose --dry-run --type= --action= --subsystem-match=
-                               --subsystem-nomatch= --attr-match= --attr-nomatch= --property-match=
-                               --tag-match= --sysname-match= --parent-match='
+                        if __contains_word "$prev" ${OPTS[TRIGGER_ARG]}; then
+                                case $prev in
+                                        -t|--type)
+                                                comps='devices subsystems'
+                                                ;;
+                                        -c|--action)
+                                                comps='add change remove bind unbind'
+                                                ;;
+                                        -y|--sysname-match|-b|--parent-match)
+                                                comps=$( __get_all_sysdevs )
+                                                local IFS=$'\n'
+                                                ;;
+                                        --name-match)
+                                                comps=$( __get_all_devs )
+                                                ;;
+                                        *)
+                                                comps=''
+                                                ;;
+                                esac
+                                COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+                                return 0
+                        fi
+
+                        if [[ $cur = -* ]]; then
+                                comps="${OPTS[COMMON]} ${OPTS[TRIGGER_STANDALONE]} ${OPTS[TRIGGER_ARG]}"
+                        else
+                                comps=$( __get_all_sysdevs; __get_all_device_units )
+                                local IFS=$'\n'
+                        fi
                         ;;
                 'settle')
-                        comps='--help --timeout= --seq-start= --seq-end= --exit-if-exists= --quiet'
+                        if __contains_word "$prev" ${OPTS[SETTLE]}; then
+                                case $prev in
+                                        -E|--exit-if-exists)
+                                                comps=$( compgen -A file -- "$cur" )
+                                                ;;
+                                        *)
+                                                comps=''
+                                                ;;
+                                esac
+                                COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+                                return 0
+                        fi
+
+                        comps="${OPTS[COMMON]} ${OPTS[SETTLE]}"
                         ;;
                 'control')
-                        comps='--help --exit --log-priority= --stop-exec-queue --start-exec-queue
-                               --reload --property= --children-max= --timeout='
+                        if __contains_word "$prev" ${OPTS[CONTROL_ARG]}; then
+                                case $prev in
+                                        -l|--log-priority)
+                                                comps='alert crit debug emerg err info notice warning'
+                                                ;;
+                                        *)
+                                                comps=''
+                                                ;;
+                                esac
+                                COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+                                return 0
+                        fi
+
+                        comps="${OPTS[COMMON]} ${OPTS[CONTROL_STANDALONE]} ${OPTS[CONTROL_ARG]}"
                         ;;
                 'monitor')
-                        comps='--help --kernel --udev --property --subsystem-match= --tag-match='
-                        ;;
-                'hwdb')
-                        comps='--help --update --test='
+                        if __contains_word "$prev" ${OPTS[MONITOR_ARG]}; then
+                                case $prev in
+                                        *)
+                                                comps=''
+                                                ;;
+                                esac
+                                COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+                                return 0
+                        fi
+
+                        comps="${OPTS[COMMON]} ${OPTS[MONITOR_STANDALONE]} ${OPTS[MONITOR_ARG]}"
                         ;;
                 'test')
+                        if __contains_word "$prev" ${OPTS[TEST]}; then
+                                case $prev in
+                                        -a|--action)
+                                                comps='add change remove bind unbind'
+                                                ;;
+                                        -N|--resolve-names)
+                                                comps='early late never'
+                                                ;;
+                                esac
+                                COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+                                return 0
+                        fi
+
                         if [[ $cur = -* ]]; then
-                                comps='--help --action='
+                                comps="${OPTS[COMMON]} ${OPTS[TEST]}"
                         else
                                 comps=$( __get_all_sysdevs )
+                                local IFS=$'\n'
                         fi
                         ;;
                 'test-builtin')
-                        comps='blkid btrfs hwdb input_id keyboard kmod net_id net_setup_link path_id usb_id uaccess'
+                        for ((i=0; i < COMP_CWORD; i++)); do
+                                if __contains_word "${COMP_WORDS[i]}" "${builtins[@]}"; then
+                                        builtin=${COMP_WORDS[i]}
+                                        break
+                                fi
+                        done
+
+                        if [[ -z $builtin ]]; then
+                                comps="${builtins[@]}"
+                        elif [[ $cur = -* ]]; then
+                                comps="${OPTS[COMMON]}"
+                        else
+                                comps=$( __get_all_sysdevs )
+                                local IFS=$'\n'
+                        fi
                         ;;
                 *)
                         comps=${VERBS[*]}
index 83f1f508dd459bad9d08e5b66d54414dfc402ff5..b22fcd0302708704e0b9589b37d041e15918e816 100644 (file)
@@ -266,16 +266,20 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
         return 1;
 }
 
-int read_full_stream(FILE *f, char **contents, size_t *size) {
+int read_full_stream(
+                FILE *f,
+                char **ret_contents,
+                size_t *ret_size) {
+
         _cleanup_free_ char *buf = NULL;
         struct stat st;
         size_t n, l;
         int fd;
 
         assert(f);
-        assert(contents);
+        assert(ret_contents);
 
-        n = LINE_MAX;
+        n = LINE_MAX; /* Start size */
 
         fd = fileno(f);
         if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's
@@ -331,11 +335,20 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
                 n = MIN(n * 2, READ_FULL_BYTES_MAX);
         }
 
+        if (!ret_size) {
+                /* Safety check: if the caller doesn't want to know the size of what we just read it will rely on the
+                 * trailing NUL byte. But if there's an embedded NUL byte, then we should refuse operation as otherwise
+                 * there'd be ambiguity about what we just read. */
+
+                if (memchr(buf, 0, l))
+                        return -EBADMSG;
+        }
+
         buf[l] = 0;
-        *contents = TAKE_PTR(buf);
+        *ret_contents = TAKE_PTR(buf);
 
-        if (size)
-                *size = l;
+        if (ret_size)
+                *ret_size = l;
 
         return 0;
 }
@@ -762,6 +775,9 @@ int read_line(FILE *f, size_t limit, char **ret) {
                         if (n >= limit)
                                 return -ENOBUFS;
 
+                        if (count >= INT_MAX) /* We couldn't return the counter anymore as "int", hence refuse this */
+                                return -ENOBUFS;
+
                         errno = 0;
                         c = fgetc_unlocked(f);
                         if (c == EOF) {
index 4bb7d9c5e0a6858be21a869ba5b387609f4318c3..411efb242b9abd49c0f2d4b2d52595e84b3b23f6 100644 (file)
@@ -362,7 +362,7 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u
 unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) {
         assert(addr);
 
-        return 32 - u32ctz(be32toh(addr->s_addr));
+        return 32U - u32ctz(be32toh(addr->s_addr));
 }
 
 struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
index 01118bb895477bc1d6d2d69a892361a31f37e158..f009d37d4c6f1a9a03f8c14557a3478a98eccb3c 100644 (file)
@@ -147,6 +147,12 @@ static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
         return memcmp(s1, s2, n);
 }
 
+/* Compare s1 (length n1) with s2 (length n2) in lexicographic order. */
+static inline int memcmp_nn(const void *s1, size_t n1, const void *s2, size_t n2) {
+        return memcmp_safe(s1, s2, MIN(n1, n2))
+            ?: CMP(n1, n2);
+}
+
 int on_ac_power(void);
 
 #define memzero(x,l)                                            \
@@ -193,7 +199,7 @@ static inline unsigned u64log2(uint64_t n) {
 
 static inline unsigned u32ctz(uint32_t n) {
 #if __SIZEOF_INT__ == 4
-        return __builtin_ctz(n);
+        return n != 0 ? __builtin_ctz(n) : 32;
 #else
 #error "Wut?"
 #endif
index 12f9924c17584f69b5d9ba4d371f57407aa537eb..a7ce3fceaabd93a3144ae26026e6b39c3e037af4 100644 (file)
@@ -1485,7 +1485,7 @@ static const char *migrate_callback(CGroupMask mask, void *userdata) {
         return unit_get_realized_cgroup_path(userdata, mask);
 }
 
-char *unit_default_cgroup_path(Unit *u) {
+char *unit_default_cgroup_path(const Unit *u) {
         _cleanup_free_ char *escaped = NULL, *slice = NULL;
         int r;
 
index 6d094e9ecda9ef90ca859b0ea454c77ee086519f..266daa20a5b6ef597ef60ae06b087da77e941b58 100644 (file)
@@ -164,7 +164,7 @@ void unit_invalidate_cgroup_members_masks(Unit *u);
 void unit_add_to_cgroup_realize_queue(Unit *u);
 
 const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask);
-char *unit_default_cgroup_path(Unit *u);
+char *unit_default_cgroup_path(const Unit *u);
 int unit_set_cgroup_path(Unit *u, const char *path);
 int unit_pick_cgroup_path(Unit *u);
 
index 889492aeece01439097c733ad0761f015ce5e045..089461a18aa53c4926d8310a184c7a9fbc87e763 100644 (file)
@@ -10,6 +10,7 @@
 #include "fileio.h"
 #include "fs-util.h"
 #include "io-util.h"
+#include "nscd-flush.h"
 #include "parse-util.h"
 #include "random-util.h"
 #include "serialize.h"
@@ -383,6 +384,7 @@ static int dynamic_user_realize(
         _cleanup_close_ int etc_passwd_lock_fd = -1;
         uid_t num = UID_INVALID; /* a uid if is_user, and a gid otherwise */
         gid_t gid = GID_INVALID; /* a gid if is_user, ignored otherwise */
+        bool flush_cache = false;
         int r;
 
         assert(d);
@@ -471,6 +473,7 @@ static int dynamic_user_realize(
                         }
 
                         /* Great! Nothing is stored here, still. Store our newly acquired data. */
+                        flush_cache = true;
                 } else {
                         /* Hmm, so as it appears there's now something stored in the storage socket. Throw away what we
                          * acquired, and use what's stored now. */
@@ -500,6 +503,14 @@ static int dynamic_user_realize(
         if (r < 0)
                 return r;
 
+        if (flush_cache) {
+                /* If we allocated a new dynamic UID, refresh nscd, so that it forgets about potentially cached
+                 * negative entries. But let's do so after we release the /etc/passwd lock, so that there's no
+                 * potential for nscd wanting to lock that for completing the invalidation. */
+                etc_passwd_lock_fd = safe_close(etc_passwd_lock_fd);
+                (void) nscd_flush_cache(STRV_MAKE("passwd", "group"));
+        }
+
         if (is_user) {
                 *ret_uid = num;
                 *ret_gid = gid != GID_INVALID ? gid : num;
@@ -572,6 +583,8 @@ static int dynamic_user_close(DynamicUser *d) {
 
         /* This dynamic user was realized and dynamically allocated. In this case, let's remove the lock file. */
         unlink_uid_lock(lock_fd, uid, d->name);
+
+        (void) nscd_flush_cache(STRV_MAKE("passwd", "group"));
         return 1;
 }
 
index fc5644f489690e87ea8a5873248a7fa23ae9b339..4ebe92fd45cc6ca3a04037b18176ab4d74f2f754 100644 (file)
@@ -4531,7 +4531,6 @@ static int load_from_path(Unit *u, const char *path) {
                                 r = open_follow(&filename, &f, symlink_names, &id);
                         if (r >= 0)
                                 break;
-                        filename = mfree(filename);
 
                         /* ENOENT means that the file is missing or is a dangling symlink.
                          * ENOTDIR means that one of paths we expect to be is a directory
@@ -4543,6 +4542,7 @@ static int load_from_path(Unit *u, const char *path) {
                         else if (!IN_SET(r, -ENOENT, -ENOTDIR))
                                 return r;
 
+                        filename = mfree(filename);
                         /* Empty the symlink names for the next run */
                         set_clear_free(symlink_names);
                 }
index bce8020cfd4fa32db7dcdd94790cc2d4e96400fb..9f8fc46434e7a97373d98c91e4b9cbea8d9fdaa7 100644 (file)
@@ -227,6 +227,9 @@ struct Manager {
         /* Data specific to the mount subsystem */
         struct libmnt_monitor *mount_monitor;
         sd_event_source *mount_event_source;
+        sd_event_source *mount_timeout_source;
+        usec_t mount_last_read_usec;
+        usec_t mount_last_duration_usec;
 
         /* Data specific to the swap filesystem */
         FILE *proc_swaps;
index ead9bc1f441564993b20c7e78c22327a904a71e4..cfdcc6e6f541b09dd1eccf1765f0acfb2ec9e6f7 100644 (file)
@@ -55,6 +55,7 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
 
 static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
 static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int mount_dispatch_proc_self_mountinfo_timer(sd_event_source *source, usec_t usec, void *userdata);
 
 static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
         return IN_SET(state,
@@ -1665,6 +1666,7 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
 static void mount_shutdown(Manager *m) {
         assert(m);
 
+        m->mount_timeout_source = sd_event_source_unref(m->mount_timeout_source);
         m->mount_event_source = sd_event_source_unref(m->mount_event_source);
 
         mnt_unref_monitor(m->mount_monitor);
@@ -1780,13 +1782,50 @@ fail:
         mount_shutdown(m);
 }
 
+static void mount_process_proc_self_mountinfo(Manager *m);
+
 static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
-        _cleanup_set_free_free_ Set *around = NULL, *gone = NULL;
         Manager *m = userdata;
-        const char *what;
-        Iterator i;
-        Unit *u;
         int r;
+        usec_t next_read = usec_add(m->mount_last_read_usec,
+                                    m->mount_last_duration_usec * 10);
+
+        if (now(CLOCK_MONOTONIC) < next_read) {
+                /* The (current) API for getting mount events from the Linux kernel
+                 * involves getting a "something changed" notification, and then having
+                 * to re-read the entire /proc/self/mountinfo file.  When there are lots
+                 * of mountpoints, this file is large and parsing it can take noticeable
+                 * time.  As most of the file won't have changed, this can be seen as wasted time.
+                 * If there is a "mount storm" such as 1000 mount points being created
+                 * in quick succession, this will result in 1000 successive notification.
+                 * If we respond to every notification, we will do quadratically more work
+                 * than if we respond just once after all the notifications have arrived.
+                 * In this (pathological) case, a delay in scheduling would actually
+                 * improve throughput as we would combine notifications and parse
+                 * the file less often.  We cannot expect the scheduler to notice
+                 * this pathology without help.
+                 * So when the rate of notifications means we are spending more than
+                 * 10% of real time handling them, we set a timer and stop listening
+                 * to notifications for a while.
+                 * If/when Linux provides an API which provides only details of what
+                 * has changed, this rate-limiting can be removed.
+                 */
+
+                r = sd_event_source_set_enabled(source, SD_EVENT_OFF);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to disable monitoring of /proc/self/mounting, ignoring: %m");
+                if (!m->mount_timeout_source) {
+                        r = sd_event_add_time(m->event, &m->mount_timeout_source,
+                                              CLOCK_MONOTONIC,
+                                              next_read,
+                                              0,
+                                              mount_dispatch_proc_self_mountinfo_timer,
+                                              m);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to set timeout to reread /proc/self/mounting, ignoring: %m");
+                }
+                return 0;
+        }
 
         assert(m);
         assert(revents & EPOLLIN);
@@ -1814,13 +1853,40 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                         return 0;
         }
 
+        mount_process_proc_self_mountinfo(m);
+        return 0;
+}
+
+static int mount_dispatch_proc_self_mountinfo_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Manager *m = userdata;
+        int r;
+
+        r = sd_event_source_set_enabled(m->mount_event_source, SD_EVENT_ON);
+        if (r < 0)
+                log_warning_errno(r, "Failed to reenable /proc/self/mountinfo monitor, ignoring: %m");
+        m->mount_timeout_source = sd_event_source_unref(source);
+        mount_process_proc_self_mountinfo(m);
+        return 0;
+}
+
+static void mount_process_proc_self_mountinfo(Manager *m) {
+        _cleanup_set_free_free_ Set *around = NULL, *gone = NULL;
+        const char *what;
+        Iterator i;
+        Unit *u;
+        int r;
+
+        m->mount_last_read_usec = now(CLOCK_MONOTONIC);
+        /* If an error occurs, assume 10ms */
+        m->mount_last_duration_usec = 10 * USEC_PER_MSEC;
+
         r = mount_load_proc_self_mountinfo(m, true);
         if (r < 0) {
                 /* Reset flags, just in case, for later calls */
                 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT])
                         MOUNT(u)->proc_flags = 0;
 
-                return 0;
+                return;
         }
 
         manager_dispatch_load_queue(m);
@@ -1908,8 +1974,8 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                 /* Let the device units know that the device is no longer mounted */
                 device_found_node(m, what, 0, DEVICE_FOUND_MOUNT);
         }
-
-        return 0;
+        m->mount_last_duration_usec = usec_sub_unsigned(now(CLOCK_MONOTONIC),
+                                                        m->mount_last_read_usec);
 }
 
 static void mount_reset_failed(Unit *u) {
index f57c099c39560c0e48790d78fd295e0d476a82b6..a8e84ebe8097af88fc91ae81501c7f98e509a7b3 100644 (file)
 #include "unit.h"
 #include "user-util.h"
 
-static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
 
         assert(u);
 
         return unit_name_to_prefix_and_instance(u->id, ret);
 }
 
-static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
 
         assert(u);
 
         return unit_name_to_prefix(u->id, ret);
 }
 
-static int specifier_prefix_unescaped(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_prefix_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
         _cleanup_free_ char *p = NULL;
-        Unit *u = userdata;
+        const Unit *u = userdata;
         int r;
 
         assert(u);
@@ -42,16 +42,16 @@ static int specifier_prefix_unescaped(char specifier, void *data, void *userdata
         return unit_name_unescape(p, ret);
 }
 
-static int specifier_instance_unescaped(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_instance_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
 
         assert(u);
 
         return unit_name_unescape(strempty(u->instance), ret);
 }
 
-static int specifier_last_component(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
         _cleanup_free_ char *prefix = NULL;
         char *dash;
         int r;
@@ -70,7 +70,7 @@ static int specifier_last_component(char specifier, void *data, void *userdata,
         return 0;
 }
 
-static int specifier_last_component_unescaped(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_last_component_unescaped(char specifier, const void *data, const void *userdata, char **ret) {
         _cleanup_free_ char *p = NULL;
         int r;
 
@@ -81,8 +81,8 @@ static int specifier_last_component_unescaped(char specifier, void *data, void *
         return unit_name_unescape(p, ret);
 }
 
-static int specifier_filename(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_filename(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
 
         assert(u);
 
@@ -92,12 +92,12 @@ static int specifier_filename(char specifier, void *data, void *userdata, char *
                 return unit_name_to_path(u->id, ret);
 }
 
-static void bad_specifier(Unit *u, char specifier) {
+static void bad_specifier(const Unit *u, char specifier) {
         log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier);
 }
 
-static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_cgroup(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
         char *n;
 
         assert(u);
@@ -115,8 +115,8 @@ static int specifier_cgroup(char specifier, void *data, void *userdata, char **r
         return 0;
 }
 
-static int specifier_cgroup_root(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_cgroup_root(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
         char *n;
 
         assert(u);
@@ -131,8 +131,8 @@ static int specifier_cgroup_root(char specifier, void *data, void *userdata, cha
         return 0;
 }
 
-static int specifier_cgroup_slice(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_cgroup_slice(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
         char *n;
 
         assert(u);
@@ -140,7 +140,7 @@ static int specifier_cgroup_slice(char specifier, void *data, void *userdata, ch
         bad_specifier(u, specifier);
 
         if (UNIT_ISSET(u->slice)) {
-                Unit *slice;
+                const Unit *slice;
 
                 slice = UNIT_DEREF(u->slice);
 
@@ -157,8 +157,8 @@ static int specifier_cgroup_slice(char specifier, void *data, void *userdata, ch
         return 0;
 }
 
-static int specifier_special_directory(char specifier, void *data, void *userdata, char **ret) {
-        Unit *u = userdata;
+static int specifier_special_directory(char specifier, const void *data, const void *userdata, char **ret) {
+        const Unit *u = userdata;
         char *n = NULL;
 
         assert(u);
index 171567022facf098926b9ed783fc4f8b53f5a1ed..24b14fbcd63759791cebea6882e3f1d1df1cbd10 100644 (file)
@@ -132,7 +132,7 @@ int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret) {
         return r;
 }
 
-bool unit_has_name(Unit *u, const char *name) {
+bool unit_has_name(const Unit *u, const char *name) {
         assert(u);
         assert(name);
 
@@ -4741,7 +4741,7 @@ void unit_warn_if_dir_nonempty(Unit *u, const char* where) {
 }
 
 int unit_fail_if_noncanonical(Unit *u, const char* where) {
-        _cleanup_free_ char *canonical_where;
+        _cleanup_free_ char *canonical_where = NULL;
         int r;
 
         assert(u);
index 312742f11b591ed9be2f03eabc3c129af12f60ba..6fd39eaca3467a7d51b4d8ac17f76fc1d34bf390 100644 (file)
@@ -648,7 +648,7 @@ int unit_set_default_slice(Unit *u);
 
 const char *unit_description(Unit *u) _pure_;
 
-bool unit_has_name(Unit *u, const char *name);
+bool unit_has_name(const Unit *u, const char *name);
 
 UnitActiveState unit_active_state(Unit *u);
 
index 616b42f33ff667ebbfeb7697fab83206aa72ee70..55a8242fcfc40d90321b2eb5343fe6b727455854 100644 (file)
@@ -61,7 +61,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_usr_what, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_usr_fstype, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep);
 
-
 static int write_options(FILE *f, const char *options) {
         _cleanup_free_ char *o = NULL;
 
index c1f9e27523fa2c2e963a2218b4f278a66856a8c7..7777450c35401db8aaacc2950f814ba34ac886ea 100644 (file)
@@ -18,6 +18,7 @@
 #include "id128-util.h"
 #include "main-func.h"
 #include "missing_capability.h"
+#include "nscd-flush.h"
 #include "os-util.h"
 #include "parse-util.h"
 #include "path-util.h"
@@ -113,8 +114,12 @@ static int context_read_data(Context *c) {
 
         r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &c->uuid);
         if (r < 0)
-                log_info_errno(r, "Failed to read product UUID, ignoring: %m");
-        c->has_uuid = (r >= 0);
+                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+                               "Failed to read product UUID, ignoring: %m");
+        else if (sd_id128_is_null(c->uuid) || sd_id128_is_allf(c->uuid))
+                log_debug("DMI product UUID " SD_ID128_FORMAT_STR " is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(c->uuid));
+        else
+                c->has_uuid = true;
 
         return 0;
 }
@@ -286,6 +291,8 @@ static int context_update_kernel_hostname(Context *c) {
         if (sethostname_idempotent(hn) < 0)
                 return -errno;
 
+        (void) nscd_flush_cache(STRV_MAKE("hosts"));
+
         return 0;
 }
 
index 1f1603b3767f9b2cb8897ba7c34743cc8ae1611e..8253a45128c6a29e61424153700f75d1ce99b0a5 100644 (file)
@@ -14,6 +14,7 @@
 #include "journal-util.h"
 #include "journald-context.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "process-util.h"
 #include "string-util.h"
 #include "syslog-util.h"
@@ -252,9 +253,11 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u
 
         /* Try to acquire the current cgroup path */
         r = cg_pid_get_path_shifted(c->pid, s->cgroup_root, &t);
-        if (r < 0) {
+        if (r < 0 || empty_or_root(t)) {
 
-                /* If that didn't work, we use the unit ID passed in as fallback, if we have nothing cached yet */
+                /* We use the unit ID passed in as fallback if we have nothing cached yet and cg_pid_get_path_shifted()
+                 * failed or process is running in a root cgroup. Zombie processes are automatically migrated to root cgroup
+                 * on cgroupsv1 and we want to be able to map log messages from them too. */
                 if (unit_id && !c->unit) {
                         c->unit = strdup(unit_id);
                         if (c->unit)
index 952197e714930992c292e2fa7a732b87bd116aac..199d8aee0ac4300e379e4370224777a559b41efa 100644 (file)
@@ -9,6 +9,7 @@
 #include "lldp-neighbor.h"
 #include "missing.h"
 #include "unaligned.h"
+#include "util.h"
 
 static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) {
         siphash24_compress(id->chassis_id, id->chassis_id_size, state);
@@ -18,21 +19,8 @@ static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash
 }
 
 int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) {
-        int r;
-
-        r = memcmp(x->chassis_id, y->chassis_id, MIN(x->chassis_id_size, y->chassis_id_size));
-        if (r != 0)
-                return r;
-
-        r = CMP(x->chassis_id_size, y->chassis_id_size);
-        if (r != 0)
-                return r;
-
-        r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size));
-        if (r != 0)
-                return r;
-
-        return CMP(x->port_id_size, y->port_id_size);
+        return memcmp_nn(x->chassis_id, x->chassis_id_size, y->chassis_id, y->chassis_id_size)
+            ?: memcmp_nn(x->port_id, x->port_id_size, y->port_id, y->port_id_size);
 }
 
 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(lldp_neighbor_hash_ops, LLDPNeighborID, lldp_neighbor_id_hash_func, lldp_neighbor_id_compare_func,
index b352f0bfe5e054344d5d5c0818592e6e6644364a..f208b294d8f1dcb01978405b842624172103fe7f 100644 (file)
@@ -320,7 +320,7 @@ struct sd_bus {
         usec_t method_call_timeout;
 };
 
-/* For method calls we time-out at 25s, like in the D-Bus reference implementation */
+/* For method calls we timeout at 25s, like in the D-Bus reference implementation */
 #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
 
 /* For the authentication phase we grant 90s, to provide extra room during boot, when RNGs and such are not filled up
index fcf9b761ee9fb6e20085ee6c9ab52934faaa64cd..b86932663e753c3a1fd6f56647d7b77de773ac1a 100644 (file)
@@ -93,6 +93,12 @@ _public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, siz
         assert_return(m, -EINVAL);
         assert_return((size_t) n == size, -EINVAL);
 
+        if (m->bound)
+                return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                       "sd-device-monitor: Socket fd is already bound. "
+                                       "It may be dangerous to change buffer size. "
+                                       "Refusing to change buffer size.");
+
         if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n) < 0) {
                 r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n);
                 if (r < 0)
@@ -211,11 +217,9 @@ _public_ int sd_device_monitor_start(sd_device_monitor *m, sd_device_monitor_han
                         return r;
         }
 
-        if (!m->bound) {
-                r = device_monitor_enable_receiving(m);
-                if (r < 0)
-                        return r;
-        }
+        r = device_monitor_enable_receiving(m);
+        if (r < 0)
+                return r;
 
         m->callback = callback;
         m->userdata = userdata;
@@ -277,20 +281,20 @@ int device_monitor_enable_receiving(sd_device_monitor *m) {
                 return log_debug_errno(r, "sd-device-monitor: Failed to update filter: %m");
 
         if (!m->bound) {
+                /* enable receiving of sender credentials */
+                r = setsockopt_int(m->sock, SOL_SOCKET, SO_PASSCRED, true);
+                if (r < 0)
+                        return log_debug_errno(r, "sd-device-monitor: Failed to set socket option SO_PASSCRED: %m");
+
                 if (bind(m->sock, &m->snl.sa, sizeof(struct sockaddr_nl)) < 0)
                         return log_debug_errno(errno, "sd-device-monitor: Failed to bind monitoring socket: %m");
 
                 m->bound = true;
-        }
-
-        r = monitor_set_nl_address(m);
-        if (r < 0)
-                return log_debug_errno(r, "sd-device-monitor: Failed to set address: %m");
 
-        /* enable receiving of sender credentials */
-        r = setsockopt_int(m->sock, SOL_SOCKET, SO_PASSCRED, true);
-        if (r < 0)
-                return log_debug_errno(r, "sd-device-monitor: Failed to set socket option SO_PASSCRED: %m");
+                r = monitor_set_nl_address(m);
+                if (r < 0)
+                        return log_debug_errno(r, "sd-device-monitor: Failed to set address: %m");
+        }
 
         return 0;
 }
index 64ab386df3f1c0a7378a62254976c79f0a34bc3e..cd5cdcc6e55c58a9770f8af003a3ab260ed0d5d3 100644 (file)
@@ -227,6 +227,7 @@ static const NLType rtnl_link_info_data_bond_types[] = {
         [IFLA_BOND_AD_ACTOR_SYS_PRIO]   = { .type = NETLINK_TYPE_U16 },
         [IFLA_BOND_AD_USER_PORT_KEY]    = { .type = NETLINK_TYPE_U16 },
         [IFLA_BOND_AD_ACTOR_SYSTEM]     = { .type = NETLINK_TYPE_ETHER_ADDR },
+        [IFLA_BOND_TLB_DYNAMIC_LB]      = { .type = NETLINK_TYPE_U8 },
 };
 
 static const NLType rtnl_link_info_data_iptun_types[] = {
index bff2c4976b9e5d4b171c60b0ac9a18a20e97cb68..8de7adcd16d7abcd81d9497c36c1bfc0e76fb49e 100644 (file)
@@ -92,7 +92,7 @@ int main(int argc, char *argv[]) {
                 if (r == 0)
                         break;
                 if (r == -ETIMEDOUT) {
-                        /* Let's catch time-outs here, so that we can run safely in a CI that has no reliable DNS. Note
+                        /* Let's catch timeouts here, so that we can run safely in a CI that has no reliable DNS. Note
                          * that we invoke exit() directly here, as the stuck NSS call will not allow us to exit
                          * cleanly. */
 
index 6af12765f5dcb08fe085f18983440c5beaffed5d..beb5b3566a92d9d59e7541c4015ececa9a94503a 100644 (file)
@@ -398,6 +398,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
         machine_save(m);
 
         machine_send_signal(m, true);
+        (void) manager_enqueue_nscd_cache_flush(m->manager);
 
         return 0;
 }
@@ -439,6 +440,7 @@ int machine_stop(Machine *m) {
         m->stopping = true;
 
         machine_save(m);
+        (void) manager_enqueue_nscd_cache_flush(m->manager);
 
         return r;
 }
diff --git a/src/machine/machined-core.c b/src/machine/machined-core.c
new file mode 100644 (file)
index 0000000..6a40480
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "machined.h"
+#include "nscd-flush.h"
+#include "strv.h"
+
+static int on_nscd_cache_flush_event(sd_event_source *s, void *userdata) {
+        /* Let's ask glibc's nscd daemon to flush its caches. We request this for the three database machines may show
+         * up in: the hosts database (for resolvable machine names) and the user and group databases (for the user ns
+         * ranges). */
+
+        (void) nscd_flush_cache(STRV_MAKE("passwd", "group", "hosts"));
+        return 0;
+}
+
+int manager_enqueue_nscd_cache_flush(Manager *m) {
+        int r;
+
+        assert(m);
+
+        if (!m->nscd_cache_flush_event) {
+                r = sd_event_add_defer(m->event, &m->nscd_cache_flush_event, on_nscd_cache_flush_event, m);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to allocate NSCD cache flush event: %m");
+
+                sd_event_source_set_description(m->nscd_cache_flush_event, "nscd-cache-flush");
+        }
+
+        r = sd_event_source_set_enabled(m->nscd_cache_flush_event, SD_EVENT_ONESHOT);
+        if (r < 0) {
+                m->nscd_cache_flush_event = sd_event_source_unref(m->nscd_cache_flush_event);
+                return log_error_errno(r, "Failed to enable NSCD cache flush event: %m");
+        }
+
+        return 0;
+}
index dec2164bb04eda4f37b56153edf6ab92f984fc73..9f23e369a46a29c240355ec790c2c64d05c554a7 100644 (file)
@@ -25,8 +25,7 @@
 static Manager* manager_unref(Manager *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
 
-DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(machine_hash_ops, void, trivial_hash_func, trivial_compare_func,
-                                              Machine, machine_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(machine_hash_ops, char, string_hash_func, string_compare_func, Machine, machine_free);
 
 static int manager_new(Manager **ret) {
         _cleanup_(manager_unrefp) Manager *m = NULL;
@@ -38,9 +37,9 @@ static int manager_new(Manager **ret) {
         if (!m)
                 return -ENOMEM;
 
-        m->machines = hashmap_new(&string_hash_ops);
+        m->machines = hashmap_new(&machine_hash_ops);
         m->machine_units = hashmap_new(&string_hash_ops);
-        m->machine_leaders = hashmap_new(&machine_hash_ops);
+        m->machine_leaders = hashmap_new(NULL);
 
         if (!m->machines || !m->machine_units || !m->machine_leaders)
                 return -ENOMEM;
@@ -72,12 +71,13 @@ static Manager* manager_unref(Manager *m) {
 
         assert(m->n_operations == 0);
 
-        hashmap_free(m->machines);
+        hashmap_free(m->machines); /* This will free all machines, so that the machine_units/machine_leaders is empty */
         hashmap_free(m->machine_units);
         hashmap_free(m->machine_leaders);
         hashmap_free(m->image_cache);
 
         sd_event_source_unref(m->image_cache_defer_event);
+        sd_event_source_unref(m->nscd_cache_flush_event);
 
         bus_verify_polkit_async_registry_free(m->polkit_registry);
 
index ef63f96e971b6e8256878af38869c9d2b1074d65..2298a652c4d6376641c284712fcf715ca2f84626 100644 (file)
@@ -35,6 +35,8 @@ struct Manager {
 
         LIST_HEAD(Operation, operations);
         unsigned n_operations;
+
+        sd_event_source *nscd_cache_flush_event;
 };
 
 int manager_add_machine(Manager *m, const char *name, Machine **_machine);
@@ -53,3 +55,5 @@ int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_erro
 int manager_unref_unit(Manager *m, const char *unit, sd_bus_error *error);
 int manager_unit_is_active(Manager *manager, const char *unit);
 int manager_job_is_active(Manager *manager, const char *path);
+
+int manager_enqueue_nscd_cache_flush(Manager *m);
index d5158771386bf93a9eef224a1190f36515adb1c2..bc670714b45f19e8d317c1ec6073380c7a1f4d60 100644 (file)
@@ -9,6 +9,7 @@ libmachine_core_sources = files('''
         machine.c
         machine.h
         machined-dbus.c
+        machined-core.c
         machine-dbus.c
         machine-dbus.h
         image-dbus.c
index 70d314bc7949019652a2814fb61da06c10371954..550a7f89145ccf96edfad4979564e1c06167e51f 100644 (file)
@@ -307,6 +307,12 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m");
 
+        if (b->tlb_dynamic_lb >= 0) {
+                r = sd_netlink_message_append_u8(m, IFLA_BOND_TLB_DYNAMIC_LB, b->tlb_dynamic_lb);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_TLB_DYNAMIC_LB attribute: %m");
+        }
+
         if (b->arp_interval > 0)  {
                 if (b->n_arp_ip_targets > 0) {
 
@@ -534,6 +540,7 @@ static void bond_init(NetDev *netdev) {
         b->primary_reselect = _NETDEV_BOND_PRIMARY_RESELECT_INVALID;
 
         b->all_slaves_active = false;
+        b->tlb_dynamic_lb = -1;
 
         b->resend_igmp = RESEND_IGMP_DEFAULT;
         b->packets_per_slave = PACKETS_PER_SLAVE_DEFAULT;
index 99ef25d0d34257b56c18278f511d473ccbd8da08..31b922b03279e98c924553c915866347eef28b8d 100644 (file)
@@ -99,6 +99,8 @@ typedef struct Bond {
         BondArpAllTargets arp_all_targets;
         BondPrimaryReselect primary_reselect;
 
+        int tlb_dynamic_lb;
+
         bool all_slaves_active;
 
         unsigned resend_igmp;
index fbc7a59e9e8ca3749947b14ff0fd8be20d63b232..f7ca98fa4671bb5b6c111ec7c75ac047b2ce4253 100644 (file)
@@ -140,7 +140,8 @@ Bond.PrimaryReselectPolicy,        config_parse_bond_primary_reselect,   0,
 Bond.ResendIGMP,                   config_parse_unsigned,                0,                             offsetof(Bond, resend_igmp)
 Bond.PacketsPerSlave,              config_parse_unsigned,                0,                             offsetof(Bond, packets_per_slave)
 Bond.GratuitousARP,                config_parse_unsigned,                0,                             offsetof(Bond, num_grat_arp)
-Bond.AllSlavesActive,              config_parse_unsigned,                0,                             offsetof(Bond, all_slaves_active)
+Bond.AllSlavesActive,              config_parse_bool,                    0,                             offsetof(Bond, all_slaves_active)
+Bond.DynamicTransmitLoadBalancing, config_parse_tristate,                0,                             offsetof(Bond, tlb_dynamic_lb)
 Bond.MinLinks,                     config_parse_unsigned,                0,                             offsetof(Bond, min_links)
 Bond.MIIMonitorSec,                config_parse_sec,                     0,                             offsetof(Bond, miimon)
 Bond.UpDelaySec,                   config_parse_sec,                     0,                             offsetof(Bond, updelay)
index ffc460dbf298a61660cdaee6ed84fcd527fa3c8e..c3079aca1d4279a573ff265931e5447e51248f65 100644 (file)
@@ -15,3 +15,4 @@
 # operation for /etc/resolv.conf.
 
 nameserver 127.0.0.53
+options edns0
index 2c28ec227a5c601c053ccb7e3883e984255c9f4b..b8e6a7abe1b59015a9900e539089e127ce0b07c2 100644 (file)
@@ -141,7 +141,7 @@ static int dnssd_service_load(Manager *manager, const char *filename) {
         return 0;
 }
 
-static int specifier_dnssd_host_name(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_dnssd_host_name(char specifier, const void *data, const void *userdata, char **ret) {
         DnssdService *s  = (DnssdService *) userdata;
         char *n;
 
index 063d3f35c367a6287c77562a8a1d9042a6839b5a..81ab2056ac65e4dbc5e81a17c573fc4ed1a1f3a1 100644 (file)
@@ -16,8 +16,8 @@ typedef struct LinkAddress LinkAddress;
 #include "resolved-dns-server.h"
 #include "resolved-manager.h"
 
-#define LINK_SEARCH_DOMAINS_MAX 32
-#define LINK_DNS_SERVERS_MAX 32
+#define LINK_SEARCH_DOMAINS_MAX 256
+#define LINK_DNS_SERVERS_MAX 256
 
 struct LinkAddress {
         Link *link;
index 79a473f57efb891affc20a8cf98a119038339a45..06c76f6014dc438cb669faeefed94f797c8753a8 100644 (file)
@@ -20,8 +20,8 @@ typedef struct Manager Manager;
 #include "resolved-dns-trust-anchor.h"
 #include "resolved-link.h"
 
-#define MANAGER_SEARCH_DOMAINS_MAX 32
-#define MANAGER_DNS_SERVERS_MAX 32
+#define MANAGER_SEARCH_DOMAINS_MAX 256
+#define MANAGER_DNS_SERVERS_MAX 256
 
 typedef struct EtcHosts {
         Hashmap *by_address;
index ad47d13d238891f452bed617975bb3cd997e5f57..5fcd59d8767ab01b6be3ca5b608b85d2f385774e 100644 (file)
@@ -321,7 +321,8 @@ static int write_stub_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet
                        "# See man:systemd-resolved.service(8) for details about the supported modes of\n"
                        "# operation for /etc/resolv.conf.\n"
                        "\n"
-                       "nameserver 127.0.0.53\n", f);
+                       "nameserver 127.0.0.53\n"
+                       "options edns0\n", f);
 
         if (!ordered_set_isempty(domains))
                 write_resolv_conf_search(domains, f);
index b87d6b9d55e9dbaa001b3beaf342041cf262d4fb..d2143beda3a05a5364b7f25389791910d5956000 100644 (file)
@@ -14,7 +14,7 @@
 #include "unit-name.h"
 #include "user-util.h"
 
-static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) {
         const UnitFileInstallInfo *i = userdata;
         _cleanup_free_ char *prefix = NULL;
         int r;
@@ -38,7 +38,7 @@ static int specifier_prefix_and_instance(char specifier, void *data, void *userd
         return 0;
 }
 
-static int specifier_name(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_name(char specifier, const void *data, const void *userdata, char **ret) {
         const UnitFileInstallInfo *i = userdata;
         char *ans;
 
@@ -54,7 +54,7 @@ static int specifier_name(char specifier, void *data, void *userdata, char **ret
         return 0;
 }
 
-static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) {
         const UnitFileInstallInfo *i = userdata;
 
         assert(i);
@@ -62,7 +62,7 @@ static int specifier_prefix(char specifier, void *data, void *userdata, char **r
         return unit_name_to_prefix(i->name, ret);
 }
 
-static int specifier_instance(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_instance(char specifier, const void *data, const void *userdata, char **ret) {
         const UnitFileInstallInfo *i = userdata;
         char *instance;
         int r;
@@ -83,7 +83,7 @@ static int specifier_instance(char specifier, void *data, void *userdata, char *
         return 0;
 }
 
-static int specifier_last_component(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) {
         _cleanup_free_ char *prefix = NULL;
         char *dash;
         int r;
@@ -104,8 +104,7 @@ static int specifier_last_component(char specifier, void *data, void *userdata,
         return 0;
 }
 
-int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) {
-
+int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret) {
         /* This is similar to unit_full_printf() but does not support
          * anything path-related.
          *
index 378b3bfd927da40605b88446c35e9d2577e464e3..fa8ea7ef81daa92946faf51601f84e934202019c 100644 (file)
@@ -3,4 +3,4 @@
 
 #include "install.h"
 
-int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret);
+int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret);
index 9e3d9a63b46f8e197894debf74febd428d626c0d..3104043af64233534d5518fcd792496379d089db 100644 (file)
@@ -68,7 +68,7 @@ typedef struct {
         size_t n_rules;
 } Presets;
 
-static inline bool unit_file_install_info_has_rules(UnitFileInstallInfo *i) {
+static inline bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) {
         assert(i);
 
         return !strv_isempty(i->aliases) ||
@@ -76,7 +76,7 @@ static inline bool unit_file_install_info_has_rules(UnitFileInstallInfo *i) {
                !strv_isempty(i->required_by);
 }
 
-static inline bool unit_file_install_info_has_also(UnitFileInstallInfo *i) {
+static inline bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) {
         assert(i);
 
         return !strv_isempty(i->also);
@@ -477,8 +477,10 @@ static int create_symlink(
         if (!dirname)
                 return -ENOMEM;
 
-        if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path))
+        if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path)) {
+                log_debug("Symlink %s â†’ %s already exists", new_path, dest);
                 return 1;
+        }
 
         if (!force) {
                 unit_file_changes_add(changes, n_changes, -EEXIST, new_path, dest);
@@ -711,8 +713,9 @@ static int is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *
 
 static int find_symlinks_fd(
                 const char *root_dir,
-                UnitFileInstallInfo *i,
+                const UnitFileInstallInfo *i,
                 bool match_aliases,
+                bool ignore_same_name,
                 int fd,
                 const char *path,
                 const char *config_path,
@@ -759,7 +762,7 @@ static int find_symlinks_fd(
                         }
 
                         /* This will close nfd, regardless whether it succeeds or not */
-                        q = find_symlinks_fd(root_dir, i, match_aliases, nfd,
+                        q = find_symlinks_fd(root_dir, i, match_aliases, ignore_same_name, nfd,
                                              p, config_path, same_name_link);
                         if (q > 0)
                                 return 1;
@@ -768,7 +771,7 @@ static int find_symlinks_fd(
 
                 } else if (de->d_type == DT_LNK) {
                         _cleanup_free_ char *p = NULL, *dest = NULL;
-                        bool found_path, found_dest, b = false;
+                        bool found_path = false, found_dest, b = false;
                         int q;
 
                         /* Acquire symlink name */
@@ -794,23 +797,20 @@ static int find_symlinks_fd(
                                 if (!x)
                                         return -ENOMEM;
 
-                                free(dest);
-                                dest = x;
+                                free_and_replace(dest, x);
                         }
 
-                        /* Check if the symlink itself matches what we
-                         * are looking for */
-                        if (path_is_absolute(i->name))
-                                found_path = path_equal(p, i->name);
-                        else
-                                found_path = streq(de->d_name, i->name);
+                        assert(unit_name_is_valid(i->name, UNIT_NAME_ANY));
+                        if (!ignore_same_name)
+                                /* Check if the symlink itself matches what we are looking for.
+                                 *
+                                 * If ignore_same_name is specified, we are in one of the directories which
+                                 * have lower priority than the unit file, and even if a file or symlink with
+                                 * this name was found, we should ignore it. */
+                                 found_path = streq(de->d_name, i->name);
 
-                        /* Check if what the symlink points to
-                         * matches what we are looking for */
-                        if (path_is_absolute(i->name))
-                                found_dest = path_equal(dest, i->name);
-                        else
-                                found_dest = streq(basename(dest), i->name);
+                        /* Check if what the symlink points to matches what we are looking for */
+                        found_dest = streq(basename(dest), i->name);
 
                         if (found_path && found_dest) {
                                 _cleanup_free_ char *t = NULL;
@@ -845,8 +845,9 @@ static int find_symlinks_fd(
 
 static int find_symlinks(
                 const char *root_dir,
-                UnitFileInstallInfo *i,
+                const UnitFileInstallInfo *i,
                 bool match_name,
+                bool ignore_same_name,
                 const char *config_path,
                 bool *same_name_link) {
 
@@ -864,29 +865,34 @@ static int find_symlinks(
         }
 
         /* This takes possession of fd and closes it */
-        return find_symlinks_fd(root_dir, i, match_name, fd,
+        return find_symlinks_fd(root_dir, i, match_name, ignore_same_name, fd,
                                 config_path, config_path, same_name_link);
 }
 
 static int find_symlinks_in_scope(
                 UnitFileScope scope,
                 const LookupPaths *paths,
-                UnitFileInstallInfo *i,
+                const UnitFileInstallInfo *i,
                 bool match_name,
                 UnitFileState *state) {
 
         bool same_name_link_runtime = false, same_name_link_config = false;
         bool enabled_in_runtime = false, enabled_at_all = false;
+        bool ignore_same_name = false;
         char **p;
         int r;
 
         assert(paths);
         assert(i);
 
+        /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
+         * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
+         * efectively masked, so we should ignore them. */
+
         STRV_FOREACH(p, paths->search_path)  {
                 bool same_name_link = false;
 
-                r = find_symlinks(paths->root_dir, i, match_name, *p, &same_name_link);
+                r = find_symlinks(paths->root_dir, i, match_name, ignore_same_name, *p, &same_name_link);
                 if (r < 0)
                         return r;
                 if (r > 0) {
@@ -923,6 +929,11 @@ static int find_symlinks_in_scope(
                                         same_name_link_runtime = true;
                         }
                 }
+
+                /* Check if next iteration will be "below" the unit file (either a regular file
+                 * or a symlink), and hence should be ignored */
+                if (!ignore_same_name && path_startswith(i->path, *p))
+                        ignore_same_name = true;
         }
 
         if (enabled_in_runtime) {
@@ -987,7 +998,7 @@ static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *nam
 }
 
 static int install_info_may_process(
-                UnitFileInstallInfo *i,
+                const UnitFileInstallInfo *i,
                 const LookupPaths *paths,
                 UnitFileChange **changes,
                 size_t *n_changes) {
@@ -2665,7 +2676,11 @@ int unit_file_lookup_state(
         r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
                                   &i, NULL, NULL);
         if (r < 0)
-                return r;
+                return log_debug_errno(r, "Failed to discover unit %s: %m", name);
+
+        assert(IN_SET(i->type, UNIT_FILE_TYPE_REGULAR, UNIT_FILE_TYPE_MASKED));
+        log_debug("Found unit %s at %s (%s)", name, strna(i->path),
+                  i->type == UNIT_FILE_TYPE_REGULAR ? "regular file" : "mask");
 
         /* Shortcut things, if the caller just wants to know if this unit exists. */
         if (!ret)
index ca2e05325ee558121324f09aebb81b63ec3c99d3..99d6ba14f19c44847b9a01dbffee2c6375db8319 100644 (file)
@@ -82,6 +82,8 @@ shared_sources = files('''
         install-printf.h
         install.c
         install.h
+        ip-protocol-list.c
+        ip-protocol-list.h
         journal-importer.c
         journal-importer.h
         journal-util.c
@@ -103,6 +105,8 @@ shared_sources = files('''
         module-util.h
         mount-util.c
         mount-util.h
+        nscd-flush.c
+        nscd-flush.h
         nsflags.c
         nsflags.h
         os-util.c
@@ -128,8 +132,6 @@ shared_sources = files('''
         serialize.h
         sleep-config.c
         sleep-config.h
-        ip-protocol-list.c
-        ip-protocol-list.h
         spawn-ask-password-agent.c
         spawn-ask-password-agent.h
         spawn-polkit-agent.c
diff --git a/src/shared/nscd-flush.c b/src/shared/nscd-flush.c
new file mode 100644 (file)
index 0000000..5a04468
--- /dev/null
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <sys/poll.h>
+
+#include "fd-util.h"
+#include "io-util.h"
+#include "nscd-flush.h"
+#include "socket-util.h"
+#include "strv.h"
+#include "time-util.h"
+
+#define NSCD_FLUSH_CACHE_TIMEOUT_USEC (5*USEC_PER_SEC)
+
+struct nscdInvalidateRequest {
+        int32_t version;
+        int32_t type; /* in glibc this is an enum. We don't replicate this here 1:1. Also, wtf, how unportable is that
+                       * even? */
+        int32_t key_len;
+        char dbname[];
+};
+
+static const union sockaddr_union nscd_sa = {
+        .un.sun_family = AF_UNIX,
+        .un.sun_path = "/run/nscd/socket",
+};
+
+static int nscd_flush_cache_one(const char *database, usec_t end) {
+        size_t req_size, has_written = 0, has_read = 0, l;
+        struct nscdInvalidateRequest *req;
+        _cleanup_close_ int fd = -1;
+        int32_t resp;
+        int events;
+
+        assert(database);
+
+        l = strlen(database);
+        req_size = offsetof(struct nscdInvalidateRequest, dbname) + l + 1;
+
+        req = alloca(req_size);
+        *req = (struct nscdInvalidateRequest) {
+                .version = 2,
+                .type = 10,
+                .key_len = l + 1,
+        };
+
+        strcpy(req->dbname, database);
+
+        fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0)
+                return log_debug_errno(errno, "Failed to allocate nscd socket: %m");
+
+        /* Note: connect() returns EINPROGRESS if O_NONBLOCK is set and establishing a connection takes time. The
+         * kernel lets us know this way that the connection is now being established, and we should watch with poll()
+         * to learn when it is fully established. That said, AF_UNIX on Linux never triggers this IRL (connect() is
+         * always instant on AF_UNIX), hence handling this is mostly just an excercise in defensive, protocol-agnostic
+         * programming.
+         *
+         * connect() returns EAGAIN if the socket's backlog limit has been reached. When we see this we give up right
+         * away, after all this entire function here is written in a defensive style so that a non-responding nscd
+         * doesn't stall us for good. (Even if we wanted to handle this better: the Linux kernel doesn't really have a
+         * nice way to connect() to a server synchronously with a time limit that would also cover dealing with the
+         * backlog limit. After all SO_RCVTIMEO and SR_SNDTIMEO don't apply to connect(), and alarm() is frickin' ugly
+         * and not really reasonably usable from threads-aware code.) */
+        if (connect(fd, &nscd_sa.sa, SOCKADDR_UN_LEN(nscd_sa.un)) < 0) {
+                if (errno == EAGAIN)
+                        return log_debug_errno(errno, "nscd is overloaded (backlog limit reached) and refuses to take further connections: %m");
+                if (errno != EINPROGRESS)
+                        return log_debug_errno(errno, "Failed to connect to nscd socket: %m");
+
+                /* Continue in case of EINPROGRESS, but don't bother with send() or recv() until being notified that
+                 * establishing the connection is complete. */
+                events = 0;
+        } else
+                events = POLLIN|POLLOUT; /* Let's assume initially that we can write and read to the fd, to suppress
+                                          * one poll() invocation */
+        for (;;) {
+                usec_t p;
+
+                if (events & POLLOUT) {
+                        ssize_t m;
+
+                        assert(has_written < req_size);
+
+                        m = send(fd, (uint8_t*) req + has_written, req_size - has_written, MSG_NOSIGNAL);
+                        if (m < 0) {
+                                if (errno != EAGAIN) /* Note that EAGAIN is returned by the kernel whenever it can't
+                                                      * take the data right now, and that includes if the connect() is
+                                                      * asynchronous and we saw EINPROGRESS on it, and it hasn't
+                                                      * completed yet. */
+                                        return log_debug_errno(errno, "Failed to write to nscd socket: %m");
+                        } else
+                                has_written += m;
+                }
+
+                if (events & (POLLIN|POLLERR|POLLHUP)) {
+                        ssize_t m;
+
+                        if (has_read >= sizeof(resp))
+                                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Response from nscd longer than expected: %m");
+
+                        m = recv(fd, (uint8_t*) &resp + has_read, sizeof(resp) - has_read, 0);
+                        if (m < 0) {
+                                if (errno != EAGAIN)
+                                        return log_debug_errno(errno, "Failed to read from nscd socket: %m");
+                        } else if (m == 0) { /* EOF */
+                                if (has_read == 0 && has_written >= req_size) /* Older nscd immediately terminated the
+                                                                               * connection, accept that as OK */
+                                        return 1;
+
+                                return log_debug_errno(SYNTHETIC_ERRNO(EIO), "nscd prematurely ended connection.");
+                        } else
+                                has_read += m;
+                }
+
+                if (has_written >= req_size && has_read >= sizeof(resp)) { /* done? */
+                        if (resp < 0)
+                                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "nscd sent us a negative error numer: %i", resp);
+                        if (resp > 0)
+                                return log_debug_errno(resp, "nscd return failure code on invalidating '%s'.", database);
+                        return 1;
+                }
+
+                p = now(CLOCK_MONOTONIC);
+                if (p >= end)
+                        return -ETIMEDOUT;
+
+                events = fd_wait_for_event(fd, POLLIN | (has_written < req_size ? POLLOUT : 0), end - p);
+                if (events < 0)
+                        return events;
+        }
+}
+
+int nscd_flush_cache(char **databases) {
+        usec_t end;
+        int r = 0;
+        char **i;
+
+        /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s time-out, so that we
+         * don't block indefinitely on another service. */
+
+        end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);
+
+        STRV_FOREACH(i, databases) {
+                int k;
+
+                k = nscd_flush_cache_one(*i, end);
+                if (k < 0 && r >= 0)
+                        r = k;
+        }
+
+        return r;
+}
diff --git a/src/shared/nscd-flush.h b/src/shared/nscd-flush.h
new file mode 100644 (file)
index 0000000..22774bf
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int nscd_flush_cache(char **databases);
index 78dda05b4868b2afa2b1cf1c08583baeb8deaadd..b8f7537f7a0feb50be0d04a5bd210251a42f2c94 100644 (file)
@@ -27,7 +27,7 @@
  * and "%" used for escaping. */
 #define POSSIBLE_SPECIFIERS ALPHANUMERICAL "%"
 
-int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) {
+int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **_ret) {
         size_t l, allocated = 0;
         _cleanup_free_ char *ret = NULL;
         char *t;
@@ -102,7 +102,7 @@ int specifier_printf(const char *text, const Specifier table[], void *userdata,
 
 /* Generic handler for simple string replacements */
 
-int specifier_string(char specifier, void *data, void *userdata, char **ret) {
+int specifier_string(char specifier, const void *data, const void *userdata, char **ret) {
         char *n;
 
         n = strdup(strempty(data));
@@ -113,7 +113,7 @@ int specifier_string(char specifier, void *data, void *userdata, char **ret) {
         return 0;
 }
 
-int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) {
+int specifier_machine_id(char specifier, const void *data, const void *userdata, char **ret) {
         sd_id128_t id;
         char *n;
         int r;
@@ -130,7 +130,7 @@ int specifier_machine_id(char specifier, void *data, void *userdata, char **ret)
         return 0;
 }
 
-int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) {
+int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret) {
         sd_id128_t id;
         char *n;
         int r;
@@ -147,7 +147,7 @@ int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) {
         return 0;
 }
 
-int specifier_host_name(char specifier, void *data, void *userdata, char **ret) {
+int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret) {
         char *n;
 
         n = gethostname_malloc();
@@ -158,7 +158,7 @@ int specifier_host_name(char specifier, void *data, void *userdata, char **ret)
         return 0;
 }
 
-int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) {
+int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret) {
         struct utsname uts;
         char *n;
         int r;
@@ -175,7 +175,7 @@ int specifier_kernel_release(char specifier, void *data, void *userdata, char **
         return 0;
 }
 
-int specifier_group_name(char specifier, void *data, void *userdata, char **ret) {
+int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret) {
         char *t;
 
         t = gid_to_name(getgid());
@@ -186,14 +186,14 @@ int specifier_group_name(char specifier, void *data, void *userdata, char **ret)
         return 0;
 }
 
-int specifier_group_id(char specifier, void *data, void *userdata, char **ret) {
+int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret) {
         if (asprintf(ret, UID_FMT, getgid()) < 0)
                 return -ENOMEM;
 
         return 0;
 }
 
-int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
+int specifier_user_name(char specifier, const void *data, const void *userdata, char **ret) {
         char *t;
 
         /* If we are UID 0 (root), this will not result in NSS, otherwise it might. This is good, as we want to be able
@@ -211,7 +211,7 @@ int specifier_user_name(char specifier, void *data, void *userdata, char **ret)
         return 0;
 }
 
-int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
+int specifier_user_id(char specifier, const void *data, const void *userdata, char **ret) {
 
         if (asprintf(ret, UID_FMT, getuid()) < 0)
                 return -ENOMEM;
@@ -219,7 +219,7 @@ int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
         return 0;
 }
 
-int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
+int specifier_user_home(char specifier, const void *data, const void *userdata, char **ret) {
 
         /* On PID 1 (which runs as root) this will not result in NSS,
          * which is good. See above */
@@ -227,7 +227,7 @@ int specifier_user_home(char specifier, void *data, void *userdata, char **ret)
         return get_home_dir(ret);
 }
 
-int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
+int specifier_user_shell(char specifier, const void *data, const void *userdata, char **ret) {
 
         /* On PID 1 (which runs as root) this will not result in NSS,
          * which is good. See above */
@@ -235,7 +235,7 @@ int specifier_user_shell(char specifier, void *data, void *userdata, char **ret)
         return get_shell(ret);
 }
 
-int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret) {
+int specifier_tmp_dir(char specifier, const void *data, const void *userdata, char **ret) {
         const char *p;
         char *copy;
         int r;
@@ -252,7 +252,7 @@ int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret) {
         return 0;
 }
 
-int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret) {
+int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata, char **ret) {
         const char *p;
         char *copy;
         int r;
index 722200b9980101757995d336df4d4d837d995918..d0221ef714a794def0f846c91af12d78e1479b4e 100644 (file)
@@ -3,32 +3,32 @@
 
 #include "string-util.h"
 
-typedef int (*SpecifierCallback)(char specifier, void *data, void *userdata, char **ret);
+typedef int (*SpecifierCallback)(char specifier, const void *data, const void *userdata, char **ret);
 
 typedef struct Specifier {
         const char specifier;
         const SpecifierCallback lookup;
-        void *data;
+        const void *data;
 } Specifier;
 
-int specifier_printf(const char *text, const Specifier table[], void *userdata, char **ret);
+int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **ret);
 
-int specifier_string(char specifier, void *data, void *userdata, char **ret);
+int specifier_string(char specifier, const void *data, const void *userdata, char **ret);
 
-int specifier_machine_id(char specifier, void *data, void *userdata, char **ret);
-int specifier_boot_id(char specifier, void *data, void *userdata, char **ret);
-int specifier_host_name(char specifier, void *data, void *userdata, char **ret);
-int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret);
+int specifier_machine_id(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret);
 
-int specifier_group_name(char specifier, void *data, void *userdata, char **ret);
-int specifier_group_id(char specifier, void *data, void *userdata, char **ret);
-int specifier_user_name(char specifier, void *data, void *userdata, char **ret);
-int specifier_user_id(char specifier, void *data, void *userdata, char **ret);
-int specifier_user_home(char specifier, void *data, void *userdata, char **ret);
-int specifier_user_shell(char specifier, void *data, void *userdata, char **ret);
+int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_user_name(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_user_id(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_user_home(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_user_shell(char specifier, const void *data, const void *userdata, char **ret);
 
-int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret);
-int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret);
+int specifier_tmp_dir(char specifier, const void *data, const void *userdata, char **ret);
+int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata, char **ret);
 
 static inline char* specifier_escape(const char *string) {
         return strreplace(string, "%", "%%");
index 1cfe51018073db09e8fa199fba49761aa36ae31d..c67d79032378948028aa996740735d66a7a6af8a 100644 (file)
@@ -115,7 +115,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign
 
                 value = strchr(p, '=');
                 if (!value) {
-                        log_error("Line is not an assignment at '%s:%u': %s", path, c, value);
+                        log_error("Line is not an assignment at '%s:%u': %s", path, c, p);
 
                         if (r == 0)
                                 r = -EINVAL;
index 78cf9462b0cfd1a92bb3a9017a523735ad4b3cc8..f4c05a36831409867fc517a195314fd579a9a39f 100644 (file)
@@ -41,19 +41,20 @@ int sd_id128_from_string(const char *s, sd_id128_t *ret);
 int sd_id128_randomize(sd_id128_t *ret);
 
 int sd_id128_get_machine(sd_id128_t *ret);
-int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret);
-int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
 int sd_id128_get_boot(sd_id128_t *ret);
 int sd_id128_get_invocation(sd_id128_t *ret);
 
-#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
-        ((const sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \
-                                   0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }})
+int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret);
+int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
 
 #define SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
         { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \
                      0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }}
 
+#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
+        ((const sd_id128_t) SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15))
+
+
 /* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16
  * times. It is hence not a good idea to call this macro with an
  * expensive function as parameter or an expression with side
@@ -109,7 +110,12 @@ _sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) {
         return a.qwords[0] == 0 && a.qwords[1] == 0;
 }
 
+_sd_pure_ static __inline__ int sd_id128_is_allf(sd_id128_t a) {
+        return a.qwords[0] == UINT64_C(0xFFFFFFFFFFFFFFFF) && a.qwords[1] == UINT64_C(0xFFFFFFFFFFFFFFFF);
+}
+
 #define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }})
+#define SD_ID128_ALLF ((const sd_id128_t) { .qwords = { UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF) }})
 
 _SD_END_DECLARATIONS;
 
index 9863ecc8f034aa279607f5c1d01ab75aec90aa4e..ea049a6fbad33e353fe66e28e4130f5dca6b111e 100644 (file)
@@ -94,6 +94,17 @@ tests += [
           libblkid],
          '', 'manual'],
 
+        [['src/test/test-nscd-flush.c'],
+         [libcore,
+          libshared],
+         [threads,
+          librt,
+          libseccomp,
+          libselinux,
+          libmount,
+          libblkid],
+         '', 'manual'],
+
         [['src/test/test-loopback.c'],
          [libcore,
           libshared],
index 53c791814ef4a49856b1e48364625cf99401f968..fd0cc27de83dcaae885d3641c384d5c93f9f51d6 100644 (file)
@@ -713,6 +713,41 @@ static void test_read_line3(void) {
         assert_se(read_line(f, LINE_MAX, NULL) == 0);
 }
 
+static void test_read_line4(void) {
+        static const struct {
+                size_t length;
+                const char *string;
+        } eof_endings[] = {
+                /* Each of these will be followed by EOF and should generate the one same single string */
+                { 3, "foo" },
+                { 4, "foo\n" },
+                { 4, "foo\r" },
+                { 4, "foo\0" },
+                { 5, "foo\n\0" },
+                { 5, "foo\r\0" },
+                { 5, "foo\r\n" },
+                { 5, "foo\n\r" },
+                { 6, "foo\r\n\0" },
+                { 6, "foo\n\r\0" },
+        };
+
+        size_t i;
+        int r;
+
+        for (i = 0; i < ELEMENTSOF(eof_endings); i++) {
+                _cleanup_fclose_ FILE *f = NULL;
+                _cleanup_free_ char *s = NULL;
+
+                assert_se(f = fmemopen((void*) eof_endings[i].string, eof_endings[i].length, "r"));
+
+                r = read_line(f, (size_t) -1, &s);
+                assert_se((size_t) r == eof_endings[i].length);
+                assert_se(streq_ptr(s, "foo"));
+
+                assert_se(read_line(f, (size_t) -1, NULL) == 0); /* Ensure we hit EOF */
+        }
+}
+
 int main(int argc, char *argv[]) {
         test_setup_logging(LOG_DEBUG);
 
@@ -735,6 +770,7 @@ int main(int argc, char *argv[]) {
         test_read_line();
         test_read_line2();
         test_read_line3();
+        test_read_line4();
 
         return 0;
 }
index d3ece0bc0bad2c50010dce1360f6cf2fcac13518..5aa4d19dbec499388c43f805e34850998b2d171a 100644 (file)
@@ -358,7 +358,7 @@ static void test_source(void) {
                "%s"
                "--- original end ---\n", data);
 
-        assert_se(f = fmemopen((void*) data, sizeof(data), "r"));
+        assert_se(f = fmemopen((void*) data, strlen(data), "r"));
 
         assert_se(json_parse_file(f, "waldo", &v, NULL, NULL) >= 0);
 
diff --git a/src/test/test-nscd-flush.c b/src/test/test-nscd-flush.c
new file mode 100644 (file)
index 0000000..97c2195
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "main-func.h"
+#include "nscd-flush.h"
+#include "strv.h"
+#include "tests.h"
+
+static int run(int argc, char *argv[]) {
+        int r;
+
+        test_setup_logging(LOG_DEBUG);
+
+        r = nscd_flush_cache(STRV_MAKE("group", "passwd", "hosts"));
+        if (r < 0)
+                return log_error_errno(r, "Failed to flush NSCD cache");
+
+        return 0;
+}
+
+DEFINE_MAIN_FUNCTION(run);
index 13c289270de8c955c1faccdd241bccddf8bcab7f..f5578f9fc277c5bcc3901278783815ef54730374 100644 (file)
@@ -530,7 +530,7 @@ static void test_load_env_file_1(void) {
 
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
-        assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
+        assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1));
 
         r = load_env_file(NULL, name, &data);
         assert_se(r == 0);
@@ -552,7 +552,7 @@ static void test_load_env_file_2(void) {
 
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
-        assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
+        assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2));
 
         r = load_env_file(NULL, name, &data);
         assert_se(r == 0);
@@ -569,7 +569,7 @@ static void test_load_env_file_3(void) {
 
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
-        assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
+        assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3));
 
         r = load_env_file(NULL, name, &data);
         assert_se(r == 0);
@@ -584,7 +584,7 @@ static void test_load_env_file_4(void) {
 
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
-        assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
+        assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4));
 
         r = load_env_file(NULL, name, &data);
         assert_se(r == 0);
@@ -603,7 +603,7 @@ static void test_load_env_file_5(void) {
 
         fd = mkostemp_safe(name);
         assert_se(fd >= 0);
-        assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
+        assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5));
 
         r = load_env_file(NULL, name, &data);
         assert_se(r == 0);
index 08c57a3fb166f27af2ca57433799589f91e3ad97..19225f8cfd7135182d36555b9eb0cdbbb38081bf 100644 (file)
@@ -180,8 +180,8 @@ STATIC_DESTRUCTOR_REGISTER(arg_include_prefixes, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_exclude_prefixes, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
 
-static int specifier_machine_id_safe(char specifier, void *data, void *userdata, char **ret);
-static int specifier_directory(char specifier, void *data, void *userdata, char **ret);
+static int specifier_machine_id_safe(char specifier, const void *data, const void *userdata, char **ret);
+static int specifier_directory(char specifier, const void *data, const void *userdata, char **ret);
 
 static const Specifier specifier_table[] = {
         { 'm', specifier_machine_id_safe, NULL },
@@ -204,7 +204,7 @@ static const Specifier specifier_table[] = {
         {}
 };
 
-static int specifier_machine_id_safe(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_machine_id_safe(char specifier, const void *data, const void *userdata, char **ret) {
         int r;
 
         /* If /etc/machine_id is missing or empty (e.g. in a chroot environment)
@@ -218,7 +218,7 @@ static int specifier_machine_id_safe(char specifier, void *data, void *userdata,
         return r;
 }
 
-static int specifier_directory(char specifier, void *data, void *userdata, char **ret) {
+static int specifier_directory(char specifier, const void *data, const void *userdata, char **ret) {
         struct table_entry {
                 uint64_t type;
                 const char *suffix;
index 4fef869eecf9221eb2ebb37a4a4e37d8a9831dbe..fb8724ea8723fbe2e9469362f6398c25fde1fe2a 100644 (file)
@@ -1632,8 +1632,7 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
         if (r < 0)
                 return log_error_errno(r, "Failed to initialize device monitor: %m");
 
-        if (fd_uevent < 0)
-                (void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
+        (void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024);
 
         /* unnamed socket from workers to the main daemon */
         r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch);
index 5a8d41eb68385e2949940b80752062eb4207e492..cd7c3aadedb29925f064a4fd1545879baa84f136 100644 (file)
@@ -129,6 +129,7 @@ MinLinks=
 LACPTransmitRate=
 ARPIntervalSec=
 AllSlavesActive=
+DynamicTransmitLoadBalancing=
 [FooOverUDP]
 Protocol=
 Port=
diff --git a/test/test-network/conf/25-bond-balanced-tlb.netdev b/test/test-network/conf/25-bond-balanced-tlb.netdev
new file mode 100644 (file)
index 0000000..439ddf2
--- /dev/null
@@ -0,0 +1,7 @@
+[NetDev]
+Name=bond99
+Kind=bond
+
+[Bond]
+Mode=balance-tlb
+DynamicTransmitLoadBalancing=true
index 65cc43e8b6b2b3bbed5454b9b878d9090b63da35..19572be1514ad097caa386dd7f86be4d026e7180 100755 (executable)
@@ -213,6 +213,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '21-vlan.network',
         '25-6rd-tunnel.netdev',
         '25-bond.netdev',
+        '25-bond-balanced-tlb.netdev',
         '25-bridge.netdev',
         '25-erspan-tunnel.netdev',
         '25-geneve.netdev',
@@ -300,6 +301,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertEqual('811',               self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
         self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
 
+    def test_bond_balanced_tlb(self):
+        self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
+        self.start_networkd()
+
+        self.assertTrue(self.link_exits('bond99'))
+
+        self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
+        self.assertEqual('1',             self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
+
     def test_vlan(self):
         self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
         self.start_networkd()