1
0
mirror of https://github.com/systemd/systemd synced 2026-04-25 16:34:50 +02:00

Compare commits

..

18 Commits

Author SHA1 Message Date
Luca Boccassi
a2587faa72
Merge pull request #23008 from poettering/loop-dissect-tweaks-safe
loop-util tweaks
2022-04-07 21:42:47 +01:00
Lennart Poettering
1cefb9a6af dissect: improve debug logging in probe_filesystem() 2022-04-07 18:56:38 +02:00
Lennart Poettering
e745ddb16f test-loop-block: conditionalize things on HAVE_BLKID correctly 2022-04-07 18:56:38 +02:00
Lennart Poettering
d4dd3689fa test: allow specifying test threads/iterations/timeouts via cmdline
That's useful when running tests manually.
2022-04-07 18:55:59 +02:00
Lennart Poettering
3b195f63fc loop-util: add debug message with details about acquired loopback device 2022-04-07 18:55:58 +02:00
Lennart Poettering
3e9210577d loop-util: explicitly close loopback block device before sleeping
attach_empty() file takes a BSD file lock on the device, and we really
should release that before going to sleep. hence explicitly close the
block device before the sleep instead of relying on _cleanup_ to close
it after the sleep.
2022-04-07 18:55:58 +02:00
Lennart Poettering
49043f8115 loop-util: use ERRNO_IS_DEVICE_ABSENT() macro where appropriate 2022-04-07 18:55:58 +02:00
Lennart Poettering
cc53046620 loop-util: take a LOCK_EX BSD file lock on control device while we acquire a loopback device 2022-04-07 18:55:58 +02:00
Lennart Poettering
da9ae8ea6c test-loop-block: don't spawn threads in case N_THREADS is 1
Let's simplify things if we are only supposed to create a single thread.
Makes it easier to debug things with gdb.
2022-04-07 18:55:58 +02:00
Lennart Poettering
7ffc7f3fcc loop-util: slightly rework device_has_block_children()
Let's match by devtype, i.e. the official way to distinguish "whole"
block devices from partitions.

Also add debug logging for devices we thus ignore.
2022-04-07 18:55:58 +02:00
Lennart Poettering
a145f8c06c loop-util: let's cut trailing whitespace, not trailing lines
This doesn't really make any real difference, given the file should only
contain a single line. But it's conceptually more correct to just remove
the trailing newline/whitespace then the whole lines coming after that.
i.e. if the file actually contains more lines than one, this should
probably be considered an error.
2022-04-07 18:55:58 +02:00
Luca Boccassi
cedf5b1aef core: fix dm-verity auto-discovery in MountImageUnit()
The implementation of MountImageUnit()/systemctl mount-image was
changed to use a /proc/self/fd path as the source, but that causes
the dm-verity files autodiscovery to fail, as it looks for files
in the same directory as the image.

Use the original file path when setting up dm-verity.
2022-04-07 17:31:04 +01:00
Gibeom Gwon
1e582ede3b calendarspec: fix possibly skips next elapse
If the time unit changes after adding the repetition value, the
timer may skip the next elapse. This patch reset sub time units
to minimum value when upper unit is changed.

Fixes #22665.
2022-04-07 17:44:35 +02:00
Zbigniew Jędrzejewski-Szmek
cbb6068d0f
Merge pull request #21795 from Werkov/bfq-io-weight-2
IODeviceWeight= configures bfq.io.weight  too
2022-04-07 17:23:16 +02:00
Michal Koutný
3e6eafddbf core/cgroup: Silence IODeviceWeight= exclusive policy warnings
A single device cannot have more than a single proportional control
policy at the same time. So either io.bfq.weight or io.weight will
always fail. Process the resulting values and emit a warning message
only when none was really configured.

This patch also drops warnings when setting [blk]io.bfq.weight fails,
the code would be too convoluted otherwise.
2022-03-29 18:06:40 +02:00
Michal Koutný
8d75f60e3a core/cgroup: Silence warnings IODeviceWeigth= on old kernels
Old kernels (795fe54c2a82 ("bfq: Add per-device weight") v5.4) won't
allow io.bfq.weight per-device configuration, don't get too excited
about it but give the user one warning message to be aware this settings
don't apply.
2022-03-29 18:06:08 +02:00
Michal Koutný
1cf4a685ad core/cgroup: Refactor device weight property name
Use arithmetic over explicit list of existing property names.
2022-03-29 17:46:11 +02:00
Michal Koutný
9f0c0c4e15 core/cgroup: Apply IODeviceWeight= through BFQ attributes as well
There are two possible IO control mechanisms (io.cost and BFQ) that
expose separate weights APIs. In systemd units we configure only a
single device weight value so we need to write it to both attribute
files.
This patch extends to devices what is already done for default cgroup IO
weight in commit 2dbc45aea747 ("cgroup: Also set io.bfq.weight"). This
is possible with kernels >= v5.4 with commit 795fe54c2a82 ("bfq: Add
per-device weight"). A warning is logged if the write fails on older kernels.

Since per-device weight of a particular device cannot use both io.cost
policy and BFQ scheduler, at least one warning is always expected with
this approach (the method that is unconfigured).
2022-03-23 19:20:51 +01:00
10 changed files with 200 additions and 67 deletions

View File

@ -1063,10 +1063,18 @@ static uint64_t cgroup_weight_io_to_blkio(uint64_t io_weight) {
CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX);
}
static void set_bfq_weight(Unit *u, const char *controller, uint64_t io_weight) {
char buf[DECIMAL_STR_MAX(uint64_t)+STRLEN("\n")];
static int set_bfq_weight(Unit *u, const char *controller, dev_t dev, uint64_t io_weight) {
static const char * const prop_names[] = {
"IOWeight",
"BlockIOWeight",
"IODeviceWeight",
"BlockIODeviceWeight",
};
static bool warned = false;
char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+STRLEN("\n")];
const char *p;
uint64_t bfq_weight;
int r;
/* FIXME: drop this function when distro kernels properly support BFQ through "io.weight"
* See also: https://github.com/systemd/systemd/pull/13335 and
@ -1075,25 +1083,50 @@ static void set_bfq_weight(Unit *u, const char *controller, uint64_t io_weight)
/* Adjust to kernel range is 1..1000, the default is 100. */
bfq_weight = BFQ_WEIGHT(io_weight);
xsprintf(buf, "%" PRIu64 "\n", bfq_weight);
if (major(dev) > 0)
xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), bfq_weight);
else
xsprintf(buf, "%" PRIu64 "\n", bfq_weight);
if (set_attribute_and_warn(u, controller, p, buf) >= 0 && io_weight != bfq_weight)
log_unit_debug(u, "%sIOWeight=%" PRIu64 " scaled to %s=%" PRIu64,
streq(controller, "blkio") ? "Block" : "",
r = cg_set_attribute(controller, u->cgroup_path, p, buf);
/* FIXME: drop this when kernels prior
* 795fe54c2a82 ("bfq: Add per-device weight") v5.4
* are not interesting anymore. Old kernels will fail with EINVAL, while new kernels won't return
* EINVAL on properly formatted input by us. Treat EINVAL accordingly. */
if (r == -EINVAL && major(dev) > 0) {
if (!warned) {
log_unit_warning(u, "Kernel version does not accept per-device setting in %s.", p);
warned = true;
}
r = -EOPNOTSUPP; /* mask as unconfigured device */
} else if (r >= 0 && io_weight != bfq_weight)
log_unit_debug(u, "%s=%" PRIu64 " scaled to %s=%" PRIu64,
prop_names[2*(major(dev) > 0) + streq(controller, "blkio")],
io_weight, p, bfq_weight);
return r;
}
static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_t io_weight) {
char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
dev_t dev;
int r;
int r, r1, r2;
r = lookup_block_device(dev_path, &dev);
if (r < 0)
if (lookup_block_device(dev_path, &dev) < 0)
return;
r1 = set_bfq_weight(u, "io", dev, io_weight);
xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), io_weight);
(void) set_attribute_and_warn(u, "io", "io.weight", buf);
r2 = cg_set_attribute("io", u->cgroup_path, "io.weight", buf);
/* Look at the configured device, when both fail, prefer io.weight errno. */
r = r2 == -EOPNOTSUPP ? r1 : r2;
if (r < 0)
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r),
r, "Failed to set 'io[.bfq].weight' attribute on '%s' to '%.*s': %m",
empty_to_root(u->cgroup_path), (int) strcspn(buf, NEWLINE), buf);
}
static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint64_t blkio_weight) {
@ -1298,7 +1331,7 @@ static void set_io_weight(Unit *u, uint64_t weight) {
assert(u);
set_bfq_weight(u, "io", weight);
(void) set_bfq_weight(u, "io", makedev(0, 0), weight);
xsprintf(buf, "default %" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "io", "io.weight", buf);
@ -1309,7 +1342,7 @@ static void set_blkio_weight(Unit *u, uint64_t weight) {
assert(u);
set_bfq_weight(u, "blkio", weight);
(void) set_bfq_weight(u, "blkio", makedev(0, 0), weight);
xsprintf(buf, "%" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "blkio", "blkio.weight", buf);

View File

@ -1216,7 +1216,7 @@ static int mount_image(const MountEntry *m, const char *root_directory) {
}
r = verity_dissect_and_mount(
mount_entry_source(m), mount_entry_path(m), m->image_options,
/* src_fd= */ -1, mount_entry_source(m), mount_entry_path(m), m->image_options,
host_os_release_id, host_os_release_version_id, host_os_release_sysext_level, NULL);
if (r == -ENOENT && m->ignore)
return 0;

View File

@ -1181,6 +1181,7 @@ static int find_matching_component(
static int tm_within_bounds(struct tm *tm, bool utc) {
struct tm t;
int cmp;
assert(tm);
/*
@ -1195,13 +1196,25 @@ static int tm_within_bounds(struct tm *tm, bool utc) {
if (mktime_or_timegm(&t, utc) < 0)
return negative_errno();
/* Did any normalization take place? If so, it was out of bounds before */
int cmp = CMP(t.tm_year, tm->tm_year) ?:
CMP(t.tm_mon, tm->tm_mon) ?:
CMP(t.tm_mday, tm->tm_mday) ?:
CMP(t.tm_hour, tm->tm_hour) ?:
CMP(t.tm_min, tm->tm_min) ?:
CMP(t.tm_sec, tm->tm_sec);
/*
* Did any normalization take place? If so, it was out of bounds before.
* Normalization could skip next elapse, e.g. result of normalizing 3-33
* is 4-2. This skips 4-1. So reset the sub time unit if upper unit was
* out of bounds. Normalization has occurred implies find_matching_component() > 0,
* other sub time units are already reset in find_next().
*/
if ((cmp = CMP(t.tm_year, tm->tm_year)) != 0)
t.tm_mon = 0;
else if ((cmp = CMP(t.tm_mon, tm->tm_mon)) != 0)
t.tm_mday = 1;
else if ((cmp = CMP(t.tm_mday, tm->tm_mday)) != 0)
t.tm_hour = 0;
else if ((cmp = CMP(t.tm_hour, tm->tm_hour)) != 0)
t.tm_min = 0;
else if ((cmp = CMP(t.tm_min, tm->tm_min)) != 0)
t.tm_sec = 0;
else
cmp = CMP(t.tm_sec, tm->tm_sec);
if (cmp < 0)
return -EDEADLK; /* Refuse to go backward */

View File

@ -92,21 +92,21 @@ int probe_filesystem(const char *node, char **ret_fstype) {
errno = 0;
r = blkid_do_safeprobe(b);
if (r == 1) {
log_debug("No type detected on partition %s", node);
if (r == 1)
goto not_found;
}
if (r == -2)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Results ambiguous for partition %s", node);
if (r != 0)
return errno_or_else(EIO);
return log_debug_errno(errno_or_else(EIO), "Failed to probe partition %s: %m", node);
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
if (fstype) {
char *t;
log_debug("Probed fstype '%s' on partition %s.", fstype, node);
t = strdup(fstype);
if (!t)
return -ENOMEM;
@ -116,6 +116,7 @@ int probe_filesystem(const char *node, char **ret_fstype) {
}
not_found:
log_debug("No type detected on partition %s", node);
*ret_fstype = NULL;
return 0;
#else
@ -3448,6 +3449,7 @@ static const char *const partition_designator_table[] = {
};
int verity_dissect_and_mount(
int src_fd,
const char *src,
const char *dest,
const MountOptions *options,
@ -3466,14 +3468,17 @@ int verity_dissect_and_mount(
assert(src);
assert(dest);
/* We might get an FD for the image, but we use the original path to look for the dm-verity files */
r = verity_settings_load(&verity, src, NULL, NULL);
if (r < 0)
return log_debug_errno(r, "Failed to load root hash: %m");
dissect_image_flags = verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
/* Note that we don't use loop_device_make here, as the FD is most likely O_PATH which would not be
* accepted by LOOP_CONFIGURE, so just let loop_device_make_by_path reopen it as a regular FD. */
r = loop_device_make_by_path(
src,
src_fd >= 0 ? FORMAT_PROC_FD_PATH(src_fd) : src,
-1,
verity.data_path ? 0 : LO_FLAGS_PARTSCAN,
&loop_device);

View File

@ -285,4 +285,4 @@ bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesi
int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image);
int verity_dissect_and_mount(const char *src, const char *dest, const MountOptions *options, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_sysext_scope);
int verity_dissect_and_mount(int src_fd, const char *src, const char *dest, const MountOptions *options, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_sysext_scope);

View File

@ -62,9 +62,7 @@ static int get_current_uevent_seqnum(uint64_t *ret) {
if (r < 0)
return log_debug_errno(r, "Failed to read current uevent sequence number: %m");
truncate_nl(p);
r = safe_atou64(p, ret);
r = safe_atou64(strstrip(p), ret);
if (r < 0)
return log_debug_errno(r, "Failed to parse current uevent sequence number: %s", p);
@ -73,7 +71,7 @@ static int get_current_uevent_seqnum(uint64_t *ret) {
static int device_has_block_children(sd_device *d) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
const char *main_sn, *main_ss;
const char *main_ss, *main_dt;
sd_device *q;
int r;
@ -82,10 +80,6 @@ static int device_has_block_children(sd_device *d) {
/* Checks if the specified device currently has block device children (i.e. partition block
* devices). */
r = sd_device_get_sysname(d, &main_sn);
if (r < 0)
return r;
r = sd_device_get_subsystem(d, &main_ss);
if (r < 0)
return r;
@ -93,6 +87,13 @@ static int device_has_block_children(sd_device *d) {
if (!streq(main_ss, "block"))
return -EINVAL;
r = sd_device_get_devtype(d, &main_dt);
if (r < 0)
return r;
if (!streq(main_dt, "disk")) /* Refuse invocation on partition block device, insist on "whole" device */
return -EINVAL;
r = sd_device_enumerator_new(&e);
if (r < 0)
return r;
@ -106,26 +107,34 @@ static int device_has_block_children(sd_device *d) {
return r;
FOREACH_DEVICE(e, q) {
const char *ss, *sn;
const char *ss, *dt;
r = sd_device_get_subsystem(q, &ss);
if (r < 0)
if (r < 0) {
log_device_debug_errno(q, r, "Failed to get subsystem of child, ignoring: %m");
continue;
}
if (!streq(ss, "block"))
if (!streq(ss, "block")) {
log_device_debug(q, "Skipping child that is not a block device (subsystem=%s).", ss);
continue;
}
r = sd_device_get_sysname(q, &sn);
if (r < 0)
r = sd_device_get_devtype(q, &dt);
if (r < 0) {
log_device_debug_errno(q, r, "Failed to get devtype of child, ignoring: %m");
continue;
}
if (streq(sn, main_sn))
if (!streq(dt, "partition")) {
log_device_debug(q, "Skipping non-partition child (devtype=%s).", dt);
continue;
}
return 1; /* we have block device children */
return true; /* we have block device children */
}
return 0;
return false;
}
static int loop_configure(
@ -505,6 +514,17 @@ static int loop_device_make_internal(
for (unsigned n_attempts = 0;;) {
_cleanup_close_ int loop = -1;
/* Let's take a lock on the control device first. On a busy system, where many programs
* attempt to allocate a loopback device at the same time, we might otherwise keep looping
* around relatively heavy operations: asking for a free loopback device, then opening it,
* validating it, attaching something to it. Let's serialize this whole operation, to make
* unnecessary busywork less likely. Note that this is just something we do to optimize our
* own code (and whoever else decides to use LOCK_EX locks for this), taking this lock is not
* necessary, it just means it's less likely we have to iterate through this loop again and
* again if our own code races against our own code. */
if (flock(control, LOCK_EX) < 0)
return -errno;
nr = ioctl(control, LOOP_CTL_GET_FREE);
if (nr < 0)
return -errno;
@ -516,7 +536,7 @@ static int loop_device_make_internal(
if (loop < 0) {
/* Somebody might've gotten the same number from the kernel, used the device,
* and called LOOP_CTL_REMOVE on it. Let's retry with a new number. */
if (!IN_SET(errno, ENOENT, ENXIO))
if (!ERRNO_IS_DEVICE_ABSENT(errno))
return -errno;
} else {
r = loop_configure(loop, nr, &config, &try_loop_configure, &seqnum, &timestamp);
@ -533,9 +553,17 @@ static int loop_device_make_internal(
return r;
}
/* OK, this didn't work, let's try again a bit later, but first release the lock on the
* control device */
if (flock(control, LOCK_UN) < 0)
return -errno;
if (++n_attempts >= 64) /* Give up eventually */
return -EBUSY;
/* Now close the loop device explicitly. This will release any lock acquired by
* attach_empty_file() or similar, while we sleep below. */
loop = safe_close(loop);
loopdev = mfree(loopdev);
/* Wait some random time, to make collision less likely. Let's pick a random time in the
@ -588,6 +616,12 @@ static int loop_device_make_internal(
.timestamp_not_before = timestamp,
};
log_debug("Successfully acquired %s, devno=%u:%u, nr=%i, diskseq=%" PRIu64,
d->node,
major(d->devno), minor(d->devno),
d->nr,
d->diskseq);
*ret = d;
return d->fd;
}

View File

@ -789,6 +789,7 @@ static int mount_in_namespace(
bool mount_slave_created = false, mount_slave_mounted = false,
mount_tmp_created = false, mount_tmp_mounted = false,
mount_outside_created = false, mount_outside_mounted = false;
_cleanup_free_ char *chased_src_path = NULL;
struct stat st, self_mntns_st;
pid_t child;
int r;
@ -826,9 +827,10 @@ static int mount_in_namespace(
if (r < 0)
return log_debug_errno(r == -ENOENT ? SYNTHETIC_ERRNO(EOPNOTSUPP) : r, "Target does not allow propagation of mount points");
r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, NULL, &chased_src_fd);
r = chase_symlinks(src, NULL, 0, &chased_src_path, &chased_src_fd);
if (r < 0)
return log_debug_errno(r, "Failed to resolve source path of %s: %m", src);
log_debug("Chased source path of %s to %s", src, chased_src_path);
if (fstat(chased_src_fd, &st) < 0)
return log_debug_errno(errno, "Failed to stat() resolved source path %s: %m", src);
@ -873,7 +875,7 @@ static int mount_in_namespace(
mount_tmp_created = true;
if (is_image)
r = verity_dissect_and_mount(FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, options, NULL, NULL, NULL, NULL);
r = verity_dissect_and_mount(chased_src_fd, chased_src_path, mount_tmp, options, NULL, NULL, NULL, NULL);
else
r = mount_follow_verbose(LOG_DEBUG, FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, NULL, MS_BIND, NULL);
if (r < 0)

View File

@ -199,6 +199,8 @@ TEST(calendar_spec_next) {
test_next("2016-02~01 UTC", "", 12345, 1456704000000000);
test_next("Mon 2017-05~01..07 UTC", "", 12345, 1496016000000000);
test_next("Mon 2017-05~07/1 UTC", "", 12345, 1496016000000000);
test_next("*-*-01/5 04:00:00 UTC", "", 1646010000000000, 1646107200000000);
test_next("*-01/7-01 04:00:00 UTC", "", 1664607600000000, 1672545600000000);
test_next("2017-08-06 9,11,13,15,17:00 UTC", "", 1502029800000000, 1502031600000000);
test_next("2017-08-06 9..17/2:00 UTC", "", 1502029800000000, 1502031600000000);
test_next("2016-12-* 3..21/6:00 UTC", "", 1482613200000001, 1482634800000000);

View File

@ -10,10 +10,12 @@
#include "fileio.h"
#include "fs-util.h"
#include "gpt.h"
#include "main-func.h"
#include "missing_loop.h"
#include "mkfs-util.h"
#include "mount-util.h"
#include "namespace-util.h"
#include "parse-util.h"
#include "string-util.h"
#include "strv.h"
#include "tests.h"
@ -21,16 +23,18 @@
#include "user-util.h"
#include "virt.h"
#define N_THREADS 5
#define N_ITERATIONS 3
static unsigned arg_n_threads = 5;
static unsigned arg_n_iterations = 3;
static usec_t arg_timeout = 0;
#if HAVE_BLKID
static usec_t end = 0;
static void* thread_func(void *ptr) {
int fd = PTR_TO_FD(ptr);
int r;
for (unsigned i = 0; i < N_ITERATIONS; i++) {
for (unsigned i = 0; i < arg_n_iterations; i++) {
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *mounted = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected = NULL;
@ -97,6 +101,7 @@ static void* thread_func(void *ptr) {
return NULL;
}
#endif
static bool have_root_gpt_type(void) {
#ifdef GPT_ROOT_NATIVE
@ -106,20 +111,42 @@ static bool have_root_gpt_type(void) {
#endif
}
int main(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
_cleanup_free_ char *p = NULL, *cmd = NULL;
_cleanup_(pclosep) FILE *sfdisk = NULL;
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
_cleanup_close_ int fd = -1;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *mounted = NULL;
pthread_t threads[N_THREADS];
sd_id128_t id;
int r;
test_setup_logging(LOG_DEBUG);
log_show_tid(true);
log_show_time(true);
log_show_color(true);
if (argc >= 2) {
r = safe_atou(argv[1], &arg_n_threads);
if (r < 0)
return log_error_errno(r, "Failed to parse first argument (number of threads): %s", argv[1]);
if (arg_n_threads <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Number of threads must be at least 1, refusing.");
}
if (argc >= 3) {
r = safe_atou(argv[2], &arg_n_iterations);
if (r < 0)
return log_error_errno(r, "Failed to parse second argument (number of iterations): %s", argv[2]);
if (arg_n_iterations <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Number of iterations must be at least 1, refusing.");
}
if (argc >= 4) {
r = parse_sec(argv[3], &arg_timeout);
if (r < 0)
return log_error_errno(r, "Failed to parse third argument (timeout): %s", argv[3]);
}
if (argc >= 5)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many arguments (expected 3 at max).");
if (!have_root_gpt_type()) {
log_tests_skipped("No root partition GPT defined for this architecture, exiting.");
@ -187,6 +214,13 @@ int main(int argc, char *argv[]) {
sfdisk = NULL;
assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, LO_FLAGS_PARTSCAN, &loop) >= 0);
#if HAVE_BLKID
_cleanup_(dissected_image_unrefp) DissectedImage *dissected = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *mounted = NULL;
pthread_t threads[arg_n_threads];
sd_id128_t id;
assert_se(dissect_image(loop->fd, NULL, NULL, loop->diskseq, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
assert_se(dissected->partitions[PARTITION_ESP].found);
@ -223,27 +257,37 @@ int main(int argc, char *argv[]) {
log_notice("Threads are being started now");
/* Let's make sure we run for 10s on slow systems at max */
end = usec_add(now(CLOCK_MONOTONIC),
slow_tests_enabled() ? 5 * USEC_PER_SEC :
1 * USEC_PER_SEC);
/* zero timeout means pick default: let's make sure we run for 10s on slow systems at max */
if (arg_timeout == 0)
arg_timeout = slow_tests_enabled() ? 5 * USEC_PER_SEC : 1 * USEC_PER_SEC;
for (unsigned i = 0; i < N_THREADS; i++)
assert_se(pthread_create(threads + i, NULL, thread_func, FD_TO_PTR(fd)) == 0);
end = usec_add(now(CLOCK_MONOTONIC), arg_timeout);
if (arg_n_threads > 1)
for (unsigned i = 0; i < arg_n_threads; i++)
assert_se(pthread_create(threads + i, NULL, thread_func, FD_TO_PTR(fd)) == 0);
log_notice("All threads started now.");
for (unsigned i = 0; i < N_THREADS; i++) {
log_notice("Joining thread #%u.", i);
if (arg_n_threads == 1)
assert_se(thread_func(FD_TO_PTR(fd)) == NULL);
else
for (unsigned i = 0; i < arg_n_threads; i++) {
log_notice("Joining thread #%u.", i);
void *k;
assert_se(pthread_join(threads[i], &k) == 0);
assert_se(k == NULL);
void *k;
assert_se(pthread_join(threads[i], &k) == 0);
assert_se(k == NULL);
log_notice("Joined thread #%u.", i);
}
log_notice("Joined thread #%u.", i);
}
log_notice("Threads are all terminated now.");
#else
log_notice("Cutting test short, since we do not have libblkid.");
#endif
return 0;
}
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);

View File

@ -285,7 +285,7 @@ Type=notify
RemainAfterExit=yes
MountAPIVFS=yes
PrivateTmp=yes
ExecStart=/bin/sh -c 'systemd-notify --ready; while ! grep -q -F MARKER /tmp/img/usr/lib/os-release; do sleep 0.1; done; mount | grep -F "/tmp/img" | grep -q -F "nosuid"'
ExecStart=/bin/sh -c 'systemd-notify --ready; while ! grep -q -F MARKER /tmp/img/usr/lib/os-release; do sleep 0.1; done; mount | grep -F "/dev/mapper/${roothash}-verity" | grep -q -F "nosuid"'
EOF
systemctl start testservice-50d.service