mirror of
https://github.com/systemd/systemd
synced 2026-04-25 16:34:50 +02:00
Compare commits
18 Commits
673d1f4ab9
...
a2587faa72
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2587faa72 | ||
|
|
1cefb9a6af | ||
|
|
e745ddb16f | ||
|
|
d4dd3689fa | ||
|
|
3b195f63fc | ||
|
|
3e9210577d | ||
|
|
49043f8115 | ||
|
|
cc53046620 | ||
|
|
da9ae8ea6c | ||
|
|
7ffc7f3fcc | ||
|
|
a145f8c06c | ||
|
|
cedf5b1aef | ||
|
|
1e582ede3b | ||
|
|
cbb6068d0f | ||
|
|
3e6eafddbf | ||
|
|
8d75f60e3a | ||
|
|
1cf4a685ad | ||
|
|
9f0c0c4e15 |
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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, ×tamp);
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user