sensor:modalias:acpi:SMO8500*:dmi:*svn*DEXP*:*pn*DEXPOEM*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+#########################################
+# DIGMA
+#########################################
+
+# Digma CITI E203
+sensor:modalias:acpi:BOSC0200*:dmi:*:svnDigma:pnCITIE203ES2010EW:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+
#########################################
# Endless
#########################################
<filename>umount.target</filename> in order to be stopped during shutdown.</para></listitem>
<listitem><para>Mount units referring to local file systems automatically gain
- an <varname>After=</varname> dependency on <filename>local-fs-pre.target</filename>.</para></listitem>
+ an <varname>After=</varname> dependency on <filename>local-fs-pre.target</filename>, and a
+ <varname>Before=</varname> dependency on <filename>local-fs.target</filename> unless
+ <option>nofail</option> mount option is set.</para></listitem>
<listitem><para>Network mount units
automatically acquire <varname>After=</varname> dependencies on <filename>remote-fs-pre.target</filename>,
- <filename>network.target</filename> and <filename>network-online.target</filename>. Towards the latter a
+ <filename>network.target</filename> and <filename>network-online.target</filename>, and gain a
+ <varname>Before=</varname> dependency on <filename>remote-fs.target</filename> unless
+ <option>nofail</option> mount option is set. Towards the latter a
<varname>Wants=</varname> unit is added as well.</para></listitem>
</itemizedlist>
<varlistentry>
<term><option>-a</option></term>
- <term><option>-all</option></term>
+ <term><option>--all</option></term>
<listitem><para>When showing properties of
<citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
# SPDX-License-Identifier: LGPL-2.1+
project('systemd', 'c',
- version : '240',
+ version : '241',
license : 'LGPLv2+',
default_options: [
'c_std=gnu99',
meson_version : '>= 0.46',
)
-libsystemd_version = '0.24.0'
-libudev_version = '1.6.12'
+libsystemd_version = '0.25.0'
+libudev_version = '1.6.13'
# We need the same data in two different formats, ugh!
# Also, for hysterical reasons, we use different variable
return 1;
}
-void *prioq_peek(Prioq *q) {
-
+void *prioq_peek_by_index(Prioq *q, unsigned idx) {
if (!q)
return NULL;
- if (q->n_items <= 0)
+ if (idx >= q->n_items)
return NULL;
- return q->items[0].data;
+ return q->items[idx].data;
}
void *prioq_pop(Prioq *q) {
int prioq_remove(Prioq *q, void *data, unsigned *idx);
int prioq_reshuffle(Prioq *q, void *data, unsigned *idx);
-void *prioq_peek(Prioq *q) _pure_;
+void *prioq_peek_by_index(Prioq *q, unsigned idx) _pure_;
+static inline void *prioq_peek(Prioq *q) {
+ return prioq_peek_by_index(q, 0);
+}
void *prioq_pop(Prioq *q);
+#define PRIOQ_FOREACH_ITEM(q, p) \
+ for (unsigned _i = 0; (p = prioq_peek_by_index(q, _i)); _i++)
+
unsigned prioq_size(Prioq *q) _pure_;
bool prioq_isempty(Prioq *q) _pure_;
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
_cleanup_fclose_ FILE *f = NULL;
bool space = false;
- char *k, *ans = NULL;
+ char *k;
+ _cleanup_free_ char *ans = NULL;
const char *p;
int c;
if (!ans)
return -ENOMEM;
- *line = ans;
+ *line = TAKE_PTR(ans);
return 0;
} else {
_cleanup_free_ char *t = NULL;
int h;
- free(ans);
+ ans = mfree(ans);
if (!comm_fallback)
return -ENOENT;
if (!ans)
return -ENOMEM;
}
+
+ *line = TAKE_PTR(ans);
+ return 0;
}
- *line = ans;
+ k = realloc(ans, strlen(ans) + 1);
+ if (!k)
+ return -ENOMEM;
+
+ ans = NULL;
+ *line = k;
+
return 0;
}
return 0;
}
-int procfs_memory_get_current(uint64_t *ret) {
+int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used) {
uint64_t mem_total = UINT64_MAX, mem_free = UINT64_MAX;
_cleanup_fclose_ FILE *f = NULL;
int r;
- assert(ret);
-
f = fopen("/proc/meminfo", "re");
if (!f)
return -errno;
if (mem_free > mem_total)
return -EINVAL;
- *ret = (mem_total - mem_free) * 1024U;
+ if (ret_total)
+ *ret_total = mem_total * 1024U;
+ if (ret_used)
+ *ret_used = (mem_total - mem_free) * 1024U;
return 0;
}
int procfs_cpu_get_usage(nsec_t *ret);
-int procfs_memory_get_current(uint64_t *ret);
+int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used);
+static inline int procfs_memory_get_used(uint64_t *ret) {
+ return procfs_memory_get(NULL, ret);
+}
} else if (streq(controller, "memory")) {
if (is_root_cgroup(path)) {
- r = procfs_memory_get_current(&g->memory);
+ r = procfs_memory_get_used(&g->memory);
if (r < 0)
return r;
} else {
/* The root cgroup doesn't expose this information, let's get it from /proc instead */
if (unit_has_host_root_cgroup(u))
- return procfs_memory_get_current(ret);
+ return procfs_memory_get_used(ret);
if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
return -ENODATA;
return get_mount_parameters_fragment(m);
}
+static int update_parameters_proc_self_mount_info(
+ Mount *m,
+ const char *what,
+ const char *options,
+ const char *fstype) {
+
+ MountParameters *p;
+ int r, q, w;
+
+ p = &m->parameters_proc_self_mountinfo;
+
+ r = free_and_strdup(&p->what, what);
+ if (r < 0)
+ return r;
+
+ q = free_and_strdup(&p->options, options);
+ if (q < 0)
+ return q;
+
+ w = free_and_strdup(&p->fstype, fstype);
+ if (w < 0)
+ return w;
+
+ return r > 0 || q > 0 || w > 0;
+}
+
static int mount_add_mount_dependencies(Mount *m) {
MountParameters *pm;
Unit *other;
* automatically stopped when the device disappears suddenly. */
dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
- mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
+ /* We always use 'what' from /proc/self/mountinfo if mounted */
+ mask = m->from_proc_self_mountinfo ? UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT : UNIT_DEPENDENCY_FILE;
r = unit_add_node_dependency(UNIT(m), p->what, device_wants_mount, dep, mask);
if (r < 0)
const char *after, *before;
UnitDependencyMask mask;
MountParameters *p;
+ bool nofail;
int r;
assert(m);
return 0;
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
+ nofail = m->from_fragment ? fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0") : false;
if (mount_is_network(p)) {
/* We order ourselves after network.target. This is
before = SPECIAL_LOCAL_FS_TARGET;
}
- r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
- if (r < 0)
- return r;
+ if (!nofail) {
+ r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
+ if (r < 0)
+ return r;
+ }
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
if (r < 0)
unit_unref_uid_gid(UNIT(m), true);
dynamic_creds_destroy(&m->dynamic_creds);
+
+ /* Any dependencies based on /proc/self/mountinfo are now stale */
+ unit_remove_dependencies(UNIT(m), UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
}
static void mount_enter_mounted(Mount *m, MountResult f) {
return 0;
}
-static int update_parameters_proc_self_mount_info(
- Mount *m,
- const char *what,
- const char *options,
- const char *fstype) {
-
- MountParameters *p;
- int r, q, w;
-
- p = &m->parameters_proc_self_mountinfo;
-
- r = free_and_strdup(&p->what, what);
- if (r < 0)
- return r;
-
- q = free_and_strdup(&p->options, options);
- if (q < 0)
- return q;
-
- w = free_and_strdup(&p->fstype, fstype);
- if (w < 0)
- return w;
-
- return r > 0 || q > 0 || w > 0;
-}
-
static int mount_setup_new_unit(
Manager *m,
const char *name,
}
mount->from_proc_self_mountinfo = false;
+ assert_se(update_parameters_proc_self_mount_info(mount, NULL, NULL, NULL) >= 0);
switch (mount->state) {
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "procfs-util.h"
#include "string-util.h"
#include "syslog-util.h"
#include "unaligned.h"
/* Keep at most 16K entries in the cache. (Note though that this limit may be violated if enough streams pin entries in
* the cache, in which case we *do* permit this limit to be breached. That's safe however, as the number of stream
* clients itself is limited.) */
-#define CACHE_MAX (16*1024)
+#define CACHE_MAX_FALLBACK 128U
+#define CACHE_MAX_MAX (16*1024U)
+#define CACHE_MAX_MIN 64U
+
+static size_t cache_max(void) {
+ static size_t cached = -1;
+
+ if (cached == (size_t) -1) {
+ uint64_t mem_total;
+ int r;
+
+ r = procfs_memory_get(&mem_total, NULL);
+ if (r < 0) {
+ log_warning_errno(r, "Cannot query /proc/meminfo for MemTotal: %m");
+ cached = CACHE_MAX_FALLBACK;
+ } else {
+ /* Cache entries are usually a few kB, but the process cmdline is controlled by the
+ * user and can be up to _SC_ARG_MAX, usually 2MB. Let's say that approximately up to
+ * 1/8th of memory may be used by the cache.
+ *
+ * In the common case, this formula gives 64 cache entries for each GB of RAM.
+ */
+ long l = sysconf(_SC_ARG_MAX);
+ assert(l > 0);
+
+ cached = CLAMP(mem_total / 8 / (uint64_t) l, CACHE_MAX_MIN, CACHE_MAX_MAX);
+ }
+ }
+
+ return cached;
+}
static int client_context_compare(const void *a, const void *b) {
const ClientContext *x = a, *y = b;
}
static void client_context_try_shrink_to(Server *s, size_t limit) {
+ ClientContext *c;
+ usec_t t;
+
assert(s);
+ /* Flush any cache entries for PIDs that have already moved on. Don't do this
+ * too often, since it's a slow process. */
+ t = now(CLOCK_MONOTONIC);
+ if (s->last_cache_pid_flush + MAX_USEC < t) {
+ unsigned n = prioq_size(s->client_contexts_lru), idx = 0;
+
+ /* We do a number of iterations based on the initial size of the prioq. When we remove an
+ * item, a new item is moved into its places, and items to the right might be reshuffled.
+ */
+ for (unsigned i = 0; i < n; i++) {
+ c = prioq_peek_by_index(s->client_contexts_lru, idx);
+
+ assert(c->n_ref == 0);
+
+ if (!pid_is_unwaited(c->pid))
+ client_context_free(s, c);
+ else
+ idx ++;
+ }
+
+ s->last_cache_pid_flush = t;
+ }
+
/* Bring the number of cache entries below the indicated limit, so that we can create a new entry without
* breaching the limit. Note that we only flush out entries that aren't pinned here. This means the number of
* cache entries may very well grow beyond the limit, if all entries stored remain pinned. */
while (hashmap_size(s->client_contexts) > limit) {
- ClientContext *c;
-
c = prioq_pop(s->client_contexts_lru);
if (!c)
break; /* All remaining entries are pinned, give up */
return 0;
}
- client_context_try_shrink_to(s, CACHE_MAX-1);
+ client_context_try_shrink_to(s, cache_max()-1);
r = client_context_new(s, pid, &c);
if (r < 0)
Hashmap *client_contexts;
Prioq *client_contexts_lru;
+ usec_t last_cache_pid_flush;
+
ClientContext *my_context; /* the context of journald itself */
ClientContext *pid1_context; /* the context of PID 1 */
};
if (legacy_unstable_byteorder)
/* for historical reasons (a bug), the bits were swapped and thus
- * the result was endianness dependant. Preserve that behavior. */
+ * the result was endianness dependent. Preserve that behavior. */
id32 = __bswap_32(id32);
else
/* the fixed behavior returns a stable byte order. Since LE is expected
r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not append IFLA_PROTINFO attribute: %m");
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
if (r < 0)
return r;
LIST_FOREACH(addresses, ad, link->network->static_addresses) {
- r = address_configure(ad, link, address_handler, false);
+ bool update;
+
+ update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0;
+
+ r = address_configure(ad, link, address_handler, update);
if (r < 0) {
log_link_warning_errno(link, r, "Could not set addresses: %m");
link_enter_failed(link);
return 1;
}
-int link_up(Link *link) {
+static int link_up(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
uint8_t ipv6ll_mode;
int r;
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
-int link_up(Link *link);
int link_down(Link *link);
void link_enter_failed(Link *link);
if (r < 0)
goto finish;
+ /* Ignore SIGPIPE here, because we use splice() on the ptyfwd stuff and that will generate SIGPIPE if
+ * the result is closed. Note that the container payload child will reset signal mask+handler anyway,
+ * so just turning this off here means we only turn it off in nspawn itself, not any children. */
+ (void) ignore_signals(SIGPIPE, -1);
+
n_fd_passed = sd_listen_fds(false);
if (n_fd_passed > 0) {
r = fdset_new_listen_fds(&fds, false);
#include <linux/libbpf.h>
#include <string.h>
+#include <sys/mman.h>
#include <unistd.h>
#include "bpf-firewall.h"
#include "tests.h"
#include "unit.h"
+/* We use the same limit here that PID 1 bumps RLIMIT_MEMLOCK to if it can */
+#define CAN_MEMLOCK_SIZE (64U*1024U*1024U)
+
+static bool can_memlock(void) {
+ void *p;
+ bool b;
+
+ /* Let's see if we can mlock() a larger blob of memory. BPF programs are charged against
+ * RLIMIT_MEMLOCK, hence let's first make sure we can lock memory at all, and skip the test if we
+ * cannot. Why not check RLIMIT_MEMLOCK explicitly? Because in container environments the
+ * RLIMIT_MEMLOCK value we see might not match the RLIMIT_MEMLOCK value actually in effect. */
+
+ p = mmap(NULL, CAN_MEMLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
+ if (p == MAP_FAILED)
+ return false;
+
+ b = mlock(p, CAN_MEMLOCK_SIZE) >= 0;
+ if (b)
+ assert_se(munlock(p, CAN_MEMLOCK_SIZE) >= 0);
+
+ assert_se(munmap(p, CAN_MEMLOCK_SIZE) >= 0);
+ return b;
+}
+
int main(int argc, char *argv[]) {
struct bpf_insn exit_insn[] = {
BPF_MOV64_IMM(BPF_REG_0, 1),
_cleanup_(manager_freep) Manager *m = NULL;
Unit *u;
char log_buf[65535];
+ struct rlimit rl;
int r;
test_setup_logging(LOG_DEBUG);
if (is_run_on_travis_ci())
return log_tests_skipped("test-bpf fails on Travis CI: https://github.com/systemd/systemd/issues/9666");
+ assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0);
+ rl.rlim_cur = rl.rlim_max = MAX3(rl.rlim_cur, rl.rlim_max, CAN_MEMLOCK_SIZE);
+ (void) setrlimit(RLIMIT_MEMLOCK, &rl);
+
+ if (!can_memlock())
+ return log_tests_skipped("Can't use mlock(), skipping.");
+
r = enter_cgroup_subroot();
if (r == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available");
assert_se(q = prioq_new((compare_func_t) test_compare));
assert_se(s = set_new(&test_hash_ops));
+ assert_se(prioq_peek(q) == NULL);
+ assert_se(prioq_peek_by_index(q, 0) == NULL);
+ assert_se(prioq_peek_by_index(q, 1) == NULL);
+ assert_se(prioq_peek_by_index(q, (unsigned) -1) == NULL);
+
for (i = 0; i < SET_SIZE; i++) {
assert_se(t = new0(struct test, 1));
t->value = (unsigned) rand();
assert_se(set_consume(s, t) >= 0);
}
+ for (i = 0; i < SET_SIZE; i++)
+ assert_se(prioq_peek_by_index(q, i));
+ assert_se(prioq_peek_by_index(q, SET_SIZE) == NULL);
+
+ unsigned count = 0;
+ PRIOQ_FOREACH_ITEM(q, t) {
+ assert_se(t);
+ count++;
+ }
+ assert_se(count == SET_SIZE);
+
while ((t = set_steal_first(s))) {
assert_se(prioq_remove(q, t, &t->idx) == 1);
assert_se(prioq_remove(q, t, &t->idx) == 0);
assert_se(procfs_cpu_get_usage(&nsec) >= 0);
log_info("Current system CPU time: %s", format_timespan(buf, sizeof(buf), nsec/NSEC_PER_USEC, 1));
- assert_se(procfs_memory_get_current(&v) >= 0);
+ assert_se(procfs_memory_get_used(&v) >= 0);
log_info("Current memory usage: %s", format_bytes(buf, sizeof(buf), v));
assert_se(procfs_tasks_get_current(&v) >= 0);
m->good = true;
server_address_pretty(m->current_server_address, &pretty);
- log_info("Synchronized to time server %s (%s).", strna(pretty), m->current_server_name->string);
- sd_notifyf(false, "STATUS=Synchronized to time server %s (%s).", strna(pretty), m->current_server_name->string);
+ /* "for the first time", as further successful syncs will not be logged. */
+ log_info("Synchronized to time server for the first time %s (%s).", strna(pretty), m->current_server_name->string);
+ sd_notifyf(false, "STATUS=Synchronized to time server for the first time %s (%s).", strna(pretty), m->current_server_name->string);
}
r = manager_arm_timer(m, m->poll_interval_usec);
&& KERNEL_BIN="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux"
fi
+ CONSOLE=ttyS0
+
if [[ ! "$KERNEL_BIN" ]]; then
if [[ "$LOOKS_LIKE_ARCH" ]]; then
KERNEL_BIN=/boot/vmlinuz-linux
else
- KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER
+ [ "$ARCH" ] || ARCH=$(uname -m)
+ case $ARCH in
+ ppc64*)
+ KERNEL_BIN=/boot/vmlinux-$KERNEL_VER
+ CONSOLE=hvc0
+ ;;
+ *)
+ KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER
+ ;;
+ esac
fi
fi
raid=noautodetect \
loglevel=2 \
init=$PATH_TO_INIT \
-console=ttyS0 \
+console=$CONSOLE \
selinux=0 \
printk.devkmsg=on \
$_cgroup_args \
'dhcp-client-listen-port.network',
'dhcp-client-route-metric.network',
'dhcp-client-route-table.network',
+ 'dhcp-client.network'
'dhcp-server-veth-peer.network',
- 'dhcp-v4-server-veth-peer.network']
+ 'dhcp-v4-server-veth-peer.network',
+ 'static.network']
def setUp(self):
self.link_remove(self.links)
print(output)
self.assertRegex(output, '192.168.5.*')
+ def test_dhcp_client_reuse_address_as_static(self):
+ self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
+ self.start_networkd()
+
+ self.assertTrue(self.link_exits('veth99'))
+
+ self.start_dnsmasq()
+
+ output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, '192.168.5')
+ self.assertRegex(output, '2600::')
+
+ ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
+ ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
+ static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
+ print(static_network)
+
+ self.remove_unit_from_networkd_path(['dhcp-client.network'])
+
+ with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
+ f.write(static_network)
+
+ self.start_networkd()
+
+ self.assertTrue(self.link_exits('veth99'))
+
+ output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, '192.168.5')
+ self.assertRegex(output, 'valid_lft forever preferred_lft forever')
+
+ output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, '2600::')
+ self.assertRegex(output, 'valid_lft forever preferred_lft forever')
+
if __name__ == '__main__':
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
verbosity=3))
Conflicts=shutdown.target
After=systemd-sysusers.service
Before=sysinit.target local-fs-pre.target systemd-udevd.service shutdown.target
-ConditionCapability=CAP_SYS_MODULE
[Service]
Type=oneshot