[systemd-devel] [PATCH] shared: rename hasprefix() to startswith(), which is functionally identical and removed
as most (if not all) of the prefix strings are static, these will get forward constant propagation optimized into single memcmp() calls, which should be much better than the non-SIMD hand-rolled version. --- src/journal/journal-send.c | 2 +- src/journal/journald-native.c | 12 ++-- src/libsystemd-bus/bus-match.c | 26 +- src/shared/logs-show.c | 2 +- src/shared/macro.h | 2 +- src/shared/util.c | 17 - src/shared/util.h | 1 - 7 files changed, 22 insertions(+), 40 deletions(-) diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index fef66fc..d00e26f 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -245,7 +245,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) { have_syslog_identifier = have_syslog_identifier || (c == (char *) iov[i].iov_base + 17 - hasprefix(iov[i].iov_base, SYSLOG_IDENTIFIER)); + startswith(iov[i].iov_base, SYSLOG_IDENTIFIER)); nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len); if (nl) { diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 0f9af37..c50cf64 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -154,23 +154,23 @@ void server_process_native_message( * of this entry for the rate limiting * logic */ if (l == 10 -hasprefix(p, PRIORITY=) +startswith(p, PRIORITY=) p[9] = '0' p[9] = '9') priority = (priority LOG_FACMASK) | (p[9] - '0'); else if (l == 17 - hasprefix(p, SYSLOG_FACILITY=) + startswith(p, SYSLOG_FACILITY=) p[16] = '0' p[16] = '9') priority = (priority LOG_PRIMASK) | ((p[16] - '0') 3); else if (l == 18 - hasprefix(p, SYSLOG_FACILITY=) + startswith(p, SYSLOG_FACILITY=) p[16] = '0' p[16] = '9' p[17] = '0' p[17] = '9') priority = (priority LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) 3); else if (l = 19 - hasprefix(p, SYSLOG_IDENTIFIER=)) { + startswith(p, SYSLOG_IDENTIFIER=)) { char *t; t = strndup(p + 18, l - 18); @@ -179,7 +179,7 @@ void server_process_native_message( identifier = t; } } else if (l = 8 - hasprefix(p, MESSAGE=)) { + startswith(p, MESSAGE=)) { char *t; t = strndup(p + 8, l - 8); @@ -189,7 +189,7 @@ void server_process_native_message( } } else if (l strlen(OBJECT_PID=) l strlen(OBJECT_PID=) + DECIMAL_STR_MAX(pid_t) - hasprefix(p, OBJECT_PID=) + startswith(p, OBJECT_PID=) allow_object_pid(ucred)) { char buf[DECIMAL_STR_MAX(pid_t)]; memcpy(buf, p + strlen(OBJECT_PID=), l - strlen(OBJECT_PID=)); diff --git a/src/libsystemd-bus/bus-match.c b/src/libsystemd-bus/bus-match.c index 750acfe..1411167 100644 --- a/src/libsystemd-bus/bus-match.c +++ b/src/libsystemd-bus/bus-match.c @@ -555,22 +555,22 @@ static int bus_match_find_leaf( enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) { assert(k); -if (n == 4 hasprefix(k, type)) +if (n == 4 startswith(k, type)) return BUS_MATCH_MESSAGE_TYPE; -if (n == 6 hasprefix(k, sender)) +if (n == 6 startswith(k, sender)) return BUS_MATCH_SENDER; -if (n == 11 hasprefix(k, destination)) +if (n == 11 startswith(k, destination)) return BUS_MATCH_DESTINATION; -if (n == 9 hasprefix(k, interface)) +if (n ==
[systemd-devel] [PATCH v2] shared: rename hasprefix() to startswith(), which is functionally identical and removed
as most (if not all) of the prefix strings are static, these will get forward constant propagation optimized into single memcmp() calls, which should be much better than the non-SIMD hand-rolled version. --- TODO | 2 -- src/journal/journal-send.c | 2 +- src/journal/journald-native.c | 12 ++-- src/libsystemd-bus/bus-match.c | 26 +- src/shared/logs-show.c | 2 +- src/shared/macro.h | 2 +- src/shared/util.c | 17 - src/shared/util.h | 1 - 8 files changed, 22 insertions(+), 42 deletions(-) diff --git a/TODO b/TODO index 5d4ba8f..ad600c2 100644 --- a/TODO +++ b/TODO @@ -57,8 +57,6 @@ Features: * Get rid of systemd-sysv: https://fedoraproject.org/wiki/User:Toshio/Systemd_Convert_draft -* do we really need both hasprefix() and startswith()? - * when a kernel driver logs in a tight loop we should ratelimit that too. * journald: when we drop syslog messages because the syslog socket is diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index fef66fc..d00e26f 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -245,7 +245,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) { have_syslog_identifier = have_syslog_identifier || (c == (char *) iov[i].iov_base + 17 - hasprefix(iov[i].iov_base, SYSLOG_IDENTIFIER)); + startswith(iov[i].iov_base, SYSLOG_IDENTIFIER)); nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len); if (nl) { diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 0f9af37..c50cf64 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -154,23 +154,23 @@ void server_process_native_message( * of this entry for the rate limiting * logic */ if (l == 10 -hasprefix(p, PRIORITY=) +startswith(p, PRIORITY=) p[9] = '0' p[9] = '9') priority = (priority LOG_FACMASK) | (p[9] - '0'); else if (l == 17 - hasprefix(p, SYSLOG_FACILITY=) + startswith(p, SYSLOG_FACILITY=) p[16] = '0' p[16] = '9') priority = (priority LOG_PRIMASK) | ((p[16] - '0') 3); else if (l == 18 - hasprefix(p, SYSLOG_FACILITY=) + startswith(p, SYSLOG_FACILITY=) p[16] = '0' p[16] = '9' p[17] = '0' p[17] = '9') priority = (priority LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) 3); else if (l = 19 - hasprefix(p, SYSLOG_IDENTIFIER=)) { + startswith(p, SYSLOG_IDENTIFIER=)) { char *t; t = strndup(p + 18, l - 18); @@ -179,7 +179,7 @@ void server_process_native_message( identifier = t; } } else if (l = 8 - hasprefix(p, MESSAGE=)) { + startswith(p, MESSAGE=)) { char *t; t = strndup(p + 8, l - 8); @@ -189,7 +189,7 @@ void server_process_native_message( } } else if (l strlen(OBJECT_PID=) l strlen(OBJECT_PID=) + DECIMAL_STR_MAX(pid_t) - hasprefix(p, OBJECT_PID=) + startswith(p, OBJECT_PID=) allow_object_pid(ucred)) { char buf[DECIMAL_STR_MAX(pid_t)]; memcpy(buf, p + strlen(OBJECT_PID=), l - strlen(OBJECT_PID=)); diff --git a/src/libsystemd-bus/bus-match.c b/src/libsystemd-bus/bus-match.c index 750acfe..1411167 100644 --- a/src/libsystemd-bus/bus-match.c +++ b/src/libsystemd-bus/bus-match.c @@ -555,22 +555,22 @@ static int bus_match_find_leaf( enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) { assert(k); -if (n == 4
[systemd-devel] [PATCH] journalctl: have a useful --setup-keys error message when using non-persistant logging
Generating seed... Generating key pair... Generating sealing key... Failed to open /var/log/journal/33f46101703a10c5fc6fa4f451840101/fss.tmp.k2wDDU: No such file or directory --- src/journal/journalctl.c | 17 + 1 file changed, 17 insertions(+) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 7baea23..458d80d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -725,6 +725,23 @@ static int setup_keys(void) { char *p = NULL, *k = NULL; struct FSSHeader h; uint64_t n; +stat st; + +r = stat(/var/log/journal, st); +if (r 0) { +if (errno == ENOENT || errno == ENOTDIR) { +log_error(%s is not a directory, must be using persistant logging for FSS: %s, /var/log/journal, strerror(errno)); +return -errno; +} else { +log_error(stat(\%s\) failed: %m, /var/log/journal); +return -errno; +} +} + +if (!S_ISDIR(st.st_mode)) { +log_error(%s is not a directory, must be using persistant logging for FSS: %s, /var/log/journal, strerror(ENOTDIR)); +return -ENOTDIR; +} r = sd_id128_get_machine(machine); if (r 0) { -- 1.8.3.2 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/2] journalctl: add --force option to recreate FSS
reuse -f? --- src/journal/journalctl.c | 24 +--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 32665b7..5f44fce 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -79,6 +79,7 @@ static int arg_priorities = 0xFF; static const char *arg_verify_key = NULL; #ifdef HAVE_GCRYPT static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; +static bool arg_force = false; #endif static usec_t arg_since, arg_until; static bool arg_since_set = false, arg_until_set = false; @@ -149,6 +150,7 @@ static int help(void) { --update-catalogUpdate the message catalog database\n #ifdef HAVE_GCRYPT --setup-keysGenerate new FSS key pair\n +--force Force overriding new FSS key pair with --setup-keys\n --verifyVerify journal file consistency\n #endif , program_invocation_short_name); @@ -179,6 +181,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_LIST_CATALOG, ARG_DUMP_CATALOG, ARG_UPDATE_CATALOG, +ARG_FORCE, }; static const struct option options[] = { @@ -187,6 +190,7 @@ static int parse_argv(int argc, char *argv[]) { { no-pager, no_argument, NULL, ARG_NO_PAGER }, { pager-end,no_argument, NULL, 'e' }, { follow, no_argument, NULL, 'f' }, +{ force,no_argument, NULL, ARG_FORCE}, { output, required_argument, NULL, 'o' }, { all, no_argument, NULL, 'a' }, { full, no_argument, NULL, 'l' }, @@ -375,6 +379,10 @@ static int parse_argv(int argc, char *argv[]) { break; #ifdef HAVE_GCRYPT +case ARG_FORCE: +arg_force = true; +break; + case ARG_SETUP_KEYS: arg_action = ACTION_SETUP_KEYS; break; @@ -397,6 +405,7 @@ static int parse_argv(int argc, char *argv[]) { case ARG_SETUP_KEYS: case ARG_VERIFY_KEY: case ARG_INTERVAL: +case ARG_FORCE: log_error(Forward-secure sealing not available.); return -ENOTSUP; #endif @@ -756,9 +765,18 @@ static int setup_keys(void) { return log_oom(); if (access(p, F_OK) = 0) { -log_error(Sealing key file %s exists already., p); -r = -EEXIST; -goto finish; +if (arg_force) { +r = unlink(p); +if (r 0) { +log_error(unlink(\%s\) failed: %m, p); +r = -errno; +goto finish; +} +} else { +log_error(Sealing key file %s exists already. (--force to recreate), p); +r = -EEXIST; +goto finish; +} } if (asprintf(k, /var/log/journal/ SD_ID128_FORMAT_STR /fss.tmp.XX, -- 1.8.3.2 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH v4] journal: add logging of effective capabilities _CAP_EFFECTIVE
I think this is the most important of the capabilities bitmasks to log. --- TODO | 2 -- man/systemd.journal-fields.xml | 9 + src/journal/journald-server.c | 7 +++ src/shared/util.c | 34 ++ src/shared/util.h | 1 + 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index 5d4ba8f..0782038 100644 --- a/TODO +++ b/TODO @@ -208,8 +208,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) -* we should log capabilities too - * Support SO_REUSEPORT with socket activation: - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml index ed62edc..452406c 100644 --- a/man/systemd.journal-fields.xml +++ b/man/systemd.journal-fields.xml @@ -197,6 +197,15 @@ /varlistentry varlistentry +termvarname_CAP_EFFECTIVE=/varname/term +listitem +paraThe effective citerefentryrefentrytitlecapabilities/refentrytitlemanvolnum7/manvolnum/citerefentry of +the process the journal entry +originates from./para +/listitem +/varlistentry + +varlistentry termvarname_AUDIT_SESSION=/varname/term termvarname_AUDIT_LOGINUID=/varname/term listitem diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 6beaa8a..332ba41 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -578,6 +578,13 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], x); } +r = get_process_capeff(ucred-pid, t); +if (r = 0) { +x = strappenda(_CAP_EFFECTIVE=, t); +free(t); +IOVEC_SET_STRING(iovec[n++], x); +} + #ifdef HAVE_AUDIT r = audit_session_from_pid(ucred-pid, audit); if (r = 0) { diff --git a/src/shared/util.c b/src/shared/util.c index ceee6f2..7e9c8ea 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -726,6 +726,40 @@ int is_kernel_thread(pid_t pid) { return 0; } +int get_process_capeff(pid_t pid, char **capeff) { +const char *p; +_cleanup_free_ char *status = NULL; +char *t = NULL; +int r; + +assert(capeff); +assert(pid = 0); + +if (pid == 0) +p = /proc/self/status; +else +p = procfs_file_alloca(pid, status); + +r = read_full_file(p, status, NULL); +if (r 0) +return r; + +t = strstr(status, \nCapEff:\t); +if (!t) +return -ENOENT; + +for (t += strlen(\nCapEff:\t); t[0] == '0'; t++) +continue; + +if (t[0] == '\n') +t--; + +*capeff = strndup(t, strchr(t, '\n') - t); +if (!*capeff) +return -ENOMEM; + +return 0; +} int get_process_exe(pid_t pid, char **name) { const char *p; diff --git a/src/shared/util.h b/src/shared/util.h index ddb21b4..fac08ca 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -210,6 +210,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char * int get_process_exe(pid_t pid, char **name); int get_process_uid(pid_t pid, uid_t *uid); int get_process_gid(pid_t pid, gid_t *gid); +int get_process_capeff(pid_t pid, char **capeff); char hexchar(int x) _const_; int unhexchar(char c) _const_; -- 1.8.3.2 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] configure: add -Wno-cast-align to CFLAGS
these warnings on !x86 arches for good code are annoying, and there is no way to mark the offending code safe, so I guess we are just going to have to deal with the resulting problems as we come across them. Also, these warnings are present for armv6+armv7, when they moreso effect armv5. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index afbe8e9..709262e 100644 --- a/configure.ac +++ b/configure.ac @@ -129,6 +129,7 @@ CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ -Wno-unused-parameter \ -Wno-missing-field-initializers \ -Wno-unused-result \ +-Wno-cast-align \ -Werror=overflow \ -ffast-math \ -fno-common \ -- 1.8.3.2 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] shared: fix build on !x86
--- src/shared/virt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/virt.c b/src/shared/virt.c index 1abd686..4f8134a 100644 --- a/src/shared/virt.c +++ b/src/shared/virt.c @@ -29,6 +29,8 @@ /* Returns a short identifier for the various VM implementations */ int detect_vm(const char **id) { +_cleanup_free_ char *cpuinfo_contents = NULL; +int r; #if defined(__i386__) || defined(__x86_64__) @@ -67,8 +69,6 @@ int detect_vm(const char **id) { const char *j, *k; bool hypervisor; _cleanup_free_ char *hvtype = NULL; -_cleanup_free_ char *cpuinfo_contents = NULL; -int r; /* Try high-level hypervisor sysfs file first: * -- 1.8.3.2 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] build: do not link everything with -lrt (and therefore -pthread)
--- Makefile.am | 1 + configure.ac | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 3ece887..f96866c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1832,6 +1832,7 @@ libsystemd_daemon_internal_la_SOURCES = \ $(libsystemd_daemon_la_SOURCES) libsystemd_daemon_la_CFLAGS = \ + $(RT_LIBS) \ $(AM_CFLAGS) \ -fvisibility=hidden \ -DSD_EXPORT_SYMBOLS diff --git a/configure.ac b/configure.ac index a14b609..5735bd5 100644 --- a/configure.ac +++ b/configure.ac @@ -194,7 +194,6 @@ AM_CONDITIONAL([HAVE_PYTHON_DEVEL], [test $have_python_devel = yes]) # -- -AC_SEARCH_LIBS([mq_open], [rt], [], [AC_MSG_ERROR([*** POSIX RT library not found])]) AC_SEARCH_LIBS([dlsym], [dl], [], [AC_MSG_ERROR([*** Dynamic linking loader library not found])]) save_LIBS=$LIBS @@ -202,6 +201,9 @@ LIBS= AC_SEARCH_LIBS([cap_init], [cap], [], [AC_MSG_ERROR([*** POSIX caps library not found])]) AC_CHECK_HEADERS([sys/capability.h], [], [AC_MSG_ERROR([*** POSIX caps headers not found])]) CAP_LIBS=$LIBS +AC_SEARCH_LIBS([mq_open], [rt], [], [AC_MSG_ERROR([*** POSIX RT library not found])]) +RT_LIBS=$LIBS +AC_SUBST(RT_LIBS) LIBS=$save_LIBS AC_SUBST(CAP_LIBS) -- 1.8.3.2 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] man: make reference to bind(2) explicit
--- man/systemd.socket.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 852010b..1fc28c5 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -510,7 +510,7 @@ varlistentry termvarnameReusePort=/varname/term listitemparaTakes a boolean -value. If true, allows multiple bind()s +value. If true, allows multiple citerefentryrefentrytitlebind/refentrytitlemanvolnum2/manvolnum/citerefentrys to this TCP or UDP port. This controls the SO_REUSEPORT socket option. See -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] remove hasprefix(), use startswith()
memcmp() could read from uninitilized memory if string is at the end of a page boundry and shorter than prefix --- TODO | 2 -- src/journal/journal-send.c | 2 +- src/journal/journald-native.c | 12 ++-- src/libsystemd-bus/bus-match.c | 26 +- src/shared/logs-show.c | 2 +- src/shared/macro.h | 2 -- 6 files changed, 21 insertions(+), 25 deletions(-) diff --git a/TODO b/TODO index 9bc14fd..3800ce4 100644 --- a/TODO +++ b/TODO @@ -96,8 +96,6 @@ Features: * systemctl list-unit-files should list generated files (and probably with a new state generated for them, or so) -* do we really need both hasprefix() and startswith()? - * journald: when we drop syslog messages because the syslog socket is full, make sure to write how many messages are lost as first thing to syslog when it works again. diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index fef66fc..d00e26f 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -245,7 +245,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) { have_syslog_identifier = have_syslog_identifier || (c == (char *) iov[i].iov_base + 17 - hasprefix(iov[i].iov_base, SYSLOG_IDENTIFIER)); + startswith(iov[i].iov_base, SYSLOG_IDENTIFIER)); nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len); if (nl) { diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 0f9af37..c50cf64 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -154,23 +154,23 @@ void server_process_native_message( * of this entry for the rate limiting * logic */ if (l == 10 -hasprefix(p, PRIORITY=) +startswith(p, PRIORITY=) p[9] = '0' p[9] = '9') priority = (priority LOG_FACMASK) | (p[9] - '0'); else if (l == 17 - hasprefix(p, SYSLOG_FACILITY=) + startswith(p, SYSLOG_FACILITY=) p[16] = '0' p[16] = '9') priority = (priority LOG_PRIMASK) | ((p[16] - '0') 3); else if (l == 18 - hasprefix(p, SYSLOG_FACILITY=) + startswith(p, SYSLOG_FACILITY=) p[16] = '0' p[16] = '9' p[17] = '0' p[17] = '9') priority = (priority LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) 3); else if (l = 19 - hasprefix(p, SYSLOG_IDENTIFIER=)) { + startswith(p, SYSLOG_IDENTIFIER=)) { char *t; t = strndup(p + 18, l - 18); @@ -179,7 +179,7 @@ void server_process_native_message( identifier = t; } } else if (l = 8 - hasprefix(p, MESSAGE=)) { + startswith(p, MESSAGE=)) { char *t; t = strndup(p + 8, l - 8); @@ -189,7 +189,7 @@ void server_process_native_message( } } else if (l strlen(OBJECT_PID=) l strlen(OBJECT_PID=) + DECIMAL_STR_MAX(pid_t) - hasprefix(p, OBJECT_PID=) + startswith(p, OBJECT_PID=) allow_object_pid(ucred)) { char buf[DECIMAL_STR_MAX(pid_t)]; memcpy(buf, p + strlen(OBJECT_PID=), l - strlen(OBJECT_PID=)); diff --git a/src/libsystemd-bus/bus-match.c b/src/libsystemd-bus/bus-match.c index 750acfe..1411167 100644 --- a/src/libsystemd-bus/bus-match.c +++ b/src/libsystemd-bus/bus-match.c @@ -555,22 +555,22 @@ static int bus_match_find_leaf( enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) { assert(k); -if (n == 4 hasprefix(k, type)) +if (n == 4 startswith(k, type)) return BUS_MATCH_MESSAGE_TYPE; -if (n == 6
[systemd-devel] [PATCH] udev: fix printf(3) type specifier
From: Shawn Landden shawnland...@gmail.com src/udev/udev-rules.c: In function 'add_rule': src/udev/udev-rules.c:1078:33: warning: format '%lu' expects argument of type 'long unsigned int', but argument 8 has type 'int' [-Wformat=] log_error(invalid key/value pair in file %s on line %u, ^ --- src/udev/udev-rules.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 1634812..f14158b 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1076,7 +1076,7 @@ static int add_rule(struct udev_rules *rules, char *line, tmp = cescape(buf); log_error(invalid key/value pair in file %s on line %u, - starting at character %lu ('%s')\n, + starting at character %tu ('%s')\n, filename, lineno, linepos - line + 1, tmp); if (linepos[1] == '#') log_info(hint: comments can only start at beginning of line); -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] util, utf8: recognize wide characters in wellipsize_mem()
--- src/shared/utf8.c | 64 +++ src/shared/utf8.h | 4 +++- src/shared/util.c | 19 ++--- src/shared/util.h | 1 + 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/shared/utf8.c b/src/shared/utf8.c index 8a37c3a..607f0c1 100644 --- a/src/shared/utf8.c +++ b/src/shared/utf8.c @@ -372,4 +372,68 @@ utf8_get_char (const char *p) UTF8_GET (result, p, i, mask, len); return result; +} + +struct Interval +{ + unichar start, end; +}; + +static int +interval_compare (const void *key, const void *elt) +{ + unichar c = (unichar) (long) (key); + struct Interval *interval = (struct Interval *)elt; + + if (c interval-start) +return -1; + if (c interval-end) +return +1; + + return 0; +} + +/* + * NOTE: + * + * The tables for g_unichar_iswide() and g_unichar_iswide_cjk() are + * generated from the Unicode Character Database's file + * extracted/DerivedEastAsianWidth.txt using the gen-iswide-table.py + * in this way: + * + * ./gen-iswide-table.py path/to/ucd/extracted/DerivedEastAsianWidth.txt | fmt + * + * Last update for Unicode 6.0. + */ + +/** + * g_unichar_iswide: + * @c: a Unicode character + * + * Determines if a character is typically rendered in a double-width + * cell. + * + * Return value: %TRUE if the character is wide + **/ +bool +unichar_iswide (unichar c) +{ + /* See NOTE earlier for how to update this table. */ + static const struct Interval wide[] = { +{0x1100, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, +{0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E}, {0x3041, 0x3096}, +{0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, +{0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x32FE}, +{0x3300, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, +{0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, +{0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, +{0x1B000, 0x1B001}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23A}, {0x1F240, +0x1F248}, {0x1F250, 0x1F251}, {0x2, 0x2FFFD}, {0x3, 0x3FFFD} + }; + + if (bsearch ((long)c, wide, (sizeof (wide) / sizeof ((wide)[0])), sizeof wide[0], + interval_compare)) +return true; + + return false; } \ No newline at end of file diff --git a/src/shared/utf8.h b/src/shared/utf8.h index 020bc27..f1be180 100644 --- a/src/shared/utf8.h +++ b/src/shared/utf8.h @@ -131,4 +131,6 @@ static const char utf8_skip_data[256] = { * Before using this macro, use g_utf8_validate() to validate strings * that may contain invalid UTF-8. */ -#define utf8_next_char(p) (char *)((p) + utf8_skip_data[*(const char *)(p)]) \ No newline at end of file +#define utf8_next_char(p) (char *)((p) + utf8_skip_data[*(const char *)(p)]) + +bool unichar_iswide (unichar c); \ No newline at end of file diff --git a/src/shared/util.c b/src/shared/util.c index 58a1787..1c73b3e 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -3357,22 +3357,35 @@ char *wellipsize_mem(const char *s, size_t old_length, size_t new_length, unsign if (x new_length - 3) x = new_length - 3; -for (i = (char *)s;k x;i = utf8_next_char(i)) +for (i = (char *)s;k x;i = utf8_next_char(i)) { +c = utf8_get_char(i); k++; +if (unichar_iswide(c)) +k++; +} + +if (k x) /* last character was wide and went over quota */ +x++; j = i - s; memcpy(e, s, j); -e[j] = '.'; /* TODO: use … tri-dot? */ -e[j+1] = '.'; /* 0xe2 0x80 0xa6 */ +e[j] = '.'; /* TODO: use … tri-dot? */ +e[j+1] = '.'; /* 0xE2 0x80 0xA6 */ e[j+2] = '.'; k = 0; for (i = (char *)s + old_length; k new_length - x - 3;) { i = utf8_prev_char(i); +c = utf8_get_char(i); k++; +if (unichar_iswide(c)) +k++; } +if (k new_length - x - 3) /* last (reverse) character was wide and went over quota */ +i = utf8_next_char(i); + strcpy(e + j + 3, i); return e; diff --git a/src/shared/util.h b/src/shared/util.h index 9b17db9..97d8697 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -405,6 +405,7 @@ int running_in_chroot(void); char *ellipsize(const char *s, size_t length, unsigned percent); char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent); char *wellipsize(const char *s, size_t length, unsigned percent); +/* bytes columns */ char *wellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent); int touch(const char *path); -- 1.8.4.rc3 ___ systemd-devel
[systemd-devel] [PATCH 2/3] util, utf8: new wellipsize and wellipsize_mem that take into account multi-byte characters
This version counts all multibyte characters as 1 width, not taking into account double width cjk characters and zerowidth characters --- src/shared/util.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/util.c b/src/shared/util.c index b791433..c6375e5 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -3310,14 +3310,14 @@ char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, u continue; memcpy(r, s, x); -r[x] = '.'; -r[x+1] = '.'; -r[x+2] = '.'; +r[x] = 0xe2; +r[x+1] = 0x80; +r[x+2] = 0xa6; for (j=(x+3);(unsigned char)s[j] 0x80;j++) continue; -memcpy(r + x + 3, +memcpy(r + x + 1, s + old_length - (new_length - j), new_length - j); -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] util, utf8: recognize wide characters in wellipsize_mem()
Original Message From: Zbigniew Jędrzejewski-Szmek To: shawnland...@gmail.com CC: systemd-devel@lists.freedesktop.org, Shawn Landden Sent: Tue, Sep 10, 2013, 08:59 Subject: Re: [systemd-devel] [PATCH] util, utf8: recognize wide characters in wellipsize_mem() Hi Shawn, thank you for attacking this, and sorry for the long delay in answering. I think that the approach of copying working code from elsewhere for this is right, but I think it should go into its own file, so that two coding styles are not mixed.The functions come from the same original source however (same two files in glib) so I think they should go together, perhaps the older take functions should be transfered back to their original style? Also, can those new functions replace normal ellipsize and ellipsize_mem, so that we have support everywhere?renamed old to ascii_* e = new0(char, new_length*4 old_length ? new_length*4 : old_length); → we have a min macro fixed There are some compilation warnings: ../src/shared/utf8.c: In function 'unichar_iswide': ../src/shared/utf8.c:435:9: warning: passing argument 1 of 'bsearch' makes pointer from integer without a cast [enabled by default] interval_compare)) ^ In file included from ../src/shared/utf8.c:51:0: /usr/include/stdlib.h:754:14: note: expected 'const void *' but argument is of type 'long int' extern void *bsearch (const void *__key, const void *__base, fixed ../src/shared/util.c: In function 'wellipsize_mem': ../src/shared/util.c:3353:9: warning: array subscript has type 'char' [-Wchar-subscripts] for (i = (char *)s;k x;i = utf8_next_char(i)) { ^ ../src/shared/util.c:3380:17: warning: array subscript has type 'char' [-Wchar-subscripts] i = utf8_next_char(i); ^not sure how to fix this,I am iterating over a pointer to char, but i am not evaluating it (it is a warning about signed vs unsigned char.) and valgrind finds some leaks: % valgrind --leak-check=full build/.libs/test-wellipsize ==19953== ==19953== HEAP SUMMARY: ==19953== in use at exit: 1,379 bytes in 6 blocks ==19953== total heap usage: 6 allocs, 0 frees, 1,379 bytes allocated ==19953== ==19953== 81 bytes in 1 blocks are definitely lost in loss record 1 of 6 ==19953==at 0x4A08121: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==19953==by 0x400F57: ellipsize_mem (util.c:3300) ==19953==by 0x401082: wellipsize_mem (util.c:3336) ==19953==by 0x40122A: wellipsize (util.c:3388) ==19953==by 0x400CFF: test_one (test-wellipsize.c:28) ==19953==by 0x400D4C: main (test-wellipsize.c:37) ... I think it was just my lazy test, which I fixed, but I am on ARM, so let me know if this persists on amd64 On Wed, Aug 28, 2013 at 03:58:29PM -0700, Shawn wrote: here is the test runner I am using, doesn't really make sense to add this to the tree as it has to be visually inspected I think it is still useful, since we don't have anything better for now. Anyway, we have a bunch of tests which can only be run manually. Your test is certainly good enough for valgrind testing and visual inspection, so it should go in. ok Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/3] util: ellipsize_mem: do not print partial utf-8 characters
, unsigned percent); + /* bytes columns */ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent); int touch(const char *path); diff --git a/src/test/test-wellipsize.c b/src/test/test-wellipsize.c new file mode 100644 index 000..f6db82c --- /dev/null +++ b/src/test/test-wellipsize.c @@ -0,0 +1,42 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Shawn Landden + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see http://www.gnu.org/licenses/. +***/ + +#include stdio.h + +#include util.h +#include utf8.h + +static void test_one(const char *p) { + _cleanup_free_ char *t = NULL; + t = ellipsize(p, 80, 70); + puts(t); +} + +int main(int argc, char *argv[]) { + test_one(s??); + test_one(?); + test_one(??); + test_one(?); + test_one(); + test_one(asdfnjaskdfnklasdgnjaskdghnkasdgfklasdfjkasdfjaksdfaskldfnaskldfnaskldfnaklsdfnaklsdfnklnaskjgdknl); + +return 0; +} -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/2] util, utf8: make ellipsize and ellipsize_mem take into account multi-byte characters
rename old versions to ascii_* Do not take into account zerowidth characters, but do consider double-wide characters. Import needed utf8 helper code from glib. --- TODO | 4 -- src/shared/utf8.c | 120 ++ src/shared/utf8.h | 100 + src/shared/util.c | 70 ++- src/shared/util.h | 3 ++ 5 files changed, 292 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index 08d4914..509b31f 100644 --- a/TODO +++ b/TODO @@ -19,10 +19,6 @@ Bugfixes: * properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point. -* ellipsize_mem must take into account multi-byte unicode characters, and - - make the resulting line the requested number of *characters*, not *bytes*, - - avoid truncuating multi-byte sequences in the middle. - * When we detect invalid UTF-8, we cant't use it in an error message: log...(Path is not UTF-8 clean, ignoring assignment: %s, rvalue); diff --git a/src/shared/utf8.c b/src/shared/utf8.c index 655cc77..a9308b5 100644 --- a/src/shared/utf8.c +++ b/src/shared/utf8.c @@ -22,6 +22,11 @@ /* This file is based on the GLIB utf8 validation functions. The * original license text follows. */ +/* gunicode.h - Unicode manipulation functions + * + * Copyright (C) 1999, 2000 Tom Tromey + * Copyright 2000, 2005 Red Hat, Inc. + */ /* gutf8.c - Operations on UTF-8 strings. * * Copyright (C) 1999 Tom Tromey @@ -317,3 +322,118 @@ char *utf16_to_utf8(const void *s, size_t length) { return r; } + +/** + * g_utf8_prev_char: + * @p: a pointer to a position within a UTF-8 encoded string + * + * Finds the previous UTF-8 character in the string before @p. + * + * @p does not have to be at the beginning of a UTF-8 character. No check + * is made to see if the character found is actually valid other than + * it starts with an appropriate byte. If @p might be the first + * character of the string, you must use g_utf8_find_prev_char() instead. + * + * Return value: a pointer to the found character. + **/ +char * +utf8_prev_char (const char *p) +{ + while (1) +{ + p--; + if ((*p 0xc0) != 0x80) + return (char *)p; +} +} + +/** + * g_utf8_get_char: + * @p: a pointer to Unicode character encoded as UTF-8 + * + * Converts a sequence of bytes encoded as UTF-8 to a Unicode character. + * If @p does not point to a valid UTF-8 encoded character, results are + * undefined. If you are not sure that the bytes are complete + * valid Unicode characters, you should use g_utf8_get_char_validated() + * instead. + * + * Return value: the resulting character + **/ +unichar +utf8_get_char (const char *p) +{ + int i, mask = 0, len; + unichar result; + unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len); + if (len == -1) +return (unichar)-1; + UTF8_GET (result, p, i, mask, len); + + return result; +} + +struct Interval +{ + unichar start, end; +}; + +static int +interval_compare (const void *key, const void *elt) +{ + unichar c = (unichar) (long) (key); + struct Interval *interval = (struct Interval *)elt; + + if (c interval-start) +return -1; + if (c interval-end) +return +1; + + return 0; +} + +/* + * NOTE: + * + * The tables for g_unichar_iswide() and g_unichar_iswide_cjk() are + * generated from the Unicode Character Database's file + * extracted/DerivedEastAsianWidth.txt using the gen-iswide-table.py + * in this way: + * + * ./gen-iswide-table.py path/to/ucd/extracted/DerivedEastAsianWidth.txt | fmt + * + * Last update for Unicode 6.0. + */ + +/** + * g_unichar_iswide: + * @c: a Unicode character + * + * Determines if a character is typically rendered in a double-width + * cell. + * + * Return value: %TRUE if the character is wide + **/ +bool +unichar_iswide (unichar c) +{ + /* See NOTE earlier for how to update this table. */ + static const struct Interval wide[] = { +{0x1100, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, +{0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E}, {0x3041, 0x3096}, +{0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, +{0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x32FE}, +{0x3300, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, +{0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, +{0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, +{0x1B000, 0x1B001}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23A}, {0x1F240, +0x1F248}, {0x1F250, 0x1F251}, {0x2, 0x2FFFD}, {0x3, 0x3FFFD} + }; + + if (bsearch ((long *)c, wide, (sizeof (wide) / sizeof ((wide)[0])), sizeof wide[0], + interval_compare)) +return true; + + return false; +} diff --git a/src/shared/utf8.h b/src/shared/utf8.h index f805ea6..f1be180 100644 --- a/src/shared/utf8.h +++
[systemd-devel] [PATCH 2/2] test: test for new ellipsize_mem (requires user)
--- Makefile.am | 7 +++ src/test/test-ellipsize.c | 42 ++ 2 files changed, 49 insertions(+) create mode 100644 src/test/test-ellipsize.c diff --git a/Makefile.am b/Makefile.am index 7b7539a..0e4f58c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1125,6 +1125,7 @@ tests += \ test-unit-file \ test-util \ test-date \ + test-ellipsize \ test-sleep \ test-replace-var \ test-sched-prio \ @@ -1303,6 +1304,12 @@ test_date_SOURCES = \ test_date_LDADD = \ libsystemd-core.la +test_ellipsize_SOURCES = \ +src/test/test-wellipsize.c + +test_ellipsize_LDADD = \ +libsystemd-core.la + test_sleep_SOURCES = \ src/test/test-sleep.c diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c new file mode 100644 index 000..f6db82c --- /dev/null +++ b/src/test/test-ellipsize.c @@ -0,0 +1,42 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Shawn Landden + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see http://www.gnu.org/licenses/. +***/ + +#include stdio.h + +#include util.h +#include utf8.h + +static void test_one(const char *p) { + _cleanup_free_ char *t = NULL; + t = ellipsize(p, 80, 70); + puts(t); +} + +int main(int argc, char *argv[]) { + test_one(s??); + test_one(?); + test_one(??); + test_one(?); + test_one(); + test_one(asdfnjaskdfnklasdgnjaskdghnkasdgfklasdfjkasdfjaksdfaskldfnaskldfnaskldfnaklsdfnaklsdfnklnaskjgdknl); + +return 0; +} -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/2] util, utf8: make ellipsize and ellipsize_mem take into account multi-byte characters
rename old versions to ascii_* Do not take into account zerowidth characters, but do consider double-wide characters. Import needed utf8 helper code from glib. --- TODO | 4 -- src/shared/utf8.c | 120 ++ src/shared/utf8.h | 100 + src/shared/util.c | 77 +-- src/shared/util.h | 3 ++ 5 files changed, 296 insertions(+), 8 deletions(-) diff --git a/TODO b/TODO index 08d4914..509b31f 100644 --- a/TODO +++ b/TODO @@ -19,10 +19,6 @@ Bugfixes: * properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point. -* ellipsize_mem must take into account multi-byte unicode characters, and - - make the resulting line the requested number of *characters*, not *bytes*, - - avoid truncuating multi-byte sequences in the middle. - * When we detect invalid UTF-8, we cant't use it in an error message: log...(Path is not UTF-8 clean, ignoring assignment: %s, rvalue); diff --git a/src/shared/utf8.c b/src/shared/utf8.c index 655cc77..a9308b5 100644 --- a/src/shared/utf8.c +++ b/src/shared/utf8.c @@ -22,6 +22,11 @@ /* This file is based on the GLIB utf8 validation functions. The * original license text follows. */ +/* gunicode.h - Unicode manipulation functions + * + * Copyright (C) 1999, 2000 Tom Tromey + * Copyright 2000, 2005 Red Hat, Inc. + */ /* gutf8.c - Operations on UTF-8 strings. * * Copyright (C) 1999 Tom Tromey @@ -317,3 +322,118 @@ char *utf16_to_utf8(const void *s, size_t length) { return r; } + +/** + * g_utf8_prev_char: + * @p: a pointer to a position within a UTF-8 encoded string + * + * Finds the previous UTF-8 character in the string before @p. + * + * @p does not have to be at the beginning of a UTF-8 character. No check + * is made to see if the character found is actually valid other than + * it starts with an appropriate byte. If @p might be the first + * character of the string, you must use g_utf8_find_prev_char() instead. + * + * Return value: a pointer to the found character. + **/ +char * +utf8_prev_char (const char *p) +{ + while (1) +{ + p--; + if ((*p 0xc0) != 0x80) + return (char *)p; +} +} + +/** + * g_utf8_get_char: + * @p: a pointer to Unicode character encoded as UTF-8 + * + * Converts a sequence of bytes encoded as UTF-8 to a Unicode character. + * If @p does not point to a valid UTF-8 encoded character, results are + * undefined. If you are not sure that the bytes are complete + * valid Unicode characters, you should use g_utf8_get_char_validated() + * instead. + * + * Return value: the resulting character + **/ +unichar +utf8_get_char (const char *p) +{ + int i, mask = 0, len; + unichar result; + unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len); + if (len == -1) +return (unichar)-1; + UTF8_GET (result, p, i, mask, len); + + return result; +} + +struct Interval +{ + unichar start, end; +}; + +static int +interval_compare (const void *key, const void *elt) +{ + unichar c = (unichar) (long) (key); + struct Interval *interval = (struct Interval *)elt; + + if (c interval-start) +return -1; + if (c interval-end) +return +1; + + return 0; +} + +/* + * NOTE: + * + * The tables for g_unichar_iswide() and g_unichar_iswide_cjk() are + * generated from the Unicode Character Database's file + * extracted/DerivedEastAsianWidth.txt using the gen-iswide-table.py + * in this way: + * + * ./gen-iswide-table.py path/to/ucd/extracted/DerivedEastAsianWidth.txt | fmt + * + * Last update for Unicode 6.0. + */ + +/** + * g_unichar_iswide: + * @c: a Unicode character + * + * Determines if a character is typically rendered in a double-width + * cell. + * + * Return value: %TRUE if the character is wide + **/ +bool +unichar_iswide (unichar c) +{ + /* See NOTE earlier for how to update this table. */ + static const struct Interval wide[] = { +{0x1100, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, +{0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E}, {0x3041, 0x3096}, +{0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, +{0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x32FE}, +{0x3300, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, +{0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, +{0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, +{0x1B000, 0x1B001}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23A}, {0x1F240, +0x1F248}, {0x1F250, 0x1F251}, {0x2, 0x2FFFD}, {0x3, 0x3FFFD} + }; + + if (bsearch ((long *)c, wide, (sizeof (wide) / sizeof ((wide)[0])), sizeof wide[0], + interval_compare)) +return true; + + return false; +} diff --git a/src/shared/utf8.h b/src/shared/utf8.h index f805ea6..f1be180 100644 --- a/src/shared/utf8.h +++
[systemd-devel] [PATCH] util: preserve get_process_capeff behavior
69ab80881552d5f79ca95f6b3be48ad122ab1ec2 tried to unify parsing of status files, but removed the logic of skipping extra '0's when getting the effective capabilities. Restore that logic. --- src/shared/util.c | 16 ++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/shared/util.c b/src/shared/util.c index bf31511..b68f15c 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -694,7 +694,8 @@ int is_kernel_thread(pid_t pid) { } int get_process_capeff(pid_t pid, char **capeff) { -const char *p; +const char *p, *t; +int r; assert(capeff); assert(pid = 0); @@ -704,7 +705,18 @@ int get_process_capeff(pid_t pid, char **capeff) { else p = procfs_file_alloca(pid, status); -return get_status_field(p, \nCapEff:, capeff); +r = get_status_field(p, \nCapEff:, capeff); + +for (t = *capeff; t[0] == '0'; t++) +continue; + +if (t[0] == '\0') +t--; + +if (t != *capeff) +memmove(*capeff, t, strlen(t) + 1); + +return r; } int get_process_exe(pid_t pid, char **name) { -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] Actually fix capability logging when effective caps are 0
--- src/shared/fileio.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 8aa4cdb..3a7f84e 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -677,13 +677,11 @@ int get_status_field(const char *filename, const char *pattern, char **field) { * always maps to the same string, irrespective of the total * capability set size. For other numbers it shouldn't matter. */ -if (*t) { -t += strspn(t, WHITESPACE 0); -/* Back off one char if there's nothing but whitespace - and zeros */ -if (!*t) -t --; -} +t += strspn(t, WHITESPACE 0); +/* Back off to last '0' if there's nothing but whitespace + and zeros */ +if (*(t - 1) == '\n') +t -= 2; len = strcspn(t, WHITESPACE); -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] Actually fix capability logging when effective caps are 0
--- src/shared/fileio.c | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 8aa4cdb..3eaa911 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -673,17 +673,15 @@ int get_status_field(const char *filename, const char *pattern, char **field) { t += strlen(pattern); /* Also skip zeros, because when this is used for capabilities, - * we don't want the zeros. This way the same cabality set + * we don't want the zeros. This way the same cabability set * always maps to the same string, irrespective of the total * capability set size. For other numbers it shouldn't matter. */ -if (*t) { -t += strspn(t, WHITESPACE 0); -/* Back off one char if there's nothing but whitespace - and zeros */ -if (!*t) -t --; -} +t += strspn(t, WHITESPACE 0); +/* Back off to last '0' if there's nothing but whitespace + and zeros */ +if (*(t - 1) == '\n') +t -= 2; len = strcspn(t, WHITESPACE); -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] Actually fix capability logging when effective caps are 0
--- src/shared/fileio.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 01b803c..909a58f 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -662,6 +662,8 @@ int get_status_field(const char *filename, const char *pattern, char **field) { assert(filename); assert(field); +assert(pattern); +assert(strlen(pattern) = 2); r = read_full_file(filename, status, NULL); if (r 0) @@ -677,13 +679,11 @@ int get_status_field(const char *filename, const char *pattern, char **field) { * always maps to the same string, irrespective of the total * capability set size. For other numbers it shouldn't matter. */ -if (*t) { -t += strspn(t, WHITESPACE 0); -/* Back off one char if there's nothing but whitespace - and zeros */ -if (!*t) -t --; -} +t += strspn(t, WHITESPACE 0); +/* Back off to last '0' if there's nothing but whitespace + and zeros */ +if (*(t - 1) == '\n') +t -= 2; len = strcspn(t, WHITESPACE); -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] util, fileio: do not use get_status_field() for get_process_capeff()
Tt is in the logging hot path and has too many special needs, like skipping extra '0's. --- src/shared/fileio.c | 16 +++- src/shared/util.c | 24 +++- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 01b803c..0df5d3f 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -662,6 +662,7 @@ int get_status_field(const char *filename, const char *pattern, char **field) { assert(filename); assert(field); +assert(pattern); r = read_full_file(filename, status, NULL); if (r 0) @@ -672,20 +673,9 @@ int get_status_field(const char *filename, const char *pattern, char **field) { return -ENOENT; t += strlen(pattern); -/* Also skip zeros, because when this is used for capabilities, - * we don't want the zeros. This way the same capability set - * always maps to the same string, irrespective of the total - * capability set size. For other numbers it shouldn't matter. - */ -if (*t) { -t += strspn(t, WHITESPACE 0); -/* Back off one char if there's nothing but whitespace - and zeros */ -if (!*t) -t --; -} +t += strspn(t, \t); -len = strcspn(t, WHITESPACE); +len = strcspn(t, \n); *field = strndup(t, len); if (!*field) diff --git a/src/shared/util.c b/src/shared/util.c index bf31511..a81541e 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -695,6 +695,10 @@ int is_kernel_thread(pid_t pid) { int get_process_capeff(pid_t pid, char **capeff) { const char *p; +_cleanup_free_ char *status = NULL; +char *t = NULL; +int r; + assert(capeff); assert(pid = 0); @@ -704,7 +708,25 @@ int get_process_capeff(pid_t pid, char **capeff) { else p = procfs_file_alloca(pid, status); -return get_status_field(p, \nCapEff:, capeff); +r = read_full_file(p, status, NULL); +if (r 0) +return r; + +t = strstr(status, \nCapEff:\t); +if (!t) +return -ENOENT; + +for (t += strlen(\nCapEff:\t); t[0] == '0'; t++) +continue; + +if (t[0] == '\n') +t--; + +*capeff = strndup(t, (char *)rawmemchr(t, '\n') - t); +if (!*capeff) +return -ENOMEM; + +return 0; } int get_process_exe(pid_t pid, char **name) { -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] util, fileio: do not use get_status_field() for get_process_capeff()
On Thu, Sep 19, 2013 at 11:58 AM, David Strauss da...@davidstrauss.net wrote: Does this supersede your earlier patch for get_status_field()? Yes. I tried to optimize the previous patch, and realized it is not really possible without splitting back out the capeff handling, which is the one where performance matters, because it gets called every time we log a message. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/2] util, utf8: make ellipsize and ellipsize_mem take into account multi-byte characters
rename old versions to ascii_* Do not take into account zerowidth characters, but do consider double-wide characters. Import needed utf8 helper code from glib. v3: rebase ontop of utf8 restructuring work --- TODO | 4 -- src/shared/utf8.c | 120 ++ src/shared/utf8.h | 100 + src/shared/util.c | 70 ++- src/shared/util.h | 3 ++ 5 files changed, 292 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index 01bc993..c54e986 100644 --- a/TODO +++ b/TODO @@ -19,10 +19,6 @@ Bugfixes: * properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point. -* ellipsize_mem must take into account multi-byte unicode characters, and - - make the resulting line the requested number of *characters*, not *bytes*, - - avoid truncuating multi-byte sequences in the middle. - * When we detect invalid UTF-8, we cant't use it in an error message: log...(Path is not UTF-8 clean, ignoring assignment: %s, rvalue); diff --git a/src/shared/utf8.c b/src/shared/utf8.c index c3d97cc..2b07265 100644 --- a/src/shared/utf8.c +++ b/src/shared/utf8.c @@ -22,6 +22,11 @@ /* This file is based on the GLIB utf8 validation functions. The * original license text follows. */ +/* gunicode.h - Unicode manipulation functions + * + * Copyright (C) 1999, 2000 Tom Tromey + * Copyright 2000, 2005 Red Hat, Inc. + */ /* gutf8.c - Operations on UTF-8 strings. * * Copyright (C) 1999 Tom Tromey @@ -285,3 +290,118 @@ int utf8_encoded_valid_unichar(const char *str) { return len; } + +/** + * g_utf8_prev_char: + * @p: a pointer to a position within a UTF-8 encoded string + * + * Finds the previous UTF-8 character in the string before @p. + * + * @p does not have to be at the beginning of a UTF-8 character. No check + * is made to see if the character found is actually valid other than + * it starts with an appropriate byte. If @p might be the first + * character of the string, you must use g_utf8_find_prev_char() instead. + * + * Return value: a pointer to the found character. + **/ +char * +utf8_prev_char (const char *p) +{ + while (1) +{ + p--; + if ((*p 0xc0) != 0x80) +return (char *)p; +} +} + +/** + * g_utf8_get_char: + * @p: a pointer to Unicode character encoded as UTF-8 + * + * Converts a sequence of bytes encoded as UTF-8 to a Unicode character. + * If @p does not point to a valid UTF-8 encoded character, results are + * undefined. If you are not sure that the bytes are complete + * valid Unicode characters, you should use g_utf8_get_char_validated() + * instead. + * + * Return value: the resulting character + **/ +unichar +utf8_get_char (const char *p) +{ + int i, mask = 0, len; + unichar result; + unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len); + if (len == -1) +return (unichar)-1; + UTF8_GET (result, p, i, mask, len); + + return result; +} + +struct Interval +{ + unichar start, end; +}; + +static int +interval_compare (const void *key, const void *elt) +{ + unichar c = (unichar) (long) (key); + struct Interval *interval = (struct Interval *)elt; + + if (c interval-start) +return -1; + if (c interval-end) +return +1; + + return 0; +} + +/* + * NOTE: + * + * The tables for g_unichar_iswide() and g_unichar_iswide_cjk() are + * generated from the Unicode Character Database's file + * extracted/DerivedEastAsianWidth.txt using the gen-iswide-table.py + * in this way: + * + * ./gen-iswide-table.py path/to/ucd/extracted/DerivedEastAsianWidth.txt | fmt + * + * Last update for Unicode 6.0. + */ + +/** + * g_unichar_iswide: + * @c: a Unicode character + * + * Determines if a character is typically rendered in a double-width + * cell. + * + * Return value: %TRUE if the character is wide + **/ +bool +unichar_iswide (unichar c) +{ + /* See NOTE earlier for how to update this table. */ + static const struct Interval wide[] = { +{0x1100, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, +{0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E}, {0x3041, 0x3096}, +{0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, +{0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x32FE}, +{0x3300, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, +{0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, +{0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, +{0x1B000, 0x1B001}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23A}, {0x1F240, +0x1F248}, {0x1F250, 0x1F251}, {0x2, 0x2FFFD}, {0x3, 0x3FFFD} + }; + + if (bsearch ((long *)c, wide, (sizeof (wide) / sizeof ((wide)[0])), sizeof wide[0], + interval_compare)) +return true; + + return false; +} diff --git a/src/shared/utf8.h b/src/shared/utf8.h index
[systemd-devel] [PATCH 2/2] test: test for ellipsize (manual)
--- Makefile.am | 7 +++ src/test/test-ellipsize.c | 42 ++ 2 files changed, 49 insertions(+) create mode 100644 src/test/test-ellipsize.c diff --git a/Makefile.am b/Makefile.am index 89a5c86..802f6eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1114,6 +1114,7 @@ manual_tests += \ test-cgroup \ test-install \ test-watchdog \ + test-ellipsize \ test-log tests += \ @@ -1319,6 +1320,12 @@ test_log_SOURCES = \ test_log_LDADD = \ libsystemd-core.la +test_ellipsize_SOURCES = \ + src/test/test-ellipsize.c + +test_ellipsize_LDADD = \ + libsystemd-core.la + test_date_SOURCES = \ src/test/test-date.c diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c new file mode 100644 index 000..fab5e4b --- /dev/null +++ b/src/test/test-ellipsize.c @@ -0,0 +1,42 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Shawn Landden + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see http://www.gnu.org/licenses/. +***/ + +#include stdio.h + +#include util.h +#include utf8.h + +static void test_one(const char *p) { +_cleanup_free_ char *t = NULL; +t = ellipsize(p, 80, 70); +puts(t); +} + +int main(int argc, char *argv[]) { + test_one(??); + test_one(-?); + test_one(-??); +test_one(s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md s??st??md); + test_one(); +test_one(Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.); + +return 0; +} -- 1.8.4.rc3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] util: preserve get_process_capeff behavior
On Thu, Sep 19, 2013 at 2:40 PM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Thu, Sep 19, 2013 at 10:28:40AM -0700, Shawn Landden wrote: We can't optimize the strcspn(t, WHITESPACE); to a strchr(t, '\n') - t; because of the kB that meminfo and a few other places have, that we want to drop. get_status_field() has to be run every time we log a message, and I am starting to not like this function at all. I think we should go back to having it hand-rolled in get_process_capeff(), at least for that one in the hot-path. Hi Shawn, I think there's value in having one function to parse /proc/self/status. I pushed some tests and a simple fix to avoid backtracking. It wasn't backtracking more than it has already gone forward. I even had an assert for this, anyways, the current version is correct. Anyway, this parsing might be going away, once we start using the equivalent of SCM_CREDENTIALS for capabilities, That requires a kernel patch, meanwhile we will have compatibility code for old kernels...I think my optimized version still makes sense, although something like SCM_CREDIENTIALS would certainly be more optimized. so I don't think it makes sense to optimize it at this point. Zbyszek -- --- Shawn Landden +1 360 389 3001 (SMS preferred) ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [ANNOUNCE] systemd 208
Ott, Tom Gundersen, Zbigniew Jędrzejewski-Szmek -- Berlin, 2013-10-02 Lennart -- Lennart Poettering - Red Hat, Inc. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- --- Shawn Landden +1 360 389 3001 (SMS preferred) ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 3/3] core: support Distribute=n to distribute to n SO_REUSEPORT workers
--- TODO | 3 +- src/core/dbus-socket.c| 2 ++ src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/service.c| 2 +- src/core/service.h| 13 +++- src/core/socket.c | 63 +++ src/core/socket.h | 2 ++ 7 files changed, 82 insertions(+), 4 deletions(-) diff --git a/TODO b/TODO index efc7e2a..0db4dc6 100644 --- a/TODO +++ b/TODO @@ -80,7 +80,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* respawn Distribute= worker threads when they die unexpectedly * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it @@ -259,7 +259,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 60a8d05..4644007 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -68,6 +68,7 @@ property name=\Listen\ type=\a(ss)\ access=\read\/\n\ property name=\Result\ type=\s\ access=\read\/\n\ property name=\ReusePort\ type=\b\ access=\read\/\n \ + property name=\Distribute\ type=\u\ access=\read\/\n \ property name=\SmackLabel\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPIn\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPOut\ type=\s\ access=\read\/\n \ @@ -196,6 +197,7 @@ static const BusProperty bus_socket_properties[] = { { MessageQueueMessageSize, bus_property_append_long, x, offsetof(Socket, mq_msgsize) }, { Result, bus_socket_append_socket_result, s, offsetof(Socket, result) }, { ReusePort, bus_property_append_bool, b, offsetof(Socket, reuseport) }, +{ Distribute, bus_property_append_unsigned, u, offsetof(Socket, distribute) }, { SmackLabel, bus_property_append_string,s, offsetof(Socket, smack), true }, { SmackLabelIPIn, bus_property_append_string,s, offsetof(Socket, smack_ip_in),true }, { SmackLabelIPOut,bus_property_append_string,s, offsetof(Socket, smack_ip_out), true }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index b64fdc9..4058a1f 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -211,6 +211,7 @@ Socket.PassCredentials, config_parse_bool, 0, Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) +Socket.Distribute, config_parse_unsigned, 0, offsetof(Socket, distribute) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.Service, config_parse_socket_service,0, 0 diff --git a/src/core/service.c b/src/core/service.c index 3da32a1..cc337cf 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1668,7 +1668,7 @@ fail: return r; } -static int service_spawn( +int service_spawn( Service *s, ExecCommand *c, bool timeout, diff --git a/src/core/service.h b/src/core/service.h index 37fa6ff..95aa707 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -26,7 +26,6 @@ typedef struct Service Service; #include unit.h #include path.h #include ratelimit.h -#include service.h #include kill.h #include exit-status.h @@ -201,6 +200,18 @@ extern const UnitVTable service_vtable; struct Socket; +int service_spawn( +Service *s, +ExecCommand *c, +bool timeout, +bool pass_fds, +bool apply_permissions, +bool apply_chroot, +bool apply_tty_stdin, +bool set_notify_socket, +bool
[systemd-devel] [PATCH 2/3] core/socket: fix SO_REUSEPORT
--- src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/socket.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index e3025d2..b64fdc9 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -210,6 +210,7 @@ Socket.Broadcast,config_parse_bool, 0, Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred) Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) +Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.Service, config_parse_socket_service,0, 0 diff --git a/src/core/socket.c b/src/core/socket.c index f505e4f..751f20b 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -771,7 +771,7 @@ static void socket_apply_socket_options(Socket *s, int fd) { if (s-reuseport) { int b = s-reuseport; -if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, b, sizeof(b))) +if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, b, sizeof(b)) 0) log_warning_unit(UNIT(s)-id, SO_REUSEPORT failed: %m); } -- 1.8.4.3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] core: support Distribute=n to distribute to n SO_REUSEPORT workers
Should SERVICE_SIMPLE test be a load-time test? v2 fix assert order --- TODO | 3 +- src/core/dbus-socket.c| 2 ++ src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/service.c| 2 +- src/core/service.h| 13 ++- src/core/socket.c | 64 +++ src/core/socket.h | 2 ++ 7 files changed, 83 insertions(+), 4 deletions(-) diff --git a/TODO b/TODO index efc7e2a..0db4dc6 100644 --- a/TODO +++ b/TODO @@ -80,7 +80,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* respawn Distribute= worker threads when they die unexpectedly * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it @@ -259,7 +259,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 60a8d05..4644007 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -68,6 +68,7 @@ property name=\Listen\ type=\a(ss)\ access=\read\/\n\ property name=\Result\ type=\s\ access=\read\/\n\ property name=\ReusePort\ type=\b\ access=\read\/\n \ + property name=\Distribute\ type=\u\ access=\read\/\n \ property name=\SmackLabel\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPIn\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPOut\ type=\s\ access=\read\/\n \ @@ -196,6 +197,7 @@ static const BusProperty bus_socket_properties[] = { { MessageQueueMessageSize, bus_property_append_long, x, offsetof(Socket, mq_msgsize) }, { Result, bus_socket_append_socket_result, s, offsetof(Socket, result) }, { ReusePort, bus_property_append_bool, b, offsetof(Socket, reuseport) }, +{ Distribute, bus_property_append_unsigned, u, offsetof(Socket, distribute) }, { SmackLabel, bus_property_append_string,s, offsetof(Socket, smack), true }, { SmackLabelIPIn, bus_property_append_string,s, offsetof(Socket, smack_ip_in),true }, { SmackLabelIPOut,bus_property_append_string,s, offsetof(Socket, smack_ip_out), true }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index b64fdc9..4058a1f 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -211,6 +211,7 @@ Socket.PassCredentials, config_parse_bool, 0, Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) +Socket.Distribute, config_parse_unsigned, 0, offsetof(Socket, distribute) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.Service, config_parse_socket_service,0, 0 diff --git a/src/core/service.c b/src/core/service.c index 3da32a1..cc337cf 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1668,7 +1668,7 @@ fail: return r; } -static int service_spawn( +int service_spawn( Service *s, ExecCommand *c, bool timeout, diff --git a/src/core/service.h b/src/core/service.h index 37fa6ff..95aa707 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -26,7 +26,6 @@ typedef struct Service Service; #include unit.h #include path.h #include ratelimit.h -#include service.h #include kill.h #include exit-status.h @@ -201,6 +200,18 @@ extern const UnitVTable service_vtable; struct Socket; +int service_spawn( +Service *s, +ExecCommand *c, +bool timeout, +bool pass_fds, +bool apply_permissions, +bool apply_chroot, +bool apply_tty_stdin, +
[systemd-devel] [PATCH 1/2] core: support Distribute=n to distribute to n SO_REUSEPORT workers
v3 make each worker its own service --- TODO | 3 +- man/systemd.socket.xml| 9 +++ src/core/dbus-socket.c| 2 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/service.c| 7 +- src/core/service.h| 1 - src/core/socket.c | 124 -- src/core/socket.h | 4 ++ 8 files changed, 96 insertions(+), 55 deletions(-) diff --git a/TODO b/TODO index 57e1122..733e528 100644 --- a/TODO +++ b/TODO @@ -82,7 +82,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* respawn Distribute= worker threads when they die unexpectedly * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it @@ -261,7 +261,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..92a9275 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -519,6 +519,15 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. If greater than one, systemd will spawn +given number of instances of service each +listening to the same socket. This option implies +varnameReuseport=/varname above./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 60a8d05..4644007 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -68,6 +68,7 @@ property name=\Listen\ type=\a(ss)\ access=\read\/\n\ property name=\Result\ type=\s\ access=\read\/\n\ property name=\ReusePort\ type=\b\ access=\read\/\n \ + property name=\Distribute\ type=\u\ access=\read\/\n \ property name=\SmackLabel\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPIn\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPOut\ type=\s\ access=\read\/\n \ @@ -196,6 +197,7 @@ static const BusProperty bus_socket_properties[] = { { MessageQueueMessageSize, bus_property_append_long, x, offsetof(Socket, mq_msgsize) }, { Result, bus_socket_append_socket_result, s, offsetof(Socket, result) }, { ReusePort, bus_property_append_bool, b, offsetof(Socket, reuseport) }, +{ Distribute, bus_property_append_unsigned, u, offsetof(Socket, distribute) }, { SmackLabel, bus_property_append_string,s, offsetof(Socket, smack), true }, { SmackLabelIPIn, bus_property_append_string,s, offsetof(Socket, smack_ip_in),true }, { SmackLabelIPOut,bus_property_append_string,s, offsetof(Socket, smack_ip_out), true }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index b64fdc9..4058a1f 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -211,6 +211,7 @@ Socket.PassCredentials, config_parse_bool, 0, Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) +Socket.Distribute, config_parse_unsigned, 0, offsetof(Socket, distribute) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.Service, config_parse_socket_service,
[systemd-devel] [PATCH 2/2] core: lazy distribute for Distribute pools
--- man/systemd.socket.xml| 9 + src/core/dbus-socket.c| 2 ++ src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/socket.c | 7 ++- src/core/socket.h | 1 + 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 92a9275..327c098 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -528,6 +528,15 @@ /varlistentry varlistentry +termvarnameLazyDistribute=/varname/term +listitemparaTakes an boolean +value. If true, Distribute=n workers will not be spawned +simultameously, but one at a time while connections come it +until n are running. Because of the nature of SO_REUSEPORT workers are +spawned at an exponentially decreasing rate to the number of incoming connections./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 4644007..4e2a31d 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -69,6 +69,7 @@ property name=\Result\ type=\s\ access=\read\/\n\ property name=\ReusePort\ type=\b\ access=\read\/\n \ property name=\Distribute\ type=\u\ access=\read\/\n \ + property name=\LazyDistribute\ type=\b\ access=\read\/\n \ property name=\SmackLabel\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPIn\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPOut\ type=\s\ access=\read\/\n \ @@ -198,6 +199,7 @@ static const BusProperty bus_socket_properties[] = { { Result, bus_socket_append_socket_result, s, offsetof(Socket, result) }, { ReusePort, bus_property_append_bool, b, offsetof(Socket, reuseport) }, { Distribute, bus_property_append_unsigned, u, offsetof(Socket, distribute) }, +{ LazyDistribute, bus_property_append_bool, b, offsetof(Socket, lazy_distribute) }, { SmackLabel, bus_property_append_string,s, offsetof(Socket, smack), true }, { SmackLabelIPIn, bus_property_append_string,s, offsetof(Socket, smack_ip_in),true }, { SmackLabelIPOut,bus_property_append_string,s, offsetof(Socket, smack_ip_out), true }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 4058a1f..a023b0e 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -212,6 +212,7 @@ Socket.PassSecurity, config_parse_bool, 0, Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) Socket.Distribute, config_parse_unsigned, 0, offsetof(Socket, distribute) +Socket.LazyDistribute, config_parse_bool, 0, offsetof(Socket, lazy_distribute) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.Service, config_parse_socket_service,0, 0 diff --git a/src/core/socket.c b/src/core/socket.c index 10a0d95..c968902 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -514,6 +514,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { %sDistribute: %d\n, prefix, s-distribute); +if (s-lazy_distribute) +fprintf(f, +%sLazyDistribute: %s\n, + prefix, yes_no(s-lazy_distribute)); + if (s-smack) fprintf(f, %sSmackLabel: %s\n, @@ -1554,7 +1559,7 @@ static void socket_enter_running(Socket *s, int cfd) { socket_enter_listening(s); } -} while(s-distribute s-n_connections); +} while(s-distribute s-n_connections !(s-lazy_distribute)); /* Notify clients about changed counters */
[systemd-devel] [PATCH] core: support Distribute=n to distribute to n SO_REUSEPORT workers
v3: make each worker its own service v4: be less intrusive --- TODO | 3 - man/systemd.socket.xml| 9 +++ src/core/dbus-socket.c| 2 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/service.c| 7 ++- src/core/service.h| 1 - src/core/socket.c | 114 -- src/core/socket.h | 4 ++ 8 files changed, 86 insertions(+), 55 deletions(-) diff --git a/TODO b/TODO index 57e1122..38cdf5d 100644 --- a/TODO +++ b/TODO @@ -82,8 +82,6 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances - * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it * we probably should replace the left-over uses of strv_append() and replace them by strv_push() or strv_extend() @@ -261,7 +259,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..92a9275 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -519,6 +519,15 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. If greater than one, systemd will spawn +given number of instances of service each +listening to the same socket. This option implies +varnameReuseport=/varname above./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 60a8d05..4644007 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -68,6 +68,7 @@ property name=\Listen\ type=\a(ss)\ access=\read\/\n\ property name=\Result\ type=\s\ access=\read\/\n\ property name=\ReusePort\ type=\b\ access=\read\/\n \ + property name=\Distribute\ type=\u\ access=\read\/\n \ property name=\SmackLabel\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPIn\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPOut\ type=\s\ access=\read\/\n \ @@ -196,6 +197,7 @@ static const BusProperty bus_socket_properties[] = { { MessageQueueMessageSize, bus_property_append_long, x, offsetof(Socket, mq_msgsize) }, { Result, bus_socket_append_socket_result, s, offsetof(Socket, result) }, { ReusePort, bus_property_append_bool, b, offsetof(Socket, reuseport) }, +{ Distribute, bus_property_append_unsigned, u, offsetof(Socket, distribute) }, { SmackLabel, bus_property_append_string,s, offsetof(Socket, smack), true }, { SmackLabelIPIn, bus_property_append_string,s, offsetof(Socket, smack_ip_in),true }, { SmackLabelIPOut,bus_property_append_string,s, offsetof(Socket, smack_ip_out), true }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index b64fdc9..4058a1f 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -211,6 +211,7 @@ Socket.PassCredentials, config_parse_bool, 0, Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) +Socket.Distribute, config_parse_unsigned, 0, offsetof(Socket, distribute) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket,
[systemd-devel] [PATCH 1/4] core/socket: use _cleanup_free_
--- src/core/socket.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/core/socket.c b/src/core/socket.c index 03b8f92..f505e4f 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1475,7 +1475,7 @@ static void socket_enter_running(Socket *s, int cfd) { socket_set_state(s, SOCKET_RUNNING); } else { -char *prefix, *instance = NULL, *name; +_cleanup_free_ char *prefix = NULL, *instance = NULL, *name = NULL; Service *service; if (s-n_connections = s-max_connections) { @@ -1503,14 +1503,11 @@ static void socket_enter_running(Socket *s, int cfd) { prefix = unit_name_to_prefix(UNIT(s)-id); if (!prefix) { -free(instance); r = -ENOMEM; goto fail; } name = unit_name_build(prefix, instance, .service); -free(prefix); -free(instance); if (!name) { r = -ENOMEM; @@ -1518,10 +1515,8 @@ static void socket_enter_running(Socket *s, int cfd) { } r = unit_add_name(UNIT_DEREF(s-service), name); -if (r 0) { -free(name); +if (r 0) goto fail; -} service = SERVICE(UNIT_DEREF(s-service)); unit_ref_unset(s-service); @@ -1530,7 +1525,6 @@ static void socket_enter_running(Socket *s, int cfd) { UNIT(service)-no_gc = false; unit_choose_id(UNIT(service), name); -free(name); r = service_set_socket_fd(service, cfd, s); if (r 0) -- 1.8.4.3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 3/4] core: support Distribute=n to distribute to n SO_REUSEPORT workers
v3: make each worker its own service v4: be less intrusive v5: misc fixups --- TODO | 3 - man/systemd.socket.xml| 11 src/core/dbus-socket.c| 2 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/service.c| 7 +- src/core/service.h| 1 - src/core/socket.c | 119 +++--- src/core/socket.h | 4 ++ 8 files changed, 89 insertions(+), 59 deletions(-) diff --git a/TODO b/TODO index efc7e2a..6067efb 100644 --- a/TODO +++ b/TODO @@ -80,8 +80,6 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances - * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it * we probably should replace the left-over uses of strv_append() and replace them by strv_push() or strv_extend() @@ -259,7 +257,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..4a2189b 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -519,6 +519,17 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. Systemd will spawn +given number of instances of service each +listening to the same socket. Default is 0. +Setting this requires corresponding service to +be an instansiated service (name ends with literal@.service/literal). +This option implies varnameReuseport=/varname above./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 60a8d05..4644007 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -68,6 +68,7 @@ property name=\Listen\ type=\a(ss)\ access=\read\/\n\ property name=\Result\ type=\s\ access=\read\/\n\ property name=\ReusePort\ type=\b\ access=\read\/\n \ + property name=\Distribute\ type=\u\ access=\read\/\n \ property name=\SmackLabel\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPIn\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPOut\ type=\s\ access=\read\/\n \ @@ -196,6 +197,7 @@ static const BusProperty bus_socket_properties[] = { { MessageQueueMessageSize, bus_property_append_long, x, offsetof(Socket, mq_msgsize) }, { Result, bus_socket_append_socket_result, s, offsetof(Socket, result) }, { ReusePort, bus_property_append_bool, b, offsetof(Socket, reuseport) }, +{ Distribute, bus_property_append_unsigned, u, offsetof(Socket, distribute) }, { SmackLabel, bus_property_append_string,s, offsetof(Socket, smack), true }, { SmackLabelIPIn, bus_property_append_string,s, offsetof(Socket, smack_ip_in),true }, { SmackLabelIPOut,bus_property_append_string,s, offsetof(Socket, smack_ip_out), true }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index b64fdc9..4058a1f 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -211,6 +211,7 @@ Socket.PassCredentials, config_parse_bool, 0, Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) +Socket.Distribute, config_parse_unsigned, 0, offsetof(Socket, distribute) Socket.MessageQueueMaxMessages, config_parse_long,
[systemd-devel] [PATCH 4/4] core: lazy distribute for Distribute pools
--- man/systemd.socket.xml| 9 + src/core/dbus-socket.c| 2 ++ src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/socket.c | 7 ++- src/core/socket.h | 1 + 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 4a2189b..fd6ec69 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -530,6 +530,15 @@ /varlistentry varlistentry +termvarnameLazyDistribute=/varname/term +listitemparaTakes an boolean +value. If true, Distribute=n workers will not be spawned +simultameously, but one at a time while connections come it +until n are running. Because of the nature of SO_REUSEPORT workers are +spawned at an exponentially decreasing rate to the number of incoming connections./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 4644007..4e2a31d 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -69,6 +69,7 @@ property name=\Result\ type=\s\ access=\read\/\n\ property name=\ReusePort\ type=\b\ access=\read\/\n \ property name=\Distribute\ type=\u\ access=\read\/\n \ + property name=\LazyDistribute\ type=\b\ access=\read\/\n \ property name=\SmackLabel\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPIn\ type=\s\ access=\read\/\n \ property name=\SmackLabelIPOut\ type=\s\ access=\read\/\n \ @@ -198,6 +199,7 @@ static const BusProperty bus_socket_properties[] = { { Result, bus_socket_append_socket_result, s, offsetof(Socket, result) }, { ReusePort, bus_property_append_bool, b, offsetof(Socket, reuseport) }, { Distribute, bus_property_append_unsigned, u, offsetof(Socket, distribute) }, +{ LazyDistribute, bus_property_append_bool, b, offsetof(Socket, lazy_distribute) }, { SmackLabel, bus_property_append_string,s, offsetof(Socket, smack), true }, { SmackLabelIPIn, bus_property_append_string,s, offsetof(Socket, smack_ip_in),true }, { SmackLabelIPOut,bus_property_append_string,s, offsetof(Socket, smack_ip_out), true }, diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 4058a1f..a023b0e 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -212,6 +212,7 @@ Socket.PassSecurity, config_parse_bool, 0, Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) Socket.Distribute, config_parse_unsigned, 0, offsetof(Socket, distribute) +Socket.LazyDistribute, config_parse_bool, 0, offsetof(Socket, lazy_distribute) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.Service, config_parse_socket_service,0, 0 diff --git a/src/core/socket.c b/src/core/socket.c index 4d4627a..a85ae88 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -514,6 +514,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { %sDistribute: %d\n, prefix, s-distribute); +if (s-lazy_distribute) +fprintf(f, +%sLazyDistribute: %s\n, + prefix, yes_no(s-lazy_distribute)); + if (s-smack) fprintf(f, %sSmackLabel: %s\n, @@ -1545,7 +1550,7 @@ static void socket_enter_running(Socket *s, int cfd) { if (s-n_connections s-distribute) socket_enter_listening(s); -} while (s-n_connections s-distribute); +} while (s-n_connections s-distribute !(s-lazy_distribute)); /* Notify
[systemd-devel] [PATCH 2/4] core/socket: fix SO_REUSEPORT
--- src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/socket.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index e3025d2..b64fdc9 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -210,6 +210,7 @@ Socket.Broadcast,config_parse_bool, 0, Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred) Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,config_parse_string,0, offsetof(Socket, tcp_congestion) +Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuseport) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) Socket.Service, config_parse_socket_service,0, 0 diff --git a/src/core/socket.c b/src/core/socket.c index f505e4f..751f20b 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -771,7 +771,7 @@ static void socket_apply_socket_options(Socket *s, int fd) { if (s-reuseport) { int b = s-reuseport; -if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, b, sizeof(b))) +if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, b, sizeof(b)) 0) log_warning_unit(UNIT(s)-id, SO_REUSEPORT failed: %m); } -- 1.8.4.3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH 4/4] core: lazy distribute for Distribute pools
On Sun, Nov 17, 2013 at 2:28 PM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Sun, Nov 17, 2013 at 08:46:46PM +0100, Lennart Poettering wrote: On Sat, 16.11.13 13:18, Shawn Landden (sh...@churchofgit.com) wrote: varlistentry + termvarnameLazyDistribute=/varname/term +listitemparaTakes an boolean +value. If true, Distribute=n workers will not be spawned +simultameously, but one at a time while connections come it +until n are running. Because of the nature of SO_REUSEPORT workers are +spawned at an exponentially decreasing rate to the number of incoming connections./para/listitem +/varlistentry + +varlistentry Hmm, so I think support for SO_REUSEPORT should just be a special case of the Distribute= logic. i.e. When Distribute= is set but ReusePort is off, then we'd pass the same original listening socket to all services we spawn. If Distribute is set but ReusePort is on then we'd create a new socket when we want to spawn a new instance, and simply bind it to the same sockaddr as the original one. What types of sockets allow multiple bind()s/accept()s without SO_REUSEPORT? I don't see what the use is having a socket passed to children that can't be used. Thinking about this: I have the suspicion that LazyDistribute shouldn't be an option but the normal and only behaviour... Agreed. OK Also, I think ReusePort=1 should be the default if Distribute is used, and the kernel supports it. I don't think there are any downsides. ReusePort=1 makes it where systemd no longer sits on the port which prevents rogue applications (root for 1024) from stealing the port. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- --- Shawn Landden +1 360 389 3001 (SMS preferred) ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] use #pragma once instead of foo*foo define guards
--- src/core/killall.h | 5 + src/core/switch-root.h | 5 + src/core/syscall-list.h | 5 + src/core/transaction.h | 5 + src/login/logind-action.h | 5 + src/login/logind-button.h | 5 + src/login/logind-inhibit.h | 5 + src/nss-myhostname/ifconf.h | 9 ++--- src/shared/audit.h | 5 + src/shared/capability.h | 5 + src/shared/cgroup-show.h| 5 + src/shared/conf-files.h | 5 + src/shared/hwclock.h| 5 + src/shared/spawn-polkit-agent.h | 5 + 14 files changed, 15 insertions(+), 59 deletions(-) diff --git a/src/core/killall.h b/src/core/killall.h index d08ac14..95b110f 100644 --- a/src/core/killall.h +++ b/src/core/killall.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef fookillallhfoo -#define fookillallhfoo +#pragma once /*** This file is part of systemd. @@ -23,5 +22,3 @@ ***/ void broadcast_signal(int sig, bool wait); - -#endif diff --git a/src/core/switch-root.h b/src/core/switch-root.h index 0c4cd1e..ab493b5 100644 --- a/src/core/switch-root.h +++ b/src/core/switch-root.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef fooswitchroothfoo -#define fooswitchroothfoo +#pragma once /*** This file is part of systemd. @@ -23,5 +22,3 @@ ***/ int switch_root(const char *switch_root); - -#endif diff --git a/src/core/syscall-list.h b/src/core/syscall-list.h index 6bb4d91..37efc56 100644 --- a/src/core/syscall-list.h +++ b/src/core/syscall-list.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef foosyscalllisthfoo -#define foosyscalllisthfoo +#pragma once /*** This file is part of systemd. @@ -40,5 +39,3 @@ const char *syscall_to_name(int id); int syscall_from_name(const char *name); int syscall_max(void); - -#endif diff --git a/src/core/transaction.h b/src/core/transaction.h index 12f9194..b6ee237 100644 --- a/src/core/transaction.h +++ b/src/core/transaction.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef footransactionhfoo -#define footransactionhfoo +#pragma once /*** This file is part of systemd. @@ -53,5 +52,3 @@ int transaction_add_job_and_dependencies( int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e); int transaction_add_isolate_jobs(Transaction *tr, Manager *m); void transaction_abort(Transaction *tr); - -#endif diff --git a/src/login/logind-action.h b/src/login/logind-action.h index 5527136..74f7144 100644 --- a/src/login/logind-action.h +++ b/src/login/logind-action.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef foologindactionhfoo -#define foologindactionhfoo +#pragma once /*** This file is part of systemd. @@ -50,5 +49,3 @@ const char* handle_action_to_string(HandleAction h) _const_; HandleAction handle_action_from_string(const char *s) _pure_; int config_parse_handle_action(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); - -#endif diff --git a/src/login/logind-button.h b/src/login/logind-button.h index 83bf1fc..824106c 100644 --- a/src/login/logind-button.h +++ b/src/login/logind-button.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef foologindbuttonhfoo -#define foologindbuttonhfoo +#pragma once /*** This file is part of systemd. @@ -45,5 +44,3 @@ void button_free(Button*b); int button_open(Button *b); int button_recheck(Button *b); int button_set_seat(Button *b, const char *sn); - -#endif diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h index ed3b2eb..da3d7e7 100644 --- a/src/login/logind-inhibit.h +++ b/src/login/logind-inhibit.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef foologindinhibithfoo -#define foologindinhibithfoo +#pragma once /*** This file is part of systemd. @@ -93,5 +92,3 @@ InhibitWhat inhibit_what_from_string(const char *s); const char *inhibit_mode_to_string(InhibitMode k); InhibitMode inhibit_mode_from_string(const char *s); - -#endif diff --git a/src/nss-myhostname/ifconf.h b/src/nss-myhostname/ifconf.h index 2764a0a..cd598d2 100644 --- a/src/nss-myhostname/ifconf.h +++ b/src/nss-myhostname/ifconf.h @@ -1,9 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef fooifconfhfoo -#define fooifconfhfoo - -#include sys/socket.h +#pragma once /*** This file is part of systemd. @@ -27,6 +24,7 @@ #include inttypes.h #include sys/types.h #include assert.h +#include sys/socket.h struct address { unsigned char family; @@ -68,6 +66,3 @@ static inline int address_compare(const void *_a, const void *_b) { return 0; } - - -#endif diff --git
[systemd-devel] [PATCH] service: remove unneccesary Socket.got_socket_fd
--- src/core/service.c | 3 +-- src/core/service.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index c0ee114..24f7a42 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2812,7 +2812,7 @@ _pure_ static bool service_check_snapshot(Unit *u) { assert(s); -return !s-got_socket_fd; +return (s-socket_fd 0); } static int service_retry_pid_file(Service *s) { @@ -3695,7 +3695,6 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock) { return -EAGAIN; s-socket_fd = fd; -s-got_socket_fd = true; unit_ref_set(s-accept_socket, UNIT(sock)); diff --git a/src/core/service.h b/src/core/service.h index 37fa6ff..40c3a85 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -26,7 +26,6 @@ typedef struct Service Service; #include unit.h #include path.h #include ratelimit.h -#include service.h #include kill.h #include exit-status.h @@ -170,7 +169,6 @@ struct Service { bool main_pid_alien:1; bool bus_name_good:1; bool forbid_restart:1; -bool got_socket_fd:1; bool start_timeout_defined:1; #ifdef HAVE_SYSV_COMPAT bool is_sysv:1; -- 1.8.4.3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 2/2] systemctl: add systemctl cat
--- TODO | 2 -- src/shared/fileio.c | 73 - src/shared/fileio.h | 1 + src/systemctl/systemctl.c | 91 +++ 4 files changed, 149 insertions(+), 18 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 576396f..18d5e45 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,16 +3665,25 @@ static int show_all( return 0; } -static int get_unit_from_arg(sd_bus *bus, char *arg, char **unitp, bool interpret_as_job_id) { -uint32_t id; +static int cat(sd_bus *bus, char **args) { int r = 0; +char **name; -if (safe_atou32(arg, id) 0) { -_cleanup_free_ char *n = NULL; -char *unit; -/* Interpret as unit name */ +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); -n = unit_name_mangle(arg); +pager_open_if_enabled(); + +STRV_FOREACH(name, args+1) { +_cleanup_free_ char *fragment_path = NULL; +_cleanup_strv_free_ char **dropin_paths = NULL; +sd_bus_error error; +FILE *stdout; +char **path; + +n = unit_name_mangle(*name); if (!n)
[systemd-devel] [PATCH 1/2] systemctl: refactor show()
--- src/systemctl/systemctl.c | 66 ++- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 84826a3..576396f 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3594,16 +3594,13 @@ static int show_one( return r; } -static int show_one_by_pid( -const char *verb, +static int get_unit_dbus_path_by_pid( sd_bus *bus, uint32_t pid, -bool *new_line, -bool *ellipsized) { +char **unit) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; -const char *path = NULL; int r; r = sd_bus_call_method( @@ -3620,11 +3617,11 @@ static int show_one_by_pid( return r; } -r = sd_bus_message_read(reply, o, path); +r = sd_bus_message_read(reply, o, unit); if (r 0) return bus_log_parse_error(r); -return show_one(verb, bus, path, false, new_line, ellipsized); +return 0; } static int show_all( @@ -3668,6 +3665,36 @@ static int show_all( return 0; } +static int get_unit_from_arg(sd_bus *bus, char *arg, char **unitp, bool interpret_as_job_id) { +uint32_t id; +int r = 0; + +if (safe_atou32(arg, id) 0) { +_cleanup_free_ char *n = NULL; +char *unit; +/* Interpret as unit name */ + +n = unit_name_mangle(arg); +if (!n) +return log_oom(); + +unit = unit_dbus_path_from_name(n); +if (!unit) +return log_oom(); + +*unitp = unit; +} else if (interpret_as_job_id) { +/* Interpret as job id */ +if (asprintf(unitp, /org/freedesktop/systemd1/job/%u, id) 0) +return log_oom(); +} else { +/* Interpret as PID */ +r = get_unit_by_pid(bus, id, unitp); +} + +return r; +} + static int show(sd_bus *bus, char **args) { int r, ret = 0; bool show_properties, show_status, new_line = false; @@ -3692,41 +3719,34 @@ static int show(sd_bus *bus, char **args) { ret = show_all(args[0], bus, false, new_line, ellipsized); else STRV_FOREACH(name, args+1) { +_cleanup_free_ char *unit = NULL; uint32_t id; if (safe_atou32(*name, id) 0) { -_cleanup_free_ char *p = NULL, *n = NULL; +_cleanup_free_ char *n = NULL; /* Interpret as unit name */ n = unit_name_mangle(*name); if (!n) return log_oom(); -p = unit_dbus_path_from_name(n); -if (!p) +unit = unit_dbus_path_from_name(n); +if (!unit) return log_oom(); -r = show_one(args[0], bus, p, show_properties, new_line, ellipsized); -if (r != 0) -ret = r; - } else if (show_properties) { -_cleanup_free_ char *p = NULL; - /* Interpret as job id */ -if (asprintf(p, /org/freedesktop/systemd1/job/%u, id) 0) +if (asprintf(unit, /org/freedesktop/systemd1/job/%u, id) 0) return log_oom(); -r = show_one(args[0], bus, p, show_properties, new_line, ellipsized); -if (r != 0) -ret = r; - } else { /* Interpret as PID */ -r = show_one_by_pid(args[0], bus, id, new_line, ellipsized); -if (r != 0) +r = get_unit_dbus_path_by_pid(bus, id, unit); +if (r 0) ret = r; } + +show_one(args[0], bus, unit, show_properties, new_line, ellipsized); } if (ellipsized !arg_quiet) -- 1.8.4.3 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] core/socket: we only want one event on standard sockets
With EPOLLONESHOT we are guaranteed to only recieve one event until we reload with socket_enter_listening(s), otherwise multiple events can be generated upon receipt of multiple chunks of data. We also only want wake-ups when external events happen, i.e. edge-triggered wakeups. --- src/core/socket.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/socket.c b/src/core/socket.c index 5fa4a5a..2f860a4 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1119,7 +1119,9 @@ static int socket_watch_fds(Socket *s) { if (p-event_source) r = sd_event_source_set_enabled(p-event_source, SD_EVENT_ON); else -r = sd_event_add_io(UNIT(s)-manager-event, p-fd, EPOLLIN, socket_dispatch_io, p, p-event_source); +r = sd_event_add_io(UNIT(s)-manager-event, p-fd, +EPOLLIN|EPOLLET|((s-accept || s-distribute) ? 0 : EPOLLONESHOT), +socket_dispatch_io, p, p-event_source); if (r 0) { log_warning_unit(UNIT(s)-id, Failed to watch listening fds: %s, strerror(-r)); -- 1.8.4.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/2] systemctl: refactor show()
v2, don't leave in unused function --- src/systemctl/systemctl.c | 36 +--- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 84826a3..6cb7a82 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3594,16 +3594,13 @@ static int show_one( return r; } -static int show_one_by_pid( -const char *verb, +static int get_unit_dbus_path_by_pid( sd_bus *bus, uint32_t pid, -bool *new_line, -bool *ellipsized) { +char **unit) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; -const char *path = NULL; int r; r = sd_bus_call_method( @@ -3620,11 +3617,11 @@ static int show_one_by_pid( return r; } -r = sd_bus_message_read(reply, o, path); +r = sd_bus_message_read(reply, o, unit); if (r 0) return bus_log_parse_error(r); -return show_one(verb, bus, path, false, new_line, ellipsized); +return 0; } static int show_all( @@ -3692,41 +3689,34 @@ static int show(sd_bus *bus, char **args) { ret = show_all(args[0], bus, false, new_line, ellipsized); else STRV_FOREACH(name, args+1) { +_cleanup_free_ char *unit = NULL; uint32_t id; if (safe_atou32(*name, id) 0) { -_cleanup_free_ char *p = NULL, *n = NULL; +_cleanup_free_ char *n = NULL; /* Interpret as unit name */ n = unit_name_mangle(*name); if (!n) return log_oom(); -p = unit_dbus_path_from_name(n); -if (!p) +unit = unit_dbus_path_from_name(n); +if (!unit) return log_oom(); -r = show_one(args[0], bus, p, show_properties, new_line, ellipsized); -if (r != 0) -ret = r; - } else if (show_properties) { -_cleanup_free_ char *p = NULL; - /* Interpret as job id */ -if (asprintf(p, /org/freedesktop/systemd1/job/%u, id) 0) +if (asprintf(unit, /org/freedesktop/systemd1/job/%u, id) 0) return log_oom(); -r = show_one(args[0], bus, p, show_properties, new_line, ellipsized); -if (r != 0) -ret = r; - } else { /* Interpret as PID */ -r = show_one_by_pid(args[0], bus, id, new_line, ellipsized); -if (r != 0) +r = get_unit_dbus_path_by_pid(bus, id, unit); +if (r 0) ret = r; } + +show_one(args[0], bus, unit, show_properties, new_line, ellipsized); } if (ellipsized !arg_quiet) -- 1.8.4.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 2/2] systemctl: add systemctl cat
--- TODO | 2 -- src/shared/fileio.c | 73 - src/shared/fileio.h | 1 + src/systemctl/systemctl.c | 91 +++ 4 files changed, 164 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6cb7a82..18d5e45 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,6 +3665,95 @@ static int show_all( return 0; } +static int cat(sd_bus *bus, char **args) { +int r = 0; +char **name; + +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); + +pager_open_if_enabled(); + +STRV_FOREACH(name, args+1) { +_cleanup_free_ char *fragment_path = NULL; +_cleanup_strv_free_ char **dropin_paths = NULL; +sd_bus_error error; +FILE *stdout; +char **path; + +n = unit_name_mangle(*name); +if (!n) +return log_oom(); + +unit = unit_dbus_path_from_name(n); +if (!unit) +return log_oom(); + +if (need_daemon_reload(bus, n)) { +log_error(Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'., +
[systemd-devel] [PATCH] nspawn: Give a more helpful error message when -D argument is bogus.
--- src/nspawn/nspawn.c | 5 + 1 file changed, 5 insertions(+) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 0973a00..1ee4ab3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -200,6 +200,11 @@ static int parse_argv(int argc, char *argv[]) { case 'D': free(arg_directory); +if (access(optarg, F_OK) 0) { +log_error(Root directory %s is not accessable: %m, optarg); +return -EACCES; +} + arg_directory = canonicalize_file_name(optarg); if (!arg_directory) { log_error(Failed to canonicalize root directory.); -- 1.8.4.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] core/socket: we only want one event on standard sockets
As we only reciece one event at a time, and dequeue it in the same go, yeah ONESHOT won't change anything. On Tue, Nov 26, 2013 at 9:33 AM, David Timothy Strauss da...@davidstrauss.net wrote: On Wed, Nov 27, 2013 at 2:32 AM, Lennart Poettering lenn...@poettering.net wrote: Well, but EPOLLET only works correctly if each time an event is triggered we dispatch *all* possibly queued events on the fd, until EAGAIN is read again. But we don't do that, heck, if Listen=no is used we don''t even read a single incoming connection of the scket, we leave that to the daemon we spawn, but we cannot trust that. So, I don't get what EPOLLET is supposed to do good here? I should have more selectively quoted before answering. I was only trying to answer why we'd continue having poll for the socket fds after queuing the initial service. I was not trying to suggest EPOLLET is appropriate for the goal of lazy distribute process pool expansion. You've clearly correct about that. I was worried that the fact that we never accept() the socket when using distribute (now I am convinced we shouldn't use it otherwise) would cause it to trigger multiple times for only one incoming connection, if the spawned thread never entered accept() (or we raced it), but reading this thread makes me think I don't fully understand the semantics of EPOLLET. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] core/socket: we only want one event on standard sockets
On Tue, Nov 26, 2013 at 1:48 PM, David Timothy Strauss da...@davidstrauss.net wrote: On Wed, Nov 27, 2013 at 6:23 AM, Shawn Landden sh...@churchofgit.com wrote: I was worried that the fact that we never accept() the socket when using distribute (now I am convinced we shouldn't use it otherwise) I'm not sure what you mean here. Distribute-style functionality is absolutely useful with Accept=true (to cap the number of simultaneous connections) Are you sure applications can handle the extra file descriptor of passing both the sockfd and the acceptfd in this case? I don't see why they wouldn't just do the accept() themselves? Can you explain what you mean here, and how it differs from the existing MaxConnections. as well as Accept=false (to allow running of a process pool of self-accepting, long-running workers). would cause it to trigger multiple times for only one incoming connection, if the spawned thread never entered accept() (or we raced it), but reading this thread makes me think I don't fully understand the semantics of EPOLLET. There are some decent examples on the man page: http://linux.die.net/man/7/epoll Yeah I had read that, and seen it in the kernel source. I am just confused and need to think about it some more. -Shawn ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] core/socket: we only want one event on standard sockets
On Tue, Nov 26, 2013 at 7:57 PM, David Timothy Strauss da...@davidstrauss.net wrote: On Wed, Nov 27, 2013 at 7:57 AM, Shawn Landden sh...@churchofgit.com wrote: Are you sure applications can handle the extra file descriptor of passing both the sockfd and the acceptfd in this case? I don't see why they wouldn't just do the accept() themselves? Can you explain what you mean here, and how it differs from the existing MaxConnections. Actually, MaxConnections was exactly what I was thinking of. I agree with you now on Distribute=true only being useful with Accept=false. The current code I have has Distribute take a number, but it certainly would be possible to use the MaxConnections number---however I don't do that as connections isn't quite the right word, and we can't easily change it because it is part of the API. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] systemctl: add systemctl cat
--- TODO | 2 - src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 97 +++ 5 files changed, 172 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/shared/util.c b/src/shared/util.c index deb74c4..e6a32b9 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { size_t a; void *q; +assert(allocated); + if (*allocated = need) return *p; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6cb7a82..633c07d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,6 +3665,101 @@ static int show_all( return 0; } +static int cat(sd_bus *bus, char **args) { +int r = 0; +char **name; + +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); + +pager_open_if_enabled(); + +STRV_FOREACH(name, args+1) { +_cleanup_free_ char *fragment_path = NULL; +_cleanup_strv_free_ char **dropin_paths = NULL; +sd_bus_error error; +FILE *stdout; +char **path; + +n = unit_name_mangle(*name);
Re: [systemd-devel] [PATCH 2/2] systemctl: add systemctl cat
On Wed, Nov 27, 2013 at 11:59 PM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Sat, Nov 23, 2013 at 07:52:53PM -0800, Shawn Landden wrote: --- TODO | 2 -- src/shared/fileio.c | 73 - src/shared/fileio.h | 1 + src/systemctl/systemctl.c | 91 +++ 4 files changed, 164 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; Can you convert this to GREEDY_REALLOC? It should be a bit simpler then. GREEDY_REALLOC isn't appropriate here, (or read_full_file() which this code is from), as in general stat is going to succeed and we are going to read the whole file in one run. + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6cb7a82..18d5e45 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,6 +3665,95 @@ static int show_all( return 0; } +static int cat(sd_bus *bus, char **args) { +int r = 0; +char **name; + +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); + +pager_open_if_enabled(); + +STRV_FOREACH(name, args+1) { +_cleanup_free_ char *fragment_path = NULL; +_cleanup_strv_free_ char
[systemd-devel] [PATCH] systemctl: add systemctl cat
v3: log_warning() inserts a trailing newline --- TODO | 2 - src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 97 +++ 5 files changed, 172 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/shared/util.c b/src/shared/util.c index deb74c4..e6a32b9 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { size_t a; void *q; +assert(allocated); + if (*allocated = need) return *p; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6cb7a82..284020c 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,6 +3665,101 @@ static int show_all( return 0; } +static int cat(sd_bus *bus, char **args) { +int r = 0; +char **name; + +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); + +pager_open_if_enabled(); + +STRV_FOREACH(name, args+1) { +_cleanup_free_ char *fragment_path = NULL; +_cleanup_strv_free_ char **dropin_paths = NULL; +sd_bus_error error; +FILE *stdout; +char **path; +
[systemd-devel] [PATCH 1/2] nspawn: --populate to run static binaries on empty target directory
nspawn has been called chroot on steroids. Continue that tradition by supporting target directories that are not root directories. This patch handles the simple case: a static binary. --- Makefile.am| 2 + man/systemd-nspawn.xml | 11 + src/nspawn/elf.c | 127 + src/nspawn/elf.h | 30 src/nspawn/nspawn.c| 46 +++--- src/shared/path-util.c | 57 -- src/shared/path-util.h | 5 +- 7 files changed, 256 insertions(+), 22 deletions(-) create mode 100644 src/nspawn/elf.c create mode 100644 src/nspawn/elf.h diff --git a/Makefile.am b/Makefile.am index 47c269d..da905a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1839,6 +1839,8 @@ systemd_cgtop_LDADD = \ # -- systemd_nspawn_SOURCES = \ src/nspawn/nspawn.c \ + src/nspawn/elf.c \ + src/nspawn/elf.h \ src/core/mount-setup.c \ src/core/mount-setup.h \ src/core/loopback-setup.c \ diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 75d2e6d..24bc0d7 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -211,6 +211,17 @@ /varlistentry varlistentry +termoption-p/option/term +termoption--populate/option/term + +listitemparaIf COMMAND does not exist in +target root directory, launch host COMMAND./para + +paraCan be used on empty target directories +(if COMMAND a static executable)./para/listitem +/varlistentry + +varlistentry termoption-u/option/term termoption--user=/option/term diff --git a/src/nspawn/elf.c b/src/nspawn/elf.c new file mode 100644 index 000..c399d59 --- /dev/null +++ b/src/nspawn/elf.c @@ -0,0 +1,127 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Shawn Landden + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see http://www.gnu.org/licenses/. +***/ + + +#include elf.h +#include fcntl.h + +#include elf.h +#include util.h +#include log.h + +int analyze_executable(const char *path, + int *_fd, + bool *_elf64, + char **_linker, + char **shebang) { + +char e_ident[sizeof(Elf64_Ehdr)]; +uint16_t e_type; +bool elf64; +int fd = -1; +int r; + +assert(path); +assert(_elf64); +assert(_linker); +assert(shebang); + +fd = open(path, O_RDONLY | O_CLOEXEC); +if (fd 0) { +log_error(open(\%s\) failed: %m, path); +return -errno; +} + +r = read(fd, e_ident, sizeof(Elf64_Ehdr)); +if (r 0) { +log_error(read() on %s failed: %m, path); +return -errno; +} + +if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { +log_error(%s is not an ELF executable., path); +return -ENOSYS; +} else +if (shebang) +*shebang = NULL; + +switch (e_ident[EI_CLASS]) { +case ELFCLASS32: +elf64 = false; +break; +case ELFCLASS64: +elf64 = true; +break; +default: +log_error(Unknown ELF class.); +return -EINVAL; +} + +if (elf64) { +Elf64_Ehdr *ehdr = (Elf64_Ehdr *)e_ident; + +e_type = ehdr-e_type; +} else { +Elf32_Ehdr *ehdr = (Elf32_Ehdr *)e_ident; + +e_type = ehdr-e_type; +} + +/* Not checking e_ident[E_DATA], file is assumed to be of host endianness. */ +if (e_type != ET_EXEC) { +log_error(%s is not an ELF executable, or is of alien endianness., path); +return -EINVAL; +} + +char phdrs[e_phentsize * e_phnum]; +char *phdr; + +lseek(fd, e_phoff, SEEK_SET); +r = read(fd
[systemd-devel] [PATCH 2/2] nspawn: --populate with dynamic libs and one-file scripts
the whitelist of dynamic linker paths comes from clang --- src/nspawn/elf.c| 174 ++- src/nspawn/elf.h| 14 +++- src/nspawn/nspawn.c | 191 +--- src/shared/util.c | 80 ++ src/shared/util.h | 2 + 5 files changed, 435 insertions(+), 26 deletions(-) diff --git a/src/nspawn/elf.c b/src/nspawn/elf.c index c399d59..2f0b7ef 100644 --- a/src/nspawn/elf.c +++ b/src/nspawn/elf.c @@ -26,23 +26,30 @@ #include elf.h #include util.h #include log.h +#include strv.h int analyze_executable(const char *path, int *_fd, bool *_elf64, char **_linker, - char **shebang) { + char **shebang, + char ***_libs) { -char e_ident[sizeof(Elf64_Ehdr)]; +char e_ident[MAX(2u + PATH_MAX, sizeof(Elf64_Ehdr))]; uint16_t e_type; +off_t e_phoff; +uint16_t e_phentsize, e_phnum; bool elf64; -int fd = -1; +_cleanup_close_ int fd = -1; +bool have_interp = false; int r; assert(path); +assert(_fd); assert(_elf64); assert(_linker); assert(shebang); +assert(_libs); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd 0) { @@ -50,18 +57,59 @@ int analyze_executable(const char *path, return -errno; } -r = read(fd, e_ident, sizeof(Elf64_Ehdr)); +r = read(fd, e_ident, MAX(2u + PATH_MAX, sizeof(Elf64_Ehdr))); if (r 0) { -log_error(read() on %s failed: %m, path); +log_error(read() on %s failed: %s, path, strerror(errno)); return -errno; } if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { -log_error(%s is not an ELF executable., path); -return -ENOSYS; -} else -if (shebang) -*shebang = NULL; +if (startswith(e_ident, #!)) { +_cleanup_close_ int shebang_fd = -1; +char shebang_e_ident[sizeof(Elf64_Ehdr)]; +char *t; + + /* from fs/binfmt_script.c:42 */ +t = (char *)e_ident + strcspn(e_ident, \t\n); +t[0] = '\0'; + +t = e_ident[2]; + +shebang_fd = open(t, O_RDONLY|O_CLOEXEC); +if (shebang_fd 0) { +log_error(Cannot read interpreter %s: %m, t); +return -errno; +} + +r = read(shebang_fd, shebang_e_ident, sizeof(Elf64_Ehdr)); +if (r SELFMAG) { +log_error(read() on %s failed: %s, t, strerror(r 0 ? errno : EIO)); +return -errno; +} + +/* the kernel actually supports interpreters of interpreters + * but we don't support that here */ +if (memcmp(shebang_e_ident, ELFMAG, SELFMAG) != 0) { +log_error(Interpreter %s is not an ELF executable., t); +return -EINVAL; +} + +*_fd = fd; +fd = shebang_fd; /* analyze and */ +shebang_fd = -1; /* don't close ELF */ +*shebang = strdup(t); +if (!*shebang) +return log_oom(); + +memcpy(e_ident, shebang_e_ident, sizeof(Elf64_Ehdr)); +} else { +log_error(%s is not an ELF executable or script starting with #!., path); +return -ENOSYS; +} +} else { +*_fd = fd; +*shebang = NULL; +} switch (e_ident[EI_CLASS]) { case ELFCLASS32: @@ -79,10 +127,16 @@ int analyze_executable(const char *path, Elf64_Ehdr *ehdr = (Elf64_Ehdr *)e_ident; e_type = ehdr-e_type; +e_phoff = ehdr-e_phoff; +e_phentsize = ehdr-e_phentsize; +e_phnum = ehdr-e_phnum; } else { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)e_ident; e_type = ehdr-e_type; +e_phoff = ehdr-e_phoff; +e_phentsize = ehdr-e_phentsize; +e_phnum = ehdr-e_phnum; } /* Not checking e_ident[E_DATA], file is assumed to be of host endianness. */ @@ -113,15 +167,103 @@ int analyze_executable(const char *path, } if (!have_interp) { -
[systemd-devel] [PATCH] systemctl: add systemctl cat
--- TODO | 2 - man/systemctl.xml | 9 src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 107 ++ 6 files changed, 191 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/man/systemctl.xml b/man/systemctl.xml index 33a2935..8a66130 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -727,7 +727,16 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service human-readable output./para /listitem /varlistentry +varlistentry + termcommandcat replaceableNAME/replaceable.../command/term + listitem +paraShow backing files of one or more units. +Prints the fragment, drop-ins, and source (sysvinit compat) +of units. Each file is preceded by a comment which includes the +file name./para + /listitem +/varlistentry varlistentry termcommandset-property replaceableNAME/replaceable replaceableASSIGNMENT/replaceable.../command/term diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/shared/util.c b/src/shared/util.c index deb74c4..e6a32b9 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { size_t a;
Re: [systemd-devel] build broken on clang
On Sat, Nov 30, 2013 at 5:46 PM, Greg KH gre...@linuxfoundation.org wrote: On Sun, Dec 01, 2013 at 12:38:44AM +0100, Thomas H.P. Andersen wrote: Hi, Since 777d7a6123cbb192a8ff9e4ac5c05b1da84b4217 the build is broken on clang: src/libsystemd-bus/bus-control.c:686:41: error: fields must have a constant size: 'variable length array in structure' extension will never be supported uint8_t buffer[sz]; ^ src/libsystemd-bus/bus-control.c:748:33: error: fields must have a constant size: 'variable length array in structure' extension will never be supported uint8_t buffer[sz]; Seems like someone needs to fix clang with this well-known gcc extension :) There was a whole talk about this at the recent Linux Plumbers Conference 2013 http://www.linuxplumbersconf.org/2013/ocw/sessions/1221 http://www.youtube.com/watch?v=aliQx0uDSX0 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] fix regression of read_full_file() in fileio.c
my e93c33d4aa broke this stupidly --- src/shared/fileio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/fileio.c b/src/shared/fileio.c index ac1b409..ede8819 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -240,6 +240,7 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; +buf = NULL; /* do not free */ if (size) *size = l; -- 1.8.4.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [RFC 05/12] gfx: add sd-gfx library with unifont section
On Sat, Nov 30, 2013 at 9:28 PM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Wed, Nov 27, 2013 at 07:48:40PM +0100, David Herrmann wrote: As a first step, we add the required header+build-chain and add the font-handling. To avoid heavy font-pipelines in systemd, we only provide a statically-sized fallback-font based on GNU-Unifont. Hi David, I don't think that GNU-Unifont is licensed in a way that allows it to be embedded in systemd. Systemd is LGPLv2+, while Unifont is GPLv2+ + FontException. FontException allows embedding in documents, so it doesn't apply. It would be possible have some sources which are GPLv2+ only, but I think we want to avoid such complications. Also, if the font was embedded in systemd, distributions would then remove it in order to replace is with the system version. So I think that including the font sources is pointless... Debian has it packaged [1], but an old version, I'm not sure if there have been recent updates, and possibly in the wrong format. Fedora doesn't seem to have it yet. But adding fonts is easy, I'd do the Fedora package myself, and other distributions could surely add/update it. So if it is acceptable for systemd-gfx *binary* to be GPLv2+ licensed, we could use the system unifont.hex file at build time, and actually link it into the binary. I propose that we try to go this way. Or we could have the package also contain the converted font in appropriate format, and mmap it at runtime. But this is more complex, and doesn't actually avoid the licensing issue, since the font would still be GPLv2+. The font is needed in the initramfs Zbyszek [1] http://packages.debian.org/sid/all/unifont/filelist ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/4] nspawn: shorten conditional path
--- src/nspawn/nspawn.c | 19 +++ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index dd7337b..0151cf3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -481,10 +481,8 @@ static int setup_timezone(const char *dest) { return 0; } -z = path_startswith(p, ../usr/share/zoneinfo/); -if (!z) -z = path_startswith(p, /usr/share/zoneinfo/); -if (!z) { +if ((z = path_startswith(p, ../usr/share/zoneinfo/)) || +(z = path_startswith(p, /usr/share/zoneinfo/))) { log_warning(/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.); return 0; } @@ -495,14 +493,11 @@ static int setup_timezone(const char *dest) { r = readlink_malloc(where, q); if (r = 0) { -y = path_startswith(q, ../usr/share/zoneinfo/); -if (!y) -y = path_startswith(q, /usr/share/zoneinfo/); - - -/* Already pointing to the right place? Then do nothing .. */ -if (y streq(y, z)) -return 0; +if ((y = path_startswith(q, ../usr/share/zoneinfo/)) || +(y = path_startswith(q, /usr/share/zoneinfo/))) +/* Already pointing to the right place? Then do nothing .. */ +if (streq(y, z)) +return 0; } check = strjoin(dest, /usr/share/zoneinfo/, z, NULL); -- 1.8.4.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 2/4] shared: mark strv_length() _pure_
--- src/shared/strv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/strv.c b/src/shared/strv.c index 607c221..cc6adfa 100644 --- a/src/shared/strv.c +++ b/src/shared/strv.c @@ -84,7 +84,7 @@ char **strv_copy(char * const *l) { return r; } -unsigned strv_length(char * const *l) { +_pure_ unsigned strv_length(char * const *l) { unsigned n = 0; if (!l) -- 1.8.4.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 4/4] nspawn: --populate with dynamic libs and one-file scripts
the whitelist of dynamic linker paths comes from clang --- man/systemd-nspawn.xml | 8 +-- src/nspawn/elf.c | 162 + src/nspawn/elf.h | 14 +++- src/nspawn/nspawn.c| 191 ++--- src/shared/util.c | 80 + src/shared/util.h | 2 + 6 files changed, 431 insertions(+), 26 deletions(-) diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 24bc0d7..723ec09 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -214,11 +214,11 @@ termoption-p/option/term termoption--populate/option/term -listitemparaIf COMMAND does not exist in -target root directory, launch host COMMAND./para +listitemparaUse COMMAND from host./para -paraCan be used on empty target directories -(if COMMAND a static executable)./para/listitem +paraCan be used on empty target directories, +if COMMAND an ELF executable, or +one-file script./para/listitem /varlistentry varlistentry diff --git a/src/nspawn/elf.c b/src/nspawn/elf.c index f91b374..62d0fda 100644 --- a/src/nspawn/elf.c +++ b/src/nspawn/elf.c @@ -26,44 +26,90 @@ #include elf.h #include util.h #include log.h +#include strv.h int analyze_executable(const char *path, int *_fd, bool *_elf64, char **_linker, - char **shebang) { + char **shebang, + char ***_libs) { -char e_ident[sizeof(Elf64_Ehdr)]; +char e_ident[MAX(2u + PATH_MAX, sizeof(Elf64_Ehdr))]; uint16_t e_type; off_t e_phoff; uint16_t e_phentsize, e_phnum; bool elf64; -int fd = -1; +_cleanup_close_ int fd = -1; bool have_interp = false; int r; assert(path); +assert(_fd); assert(_elf64); assert(_linker); assert(shebang); +assert(_libs); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd 0) { -log_error(open(\%s\) failed: %m, path); +log_error(open(%s) failed: %m, path); return -errno; } -r = read(fd, e_ident, sizeof(Elf64_Ehdr)); +r = read(fd, e_ident, MAX(2u + PATH_MAX, sizeof(Elf64_Ehdr))); if (r 0) { -log_error(read() on %s failed: %m, path); +log_error(read(%s) failed: %s, path, strerror(errno)); return -errno; } if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { -log_error(%s is not an ELF executable., path); -return -ENOSYS; -} else +if (startswith(e_ident, #!)) { +_cleanup_close_ int shebang_fd = -1; +char shebang_e_ident[sizeof(Elf64_Ehdr)]; +char *t; + + /* from fs/binfmt_script.c:42 */ +t = e_ident + strcspn(e_ident, \t\n); +t[0] = '\0'; + +t = e_ident[2]; + +shebang_fd = open(t, O_RDONLY|O_CLOEXEC); +if (shebang_fd 0) { +log_error(Cannot open interpreter %s: %m, t); +return -errno; +} + +r = read(shebang_fd, shebang_e_ident, sizeof(Elf64_Ehdr)); +if (r SELFMAG) { +log_error(read(%s) failed: %s, t, strerror(r 0 ? errno : EIO)); +return -errno; +} + +/* The kernel actually supports interpreters of interpreters + * but we don't support that here. */ +if (memcmp(shebang_e_ident, ELFMAG, SELFMAG) != 0) { +log_error(Interpreter %s is not an ELF executable., t); +return -EINVAL; +} + +*_fd = fd; +fd = shebang_fd; /* analyze and */ +shebang_fd = -1; /* don't close ELF */ +*shebang = strdup(t); +if (!*shebang) +return log_oom(); + +memcpy(e_ident, shebang_e_ident, sizeof(Elf64_Ehdr)); +} else { +log_error(%s is not an ELF executable or script starting with #!.,
[systemd-devel] [PATCH 3/4] nspawn: --populate to run static binaries on empty target directory
nspawn has been called chroot on steroids. Continue that tradition by supporting target directories that are not root directories. This patch handles the simple case: a static binary. --- Makefile.am| 2 + man/systemd-nspawn.xml | 11 + src/nspawn/elf.c | 131 + src/nspawn/elf.h | 30 +++ src/nspawn/nspawn.c| 47 +++--- src/shared/path-util.c | 57 +++-- src/shared/path-util.h | 5 +- 7 files changed, 260 insertions(+), 23 deletions(-) create mode 100644 src/nspawn/elf.c create mode 100644 src/nspawn/elf.h diff --git a/Makefile.am b/Makefile.am index 7a45029..67c26f4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1832,6 +1832,8 @@ systemd_cgtop_LDADD = \ # -- systemd_nspawn_SOURCES = \ src/nspawn/nspawn.c \ + src/nspawn/elf.c \ + src/nspawn/elf.h \ src/core/mount-setup.c \ src/core/mount-setup.h \ src/core/loopback-setup.c \ diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 75d2e6d..24bc0d7 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -211,6 +211,17 @@ /varlistentry varlistentry +termoption-p/option/term +termoption--populate/option/term + +listitemparaIf COMMAND does not exist in +target root directory, launch host COMMAND./para + +paraCan be used on empty target directories +(if COMMAND a static executable)./para/listitem +/varlistentry + +varlistentry termoption-u/option/term termoption--user=/option/term diff --git a/src/nspawn/elf.c b/src/nspawn/elf.c new file mode 100644 index 000..f91b374 --- /dev/null +++ b/src/nspawn/elf.c @@ -0,0 +1,131 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Shawn Landden + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see http://www.gnu.org/licenses/. +***/ + + +#include elf.h +#include fcntl.h + +#include elf.h +#include util.h +#include log.h + +int analyze_executable(const char *path, + int *_fd, + bool *_elf64, + char **_linker, + char **shebang) { + +char e_ident[sizeof(Elf64_Ehdr)]; +uint16_t e_type; +off_t e_phoff; +uint16_t e_phentsize, e_phnum; +bool elf64; +int fd = -1; +bool have_interp = false; +int r; + +assert(path); +assert(_elf64); +assert(_linker); +assert(shebang); + +fd = open(path, O_RDONLY | O_CLOEXEC); +if (fd 0) { +log_error(open(\%s\) failed: %m, path); +return -errno; +} + +r = read(fd, e_ident, sizeof(Elf64_Ehdr)); +if (r 0) { +log_error(read() on %s failed: %m, path); +return -errno; +} + +if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { +log_error(%s is not an ELF executable., path); +return -ENOSYS; +} else +*shebang = NULL; + +switch (e_ident[EI_CLASS]) { +case ELFCLASS32: +elf64 = false; +break; +case ELFCLASS64: +elf64 = true; +break; +default: +log_error(Unknown ELF class.); +return -EINVAL; +} + +if (elf64) { +Elf64_Ehdr *ehdr = (Elf64_Ehdr *)e_ident; + +e_type = ehdr-e_type; +e_phoff = ehdr-e_phoff; +e_phentsize = ehdr-e_phentsize; +e_phnum = ehdr-e_phnum; +} else { +Elf32_Ehdr *ehdr = (Elf32_Ehdr *)e_ident; + +e_type = ehdr-e_type; +e_phoff = ehdr-e_phoff; +e_phentsize = ehdr-e_phentsize; +e_phnum = ehdr-e_phnum; +} + +/* Not checking e_ident[E_DATA], file is assumed to be of host
[systemd-devel] [PATCH] nspawn: --populate with dynamic libs and one-file scripts
the whitelist of dynamic linker paths comes from clang --- man/systemd-nspawn.xml | 8 +-- src/nspawn/elf.c | 161 + src/nspawn/elf.h | 14 +++- src/nspawn/nspawn.c| 191 ++--- src/shared/util.c | 80 + src/shared/util.h | 2 + 6 files changed, 430 insertions(+), 26 deletions(-) diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 24bc0d7..723ec09 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -214,11 +214,11 @@ termoption-p/option/term termoption--populate/option/term -listitemparaIf COMMAND does not exist in -target root directory, launch host COMMAND./para +listitemparaUse COMMAND from host./para -paraCan be used on empty target directories -(if COMMAND a static executable)./para/listitem +paraCan be used on empty target directories, +if COMMAND an ELF executable, or +one-file script./para/listitem /varlistentry varlistentry diff --git a/src/nspawn/elf.c b/src/nspawn/elf.c index f91b374..63ada56 100644 --- a/src/nspawn/elf.c +++ b/src/nspawn/elf.c @@ -26,44 +26,90 @@ #include elf.h #include util.h #include log.h +#include strv.h int analyze_executable(const char *path, int *_fd, bool *_elf64, char **_linker, - char **shebang) { + char **shebang, + char ***_libs) { -char e_ident[sizeof(Elf64_Ehdr)]; +char e_ident[MAX(2u + PATH_MAX, sizeof(Elf64_Ehdr))]; uint16_t e_type; off_t e_phoff; uint16_t e_phentsize, e_phnum; bool elf64; -int fd = -1; +_cleanup_close_ int fd = -1; bool have_interp = false; int r; assert(path); +assert(_fd); assert(_elf64); assert(_linker); assert(shebang); +assert(_libs); fd = open(path, O_RDONLY | O_CLOEXEC); if (fd 0) { -log_error(open(\%s\) failed: %m, path); +log_error(open(%s) failed: %m, path); return -errno; } -r = read(fd, e_ident, sizeof(Elf64_Ehdr)); +r = read(fd, e_ident, MAX(2u + PATH_MAX, sizeof(Elf64_Ehdr))); if (r 0) { -log_error(read() on %s failed: %m, path); +log_error(read(%s) failed: %s, path, strerror(errno)); return -errno; } if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { -log_error(%s is not an ELF executable., path); -return -ENOSYS; -} else +if (startswith(e_ident, #!)) { +_cleanup_close_ int shebang_fd = -1; +char shebang_e_ident[sizeof(Elf64_Ehdr)]; +char *t; + + /* from fs/binfmt_script.c:42 */ +t = e_ident + strcspn(e_ident, \t\n); +t[0] = '\0'; + +t = e_ident[2]; + +shebang_fd = open(t, O_RDONLY|O_CLOEXEC); +if (shebang_fd 0) { +log_error(Cannot open interpreter %s: %m, t); +return -errno; +} + +r = read(shebang_fd, shebang_e_ident, sizeof(Elf64_Ehdr)); +if (r SELFMAG) { +log_error(read(%s) failed: %s, t, strerror(r 0 ? errno : EIO)); +return -errno; +} + +/* The kernel actually supports interpreters of interpreters + * but we don't support that here. */ +if (memcmp(shebang_e_ident, ELFMAG, SELFMAG) != 0) { +log_error(Interpreter %s is not an ELF executable., t); +return -EINVAL; +} + +*_fd = fd; +fd = shebang_fd; /* analyze and */ +shebang_fd = -1; /* don't close ELF */ +*shebang = strdup(t); +if (!*shebang) +return log_oom(); + +memcpy(e_ident, shebang_e_ident, sizeof(Elf64_Ehdr)); +} else { +log_error(%s is not an ELF executable or script starting with #!.,
[systemd-devel] [PATCH] nspawn: shorten conditional path
--- src/nspawn/nspawn.c | 19 +++ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index dd7337b..f400a65 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -481,10 +481,8 @@ static int setup_timezone(const char *dest) { return 0; } -z = path_startswith(p, ../usr/share/zoneinfo/); -if (!z) -z = path_startswith(p, /usr/share/zoneinfo/); -if (!z) { +if (!((z = path_startswith(p, ../usr/share/zoneinfo/)) || + (z = path_startswith(p, /usr/share/zoneinfo/ { log_warning(/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.); return 0; } @@ -495,14 +493,11 @@ static int setup_timezone(const char *dest) { r = readlink_malloc(where, q); if (r = 0) { -y = path_startswith(q, ../usr/share/zoneinfo/); -if (!y) -y = path_startswith(q, /usr/share/zoneinfo/); - - -/* Already pointing to the right place? Then do nothing .. */ -if (y streq(y, z)) -return 0; +if ((y = path_startswith(q, ../usr/share/zoneinfo/)) || +(y = path_startswith(q, /usr/share/zoneinfo/))) +/* Already pointing to the right place? Then do nothing .. */ +if (streq(y, z)) +return 0; } check = strjoin(dest, /usr/share/zoneinfo/, z, NULL); -- 1.8.4.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH 1/2] nspawn: --populate to run static binaries on empty target directory
On Mon, Dec 2, 2013 at 8:27 AM, Lennart Poettering lenn...@poettering.net wrote: On Sat, 30.11.13 10:20, Shawn Landden (sh...@churchofgit.com) wrote: nspawn has been called chroot on steroids. Continue that tradition by supporting target directories that are not root directories. This patch handles the simple case: a static binary. Hmm, I am not sure how I feel about this. This appears a bit too specific for me, and given the requirement for static binaries this is also so limited. The next patch is the series adds support for dynamic libraries. This patch also doesn't need bind mounts, and it executes through /proc/self/fd/%n, but support for one-file scripts and dynamic libraries in the next patch does require bind mounts. I feel you don't really understand my patch. :/ I'll sum up what I'm doing: If --populate is passed, analyze the executable, which opens it and set the exec path to /proc/self/fd/%n. If executable is static this is all you have to do. If it has a shebang, analyze that. If either the shebang or executable is dynamic, test if the linker is the GNU linker, and if it is have the linker tell use what libraries the executable needs. Then bind mount the linker, shebang (if there is one), and libraries into the target. Unmount these when the machine shuts down. I wonder if we can find a different way to support this, without adding high-level switches to nspawn itself. For example, couldn't extending --bind= a bit to also support bind mounting files (in contrast to just directories the way it currently does) already gets us 90% of the way? And then do the rest 10% by adding an example how to use this to bind mount static binaries from the host into the container to the example in the man page? Allowing bind mounting of files has been on the TODO list for a while anyway... Something like: # systemd-nspawn -D /srv/mycontainer --bind=/usr/bin/populate-container:/tmp/populate-container /tmp/populate-container This of course wouldn't check if the file executed is staticall linked, but the user should quickly get an error about missing .sos if it isn't? No, the linker would be missing, and the user would get execvpe() failed: No such file or directory, which is confusing. assert_se(sigemptyset(mask) == 0); @@ -1164,7 +1195,7 @@ int main(int argc, char *argv[]) { gid_t gid = (gid_t) -1; unsigned n_env = 2; const char *envp[] = { - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, +DEFAULT_PATH_SPLIT_USR, This bit looks like like something we really should do though. Could you isolate this out and resubmit, please? +#define DEFAULT_PATH_SPLIT_USR /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + #ifdef HAVE_SPLIT_USR -# define DEFAULT_PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR #else # define DEFAULT_PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin #endif @@ -51,6 +53,7 @@ int path_is_mount_point(const char *path, bool allow_symlink); int path_is_read_only_fs(const char *path); int path_is_os_tree(const char *path); And this too, of course... Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH 1/2] nspawn: --populate to run static binaries on empty target directory
On Mon, Dec 2, 2013 at 9:41 AM, Shawn Landden sh...@churchofgit.com wrote: On Mon, Dec 2, 2013 at 8:27 AM, Lennart Poettering lenn...@poettering.net wrote: On Sat, 30.11.13 10:20, Shawn Landden (sh...@churchofgit.com) wrote: nspawn has been called chroot on steroids. Continue that tradition by supporting target directories that are not root directories. This patch handles the simple case: a static binary. Hmm, I am not sure how I feel about this. This appears a bit too specific for me, and given the requirement for static binaries this is also so limited. The next patch is the series adds support for dynamic libraries. This patch also doesn't need bind mounts, and it executes through /proc/self/fd/%n, but support for one-file scripts and dynamic libraries in the next patch does require bind mounts. I feel you don't really understand my patch. :/ I'll sum up what I'm doing: If --populate is passed, analyze the executable, which opens it and set the exec path to /proc/self/fd/%n. If executable is static this is all you have to do. If it has a shebang, analyze that. If either the shebang or executable is dynamic, test if the linker is the GNU linker, and if it is have the linker tell use what libraries the executable needs. Then bind mount the linker, shebang (if there is one), and libraries into the target. Unmount these when the machine shuts down. I wonder if we can find a different way to support this, without adding high-level switches to nspawn itself. For example, couldn't extending --bind= a bit to also support bind mounting files (in contrast to just directories the way it currently does) already gets us 90% of the way? And then do the rest 10% by adding an example how to use this to bind mount static binaries from the host into the container to the example in the man page? Allowing bind mounting of files has been on the TODO list for a while anyway... I'll add a bind mount file feature, and then rebase the second patch on top of that. Something like: # systemd-nspawn -D /srv/mycontainer --bind=/usr/bin/populate-container:/tmp/populate-container /tmp/populate-container This of course wouldn't check if the file executed is staticall linked, but the user should quickly get an error about missing .sos if it isn't? No, the linker would be missing, and the user would get execvpe() failed: No such file or directory, which is confusing. assert_se(sigemptyset(mask) == 0); @@ -1164,7 +1195,7 @@ int main(int argc, char *argv[]) { gid_t gid = (gid_t) -1; unsigned n_env = 2; const char *envp[] = { - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, +DEFAULT_PATH_SPLIT_USR, This bit looks like like something we really should do though. Could you isolate this out and resubmit, please? +#define DEFAULT_PATH_SPLIT_USR /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + #ifdef HAVE_SPLIT_USR -# define DEFAULT_PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR #else # define DEFAULT_PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin #endif @@ -51,6 +53,7 @@ int path_is_mount_point(const char *path, bool allow_symlink); int path_is_read_only_fs(const char *path); int path_is_os_tree(const char *path); And this too, of course... Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] nspawn: fix buggy mount_binds, now works for bind-mounted files
--- src/nspawn/nspawn.c | 42 ++ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index dd7337b..c1212c0 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -416,6 +416,7 @@ static int mount_all(const char *dest) { static int mount_binds(const char *dest, char **l, unsigned long flags) { char **x, **y; +int r; STRV_FOREACH_PAIR(x, y, l) { _cleanup_free_ char *where = NULL; @@ -426,31 +427,40 @@ static int mount_binds(const char *dest, char **l, unsigned long flags) { return -errno; } -where = strjoin(dest, /, *y, NULL); +where = strjoin(dest, *y, NULL); if (!where) return log_oom(); -if (stat(where, dest_st) == 0) { +r = stat(where, dest_st); +if (r == 0) { if ((source_st.st_mode S_IFMT) != (dest_st.st_mode S_IFMT)) { log_error(The file types of %s and %s do not match. Refusing bind mount, *x, where); return -EINVAL; } -} else { -/* Create the mount point, but be conservative -- refuse to create block - * and char devices. */ -if (S_ISDIR(source_st.st_mode)) -mkdir_p_label(where, 0755); -else if (S_ISFIFO(source_st.st_mode)) -mkfifo(where, 0644); -else if (S_ISSOCK(source_st.st_mode)) -mknod(where, 0644 | S_IFSOCK, 0); -else if (S_ISREG(source_st.st_mode)) -touch(where); -else { -log_error(Refusing to create mountpoint for file: %s, *x); -return -ENOTSUP; +} else if (errno == ENOENT) { +r = mkdir_parents_label(where, 0755); +if (r 0) { +log_error(Failed to bind mount %s: %s, *x, strerror(-r)); +return r; } +} else { +log_error(Failed to bind mount %s: %s, *x, strerror(errno)); +return -errno; +} +/* Create the mount point, but be conservative -- refuse to create block +* and char devices. */ +if (S_ISDIR(source_st.st_mode)) +mkdir_label(where, 0755); +else if (S_ISFIFO(source_st.st_mode)) +mkfifo(where, 0644); +else if (S_ISSOCK(source_st.st_mode)) +mknod(where, 0644 | S_IFSOCK, 0); +else if (S_ISREG(source_st.st_mode)) +touch(where); +else { +log_error(Refusing to create mountpoint for file: %s, *x); +return -ENOTSUP; } if (mount(*x, where, bind, MS_BIND, NULL) 0) { -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] systemd-nspawn and kernel command line
On Sat, Dec 7, 2013 at 10:33 AM, Colin Guthrie gm...@colin.guthr.ie wrote: Hi, When playing with systemd-nspawn, is there a way to override the kernel command line seen inside the container. I mean it's probably not correct that the host systems /proc/cmdline leaks into the container. No it is not, /proc/cmdline cannot be changed. What is your use case? Perhaps this could be added to UTS namespaces? Cheers Col -- Colin Guthrie gmane(at)colin.guthr.ie http://colin.guthr.ie/ Day Job: Tribalogic Limited http://www.tribalogic.net/ Open Source: Mageia Contributor http://www.mageia.org/ PulseAudio Hacker http://www.pulseaudio.org/ Trac Hacker http://trac.edgewall.org/ ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] systemd-nspawn and kernel command line
On Sat, Dec 7, 2013 at 11:03 AM, Colin Guthrie gm...@colin.guthr.ie wrote: 'Twas brillig, and Shawn Landden at 07/12/13 18:57 did gyre and gimble: On Sat, Dec 7, 2013 at 10:33 AM, Colin Guthrie gm...@colin.guthr.ie wrote: Hi, When playing with systemd-nspawn, is there a way to override the kernel command line seen inside the container. I mean it's probably not correct that the host systems /proc/cmdline leaks into the container. No it is not, /proc/cmdline cannot be changed. What is your use case? Perhaps this could be added to UTS namespaces? Could you not bind mount over it with a temporary file? Might be kinda tricky to do tho' if it is possible. I didn't think of this. This is totally possible, and should now work in recent git. (but not any released versions) --bind=/foo/newcmdline:/proc/cmdline where newcmdline is a regular file My main use case is that we have a rescue system which passes rescue on the command line of the host system. If I use this system to boot containers (which would typically be the system we are rescuing, then it reads this rescue is read in the container and starts rescue.target automatically rather than whatever default.target is. We'd probably want to specifically boot a multi-user.target by default and the best way to do that temporarily would be to provide a fake command line to the booted instance. Now we could change what we use to identify our rescue image, but it would seem to me that this shouldn't be needed and faking kernel command lines as seen by containers should be something that's possible. Cheers! Col -- Colin Guthrie gmane(at)colin.guthr.ie http://colin.guthr.ie/ Day Job: Tribalogic Limited http://www.tribalogic.net/ Open Source: Mageia Contributor http://www.mageia.org/ PulseAudio Hacker http://www.pulseaudio.org/ Trac Hacker http://trac.edgewall.org/ ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] test: rework run_qemu
On Sat, Dec 7, 2013 at 3:01 PM, Ronny Chevalier chevalier.ro...@gmail.com wrote: It tries to find a suitable QEMU binary and will use KVM if present. We can now configure QEMU from outside with 4 variables : - $QEMU_BIN : path to QEMU's binary - $KERNEL_APPEND : arguments appended to kernel cmdline - $KERNEL_BIN : path to a kernel Default /boot/vmlinuz-$KERNEL_VER - $INITRD : path to an initramfs Default /boot/initramfs-${KERNEL_VER}.img - $QEMU_SMP : number of CPU simulated by QEMU. Default 1 (from Alexander Graf's script: http://www.spinics.net/lists/kvm/msg72389.html) --- TODO| 1 - test/README.testsuite | 19 ++-- test/TEST-01-BASIC/test.sh | 8 ++--- test/TEST-02-CRYPTSETUP/test.sh | 8 ++--- test/TEST-03-JOBS/test.sh | 8 ++--- test/test-functions | 65 +++-- 6 files changed, 78 insertions(+), 31 deletions(-) diff --git a/TODO b/TODO index 9698082..f493dbb 100644 --- a/TODO +++ b/TODO @@ -168,7 +168,6 @@ Features: * test/: - add 'set -e' to scripts in test/ - make stuff in test/ work with separate output dir - - qemu wrapper script: http://www.spinics.net/lists/kvm/msg72389.html * systemctl delete x.snapshot leaves no trace in logs (at least at default level). diff --git a/test/README.testsuite b/test/README.testsuite index 54d0eaa..2ae85a2 100644 --- a/test/README.testsuite +++ b/test/README.testsuite @@ -25,11 +25,24 @@ $ make all $ cd test/TEST-01-BASIC $ sudo make clean setup run +QEMU + + If you want to log in the testsuite virtual machine, you can specify -additional kernel command line parameter with $DEBUGFAIL. +additional kernel command line parameter with $KERNEL_APPEND. -$ sudo make DEBUGFAIL=systemd.unit=multi-user.target clean setup run +$ sudo make KERNEL_APPEND=systemd.unit=multi-user.target clean setup run you can even skip the clean and setup if you want to run the machine again. -$ sudo make DEBUGFAIL=systemd.unit=multi-user.target run +$ sudo make KERNEL_APPEND=systemd.unit=multi-user.target run + +You can specify a different kernel and initramfs with $KERNEL_BIN and $INITRD. +(Fedora's default kernel path and initramfs are used by default) + +$ sudo make KERNEL_BIN=/boot/vmlinuz-foo INITRD=/boot/initramfs-bar clean check + +A script will try to find your QEMU binary. If you want to specify a different +one you can use $QEMU_BIN. + +$ sudo make QEMU_BIN=/path/to/qemu/qemu-kvm clean check diff --git a/test/TEST-01-BASIC/test.sh b/test/TEST-01-BASIC/test.sh index aaf63f4..84ccf26 100755 --- a/test/TEST-01-BASIC/test.sh +++ b/test/TEST-01-BASIC/test.sh @@ -5,9 +5,6 @@ TEST_DESCRIPTION=Basic systemd setup . $TEST_BASE_DIR/test-functions -# Uncomment this to debug failures -#DEBUGFAIL=systemd.unit=multi-user.target - check_result_qemu() { ret=1 mkdir -p $TESTDIR/root @@ -23,11 +20,10 @@ check_result_qemu() { } test_run() { -if check_qemu ; then -run_qemu +if run_qemu; then check_result_qemu || return 1 else -dwarn can't run qemu-kvm, skipping +dwarn can't run QEMU, skipping fi if check_nspawn; then run_nspawn diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh index 86617df..d7e8776 100755 --- a/test/TEST-02-CRYPTSETUP/test.sh +++ b/test/TEST-02-CRYPTSETUP/test.sh @@ -5,9 +5,6 @@ TEST_DESCRIPTION=cryptsetup systemd setup . $TEST_BASE_DIR/test-functions -# Uncomment this to debug failures -#DEBUGFAIL=systemd.unit=multi-user.target - check_result_qemu() { ret=1 mkdir -p $TESTDIR/root @@ -28,11 +25,10 @@ check_result_qemu() { test_run() { -if check_qemu ; then -run_qemu +if run_qemu; then check_result_qemu || return 1 else -dwarn can't run qemu-kvm, skipping +dwarn can't run QEMU, skipping fi return 0 } diff --git a/test/TEST-03-JOBS/test.sh b/test/TEST-03-JOBS/test.sh index 6303258..41e02e2 100755 --- a/test/TEST-03-JOBS/test.sh +++ b/test/TEST-03-JOBS/test.sh @@ -5,9 +5,6 @@ TEST_DESCRIPTION=Job-related tests . $TEST_BASE_DIR/test-functions -# Uncomment this to debug failures -#DEBUGFAIL=systemd.unit=multi-user.target - check_result_qemu() { ret=1 mkdir -p $TESTDIR/root @@ -23,11 +20,10 @@ check_result_qemu() { } test_run() { -if check_qemu ; then -run_qemu +if run_qemu; then check_result_qemu || return 1 else -dwarn can't run qemu-kvm, skipping +dwarn can't run QEMU, skipping fi if check_nspawn; then run_nspawn diff --git a/test/test-functions b/test/test-functions index a184ed7..87d3a73 100644 --- a/test/test-functions +++ b/test/test-functions @@ -10,12 +10,63 @@ KERNEL_MODS=/lib/modules/$KERNEL_VER/ BASICTOOLS=sh bash
Re: [systemd-devel] [PATCH 4/4] core: lazy distribute for Distribute pools
On Sun, Dec 8, 2013 at 7:50 PM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Mon, Nov 18, 2013 at 12:36:52AM +0100, Zbigniew Jędrzejewski-Szmek wrote: On Sun, Nov 17, 2013 at 02:57:56PM -0800, Shawn Landden wrote: On Sun, Nov 17, 2013 at 2:28 PM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Sun, Nov 17, 2013 at 08:46:46PM +0100, Lennart Poettering wrote: On Sat, 16.11.13 13:18, Shawn Landden (sh...@churchofgit.com) wrote: So, what's the status here? Are you sending a new series, or is this one supposed to be merged? This one doesn't work. I have have a somewhat-working next patch, but the way epoll_wait works it actually isn't lazy at all, and would require EPOLLET to even do one-spawn-per-connection (global connection), but we can't do that with the current event loop. I ended up getting side-tracked into adding mount-namespace to lsof, cause i noticed that feature lacking while working on this Anyways, a new series will come, and I am working on it. Zbyszek -- --- Shawn Landden +1 360 389 3001 (SMS preferred) ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] update README to not suggest that systemd works without procfs
--- README | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README b/README index cc43953..f2a86c5 100644 --- a/README +++ b/README @@ -45,6 +45,7 @@ REQUIREMENTS: CONFIG_EPOLL CONFIG_NET CONFIG_SYSFS + CONFIG_PROC_FS Linux kernel = 3.8 for Smack support @@ -75,9 +76,7 @@ REQUIREMENTS: CONFIG_TMPFS_XATTR CONFIG_SECCOMP -For systemd-bootchart, a kernel with procfs support and -several proc output options enabled is required: - CONFIG_PROC_FS +For systemd-bootchar, several proc debug interfaces are required: CONFIG_SCHEDSTATS CONFIG_SCHED_DEBUG -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 2/2] epoll and signalfd has been moved into sd event loop
--- src/core/manager.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index f06df54..56c10cf 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -22,9 +22,7 @@ #include assert.h #include errno.h #include string.h -#include sys/epoll.h #include signal.h -#include sys/signalfd.h #include sys/wait.h #include unistd.h #include sys/poll.h -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH 1/2] core: support Distribute=n to distribute to n workers
Until there are some use cases for Distribute= w/o SO_REUSEPORT make it imply that. Otherwise we need a new config_parse_distribute in load-fragment.c and gain the same issues of config_parse_syscall, where NoNewPrivs can be still set to false, but only if set _after_ SystemCallFilter (only allowed when root). Because it takes a while for the service to start up, and until then we spin in a fast epoll loop, this tends to start up all the instances all at once. There are a number of ways we can slow this instanciation down: 1) Call accept() and pass an additional fd to the service 2) Use EPOLLET: requires event to be prioritized and always dispatched. 3) Disable and then reenable the event source every time we enqueue an instance. IMHO #1 is not acceptable. For #2, perhaps the new event loop infrastructure can support a special class for EPOLLET. I am going to investigate #3 right after sending this patch. --- TODO | 3 +- man/systemd.socket.xml| 11 ++ src/core/dbus-socket.c| 2 +- src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/socket.c | 64 +++ src/core/socket.h | 3 ++ 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/TODO b/TODO index 8f9aabc..15233cd 100644 --- a/TODO +++ b/TODO @@ -69,7 +69,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it * we probably should replace the left-over uses of strv_append() and replace them by strv_push() or strv_extend() @@ -187,7 +187,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..48a4b77 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -519,6 +519,17 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. Systemd will spawn up to +given number of instances of service each +listening to the same socket. Default is 0. +Setting this requires corresponding service to +be an instansiated service (name ends with literal@.service/literal). +Useful with varnameReuseport=/varname above./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 74217df..68c95a0 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -40,7 +40,6 @@ static int property_get_listen( void *userdata, sd_bus_error *error) { - Socket *s = SOCKET(userdata); SocketPort *p; int r; @@ -116,6 +115,7 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY(MessageQueueMessageSize, x, bus_property_get_long, offsetof(Socket, mq_msgsize), 0), SD_BUS_PROPERTY(Result, s, property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY(ReusePort, b, bus_property_get_bool, offsetof(Socket, reuse_port), 0), +SD_BUS_PROPERTY(Distribute, u, bus_property_get_unsigned, offsetof(Socket, distribute), 0), SD_BUS_PROPERTY(SmackLabel, s, NULL, offsetof(Socket, smack), 0), SD_BUS_PROPERTY(SmackLabelIPIn, s, NULL, offsetof(Socket, smack_ip_in), 0), SD_BUS_PROPERTY(SmackLabelIPOut, s, NULL, offsetof(Socket, smack_ip_out), 0), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index a5033b2..de82586 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -213,6 +213,7 @@ Socket.PassCredentials, config_parse_bool, 0, Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.TCPCongestion,
[systemd-devel] [PATCH] core/manager: remove infinite loop
--- src/core/manager.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index f06df54..c25343f 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2211,10 +2211,8 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { } finish: -if (ferror(f)) { +if (ferror(f)) r = -EIO; -goto finish; -} assert(m-n_reloading 0); m-n_reloading --; -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] core: support Distribute=n to distribute to n workers
Because it takes a while for the service to start up, and until then we spin in a fast epoll loop, this tends to start up all the instances all at once. There are a number of ways we can slow this instanciation down: 1) Call accept() and pass an additional fd to the service 2) Use EPOLLET: requires event to be prioritized and always dispatched. 3) Disable and then reenable the event source every time we enqueue an instance. With Type=notify, we wait until a service tells us it is ready before we listen again and thereby start up more instances. What if someone want to use the templating namespace ('@') with Distribute=? --- TODO | 3 +- man/systemd.socket.xml| 15 +++- src/core/dbus-socket.c| 2 +- src/core/load-fragment-gperf.gperf.m4 | 3 +- src/core/service.c| 4 ++ src/core/socket.c | 72 --- src/core/socket.h | 8 +++- 7 files changed, 78 insertions(+), 29 deletions(-) diff --git a/TODO b/TODO index 2fb9cd3..697d568 100644 --- a/TODO +++ b/TODO @@ -69,7 +69,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it * we probably should replace the left-over uses of strv_append() and replace them by strv_push() or strv_extend() @@ -187,7 +187,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..6799020 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -404,7 +404,8 @@ designed for usage with citerefentryrefentrytitleinetd/refentrytitlemanvolnum8/manvolnum/citerefentry to work unmodified with systemd socket -activation./para/listitem +activation. Incompatible with + varnameDistribute=/varname/para/listitem /varlistentry varlistentry @@ -519,6 +520,18 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. Systemd will spawn up to +given number of instances of service each +listening to the same socket. Default is 0. +Setting this requires corresponding service to +be an instansiated service (name ends with literal@.service/literal). +Useful with varnameReusePort=/varname above. +Incompatible with varnameAccept=true/varname./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 74217df..68c95a0 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -40,7 +40,6 @@ static int property_get_listen( void *userdata, sd_bus_error *error) { - Socket *s = SOCKET(userdata); SocketPort *p; int r; @@ -116,6 +115,7 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY(MessageQueueMessageSize, x, bus_property_get_long, offsetof(Socket, mq_msgsize), 0), SD_BUS_PROPERTY(Result, s, property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY(ReusePort, b, bus_property_get_bool, offsetof(Socket, reuse_port), 0), +SD_BUS_PROPERTY(Distribute, u, bus_property_get_unsigned, offsetof(Socket, distribute), 0), SD_BUS_PROPERTY(SmackLabel, s, NULL, offsetof(Socket, smack), 0), SD_BUS_PROPERTY(SmackLabelIPIn, s, NULL, offsetof(Socket, smack_ip_in), 0), SD_BUS_PROPERTY(SmackLabelIPOut, s, NULL, offsetof(Socket, smack_ip_out), 0), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
[systemd-devel] [PATCH] timedatectl: work with old timedated
Which does have TimeUSec. Should we specifically check for this method instead of assuming time=0 means it doesn't exist? Before: shawn@debian-T61:~/git/systemd$ ./timedatectl Local time: Wed 1969-12-31 16:00:00 PST Universal time: Thu 1970-01-01 00:00:00 UTC RTC time: n/a Timezone: America/Los_Angeles (PST, -0800) NTP enabled: n/a NTP synchronized: no RTC in local TZ: no DST active: no Last DST change: DST ended at Sun 1969-10-26 01:59:59 PDT Sun 1969-10-26 01:00:00 PST Next DST change: DST begins (the clock jumps one hour forward) at Sun 1970-04-26 01:59:59 PST Sun 1970-04-26 03:00:00 PDT After: shawn@debian-T61:~/git/systemd$ ./timedatectl Local time: Wed 2013-12-11 14:03:21 PST Universal time: Wed 2013-12-11 22:03:21 UTC RTC time: n/a Timezone: America/Los_Angeles (PST, -0800) NTP enabled: n/a NTP synchronized: no RTC in local TZ: no DST active: no Last DST change: DST ended at Sun 2013-11-03 01:59:59 PDT Sun 2013-11-03 01:00:00 PST Next DST change: DST begins (the clock jumps one hour forward) at Sun 2014-03-09 01:59:59 PST Sun 2014-03-09 03:00:00 PDT --- src/timedate/timedatectl.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 9b81513..7dba8e9 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -106,14 +106,19 @@ static void print_status_info(const StatusInfo *i) { assert(i); +if (i-time) +sec = (time_t) (i-time / USEC_PER_SEC); +else if (arg_transport == BUS_TRANSPORT_LOCAL) +sec = time(NULL); +else +return (void)fprintf(stderr, Could not get time from timedated and not operating locally.\n\n); + /* Enforce the values of /etc/localtime */ if (getenv(TZ)) { fprintf(stderr, Warning: ignoring the TZ variable, reading the system's timezone setting only.\n\n); unsetenv(TZ); } -sec = (time_t) (i-time / USEC_PER_SEC); - zero(tm); assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S %Z, localtime_r(sec, tm)) 0); char_array_0(a); -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] test-fileio: replace mktemp with mkstemp to avoid warnings
Thank you for this! On Wed, Dec 11, 2013 at 5:55 PM, Thomas H.P. Andersen pho...@gmail.com wrote: On Thu, Dec 12, 2013 at 1:41 AM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Thu, Dec 12, 2013 at 12:32:43AM +0100, Thomas H.P. Andersen wrote: From: Thomas Hindoe Paaboel Andersen pho...@gmail.com This is a fairly useless thing to do but it makes the compilers and analyzers shut up about the use of mktemp. Please apply it. Spurious warnings are very annoying. Applied. Thanks. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [HACK/RFC/PATCH] systemd-su: su on steroids
On Tue, Dec 10, 2013 at 3:18 PM, Lennart Poettering lenn...@poettering.net wrote: On Mon, 02.12.13 21:47, David Herrmann (dh.herrm...@gmail.com) wrote: 4h later, I present systemd-su: If you want to give it a try, run: systemd-su -u david /bin/sh It requires the systemd-suexec helper internally, so if you didn't install it, use something like this: SYSTEMD_SUEXEC=/home/david/dev/systemd/systemd-suexec ./systemd-su -u david sh Otherwise, systemd-su cannot find the systemd-suexec binary. Hmm, if we allow that su - tells logind to create an entirely new session even when called from an existing one, do we still need systemd-su? That should be pretty close, no? That sounds easier to do... Additionally, I create an anonymous AF_UNIX socket in systemd-su which systemd-suexec connects to. I then pass file-descriptors to systemd-suexec which installes them as STDIN/OUT/ERR. I actually think it would be quite useful to extend the StartTransientUnit() dbus call to allow passing FDs. It would allow us to store FDs with active units, which would be useful for a lot of other concepts (like storing DRM framebuffer handles..). Hmm, so we thought about adding support for something like a per-service fd storage facility in systemd. This would be populated from the .socket units, but could also be passed in for transient units by the caller or even updated by the services themselves if they want to store additional fds in systemd. This would solve a number of issues for us, including one big one: currently if you restart systemd-journald you lose the per-service stdout/stderr connections because there's no way to save them. We need to do this in order to integrate criu into systemd as well. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] timedatectl: work with old timedated
Which does have TimeUSec. Should we specifically check for this method instead of assuming time=0 means it doesn't exist? Before: shawn@debian-T61:~/git/systemd$ ./timedatectl Local time: Wed 1969-12-31 16:00:00 PST Universal time: Thu 1970-01-01 00:00:00 UTC RTC time: n/a Timezone: America/Los_Angeles (PST, -0800) NTP enabled: n/a NTP synchronized: no RTC in local TZ: no DST active: no Last DST change: DST ended at Sun 1969-10-26 01:59:59 PDT Sun 1969-10-26 01:00:00 PST Next DST change: DST begins (the clock jumps one hour forward) at Sun 1970-04-26 01:59:59 PST Sun 1970-04-26 03:00:00 PDT After: shawn@debian-T61:~/git/systemd$ ./timedatectl Local time: Wed 2013-12-11 14:03:21 PST Universal time: Wed 2013-12-11 22:03:21 UTC RTC time: n/a Timezone: America/Los_Angeles (PST, -0800) NTP enabled: n/a NTP synchronized: no RTC in local TZ: no DST active: no Last DST change: DST ended at Sun 2013-11-03 01:59:59 PDT Sun 2013-11-03 01:00:00 PST Next DST change: DST begins (the clock jumps one hour forward) at Sun 2014-03-09 01:59:59 PST Sun 2014-03-09 03:00:00 PDT --- src/timedate/timedatectl.c | 43 ++- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 9b81513..6b09559 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -98,6 +98,7 @@ static void print_status_info(const StatusInfo *i) { char s[32]; struct tm tm; time_t sec; +bool have_time = false; char *zc, *zn; time_t t, tc, tn; int dn; @@ -109,20 +110,35 @@ static void print_status_info(const StatusInfo *i) { /* Enforce the values of /etc/localtime */ if (getenv(TZ)) { fprintf(stderr, Warning: ignoring the TZ variable, reading the system's timezone setting only.\n\n); +fflush(stderr); unsetenv(TZ); } -sec = (time_t) (i-time / USEC_PER_SEC); +if (i-time != 0) { +sec = (time_t) (i-time / USEC_PER_SEC); +have_time = true; +} else if (arg_transport == BUS_TRANSPORT_LOCAL) { +sec = time(NULL); +have_time = true; +} else { +fprintf(stderr, Warning: could not get time from timedated and not operating locally.\n\n); +fflush(stderr); +} -zero(tm); -assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S %Z, localtime_r(sec, tm)) 0); -char_array_0(a); -printf( Local time: %s\n, a); +if (have_time) { +zero(tm); +assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S %Z, localtime_r(sec, tm)) 0); +char_array_0(a); +printf( Local time: %s\n, a); -zero(tm); -assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S UTC, gmtime_r(sec, tm)) 0); -char_array_0(a); -printf( Universal time: %s\n, a); +zero(tm); +assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S UTC, gmtime_r(sec, tm)) 0); +char_array_0(a); +printf( Universal time: %s\n, a); +} else { +printf( Local time: %s\n, n/a); +printf( Universal time: %s\n, n/a); +} if (i-rtc_time 0) { time_t rtc_sec; @@ -133,7 +149,7 @@ static void print_status_info(const StatusInfo *i) { char_array_0(a); printf(RTC time: %s\n, a); } else -printf(RTC time: n/a\n); +printf(RTC time: %s\n, n/a); zero(tm); assert_se(strftime(a, sizeof(a), %Z, %z, localtime_r(sec, tm)) 0); @@ -151,8 +167,8 @@ static void print_status_info(const StatusInfo *i) { tc, zc, is_dstc, tn, dn, zn, is_dstn); if (r 0) -printf( DST active: n/a\n); -else { +printf( DST active: %s\n, n/a); +else if (have_time) { printf( DST active: %s\n, yes_no(is_dstc)); t = tc - 1; @@ -183,7 +199,8 @@ static void print_status_info(const StatusInfo *i) { free(zc); free(zn); -} +} else +printf( DST active: %s\n, yes_no(is_dstc)); if (i-rtc_local) fputs(\n ANSI_HIGHLIGHT_ON -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] timedatectl: work with old timedated
On Thu, Dec 12, 2013 at 11:02 AM, Lennart Poettering lenn...@poettering.net wrote: On Thu, 12.12.13 10:00, Shawn Landden (sh...@churchofgit.com) wrote: Applied. Dropped the fflush(stderr) bits though as we that's not necessary for stderr, and not even for stdout if an \n was printed anyway... ok, I was worried about the lack of synchronization between stderr and stdout causing them to interlace. Thanks! diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 9b81513..6b09559 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -98,6 +98,7 @@ static void print_status_info(const StatusInfo *i) { char s[32]; struct tm tm; time_t sec; +bool have_time = false; char *zc, *zn; time_t t, tc, tn; int dn; @@ -109,20 +110,35 @@ static void print_status_info(const StatusInfo *i) { /* Enforce the values of /etc/localtime */ if (getenv(TZ)) { fprintf(stderr, Warning: ignoring the TZ variable, reading the system's timezone setting only.\n\n); +fflush(stderr); unsetenv(TZ); } -sec = (time_t) (i-time / USEC_PER_SEC); +if (i-time != 0) { +sec = (time_t) (i-time / USEC_PER_SEC); +have_time = true; +} else if (arg_transport == BUS_TRANSPORT_LOCAL) { +sec = time(NULL); +have_time = true; +} else { +fprintf(stderr, Warning: could not get time from timedated and not operating locally.\n\n); +fflush(stderr); +} -zero(tm); -assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S %Z, localtime_r(sec, tm)) 0); -char_array_0(a); -printf( Local time: %s\n, a); +if (have_time) { +zero(tm); +assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S %Z, localtime_r(sec, tm)) 0); +char_array_0(a); +printf( Local time: %s\n, a); -zero(tm); -assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S UTC, gmtime_r(sec, tm)) 0); -char_array_0(a); -printf( Universal time: %s\n, a); +zero(tm); +assert_se(strftime(a, sizeof(a), %a %Y-%m-%d %H:%M:%S UTC, gmtime_r(sec, tm)) 0); +char_array_0(a); +printf( Universal time: %s\n, a); +} else { +printf( Local time: %s\n, n/a); +printf( Universal time: %s\n, n/a); +} if (i-rtc_time 0) { time_t rtc_sec; @@ -133,7 +149,7 @@ static void print_status_info(const StatusInfo *i) { char_array_0(a); printf(RTC time: %s\n, a); } else -printf(RTC time: n/a\n); +printf(RTC time: %s\n, n/a); zero(tm); assert_se(strftime(a, sizeof(a), %Z, %z, localtime_r(sec, tm)) 0); @@ -151,8 +167,8 @@ static void print_status_info(const StatusInfo *i) { tc, zc, is_dstc, tn, dn, zn, is_dstn); if (r 0) -printf( DST active: n/a\n); -else { +printf( DST active: %s\n, n/a); +else if (have_time) { printf( DST active: %s\n, yes_no(is_dstc)); t = tc - 1; @@ -183,7 +199,8 @@ static void print_status_info(const StatusInfo *i) { free(zc); free(zn); -} +} else +printf( DST active: %s\n, yes_no(is_dstc)); if (i-rtc_local) fputs(\n ANSI_HIGHLIGHT_ON Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] core: support Distribute=n to distribute to n workers
If Distribute=n, turns SO_REUSEPORT on, and spawns n workers to handling incoming requests. SO_REUSEPORT sockets on the same port must all be created by the same uid, therefore using the option allows other root programs (or programs of the same user if running in --user mode) to hijack this port, even after systemd reserves it. This patch is currently not ready for merging because it is possible to do quite a number of operations, and yet have no assurance that we have accomplished anything, ending up in an infinite loop respawning a service that never accept()s the socket passed to it, and therefore leaving our copy of the socket always in EPOLLIN status. To prevent this we need to do one of: *) Call accept() and pass an additional fd to the service. *) Use EPOLLET: requires event to always dispatched when it comes in. *) Disable and then reenable the event source (requiring that we re-create the socket) every time we enqueue an instance, essentially emulating the behavior of EPOLLET. --- TODO | 3 +- man/systemd.socket.xml| 15 ++- src/core/dbus-socket.c| 4 +- src/core/load-fragment-gperf.gperf.m4 | 3 +- src/core/socket.c | 76 --- src/core/socket.h | 5 ++- src/shared/conf-parser.c | 32 +++ src/shared/conf-parser.h | 1 + 8 files changed, 109 insertions(+), 30 deletions(-) diff --git a/TODO b/TODO index dad55c4..fbc2609 100644 --- a/TODO +++ b/TODO @@ -73,7 +73,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it * move config_parse_path_strv() out of conf-parser.c @@ -187,7 +187,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..6799020 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -404,7 +404,8 @@ designed for usage with citerefentryrefentrytitleinetd/refentrytitlemanvolnum8/manvolnum/citerefentry to work unmodified with systemd socket -activation./para/listitem +activation. Incompatible with + varnameDistribute=/varname/para/listitem /varlistentry varlistentry @@ -519,6 +520,18 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. Systemd will spawn up to +given number of instances of service each +listening to the same socket. Default is 0. +Setting this requires corresponding service to +be an instansiated service (name ends with literal@.service/literal). +Useful with varnameReusePort=/varname above. +Incompatible with varnameAccept=true/varname./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 74217df..036c9af 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -40,7 +40,6 @@ static int property_get_listen( void *userdata, sd_bus_error *error) { - Socket *s = SOCKET(userdata); SocketPort *p; int r; @@ -115,7 +114,8 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY(MessageQueueMaxMessages, x, bus_property_get_long, offsetof(Socket, mq_maxmsg), 0), SD_BUS_PROPERTY(MessageQueueMessageSize, x, bus_property_get_long, offsetof(Socket, mq_msgsize), 0), SD_BUS_PROPERTY(Result, s, property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), -SD_BUS_PROPERTY(ReusePort, b,
Re: [systemd-devel] [PATCH] core: support Distribute=n to distribute to n workers
Forgot to send my notes on the last review On Fri, Dec 13, 2013 at 7:12 AM, Lennart Poettering lenn...@poettering.net wrote: On Thu, 12.12.13 23:46, Shawn Landden (sh...@churchofgit.com) wrote: -Socket.ReusePort,config_parse_bool, 0, offsetof(Socket, reuse_port) +Socket.ReusePort,config_parse_tristate, -1, offsetof(Socket, reuse_port) ^ Why -1 there? That should be there... The parse call doesn't make use of that, so it should be 0, really. fixed, and i see your point, but i still don't know where the default of -1 comes from... +if (s-reuse_port 0) { +if (s-distribute 0) +s-reuse_port = true; +else +s-reuse_port = false; +} + Nitpicking: I'd just write it like this: if (s-reuse_port 0) s-reuse_port = s-distribute 0; thats better -if (s-n_connections = s-max_connections) { +if (s-n_connections = s-max_connections !(s-distribute)) { Still too many () damn -if (se-state == SERVICE_RUNNING) -socket_set_state(s, SOCKET_RUNNING); +if (se-state == SERVICE_RUNNING) { +if (s-n_connections s-distribute) +; +else +socket_set_state(s, SOCKET_RUNNING); +} Hmm, too simple, no? We wanted that logic, that we enter SOCKET_RUNNING as long as at least one service is still starting up or when we reached the limit. I only see the check for the latter here... So before I checked for Type=notify in socket_enter_running and then only spawned one service, so that I could go back to SOCKET_LISTENING here, but without that logic, I don't see a need for any special logic here. Since we only get these notifications for Type=notify, we can't just unilaterally go to Still missing the bit where the socket is duplicated for propery SO_REUSEPORT usgae... OK, so this is the way lwn covered it, but using fork() to replicate the socket works just fine, as the attached program demonstrates (also shows lazy reverse exponential startup), and I see nothing in the original reuseport patches that indicate that this is a bad idea. I'd do this if it was simple (because it gives the EPOLLET behavior I am looking for), but it requires some new fields in SocketPort to handle the CLOEXEC switcharoos, as we will have two of the same socket open at the same time, one spawned before the connection came in to give to the child, and another spawned right after the connection came in, to hold onto for the next connection. I'd really like to avoid that since SO_REUSEPORT does not need it. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ELF @ @ @ 8 @ @ @ @ @ @ À À @ @ @ @ Ô Ô Ø Ø` Ø` À È ð ð` ð` à à @ @ D D Påtd Ì Ì@ Ì@ 4 4 Qåtd /lib64/ld-linux-x86-64.so.2 GNU GNU XÂØdú÷0íBa!^ P 6 = D e [ / K y k * libc.so.6 setuid socket htons epoll_wait fork listen getpid printf memset bind setsockopt epoll_ctl close epoll_create1 accept sleep __libc_start_main write __gmon_start__ GLIBC_2.9 GLIBC_2.3.2 GLIBC_2.2.5 ii ri · ui à Ð` ð` ø` ` ` ` ` ` (` 0` 8` @` H
[systemd-devel] [PATCH] core: support Distribute=n to distribute to n workers
If Distribute=n, turns SO_REUSEPORT on, and spawns n workers to handling incoming requests. SO_REUSEPORT sockets on the same port must all be created by the same uid, therefore using the option allows other root programs (or programs of the same user if running in --user mode) to hijack this port, even after systemd reserves it. This patch is currently not ready for merging because if the service never accept()s the socket passed to it, we stay in EPOLLIN, looping infinitely. To prevent this we need to do one of: *) Call accept() and pass an additional fd to the service. *) Use EPOLLET: requires event to always dispatched when it comes in. *) Disable and then reenable the event source (requiring that we re-create the socket) every time we enqueue an instance, essentially emulating the behavior of EPOLLET. --- TODO | 3 +- man/systemd.socket.xml| 15 +++- src/core/dbus-socket.c| 4 +- src/core/load-fragment-gperf.gperf.m4 | 3 +- src/core/service.c| 4 +- src/core/socket.c | 70 +-- src/core/socket.h | 5 ++- src/shared/conf-parser.c | 32 src/shared/conf-parser.h | 1 + 9 files changed, 108 insertions(+), 29 deletions(-) diff --git a/TODO b/TODO index dad55c4..fbc2609 100644 --- a/TODO +++ b/TODO @@ -73,7 +73,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it * move config_parse_path_strv() out of conf-parser.c @@ -187,7 +187,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..6799020 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -404,7 +404,8 @@ designed for usage with citerefentryrefentrytitleinetd/refentrytitlemanvolnum8/manvolnum/citerefentry to work unmodified with systemd socket -activation./para/listitem +activation. Incompatible with + varnameDistribute=/varname/para/listitem /varlistentry varlistentry @@ -519,6 +520,18 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. Systemd will spawn up to +given number of instances of service each +listening to the same socket. Default is 0. +Setting this requires corresponding service to +be an instansiated service (name ends with literal@.service/literal). +Useful with varnameReusePort=/varname above. +Incompatible with varnameAccept=true/varname./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 74217df..036c9af 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -40,7 +40,6 @@ static int property_get_listen( void *userdata, sd_bus_error *error) { - Socket *s = SOCKET(userdata); SocketPort *p; int r; @@ -115,7 +114,8 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY(MessageQueueMaxMessages, x, bus_property_get_long, offsetof(Socket, mq_maxmsg), 0), SD_BUS_PROPERTY(MessageQueueMessageSize, x, bus_property_get_long, offsetof(Socket, mq_msgsize), 0), SD_BUS_PROPERTY(Result, s, property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), -SD_BUS_PROPERTY(ReusePort, b, bus_property_get_bool, offsetof(Socket, reuse_port), 0), +SD_BUS_PROPERTY(ReusePort, b, bus_property_get_tristate, offsetof(Socket,
[systemd-devel] [PATCH] sd-event: we do not support EPOLLONESHOT correctly
If this event is not the highest priority, then it will not be dispatched when the epoll triggers, and since we will not get any more wakeups (due to the way EPOLLONESHOT works) will never be dispatched. Since we only handle one event per epoll_wait() wakeup, and we dequeue a ONE_SHOT event when we dispatch it, we do not have the problem described in epoll(7) of multiple events can be generated upon receipt of multiple chunks of data. --- src/libsystemd-bus/sd-event.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c index 462dd41..1cf661e 100644 --- a/src/libsystemd-bus/sd-event.c +++ b/src/libsystemd-bus/sd-event.c @@ -447,9 +447,6 @@ static int source_io_register( ev.events = events; ev.data.ptr = s; -if (enabled == SD_EVENT_ONESHOT) -ev.events |= EPOLLONESHOT; - if (s-io.registered) r = epoll_ctl(s-event-epoll_fd, EPOLL_CTL_MOD, s-io.fd, ev); else -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH 1/2] nspawn: --populate to run static binaries on empty target directory
On Tue, Dec 10, 2013 at 2:18 PM, Lennart Poettering lenn...@poettering.net wrote: On Mon, 02.12.13 09:41, Shawn Landden (sh...@churchofgit.com) wrote: On Mon, Dec 2, 2013 at 8:27 AM, Lennart Poettering lenn...@poettering.net wrote: On Sat, 30.11.13 10:20, Shawn Landden (sh...@churchofgit.com) wrote: nspawn has been called chroot on steroids. Continue that tradition by supporting target directories that are not root directories. This patch handles the simple case: a static binary. Hmm, I am not sure how I feel about this. This appears a bit too specific for me, and given the requirement for static binaries this is also so limited. The next patch is the series adds support for dynamic libraries. This patch also doesn't need bind mounts, and it executes through /proc/self/fd/%n, but support for one-file scripts and dynamic libraries in the next patch does require bind mounts. I feel you don't really understand my patch. :/ I'll sum up what I'm doing: If --populate is passed, analyze the executable, which opens it and set the exec path to /proc/self/fd/%n. If executable is static this is all you have to do. If it has a shebang, analyze that. If either the shebang or executable is dynamic, test if the linker is the GNU linker, and if it is have the linker tell use what libraries the executable needs. Then bind mount the linker, shebang (if there is one), and libraries into the target. But somethinglike this will never fully work, Agreed. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] sd-event: we do not support EPOLLONESHOT correctly
On Fri, Dec 13, 2013 at 7:17 PM, Lennart Poettering lenn...@poettering.net wrote: On Fri, 13.12.13 13:08, Shawn Landden (sh...@churchofgit.com) wrote: If this event is not the highest priority, then it will not be dispatched when the epoll triggers, and since we will not get any more wakeups (due to the way EPOLLONESHOT works) will never be dispatched. Hmm, so the way this is supposed to work is that as soon as epoll told us about some event once, we will set the event source to pending, and it stays pending until we have dispatched it, regardless if we ever get the event from epoll again or not. However, we currently will overwrite the revents field should we ever get it again with the new one. It probably makes more sense to OR it in, so that we don't forget readability if writability happens at a later point or vice versa, if you follow what I mean. I'll prep a fix for that. good With that fixed is there something else to still fix? Oh I missed how the pending code worked. Because of that I think I can use EPOLLET with sd-event, and will send a Distribute= patch that uses it. (already have it, just wasn't sure if it was only working cause my test setup has near-0 load) Since we only handle one event per epoll_wait() wakeup, and we dequeue a ONE_SHOT event when we dispatch it, we do not have the problem described in epoll(7) of multiple events can be generated upon receipt of multiple chunks of data. Not sure I follow here? That part appears to be about EPOLLET? That part explains why EPOLLET cannot be used to implement EPOLLONESHOT. The reason is that even with EPOLLET, epoll_wait can generate multiple events for the same watch, if more than one connection came in. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] core: support Distribute=n to distribute to n workers
If Distribute=n, turns SO_REUSEPORT on, and spawns n workers to handling incoming requests. SO_REUSEPORT sockets on the same port must all be created by the same uid, therefore using the option allows other root programs (or programs of the same user if running in --user mode) to hijack this port, even after systemd reserves it. We spawn workers at a rate approximentally reverse exponentially proportianal to the number of incoming connections. Faster based on the time for new workers to start accept()ing and their load, or slower if systemd is under load. --- TODO | 3 +- man/systemd.socket.xml| 15 +++- src/core/dbus-socket.c| 4 +-- src/core/load-fragment-gperf.gperf.m4 | 3 +- src/core/service.c| 4 +-- src/core/socket.c | 68 ++- src/core/socket.h | 5 ++- src/shared/conf-parser.c | 32 + src/shared/conf-parser.h | 1 + 9 files changed, 101 insertions(+), 34 deletions(-) diff --git a/TODO b/TODO index 0b43888..2abe1b4 100644 --- a/TODO +++ b/TODO @@ -73,7 +73,7 @@ Features: * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it -* Add a new Distribute=$NUMBER key to socket units that makes use of SO_REUSEPORT to distribute network traffic on $NUMBER instances +* tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it * move config_parse_path_strv() out of conf-parser.c @@ -181,7 +181,6 @@ Features: * teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) * Support SO_REUSEPORT with socket activation: - - Let systemd maintain a pool of servers. - Use for seamless upgrades, by running the new server before stopping the old. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7c10c58..6799020 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -404,7 +404,8 @@ designed for usage with citerefentryrefentrytitleinetd/refentrytitlemanvolnum8/manvolnum/citerefentry to work unmodified with systemd socket -activation./para/listitem +activation. Incompatible with + varnameDistribute=/varname/para/listitem /varlistentry varlistentry @@ -519,6 +520,18 @@ /varlistentry varlistentry +termvarnameDistribute=/varname/term +listitemparaTakes an integer +value. Systemd will spawn up to +given number of instances of service each +listening to the same socket. Default is 0. +Setting this requires corresponding service to +be an instansiated service (name ends with literal@.service/literal). +Useful with varnameReusePort=/varname above. +Incompatible with varnameAccept=true/varname./para/listitem +/varlistentry + +varlistentry termvarnameSmackLabel=/varname/term termvarnameSmackLabelIPIn=/varname/term termvarnameSmackLabelIPOut=/varname/term diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 74217df..036c9af 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -40,7 +40,6 @@ static int property_get_listen( void *userdata, sd_bus_error *error) { - Socket *s = SOCKET(userdata); SocketPort *p; int r; @@ -115,7 +114,8 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY(MessageQueueMaxMessages, x, bus_property_get_long, offsetof(Socket, mq_maxmsg), 0), SD_BUS_PROPERTY(MessageQueueMessageSize, x, bus_property_get_long, offsetof(Socket, mq_msgsize), 0), SD_BUS_PROPERTY(Result, s, property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), -SD_BUS_PROPERTY(ReusePort, b, bus_property_get_bool, offsetof(Socket, reuse_port), 0), +SD_BUS_PROPERTY(ReusePort, b, bus_property_get_tristate, offsetof(Socket, reuse_port), 0), +SD_BUS_PROPERTY(Distribute, u, bus_property_get_unsigned, offsetof(Socket, distribute), 0), SD_BUS_PROPERTY(SmackLabel, s, NULL, offsetof(Socket, smack), 0), SD_BUS_PROPERTY(SmackLabelIPIn, s, NULL, offsetof(Socket, smack_ip_in), 0),
Re: [systemd-devel] [PATCH] sd-event: we do not support EPOLLONESHOT correctly
On Fri, Dec 13, 2013 at 8:04 PM, Shawn Landden sh...@churchofgit.com wrote: On Fri, Dec 13, 2013 at 7:17 PM, Lennart Poettering lenn...@poettering.net wrote: On Fri, 13.12.13 13:08, Shawn Landden (sh...@churchofgit.com) wrote: If this event is not the highest priority, then it will not be dispatched when the epoll triggers, and since we will not get any more wakeups (due to the way EPOLLONESHOT works) will never be dispatched. Hmm, so the way this is supposed to work is that as soon as epoll told us about some event once, we will set the event source to pending, and it stays pending until we have dispatched it, regardless if we ever get the event from epoll again or not. However, we currently will overwrite the revents field should we ever get it again with the new one. It probably makes more sense to OR it in, so that we don't forget readability if writability happens at a later point or vice versa, if you follow what I mean. I'll prep a fix for that. good With that fixed is there something else to still fix? Oh I missed how the pending code worked. Because of that I think I can use EPOLLET with sd-event, and will send a Distribute= patch that uses it. (already have it, just wasn't sure if it was only working cause my test setup has near-0 load) With either of these, can't we end up in a situation where we have events pending but are still blocking on epoll_wait()? shouldn't we do something like p = have_pending() epoll_wait(foo, foo, foo, p ? timeout : 0); do prioq stuff() mark_pending() dispatch_highest_prio() to avoid this issue? Since we only handle one event per epoll_wait() wakeup, and we dequeue a ONE_SHOT event when we dispatch it, we do not have the problem described in epoll(7) of multiple events can be generated upon receipt of multiple chunks of data. Not sure I follow here? That part appears to be about EPOLLET? That part explains why EPOLLET cannot be used to implement EPOLLONESHOT. The reason is that even with EPOLLET, epoll_wait can generate multiple events for the same watch, if more than one connection came in. Lennart -- Lennart Poettering, Red Hat ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] build: use -ftrapv for development
We want to find these bugs if they exist. --- autogen.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/autogen.sh b/autogen.sh index d0a2f3f..9ffd724 100755 --- a/autogen.sh +++ b/autogen.sh @@ -54,10 +54,10 @@ args=$args \ fi if [ x$1 = xc ]; then -./configure CFLAGS='-g -O0' --enable-kdbus $args +./configure CFLAGS='-g -O0 -ftrapv' --enable-kdbus $args make clean elif [ x$1 = xg ]; then -./configure CFLAGS='-g -Og' --enable-kdbus $args +./configure CFLAGS='-g -Og -ftrapv' --enable-kdbus $args make clean else echo @@ -65,6 +65,6 @@ else echo Initialized build system. For a common configuration please run: echo echo -echo ./configure CFLAGS='-g -O0' --enable-kdbus $args +echo ./configure CFLAGS='-g -O0 -ftrapv' --enable-kdbus $args echo fi -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] udev: fix printf specifiers
This keeps the same behavior, which is wierd. --- src/udev/udev-builtin-path_id.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index 7476330..7543a11 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -71,9 +71,9 @@ static int format_lun_number(struct udev_device *dev, char **path) /* address method 0, peripheral device addressing with bus id of zero */ if (lun 256) -return path_prepend(path, lun-%d, lun); +return path_prepend(path, lun-%hhu, (unsigned char) lun); /* handle all other lun addressing methods by using a variant of the original lun format */ -return path_prepend(path, lun-0x%04x%04x, (lun 0x), (lun 16) 0x); +return path_prepend(path, lun-0x%04hx%04hx, (unsigned short)(lun 0x), (unsigned short)(lun 16) 0x); } static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys) -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] udev: fix printf specifiers
On Sat, Dec 14, 2013 at 8:11 PM, Zbigniew Jędrzejewski-Szmek zbys...@in.waw.pl wrote: On Sat, Dec 14, 2013 at 06:48:34PM -0800, Shawn Landden wrote: This keeps the same behavior, which is wierd. --- src/udev/udev-builtin-path_id.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index 7476330..7543a11 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -71,9 +71,9 @@ static int format_lun_number(struct udev_device *dev, char **path) /* address method 0, peripheral device addressing with bus id of zero */ if (lun 256) -return path_prepend(path, lun-%d, lun); +return path_prepend(path, lun-%hhu, (unsigned char) lun); /* handle all other lun addressing methods by using a variant of the original lun format */ -return path_prepend(path, lun-0x%04x%04x, (lun 0x), (lun 16) 0x); +return path_prepend(path, lun-0x%04hx%04hx, (unsigned short)(lun 0x), (unsigned short)(lun 16) 0x); } Hm, nothing wrong with this approach, but I don't like all those casts. I just decided to be explicit about what the code was doing because it is confusing, and AFAICT without any other justification, probably wrong. it could have been fixed by simply removing the long above, as the top comment says that it is only 32-bits wide. (and the formatting only supports 32-bits too) if you are going to put the least siginificant bytes first, wouldn't you want to do so byte-wise, instead of creating this mixed-endian monster? I pushed a simpler change which adds 'l' in appropriate places. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] __thread -- thread_local for C11 compat
also make thread_local available w/o including threads.h --- src/libsystemd-bus/sd-bus.c | 4 ++-- src/libsystemd-bus/sd-event.c | 2 +- src/libsystemd-id128/sd-id128.c | 8 src/login/logind-inhibit.c | 2 +- src/shared/capability.c | 4 ++-- src/shared/cgroup-util.c| 2 +- src/shared/macro.h | 8 src/shared/util.c | 6 +++--- src/shared/virt.c | 8 9 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 4eaceef..64cd663 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -2815,13 +2815,13 @@ static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus } _public_ int sd_bus_default_system(sd_bus **ret) { -static __thread sd_bus *default_system_bus = NULL; +static thread_local sd_bus *default_system_bus = NULL; return bus_default(sd_bus_open_system, default_system_bus, ret); } _public_ int sd_bus_default_user(sd_bus **ret) { -static __thread sd_bus *default_user_bus = NULL; +static thread_local sd_bus *default_user_bus = NULL; return bus_default(sd_bus_open_user, default_user_bus, ret); } diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c index 06c84d7..727528b 100644 --- a/src/libsystemd-bus/sd-event.c +++ b/src/libsystemd-bus/sd-event.c @@ -2116,7 +2116,7 @@ _public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) { _public_ int sd_event_default(sd_event **ret) { -static __thread sd_event *default_event = NULL; +static thread_local sd_event *default_event = NULL; sd_event *e; int r; diff --git a/src/libsystemd-id128/sd-id128.c b/src/libsystemd-id128/sd-id128.c index 07d2415..9ee40ab 100644 --- a/src/libsystemd-id128/sd-id128.c +++ b/src/libsystemd-id128/sd-id128.c @@ -104,8 +104,8 @@ static sd_id128_t make_v4_uuid(sd_id128_t id) { } _public_ int sd_id128_get_machine(sd_id128_t *ret) { -static __thread sd_id128_t saved_machine_id; -static __thread bool saved_machine_id_valid = false; +static thread_local sd_id128_t saved_machine_id; +static thread_local bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; ssize_t k; @@ -153,8 +153,8 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { } _public_ int sd_id128_get_boot(sd_id128_t *ret) { -static __thread sd_id128_t saved_boot_id; -static __thread bool saved_boot_id_valid = false; +static thread_local sd_id128_t saved_boot_id; +static thread_local bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; ssize_t k; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index ec6a722..042586d 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -413,7 +413,7 @@ bool manager_is_inhibited( } const char *inhibit_what_to_string(InhibitWhat w) { -static __thread char buffer[97]; +static thread_local char buffer[97]; char *p; if (w 0 || w = _INHIBIT_WHAT_MAX) diff --git a/src/shared/capability.c b/src/shared/capability.c index 3219520..f34f6ba 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -55,8 +55,8 @@ int have_effective_cap(int value) { } unsigned long cap_last_cap(void) { -static __thread unsigned long saved; -static __thread bool valid = false; +static thread_local unsigned long saved; +static thread_local bool valid = false; unsigned long p; if (valid) diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 2c2ffc5..309f65d 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -480,7 +480,7 @@ static int join_path(const char *controller, const char *path, const char *suffi int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; -static __thread bool good = false; +static thread_local bool good = false; assert(fs); diff --git a/src/shared/macro.h b/src/shared/macro.h index fd3762e..903e8ee 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -27,6 +27,14 @@ #include sys/uio.h #include inttypes.h +#if __STDC_VERSION__ = 201112L !defined(__STDC_NO_THREADS__) +#else +# define _Thread_local __thread +#endif + +/* make thread_local available w/o including threads.h */ +#define thread_local _Thread_local + #define _printf_(a,b) __attribute__ ((format (printf, a, b))) #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) #define _sentinel_ __attribute__ ((sentinel)) diff --git a/src/shared/util.c b/src/shared/util.c index 7c73074..0ce6f70 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -86,7 +86,7 @@ static volatile unsigned
[systemd-devel] [PATCH] __thread -- thread_local for C11 compat
also make thread_local available w/o including threads.h --- src/libsystemd-bus/sd-bus.c | 4 ++-- src/libsystemd-bus/sd-event.c | 2 +- src/libsystemd-id128/sd-id128.c | 8 src/login/logind-inhibit.c | 2 +- src/shared/capability.c | 4 ++-- src/shared/cgroup-util.c| 2 +- src/shared/macro.h | 10 ++ src/shared/util.c | 6 +++--- src/shared/virt.c | 8 9 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 4eaceef..64cd663 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -2815,13 +2815,13 @@ static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus } _public_ int sd_bus_default_system(sd_bus **ret) { -static __thread sd_bus *default_system_bus = NULL; +static thread_local sd_bus *default_system_bus = NULL; return bus_default(sd_bus_open_system, default_system_bus, ret); } _public_ int sd_bus_default_user(sd_bus **ret) { -static __thread sd_bus *default_user_bus = NULL; +static thread_local sd_bus *default_user_bus = NULL; return bus_default(sd_bus_open_user, default_user_bus, ret); } diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c index 06c84d7..727528b 100644 --- a/src/libsystemd-bus/sd-event.c +++ b/src/libsystemd-bus/sd-event.c @@ -2116,7 +2116,7 @@ _public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) { _public_ int sd_event_default(sd_event **ret) { -static __thread sd_event *default_event = NULL; +static thread_local sd_event *default_event = NULL; sd_event *e; int r; diff --git a/src/libsystemd-id128/sd-id128.c b/src/libsystemd-id128/sd-id128.c index 07d2415..9ee40ab 100644 --- a/src/libsystemd-id128/sd-id128.c +++ b/src/libsystemd-id128/sd-id128.c @@ -104,8 +104,8 @@ static sd_id128_t make_v4_uuid(sd_id128_t id) { } _public_ int sd_id128_get_machine(sd_id128_t *ret) { -static __thread sd_id128_t saved_machine_id; -static __thread bool saved_machine_id_valid = false; +static thread_local sd_id128_t saved_machine_id; +static thread_local bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; ssize_t k; @@ -153,8 +153,8 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { } _public_ int sd_id128_get_boot(sd_id128_t *ret) { -static __thread sd_id128_t saved_boot_id; -static __thread bool saved_boot_id_valid = false; +static thread_local sd_id128_t saved_boot_id; +static thread_local bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; ssize_t k; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index ec6a722..042586d 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -413,7 +413,7 @@ bool manager_is_inhibited( } const char *inhibit_what_to_string(InhibitWhat w) { -static __thread char buffer[97]; +static thread_local char buffer[97]; char *p; if (w 0 || w = _INHIBIT_WHAT_MAX) diff --git a/src/shared/capability.c b/src/shared/capability.c index 3219520..f34f6ba 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -55,8 +55,8 @@ int have_effective_cap(int value) { } unsigned long cap_last_cap(void) { -static __thread unsigned long saved; -static __thread bool valid = false; +static thread_local unsigned long saved; +static thread_local bool valid = false; unsigned long p; if (valid) diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 2c2ffc5..309f65d 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -480,7 +480,7 @@ static int join_path(const char *controller, const char *path, const char *suffi int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; -static __thread bool good = false; +static thread_local bool good = false; assert(fs); diff --git a/src/shared/macro.h b/src/shared/macro.h index fd3762e..c0597fa 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -27,6 +27,16 @@ #include sys/uio.h #include inttypes.h +#if __STDC_VERSION__ = 201112L !defined(__STDC_NO_THREADS__) +#else +# define _Thread_local __thread +#endif + +/* make thread_local available w/o including threads.h */ +#ifndef thread_local +# define thread_local _Thread_local +#endif + #define _printf_(a,b) __attribute__ ((format (printf, a, b))) #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) #define _sentinel_ __attribute__ ((sentinel)) diff --git a/src/shared/util.c b/src/shared/util.c index 7c73074..0ce6f70 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -86,7
Re: [systemd-devel] [PATCH] __thread -- thread_local for C11 compat
On Sun, Dec 15, 2013 at 1:56 PM, Lennart Poettering lenn...@poettering.net wrote: On Sun, 15.12.13 13:19, Shawn Landden (sh...@churchofgit.com) wrote: also make thread_local available w/o including threads.h Hmm, that looks a bit too early, no? Does gcc even support this? glibc gcc-4.9 supports _Thread_local http://gcc.gnu.org/gcc-4.9/changes.html switching -std=gnu99 to -std=gnu11 in Makefile I can compile systemd w/o the clause that defines _Thread_local as __thread and all tests pass. Perhaps we should add || (__GNUC__ == 4 __GNUC_MINOR__ = 9) to the check doesn't support threads.h afaics... I couldn't find anything in particular regarding C11 TLS support in gcc with google, any link you can recommend? Apparently C++11 support is somewhat more existant, but C11 support regarding threads appears to be very limited? My glibc certainly doesn't ship thread.h. Given that gcc __thread and C11 from C11 page 376: 3 The macros are thread_local which expands to _Thread_local; this part of threads.h is pretty simple thread_local appear to have different semantics regarding initialization I am also a bit afraid of just defining one to the other already at this point in time... --- src/libsystemd-bus/sd-bus.c | 4 ++-- src/libsystemd-bus/sd-event.c | 2 +- src/libsystemd-id128/sd-id128.c | 8 src/login/logind-inhibit.c | 2 +- src/shared/capability.c | 4 ++-- src/shared/cgroup-util.c| 2 +- src/shared/macro.h | 10 ++ src/shared/util.c | 6 +++--- src/shared/virt.c | 8 9 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 4eaceef..64cd663 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -2815,13 +2815,13 @@ static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus } _public_ int sd_bus_default_system(sd_bus **ret) { -static __thread sd_bus *default_system_bus = NULL; +static thread_local sd_bus *default_system_bus = NULL; return bus_default(sd_bus_open_system, default_system_bus, ret); } _public_ int sd_bus_default_user(sd_bus **ret) { -static __thread sd_bus *default_user_bus = NULL; +static thread_local sd_bus *default_user_bus = NULL; return bus_default(sd_bus_open_user, default_user_bus, ret); } diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c index 06c84d7..727528b 100644 --- a/src/libsystemd-bus/sd-event.c +++ b/src/libsystemd-bus/sd-event.c @@ -2116,7 +2116,7 @@ _public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) { _public_ int sd_event_default(sd_event **ret) { -static __thread sd_event *default_event = NULL; +static thread_local sd_event *default_event = NULL; sd_event *e; int r; diff --git a/src/libsystemd-id128/sd-id128.c b/src/libsystemd-id128/sd-id128.c index 07d2415..9ee40ab 100644 --- a/src/libsystemd-id128/sd-id128.c +++ b/src/libsystemd-id128/sd-id128.c @@ -104,8 +104,8 @@ static sd_id128_t make_v4_uuid(sd_id128_t id) { } _public_ int sd_id128_get_machine(sd_id128_t *ret) { -static __thread sd_id128_t saved_machine_id; -static __thread bool saved_machine_id_valid = false; +static thread_local sd_id128_t saved_machine_id; +static thread_local bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; ssize_t k; @@ -153,8 +153,8 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { } _public_ int sd_id128_get_boot(sd_id128_t *ret) { -static __thread sd_id128_t saved_boot_id; -static __thread bool saved_boot_id_valid = false; +static thread_local sd_id128_t saved_boot_id; +static thread_local bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; ssize_t k; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index ec6a722..042586d 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -413,7 +413,7 @@ bool manager_is_inhibited( } const char *inhibit_what_to_string(InhibitWhat w) { -static __thread char buffer[97]; +static thread_local char buffer[97]; char *p; if (w 0 || w = _INHIBIT_WHAT_MAX) diff --git a/src/shared/capability.c b/src/shared/capability.c index 3219520..f34f6ba 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -55,8 +55,8 @@ int have_effective_cap(int value) { } unsigned long cap_last_cap(void) { -static __thread unsigned long saved; -static __thread bool valid = false; +static thread_local unsigned long saved; +static thread_local bool valid = false; unsigned long p; if (valid) diff --git a/src
Re: [systemd-devel] [PATCH] __thread -- thread_local for C11 compat
On Sun, Dec 15, 2013 at 3:16 PM, Lennart Poettering lenn...@poettering.net wrote: On Sun, 15.12.13 14:56, Shawn Landden (sh...@churchofgit.com) wrote: On Sun, Dec 15, 2013 at 1:56 PM, Lennart Poettering lenn...@poettering.net wrote: On Sun, 15.12.13 13:19, Shawn Landden (sh...@churchofgit.com) wrote: also make thread_local available w/o including threads.h Hmm, that looks a bit too early, no? Does gcc even support this? glibc gcc-4.9 supports _Thread_local http://gcc.gnu.org/gcc-4.9/changes.html Ah, nice. I figure that should be good enough then. (That said, my Fedora 20 doesn't have gcc 4.9 yet, so I can't test this...) debian has gcc-snapshot in sid switching -std=gnu99 to -std=gnu11 in Makefile I can compile systemd w/o the clause that defines _Thread_local as __thread and all tests pass. Perhaps we should add || (__GNUC__ == 4 __GNUC_MINOR__ = 9) to the check Hmm, checks for gcc versions are really only the last resorts. If there are feature test macros, we should use those, and should they break we an still resort to version checks. +#if __STDC_VERSION__ = 201112L !defined(__STDC_NO_THREADS__) +#else +# define _Thread_local __thread I don't really like the inverted if thing with nothing on the true branch and only a false branch I must say. Also, should we really take the deviation of filling in the c low-levelism _Thread_local here? I think I'd prefer this: agreed #ifndef thread_local #if __STDC_VERSION__ = 201112L !defined(__STDC_NO_THREADS__) #define thread_local _Thread_local #else #define thread_local __thread #endif With that in place we stay away from defining our own low-level _Thread_local, instead we only define the high-level thread_local, and do so either to the C11 language feature or the gcc extension... If that looks OK (and is tested!) I'd be happy to merge such a patch. to actually use this we would have to add this patch: diff --git a/configure.ac b/configure.ac index f85e86e..5ead127 100644 --- a/configure.ac +++ b/configure.ac @@ -113,6 +113,7 @@ AS_IF([test x$enable_address_sanitizer = xyes], [ ]) CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ +-std=gnu11 \ -pipe \ -Wall \ -Wextra \ ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] __thread -- thread_local for C11 compat
Also make thread_local available w/o including threads.h. (as the latter hasn't been implemented, but this part is trivial) --- src/libsystemd-bus/sd-bus.c | 4 ++-- src/libsystemd-bus/sd-event.c | 2 +- src/libsystemd-id128/sd-id128.c | 8 src/login/logind-inhibit.c | 2 +- src/shared/capability.c | 4 ++-- src/shared/cgroup-util.c| 2 +- src/shared/macro.h | 11 +++ src/shared/util.c | 6 +++--- src/shared/virt.c | 8 9 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 4eaceef..64cd663 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -2815,13 +2815,13 @@ static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus } _public_ int sd_bus_default_system(sd_bus **ret) { -static __thread sd_bus *default_system_bus = NULL; +static thread_local sd_bus *default_system_bus = NULL; return bus_default(sd_bus_open_system, default_system_bus, ret); } _public_ int sd_bus_default_user(sd_bus **ret) { -static __thread sd_bus *default_user_bus = NULL; +static thread_local sd_bus *default_user_bus = NULL; return bus_default(sd_bus_open_user, default_user_bus, ret); } diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c index 06c84d7..727528b 100644 --- a/src/libsystemd-bus/sd-event.c +++ b/src/libsystemd-bus/sd-event.c @@ -2116,7 +2116,7 @@ _public_ int sd_event_get_now_monotonic(sd_event *e, uint64_t *usec) { _public_ int sd_event_default(sd_event **ret) { -static __thread sd_event *default_event = NULL; +static thread_local sd_event *default_event = NULL; sd_event *e; int r; diff --git a/src/libsystemd-id128/sd-id128.c b/src/libsystemd-id128/sd-id128.c index 07d2415..9ee40ab 100644 --- a/src/libsystemd-id128/sd-id128.c +++ b/src/libsystemd-id128/sd-id128.c @@ -104,8 +104,8 @@ static sd_id128_t make_v4_uuid(sd_id128_t id) { } _public_ int sd_id128_get_machine(sd_id128_t *ret) { -static __thread sd_id128_t saved_machine_id; -static __thread bool saved_machine_id_valid = false; +static thread_local sd_id128_t saved_machine_id; +static thread_local bool saved_machine_id_valid = false; _cleanup_close_ int fd = -1; char buf[33]; ssize_t k; @@ -153,8 +153,8 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { } _public_ int sd_id128_get_boot(sd_id128_t *ret) { -static __thread sd_id128_t saved_boot_id; -static __thread bool saved_boot_id_valid = false; +static thread_local sd_id128_t saved_boot_id; +static thread_local bool saved_boot_id_valid = false; _cleanup_close_ int fd = -1; char buf[36]; ssize_t k; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index ec6a722..042586d 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -413,7 +413,7 @@ bool manager_is_inhibited( } const char *inhibit_what_to_string(InhibitWhat w) { -static __thread char buffer[97]; +static thread_local char buffer[97]; char *p; if (w 0 || w = _INHIBIT_WHAT_MAX) diff --git a/src/shared/capability.c b/src/shared/capability.c index 3219520..f34f6ba 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -55,8 +55,8 @@ int have_effective_cap(int value) { } unsigned long cap_last_cap(void) { -static __thread unsigned long saved; -static __thread bool valid = false; +static thread_local unsigned long saved; +static thread_local bool valid = false; unsigned long p; if (valid) diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 2c2ffc5..309f65d 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -480,7 +480,7 @@ static int join_path(const char *controller, const char *path, const char *suffi int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; -static __thread bool good = false; +static thread_local bool good = false; assert(fs); diff --git a/src/shared/macro.h b/src/shared/macro.h index fd3762e..362d62b 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -27,6 +27,17 @@ #include sys/uio.h #include inttypes.h +#ifndef thread_local +/* don't break on glibc 2.16 that doesn't define __STDC_NO_THREADS__ + * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 */ +# if __STDC_VERSION__ = 201112L !(defined(__STDC_NO_THREADS__) || \ + (defined(__GNU_LIBRARY__) __GLIBC__ == 2 __GLIBC_MINOR__ 16)) +# define thread_local _Thread_local +# else +# define thread_local __thread +# endif +#endif + #define _printf_(a,b) __attribute__ ((format
[systemd-devel] [PATCH 1/2] util: no need for in_initrd() cache to be thread-local
the process only has one working directory, and a race is harmless --- src/shared/util.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/util.c b/src/shared/util.c index b5ffaa1..7c73074 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2737,9 +2737,9 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct _pure_ static int is_temporary_fs(struct statfs *s) { assert(s); -return -F_TYPE_EQUAL(s-f_type, TMPFS_MAGIC) || -F_TYPE_EQUAL(s-f_type, RAMFS_MAGIC); + +return F_TYPE_EQUAL(s-f_type, TMPFS_MAGIC) || + F_TYPE_EQUAL(s-f_type, RAMFS_MAGIC); } int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) { @@ -5155,7 +5155,7 @@ bool is_valid_documentation_url(const char *url) { } bool in_initrd(void) { -static __thread int saved = -1; +static int saved = -1; struct statfs s; if (saved = 0) -- 1.8.5.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] _noreturn_ -- noreturn for C11 compat
also define noreturn w/o stdnoreturn.h --- src/core/main.c | 2 +- src/journal/test-journal-interleaving.c | 2 +- src/shared/log.c| 4 ++-- src/shared/log.h| 4 ++-- src/shared/macro.h | 10 +- src/shared/pager.c | 2 +- src/shared/util.c | 2 +- src/shared/util.h | 2 +- src/udev/collect/collect.c | 2 +- 9 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 6c3d9bf..eb5413e 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -112,7 +112,7 @@ static FILE* serialization = NULL; static void nop_handler(int sig) { } -_noreturn_ static void crash(int sig) { +noreturn static void crash(int sig) { if (getpid() != 1) /* Pass this on immediately, if this is not PID 1 */ diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index af0d43e..5b74714 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -36,7 +36,7 @@ static bool arg_keep = false; -_noreturn_ static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) { +noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) { log_meta(LOG_CRIT, file, line, func, '%s' failed at %s:%u (%s): %s., text, file, line, func, strerror(eno)); diff --git a/src/shared/log.c b/src/shared/log.c index 2404de8..2517f5d 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -702,12 +702,12 @@ static void log_assert(int level, const char *text, const char *file, int line, } #pragma GCC diagnostic pop -_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) { +noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) { log_assert(LOG_CRIT, text, file, line, func, Assertion '%s' failed at %s:%u, function %s(). Aborting.); abort(); } -_noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) { +noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) { log_assert(LOG_CRIT, text, file, line, func, Code should not be reached '%s' at %s:%u, function %s(). Aborting.); abort(); } diff --git a/src/shared/log.h b/src/shared/log.h index de0e000..3dcfa11 100644 --- a/src/shared/log.h +++ b/src/shared/log.h @@ -124,13 +124,13 @@ int log_dump_internal( const char *func, char *buffer); -_noreturn_ void log_assert_failed( +noreturn void log_assert_failed( const char *text, const char *file, int line, const char *func); -_noreturn_ void log_assert_failed_unreachable( +noreturn void log_assert_failed_unreachable( const char *text, const char *file, int line, diff --git a/src/shared/macro.h b/src/shared/macro.h index 362d62b..51af289 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -38,10 +38,18 @@ # endif #endif +/* define noreturn without stdnoreturn.h */ +#ifndef noreturn +# if __STDC_VERSION__ = 201112L +# define noreturn _Noreturn +# else +# define noreturn __attribute__((noreturn)) +# endif +#endif + #define _printf_(a,b) __attribute__ ((format (printf, a, b))) #define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) #define _sentinel_ __attribute__ ((sentinel)) -#define _noreturn_ __attribute__((noreturn)) #define _unused_ __attribute__ ((unused)) #define _destructor_ __attribute__ ((destructor)) #define _pure_ __attribute__ ((pure)) diff --git a/src/shared/pager.c b/src/shared/pager.c index 9fa6114..72a29f2 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -32,7 +32,7 @@ static pid_t pager_pid = 0; -_noreturn_ static void pager_fallback(void) { +noreturn static void pager_fallback(void) { ssize_t n; do { diff --git a/src/shared/util.c b/src/shared/util.c index 0ce6f70..e1f92fd 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -3469,7 +3469,7 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid) { return -EPROTO; } -_noreturn_ void freeze(void) { +noreturn void freeze(void) { /* Make sure nobody waits for us on a socket anymore */ close_all_fds(NULL, 0); diff --git a/src/shared/util.h b/src/shared/util.h index d5fa81c..d43aeff 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -417,7 +417,7 @@ char *normalize_env_assignment(const char *s); int wait_for_terminate(pid_t pid, siginfo_t *status); int wait_for_terminate_and_warn(const char *name, pid_t pid); -_noreturn_ void freeze(void);