diff options
36 files changed, 386 insertions, 181 deletions
diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index ca82f8a512..5c8351142a 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -20,10 +20,11 @@ # where /dev/input/eventXX is the device in question. If in # doubt, simply use /dev/input/event* to reload all input rules. # -# If your changes are generally applicable, open a bug report on -# http://bugs.freedesktop.org/enter_bug.cgi?product=systemd -# and include your new rules, a description of the device, and the -# output of +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX # (or /dev/input/event*). # @@ -117,3 +118,12 @@ evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus* evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*X230* EVDEV_ABS_01=::100 EVDEV_ABS_36=::100 + +######################################### +# Dell +######################################### + +# Dell Vostro 1510 +evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnDellInc.:pnVostro1510* + EVDEV_ABS_00=::14 + EVDEV_ABS_01=::18 diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index d0fc914d17..65e939262a 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -51,10 +51,11 @@ # where /dev/input/eventXX is the keyboard in question. If in # doubt, simply use /dev/input/event* to reload all input rules. # -# If your changes are generally applicable, open a bug report on -# http://bugs.freedesktop.org/enter_bug.cgi?product=systemd -# and include your new rules, a description of the device, and the -# output of +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX # (or /dev/input/event*). diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index e2855095cd..680cb1ed7b 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -38,9 +38,9 @@ # # If your changes are generally applicable, preferably send them as a pull # request to -# https://github.com/systemd/ -# or create a bug report on the issue tracker located there and include your -# new rules, a description of the device, and the output of +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX # (or /dev/input/event*). # diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index a8c21a2ee6..775ec7fea5 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -32,10 +32,11 @@ # where /dev/input/eventXX is the pointingstick in question. If in # doubt, simply use /dev/input/event* to reload all input rules. # -# If your changes are generally applicable, open a bug report on -# http://bugs.freedesktop.org/enter_bug.cgi?product=systemd -# and include your new rules, a description of the device, and the -# output of +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of # udevadm info /dev/input/eventXX # (or /dev/input/event*). # diff --git a/man/systemd-fsck@.service.xml b/man/systemd-fsck@.service.xml index e4ffcba168..6d05e90e7b 100644 --- a/man/systemd-fsck@.service.xml +++ b/man/systemd-fsck@.service.xml @@ -61,7 +61,7 @@ responsible for file system checks. They are instantiated for each device that is configured for file system checking. <filename>systemd-fsck-root.service</filename> is responsible for - file system checks on the root file system, but in only if the + file system checks on the root file system, but only if the root filesystem wasn't checked in the initramfs. <filename>systemd-fsck@.service</filename> is used for all other file systems and for the root file system in the initramfs.</para> diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 45a4422dc3..8fd75d274e 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -263,7 +263,8 @@ <listitem><para>Similar to <varname>Environment=</varname> but reads the environment variables from a text file. The text file should contain new-line-separated variable assignments. - Empty lines and lines starting with ; or # will be ignored, + Empty lines, lines without an <literal>=</literal> separator, + or lines starting with ; or # will be ignored, which may be used for commenting. A line ending with a backslash will be concatenated with the following one, allowing multiline variable definitions. The parser strips diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 34a3060509..6b3162a35f 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -826,14 +826,12 @@ int cg_install_release_agent(const char *controller, const char *agent) { } else if (!streq(sc, agent)) return -EEXIST; - free(fs); - fs = NULL; + fs = mfree(fs); r = cg_get_path(controller, NULL, "notify_on_release", &fs); if (r < 0) return r; - free(contents); - contents = NULL; + contents = mfree(contents); r = read_one_line_file(fs, &contents); if (r < 0) return r; @@ -865,8 +863,7 @@ int cg_uninstall_release_agent(const char *controller) { if (r < 0) return r; - free(fs); - fs = NULL; + fs = mfree(fs); r = cg_get_path(controller, NULL, "release_agent", &fs); if (r < 0) diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c index 047aa294f4..6d5c205117 100644 --- a/src/basic/smack-util.c +++ b/src/basic/smack-util.c @@ -32,109 +32,93 @@ #define SMACK_FLOOR_LABEL "_" #define SMACK_STAR_LABEL "*" -bool mac_smack_use(void) { #ifdef HAVE_SMACK +bool mac_smack_use(void) { static int cached_use = -1; if (cached_use < 0) cached_use = access("/sys/fs/smackfs/", F_OK) >= 0; return cached_use; -#else - return false; -#endif } -int mac_smack_apply(const char *path, const char *label) { - int r = 0; +static const char* const smack_attr_table[_SMACK_ATTR_MAX] = { + [SMACK_ATTR_ACCESS] = "security.SMACK64", + [SMACK_ATTR_EXEC] = "security.SMACK64EXEC", + [SMACK_ATTR_MMAP] = "security.SMACK64MMAP", + [SMACK_ATTR_TRANSMUTE] = "security.SMACK64TRANSMUTE", + [SMACK_ATTR_IPIN] = "security.SMACK64IPIN", + [SMACK_ATTR_IPOUT] = "security.SMACK64IPOUT", +}; + +DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr); +int mac_smack_read(const char *path, SmackAttr attr, char **label) { assert(path); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); + assert(label); -#ifdef HAVE_SMACK if (!mac_smack_use()) return 0; - if (label) - r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0); - else - r = lremovexattr(path, "security.SMACK64"); - if (r < 0) - return -errno; -#endif - - return r; + return getxattr_malloc(path, smack_attr_to_string(attr), label, true); } -int mac_smack_apply_fd(int fd, const char *label) { - int r = 0; - +int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { assert(fd >= 0); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); + assert(label); -#ifdef HAVE_SMACK if (!mac_smack_use()) return 0; - if (label) - r = fsetxattr(fd, "security.SMACK64", label, strlen(label), 0); - else - r = fremovexattr(fd, "security.SMACK64"); - if (r < 0) - return -errno; -#endif - - return r; + return fgetxattr_malloc(fd, smack_attr_to_string(attr), label); } -int mac_smack_apply_ip_out_fd(int fd, const char *label) { - int r = 0; +int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { + int r; - assert(fd >= 0); + assert(path); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); -#ifdef HAVE_SMACK if (!mac_smack_use()) return 0; if (label) - r = fsetxattr(fd, "security.SMACK64IPOUT", label, strlen(label), 0); + r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0); else - r = fremovexattr(fd, "security.SMACK64IPOUT"); + r = lremovexattr(path, smack_attr_to_string(attr)); if (r < 0) return -errno; -#endif - return r; + return 0; } -int mac_smack_apply_ip_in_fd(int fd, const char *label) { - int r = 0; +int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { + int r; assert(fd >= 0); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); -#ifdef HAVE_SMACK if (!mac_smack_use()) return 0; if (label) - r = fsetxattr(fd, "security.SMACK64IPIN", label, strlen(label), 0); + r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0); else - r = fremovexattr(fd, "security.SMACK64IPIN"); + r = fremovexattr(fd, smack_attr_to_string(attr)); if (r < 0) return -errno; -#endif - return r; + return 0; } int mac_smack_apply_pid(pid_t pid, const char *label) { - -#ifdef HAVE_SMACK const char *p; -#endif int r = 0; assert(label); -#ifdef HAVE_SMACK if (!mac_smack_use()) return 0; @@ -142,21 +126,16 @@ int mac_smack_apply_pid(pid_t pid, const char *label) { r = write_string_file(p, label, 0); if (r < 0) return r; -#endif return r; } int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { - -#ifdef HAVE_SMACK struct stat st; -#endif int r = 0; assert(path); -#ifdef HAVE_SMACK if (!mac_smack_use()) return 0; @@ -202,7 +181,37 @@ int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path); } -#endif return r; } + + +#else +bool mac_smack_use(void) { + return false; +} + +int mac_smack_read(const char *path, SmackAttr attr, char **label) { + return -EOPNOTSUPP; +} + +int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { + return -EOPNOTSUPP; +} + +int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { + return 0; +} + +int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { + return 0; +} + +int mac_smack_apply_pid(pid_t pid, const char *label) { + return 0; +} + +int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { + return 0; +} +#endif diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h index 50f55b1f4b..1052cecf4c 100644 --- a/src/basic/smack-util.h +++ b/src/basic/smack-util.h @@ -25,12 +25,28 @@ #include <stdbool.h> +#include "macro.h" + +typedef enum SmackAttr { + SMACK_ATTR_ACCESS = 0, + SMACK_ATTR_EXEC = 1, + SMACK_ATTR_MMAP = 2, + SMACK_ATTR_TRANSMUTE = 3, + SMACK_ATTR_IPIN = 4, + SMACK_ATTR_IPOUT = 5, + _SMACK_ATTR_MAX, + _SMACK_ATTR_INVALID = -1, +} SmackAttr; + bool mac_smack_use(void); int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs); -int mac_smack_apply(const char *path, const char *label); -int mac_smack_apply_fd(int fd, const char *label); +const char* smack_attr_to_string(SmackAttr i) _const_; +SmackAttr smack_attr_from_string(const char *s) _pure_; +int mac_smack_read(const char *path, SmackAttr attr, char **label); +int mac_smack_read_fd(int fd, SmackAttr attr, char **label); +int mac_smack_apply(const char *path, SmackAttr attr, const char *label); +int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label); + int mac_smack_apply_pid(pid_t pid, const char *label); -int mac_smack_apply_ip_in_fd(int fd, const char *label); -int mac_smack_apply_ip_out_fd(int fd, const char *label); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 042b88f222..cf55263bbf 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -44,7 +44,7 @@ static volatile unsigned cached_lines = 0; int chvt(int vt) { _cleanup_close_ int fd; - fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC); + fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return -errno; @@ -230,14 +230,14 @@ int reset_terminal_fd(int fd, bool switch_to_text) { * interfere with that. */ /* Disable exclusive mode, just in case */ - ioctl(fd, TIOCNXCL); + (void) ioctl(fd, TIOCNXCL); /* Switch to text mode */ if (switch_to_text) - ioctl(fd, KDSETMODE, KD_TEXT); + (void) ioctl(fd, KDSETMODE, KD_TEXT); /* Enable console unicode mode */ - ioctl(fd, KDSKBMODE, K_UNICODE); + (void) ioctl(fd, KDSKBMODE, K_UNICODE); if (tcgetattr(fd, &termios) < 0) { r = -errno; @@ -276,7 +276,7 @@ int reset_terminal_fd(int fd, bool switch_to_text) { finish: /* Just in case, flush all crap out */ - tcflush(fd, TCIOFLUSH); + (void) tcflush(fd, TCIOFLUSH); return r; } @@ -284,7 +284,11 @@ finish: int reset_terminal(const char *name) { _cleanup_close_ int fd = -1; - fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); + /* We open the terminal with O_NONBLOCK here, to ensure we + * don't block on carrier if this is a terminal with carrier + * configured. */ + + fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return fd; @@ -304,7 +308,8 @@ int open_terminal(const char *name, int mode) { * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245 */ - assert(!(mode & O_CREAT)); + if (mode & O_CREAT) + return -EINVAL; for (;;) { fd = open(name, mode, 0); @@ -413,9 +418,8 @@ int acquire_terminal( if (r < 0 && r == -EPERM && ignore_tiocstty_eperm) r = 0; - if (r < 0 && (force || fail || r != -EPERM)) { + if (r < 0 && (force || fail || r != -EPERM)) goto fail; - } if (r >= 0) break; @@ -499,7 +503,7 @@ int release_terminal(void) { struct sigaction sa_old; int r = 0; - fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC); + fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return -errno; @@ -527,7 +531,7 @@ int terminal_vhangup_fd(int fd) { int terminal_vhangup(const char *name) { _cleanup_close_ int fd; - fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); + fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return fd; @@ -574,7 +578,7 @@ int vt_disallocate(const char *name) { return -EINVAL; /* Try to deallocate */ - fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC); + fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return fd; @@ -612,16 +616,16 @@ void warn_melody(void) { /* Yeah, this is synchronous. Kinda sucks. But well... */ - ioctl(fd, KIOCSOUND, (int)(1193180/440)); + (void) ioctl(fd, KIOCSOUND, (int)(1193180/440)); usleep(125*USEC_PER_MSEC); - ioctl(fd, KIOCSOUND, (int)(1193180/220)); + (void) ioctl(fd, KIOCSOUND, (int)(1193180/220)); usleep(125*USEC_PER_MSEC); - ioctl(fd, KIOCSOUND, (int)(1193180/220)); + (void) ioctl(fd, KIOCSOUND, (int)(1193180/220)); usleep(125*USEC_PER_MSEC); - ioctl(fd, KIOCSOUND, 0); + (void) ioctl(fd, KIOCSOUND, 0); } int make_console_stdio(void) { diff --git a/src/basic/util.c b/src/basic/util.c index a968e2156d..af58dc3766 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -6603,3 +6603,73 @@ int reset_uid_gid(void) { return 0; } + +int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) { + char *v; + size_t l; + ssize_t n; + + assert(path); + assert(name); + assert(value); + + for (l = 100; ; l = (size_t) n + 1) { + v = new0(char, l); + if (!v) + return -ENOMEM; + + if (allow_symlink) + n = lgetxattr(path, name, v, l); + else + n = getxattr(path, name, v, l); + + if (n >= 0 && (size_t) n < l) { + *value = v; + return n; + } + + free(v); + + if (n < 0 && errno != ERANGE) + return -errno; + + if (allow_symlink) + n = lgetxattr(path, name, NULL, 0); + else + n = getxattr(path, name, NULL, 0); + if (n < 0) + return -errno; + } +} + +int fgetxattr_malloc(int fd, const char *name, char **value) { + char *v; + size_t l; + ssize_t n; + + assert(fd >= 0); + assert(name); + assert(value); + + for (l = 100; ; l = (size_t) n + 1) { + v = new0(char, l); + if (!v) + return -ENOMEM; + + n = fgetxattr(fd, name, v, l); + + if (n >= 0 && (size_t) n < l) { + *value = v; + return n; + } + + free(v); + + if (n < 0 && errno != ERANGE) + return -errno; + + n = fgetxattr(fd, name, NULL, 0); + if (n < 0) + return -errno; + } +} diff --git a/src/basic/util.h b/src/basic/util.h index 88c44273d4..0a0fba9012 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -919,3 +919,6 @@ int parse_mode(const char *s, mode_t *ret); int mount_move_root(const char *path); int reset_uid_gid(void); + +int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink); +int fgetxattr_malloc(int fd, const char *name, char **value); diff --git a/src/bootchart/bootchart.c b/src/bootchart/bootchart.c index 1625d51fa8..322cec84a9 100644 --- a/src/bootchart/bootchart.c +++ b/src/bootchart/bootchart.c @@ -367,7 +367,7 @@ int main(int argc, char *argv[]) { struct timespec n; double uptime; - clock_gettime(CLOCK_BOOTTIME, &n); + clock_gettime(clock_boottime_or_monotonic(), &n); uptime = (n.tv_sec + (n.tv_nsec / (double) NSEC_PER_SEC)); log_start = gettime_ns(); diff --git a/src/bus-proxyd/driver.c b/src/bus-proxyd/driver.c index 951f515808..fa4aee691a 100644 --- a/src/bus-proxyd/driver.c +++ b/src/bus-proxyd/driver.c @@ -35,6 +35,7 @@ #include "driver.h" #include "proxy.h" #include "synthesize.h" +#include "env-util.h" static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) { _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; @@ -694,9 +695,13 @@ int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, if (!s) return synthetic_reply_method_errno(m, -ENOMEM, NULL); - r = strv_extend(&args, s); - if (r < 0) - return synthetic_reply_method_errno(m, r, NULL); + if (!env_assignment_is_valid(s)) { + log_warning("UpdateActivationEnvironment() called with invalid assignment, discarding: %s", s); + } else { + r = strv_extend(&args, s); + if (r < 0) + return synthetic_reply_method_errno(m, r, NULL); + } r = sd_bus_message_exit_container(m); if (r < 0) diff --git a/src/core/execute.c b/src/core/execute.c index 21721dc240..f14ae4d8a6 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1719,7 +1719,15 @@ static int exec_child( } #ifdef SMACK_DEFAULT_PROCESS_LABEL else { - r = mac_smack_apply_pid(0, SMACK_DEFAULT_PROCESS_LABEL); + _cleanup_free_ char *exec_label = NULL; + + r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label); + if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) { + *exit_status = EXIT_SMACK_PROCESS_LABEL; + return r; + } + + r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL); if (r < 0) { *exit_status = EXIT_SMACK_PROCESS_LABEL; return r; diff --git a/src/core/socket.c b/src/core/socket.c index 87631f8753..a387057473 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -923,13 +923,13 @@ static void socket_apply_socket_options(Socket *s, int fd) { log_unit_warning_errno(UNIT(s), errno, "TCP_CONGESTION failed: %m"); if (s->smack_ip_in) { - r = mac_smack_apply_ip_in_fd(fd, s->smack_ip_in); + r = mac_smack_apply_fd(fd, SMACK_ATTR_IPIN, s->smack_ip_in); if (r < 0) log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_in_fd: %m"); } if (s->smack_ip_out) { - r = mac_smack_apply_ip_out_fd(fd, s->smack_ip_out); + r = mac_smack_apply_fd(fd, SMACK_ATTR_IPOUT, s->smack_ip_out); if (r < 0) log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_out_fd: %m"); } @@ -946,7 +946,7 @@ static void socket_apply_fifo_options(Socket *s, int fd) { log_unit_warning_errno(UNIT(s), errno, "F_SETPIPE_SZ: %m"); if (s->smack) { - r = mac_smack_apply_fd(fd, s->smack); + r = mac_smack_apply_fd(fd, SMACK_ATTR_ACCESS, s->smack); if (r < 0) log_unit_error_errno(UNIT(s), r, "mac_smack_apply_fd: %m"); } diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 05f1ae2646..c526a85b05 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -763,8 +763,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_ROOT_PASSWORD_FILE: - free(arg_root_password); - arg_root_password = NULL; + arg_root_password = mfree(arg_root_password); r = read_one_line_file(optarg, &arg_root_password); if (r < 0) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index cc5e032344..a0af256dee 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -796,8 +796,12 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - time_now = now(clock_boottime_or_monotonic()); + if (r < 0) { + if (!existing_lease) + dhcp_lease_free(lease); + return r; + } + lease->expiration = req->lifetime * USEC_PER_SEC + time_now; r = server_send_ack(server, req, address); diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 85162dc555..e2f5862851 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -975,14 +975,9 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) client->retransmit_time = 0; client->retransmit_count = 0; - if (client->state == DHCP6_STATE_STOPPED) { - time_now = now(clock_boottime_or_monotonic()); - } else { - r = sd_event_now(client->event, clock_boottime_or_monotonic(), - &time_now); - if (r < 0) - return r; - } + r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; switch (state) { case DHCP6_STATE_STOPPED: diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index 9e04db96bb..0cb77ccf71 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -187,8 +187,7 @@ static void ipv4ll_set_next_wakeup(sd_ipv4ll *ll, int sec, int random_sec) { if (random_sec) next_timeout += random_u32() % (random_sec * USEC_PER_SEC); - if (sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) < 0) - time_now = now(clock_boottime_or_monotonic()); + assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) >= 0); ll->next_wakeup = time_now + next_timeout; ll->next_wakeup_valid = 1; diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c index 034163eb9e..574e04b541 100644 --- a/src/libsystemd-network/sd-lldp.c +++ b/src/libsystemd-network/sd-lldp.c @@ -392,7 +392,7 @@ static void lldp_mib_delete_objects(sd_lldp *lldp) { break; if (t <= 0) - t = now(CLOCK_BOOTTIME); + t = now(clock_boottime_or_monotonic()); if (p->until > t) break; @@ -490,7 +490,7 @@ int sd_lldp_save(sd_lldp *lldp, const char *lldp_file) { free(s); s = k; - time = now(CLOCK_BOOTTIME); + time = now(clock_boottime_or_monotonic()); /* Don't write expired packets */ if (time - p->until <= 0) diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c index 1de8a5e8bf..ff064f563f 100644 --- a/src/libsystemd-network/sd-pppoe.c +++ b/src/libsystemd-network/sd-pppoe.c @@ -346,9 +346,7 @@ static int pppoe_arm_timeout(sd_pppoe *ppp) { assert(ppp); r = sd_event_now(ppp->event, clock_boottime_or_monotonic(), &next_timeout); - if (r == -ENODATA) - next_timeout = now(clock_boottime_or_monotonic()); - else if (r < 0) + if (r < 0) return r; next_timeout += 500 * USEC_PER_MSEC; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 767df40e81..0f075907d5 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -73,13 +73,9 @@ static void bus_close_fds(sd_bus *b) { detach_io_events(b); - if (b->input_fd >= 0) - safe_close(b->input_fd); - - if (b->output_fd >= 0 && b->output_fd != b->input_fd) + if (b->input_fd != b->output_fd) safe_close(b->output_fd); - - b->input_fd = b->output_fd = -1; + b->output_fd = b->input_fd = safe_close(b->input_fd); } static void bus_reset_queues(sd_bus *b) { @@ -88,15 +84,13 @@ static void bus_reset_queues(sd_bus *b) { while (b->rqueue_size > 0) sd_bus_message_unref(b->rqueue[--b->rqueue_size]); - free(b->rqueue); - b->rqueue = NULL; + b->rqueue = mfree(b->rqueue); b->rqueue_allocated = 0; while (b->wqueue_size > 0) sd_bus_message_unref(b->wqueue[--b->wqueue_size]); - free(b->wqueue); - b->wqueue = NULL; + b->wqueue = mfree(b->wqueue); b->wqueue_allocated = 0; } @@ -908,15 +902,11 @@ static void bus_reset_parsed_address(sd_bus *b) { zero(b->sockaddr); b->sockaddr_size = 0; - strv_free(b->exec_argv); - free(b->exec_path); - b->exec_path = NULL; - b->exec_argv = NULL; + b->exec_argv = strv_free(b->exec_argv); + b->exec_path = mfree(b->exec_path); b->server_id = SD_ID128_NULL; - free(b->kernel); - b->kernel = NULL; - free(b->machine); - b->machine = NULL; + b->kernel = mfree(b->kernel); + b->machine = mfree(b->machine); b->nspid = 0; } diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 76964aa0cc..754fb7614e 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -2572,9 +2572,12 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { assert_return(usec, -EINVAL); assert_return(!event_pid_changed(e), -ECHILD); - /* If we haven't run yet, just get the actual time */ - if (!dual_timestamp_is_set(&e->timestamp)) - return -ENODATA; + if (!dual_timestamp_is_set(&e->timestamp)) { + /* Implicitly fall back to now() if we never ran + * before and thus have no cached time. */ + *usec = now(clock); + return 1; + } switch (clock) { diff --git a/src/login/70-power-switch.rules b/src/login/70-power-switch.rules index 695d246370..71f9fe6c72 100644 --- a/src/login/70-power-switch.rules +++ b/src/login/70-power-switch.rules @@ -11,5 +11,7 @@ SUBSYSTEM=="input", KERNEL=="event*", SUBSYSTEMS=="acpi", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", KERNELS=="thinkpad_acpi", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="twl4030_pwrbutton", TAG+="power-switch" SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="tps65217_pwr_but", TAG+="power-switch" +SUBSYSTEM=="input", KERNEL=="event*", \ + SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", ATTRS{keys}=="116", TAG+="power-switch" LABEL="power_switch_end" diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 9d6c453dbc..6c36a4ecfa 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -976,7 +976,7 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) { return log_warning_errno(r < 0 ? r : ERANGE, "Failed to parse TTL \"%s\": %m", b); - time = now(CLOCK_BOOTTIME); + time = now(clock_boottime_or_monotonic()); if (x < time) continue; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 4aa301b112..5454bdd97b 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -468,7 +468,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { } if (link->network->dhcp_hostname) { - const char *hostname; + const char *hostname = NULL; if (!link->network->hostname) r = sd_dhcp_lease_get_hostname(lease, &hostname); diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index be52891681..9ffaf4b19f 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -152,7 +152,7 @@ void dns_cache_prune(DnsCache *c) { break; if (t <= 0) - t = now(CLOCK_BOOTTIME); + t = now(clock_boottime_or_monotonic()); if (i->until > t) break; @@ -406,7 +406,7 @@ int dns_cache_put( dns_cache_make_space(c, answer->n_rrs + q->n_keys); if (timestamp <= 0) - timestamp = now(CLOCK_BOOTTIME); + timestamp = now(clock_boottime_or_monotonic()); /* Second, add in positive entries for all contained RRs */ for (i = 0; i < MIN(max_rrs, answer->n_rrs); i++) { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 4bc4157028..b8414da87e 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -34,6 +34,10 @@ #define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC) #define MULTICAST_RATELIMIT_BURST 1000 +/* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */ +#define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC) +#define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC) + int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) { DnsScope *s; @@ -48,6 +52,7 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int s->link = l; s->protocol = protocol; s->family = family; + s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC; LIST_PREPEND(scopes, m->dns_scopes, s); @@ -125,6 +130,23 @@ void dns_scope_next_dns_server(DnsScope *s) { manager_next_dns_server(s->manager); } +void dns_scope_packet_received(DnsScope *s, usec_t rtt) { + assert(s); + + if (rtt > s->max_rtt) { + s->max_rtt = rtt; + s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), + MULTICAST_RESEND_TIMEOUT_MAX_USEC); + } +} + +void dns_scope_packet_lost(DnsScope *s, usec_t usec) { + assert(s); + + if (s->resend_timeout <= usec) + s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC); +} + int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) { union in_addr_union addr; int ifindex = 0, r; diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 29479ad550..b2dac86b44 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -57,6 +57,9 @@ struct DnsScope { RateLimit ratelimit; + usec_t resend_timeout; + usec_t max_rtt; + LIST_HEAD(DnsTransaction, transactions); LIST_FIELDS(DnsScope, scopes); @@ -65,6 +68,9 @@ struct DnsScope { int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family); DnsScope* dns_scope_free(DnsScope *s); +void dns_scope_packet_received(DnsScope *s, usec_t rtt); +void dns_scope_packet_lost(DnsScope *s, usec_t usec); + int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p); int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server); int dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 92e48ae442..2ff5b192df 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -23,6 +23,10 @@ #include "resolved-dns-server.h" +/* After how much time to repeat classic DNS requests */ +#define DNS_TIMEOUT_MIN_USEC (500 * USEC_PER_MSEC) +#define DNS_TIMEOUT_MAX_USEC (5 * USEC_PER_SEC) + int dns_server_new( Manager *m, DnsServer **ret, @@ -45,6 +49,7 @@ int dns_server_new( s->type = type; s->family = family; s->address = *in_addr; + s->resend_timeout = DNS_TIMEOUT_MIN_USEC; if (type == DNS_SERVER_LINK) { LIST_FIND_TAIL(servers, l->dns_servers, tail); @@ -115,6 +120,23 @@ DnsServer* dns_server_unref(DnsServer *s) { return NULL; } +void dns_server_packet_received(DnsServer *s, usec_t rtt) { + assert(s); + + if (rtt > s->max_rtt) { + s->max_rtt = rtt; + s->resend_timeout = MIN(MAX(DNS_TIMEOUT_MIN_USEC, s->max_rtt * 2), + DNS_TIMEOUT_MAX_USEC); + } +} + +void dns_server_packet_lost(DnsServer *s, usec_t usec) { + assert(s); + + if (s->resend_timeout <= usec) + s->resend_timeout = MIN(s->resend_timeout * 2, DNS_TIMEOUT_MAX_USEC); +} + static unsigned long dns_server_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { const DnsServer *s = p; uint64_t u; diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index 06059e8829..10111fd6bd 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -46,6 +46,9 @@ struct DnsServer { int family; union in_addr_union address; + usec_t resend_timeout; + usec_t max_rtt; + bool marked:1; LIST_FIELDS(DnsServer, servers); @@ -62,6 +65,9 @@ int dns_server_new( DnsServer* dns_server_ref(DnsServer *s); DnsServer* dns_server_unref(DnsServer *s); +void dns_server_packet_received(DnsServer *s, usec_t rtt); +void dns_server_packet_lost(DnsServer *s, usec_t usec); + DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref); extern const struct hash_ops dns_server_hash_ops; diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 8a93b265c6..53779f3372 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -319,11 +319,14 @@ static void dns_transaction_next_dns_server(DnsTransaction *t) { } void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { + usec_t ts; int r; assert(t); assert(p); assert(t->state == DNS_TRANSACTION_PENDING); + assert(t->scope); + assert(t->scope->manager); /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction @@ -369,6 +372,24 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { } } + assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); + + switch (t->scope->protocol) { + case DNS_PROTOCOL_DNS: + assert(t->server); + + dns_server_packet_received(t->server, ts - t->start_usec); + + break; + case DNS_PROTOCOL_LLMNR: + case DNS_PROTOCOL_MDNS: + dns_scope_packet_received(t->scope, ts - t->start_usec); + + break; + default: + assert_not_reached("Invalid DNS protocol."); + } + if (DNS_PACKET_TC(p)) { /* Response was truncated, let's try again with good old TCP */ r = dns_transaction_open_tcp(t); @@ -434,9 +455,9 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use return r; if (dns_packet_validate_reply(p) > 0 && - DNS_PACKET_ID(p) == t->id) { + DNS_PACKET_ID(p) == t->id) dns_transaction_process_reply(t, p); - } else + else log_debug("Invalid DNS packet."); return 0; @@ -481,6 +502,12 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat /* Timeout reached? Try again, with a new server */ dns_transaction_next_dns_server(t); + /* ... and possibly increased timeout */ + if (t->server) + dns_server_packet_lost(t->server, usec - t->start_usec); + else + dns_scope_packet_lost(t->scope, usec - t->start_usec); + r = dns_transaction_go(t); if (r < 0) dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES); @@ -528,8 +555,26 @@ static int dns_transaction_make_packet(DnsTransaction *t) { return 0; } +static usec_t transaction_get_resend_timeout(DnsTransaction *t) { + assert(t); + assert(t->scope); + + switch (t->scope->protocol) { + case DNS_PROTOCOL_DNS: + assert(t->server); + + return t->server->resend_timeout; + case DNS_PROTOCOL_LLMNR: + case DNS_PROTOCOL_MDNS: + return t->scope->resend_timeout; + default: + assert_not_reached("Invalid DNS protocol."); + } +} + int dns_transaction_go(DnsTransaction *t) { bool had_stream; + usec_t ts; int r; assert(t); @@ -555,7 +600,10 @@ int dns_transaction_go(DnsTransaction *t) { return 0; } + assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); + t->n_attempts++; + t->start_usec = ts; t->received = dns_packet_unref(t->received); t->cached = dns_answer_unref(t->cached); t->cached_rcode = 0; @@ -600,7 +648,7 @@ int dns_transaction_go(DnsTransaction *t) { t->scope->manager->event, &t->timeout_event_source, clock_boottime_or_monotonic(), - now(clock_boottime_or_monotonic()) + jitter, + ts + jitter, LLMNR_JITTER_INTERVAL_USEC, on_transaction_timeout, t); if (r < 0) @@ -660,7 +708,7 @@ int dns_transaction_go(DnsTransaction *t) { t->scope->manager->event, &t->timeout_event_source, clock_boottime_or_monotonic(), - now(clock_boottime_or_monotonic()) + TRANSACTION_TIMEOUT_USEC(t->scope->protocol), 0, + ts + transaction_get_resend_timeout(t), 0, on_transaction_timeout, t); if (r < 0) return r; diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h index a8f4267bc8..d8a5647609 100644 --- a/src/resolve/resolved-dns-transaction.h +++ b/src/resolve/resolved-dns-transaction.h @@ -58,6 +58,7 @@ struct DnsTransaction { DnsAnswer *cached; int cached_rcode; + usec_t start_usec; sd_event_source *timeout_event_source; unsigned n_attempts; @@ -95,20 +96,13 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state); const char* dns_transaction_state_to_string(DnsTransactionState p) _const_; DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_; -/* After how much time to repeat classic DNS requests */ -#define DNS_TRANSACTION_TIMEOUT_USEC (5 * USEC_PER_SEC) - -/* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */ -#define LLMNR_TRANSACTION_TIMEOUT_USEC (1 * USEC_PER_SEC) - /* LLMNR Jitter interval, see RFC 4795 Section 7 */ #define LLMNR_JITTER_INTERVAL_USEC (100 * USEC_PER_MSEC) /* Maximum attempts to send DNS requests, across all DNS servers */ -#define DNS_TRANSACTION_ATTEMPTS_MAX 8 +#define DNS_TRANSACTION_ATTEMPTS_MAX 16 /* Maximum attempts to send LLMNR requests, see RFC 4795 Section 2.7 */ #define LLMNR_TRANSACTION_ATTEMPTS_MAX 3 -#define TRANSACTION_TIMEOUT_USEC(p) (p == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_TIMEOUT_USEC : DNS_TRANSACTION_TIMEOUT_USEC) #define TRANSACTION_ATTEMPTS_MAX(p) (p == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_ATTEMPTS_MAX : DNS_TRANSACTION_ATTEMPTS_MAX) diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index d824172b89..e730fb45f1 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -309,7 +309,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply, } else if (streq(name, "smack")) { smack = true; - r = mac_smack_apply(devnode, label); + r = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label); if (r < 0) log_error_errno(r, "SECLABEL: failed to set SMACK label '%s': %m", label); else @@ -323,7 +323,7 @@ static int node_permissions_apply(struct udev_device *dev, bool apply, if (!selinux) mac_selinux_fix(devnode, true, false); if (!smack) - mac_smack_apply(devnode, NULL); + mac_smack_apply(devnode, SMACK_ATTR_ACCESS, NULL); } /* always update timestamp when we re-use the node, like on media change events */ diff --git a/src/udev/udevd.c b/src/udev/udevd.c index d0b8bad48e..28ac44fb8e 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -261,7 +261,6 @@ static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *use static void worker_attach_event(struct worker *worker, struct event *event) { sd_event *e; uint64_t usec; - int r; assert(worker); assert(worker->manager); @@ -276,9 +275,7 @@ static void worker_attach_event(struct worker *worker, struct event *event) { e = worker->manager->event; - r = sd_event_now(e, clock_boottime_or_monotonic(), &usec); - if (r < 0) - return; + assert_se(sd_event_now(e, clock_boottime_or_monotonic(), &usec) >= 0); (void) sd_event_add_time(e, &event->timeout_warning, clock_boottime_or_monotonic(), usec + arg_event_timeout_warn_usec, USEC_PER_SEC, on_event_timeout_warning, event); @@ -749,9 +746,7 @@ static void manager_exit(Manager *manager) { event_queue_cleanup(manager, EVENT_QUEUED); manager_kill_workers(manager); - r = sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec); - if (r < 0) - return; + assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0); r = sd_event_add_time(manager->event, NULL, clock_boottime_or_monotonic(), usec + 30 * USEC_PER_SEC, USEC_PER_SEC, on_exit_timeout, manager); @@ -780,7 +775,6 @@ static void manager_reload(Manager *manager) { static void event_queue_start(Manager *manager) { struct udev_list_node *loop; usec_t usec; - int r; assert(manager); @@ -788,17 +782,15 @@ static void event_queue_start(Manager *manager) { manager->exit || manager->stop_exec_queue) return; - r = sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec); - if (r >= 0) { - /* check for changed config, every 3 seconds at most */ - if (manager->last_usec == 0 || - (usec - manager->last_usec) > 3 * USEC_PER_SEC) { - if (udev_rules_check_timestamp(manager->rules) || - udev_builtin_validate(manager->udev)) - manager_reload(manager); + assert_se(sd_event_now(manager->event, clock_boottime_or_monotonic(), &usec) >= 0); + /* check for changed config, every 3 seconds at most */ + if (manager->last_usec == 0 || + (usec - manager->last_usec) > 3 * USEC_PER_SEC) { + if (udev_rules_check_timestamp(manager->rules) || + udev_builtin_validate(manager->udev)) + manager_reload(manager); - manager->last_usec = usec; - } + manager->last_usec = usec; } udev_builtin_init(manager->udev); |