Merge pull request #19368 from poettering/loop-seqnum
loop-util: let's try harder to avoid loopback block device recycle issues
This commit is contained in:
@@ -1863,6 +1863,8 @@ int setup_namespace(
|
||||
loop_device->fd,
|
||||
&verity,
|
||||
root_image_options,
|
||||
loop_device->uevent_seqnum_not_before,
|
||||
loop_device->timestamp_not_before,
|
||||
dissect_image_flags,
|
||||
&dissected_image);
|
||||
if (r < 0)
|
||||
|
||||
@@ -781,6 +781,8 @@ static int run(int argc, char *argv[]) {
|
||||
arg_image,
|
||||
&arg_verity_settings,
|
||||
NULL,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
arg_flags,
|
||||
&m);
|
||||
if (r < 0)
|
||||
|
||||
@@ -672,6 +672,8 @@ static int enumerate_partitions(dev_t devnum) {
|
||||
r = dissect_image(
|
||||
fd,
|
||||
NULL, NULL,
|
||||
UINT64_MAX,
|
||||
USEC_INFINITY,
|
||||
DISSECT_IMAGE_GPT_ONLY|
|
||||
DISSECT_IMAGE_NO_UDEV|
|
||||
DISSECT_IMAGE_USR_NO_ROOT,
|
||||
|
||||
@@ -756,4 +756,5 @@ LIBSYSTEMD_249 {
|
||||
global:
|
||||
sd_device_monitor_filter_add_match_sysattr;
|
||||
sd_device_monitor_filter_add_match_parent;
|
||||
sd_device_get_usec_initialized;
|
||||
} LIBSYSTEMD_248;
|
||||
|
||||
@@ -69,7 +69,7 @@ struct sd_device {
|
||||
|
||||
char *id_filename;
|
||||
|
||||
uint64_t usec_initialized;
|
||||
usec_t usec_initialized;
|
||||
|
||||
mode_t devmode;
|
||||
uid_t devuid;
|
||||
|
||||
@@ -1428,6 +1428,27 @@ _public_ int sd_device_get_is_initialized(sd_device *device) {
|
||||
return device->is_initialized;
|
||||
}
|
||||
|
||||
_public_ int sd_device_get_usec_initialized(sd_device *device, uint64_t *ret) {
|
||||
int r;
|
||||
|
||||
assert_return(device, -EINVAL);
|
||||
|
||||
r = device_read_db(device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!device->is_initialized)
|
||||
return -EBUSY;
|
||||
|
||||
if (device->usec_initialized == 0)
|
||||
return -ENODATA;
|
||||
|
||||
if (ret)
|
||||
*ret = device->usec_initialized;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) {
|
||||
usec_t now_ts;
|
||||
int r;
|
||||
@@ -1441,10 +1462,10 @@ _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *u
|
||||
if (!device->is_initialized)
|
||||
return -EBUSY;
|
||||
|
||||
if (!device->usec_initialized)
|
||||
if (device->usec_initialized == 0)
|
||||
return -ENODATA;
|
||||
|
||||
now_ts = now(clock_boottime_or_monotonic());
|
||||
now_ts = now(CLOCK_MONOTONIC);
|
||||
|
||||
if (now_ts < device->usec_initialized)
|
||||
return -EIO;
|
||||
|
||||
@@ -5483,6 +5483,8 @@ static int run(int argc, char *argv[]) {
|
||||
arg_image,
|
||||
&arg_verity_settings,
|
||||
NULL,
|
||||
loop->uevent_seqnum_not_before,
|
||||
loop->timestamp_not_before,
|
||||
dissect_image_flags,
|
||||
&dissected_image);
|
||||
if (r == -ENOPKG) {
|
||||
|
||||
@@ -395,6 +395,8 @@ static int portable_extract_by_path(
|
||||
r = dissect_image(
|
||||
d->fd,
|
||||
NULL, NULL,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
DISSECT_IMAGE_READ_ONLY |
|
||||
DISSECT_IMAGE_GENERIC_ROOT |
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
|
||||
@@ -1201,10 +1201,13 @@ int image_read_metadata(Image *i) {
|
||||
r = dissect_image(
|
||||
d->fd,
|
||||
NULL, NULL,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
DISSECT_IMAGE_GENERIC_ROOT |
|
||||
DISSECT_IMAGE_REQUIRE_ROOT |
|
||||
DISSECT_IMAGE_RELAX_VAR_CHECK |
|
||||
DISSECT_IMAGE_USR_NO_ROOT, &m);
|
||||
DISSECT_IMAGE_USR_NO_ROOT,
|
||||
&m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
+45
-10
@@ -123,10 +123,6 @@ static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_device_enumerator_allow_uninitialized(e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_device_enumerator_add_match_subsystem(e, "block", true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -229,6 +225,7 @@ static int device_is_partition(sd_device *d, sd_device *expected_parent, blkid_p
|
||||
static int find_partition(
|
||||
sd_device *parent,
|
||||
blkid_partition pp,
|
||||
usec_t timestamp_not_before,
|
||||
sd_device **ret) {
|
||||
|
||||
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||
@@ -244,6 +241,18 @@ static int find_partition(
|
||||
return r;
|
||||
|
||||
FOREACH_DEVICE(e, q) {
|
||||
uint64_t usec;
|
||||
|
||||
r = sd_device_get_usec_initialized(q, &usec);
|
||||
if (r == -EBUSY) /* Not initialized yet */
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (timestamp_not_before != USEC_INFINITY &&
|
||||
usec < timestamp_not_before) /* udev database entry older than our attachment? Then it's not ours */
|
||||
continue;
|
||||
|
||||
r = device_is_partition(q, parent, pp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -260,6 +269,7 @@ struct wait_data {
|
||||
sd_device *parent_device;
|
||||
blkid_partition blkidp;
|
||||
sd_device *found;
|
||||
uint64_t uevent_seqnum_not_before;
|
||||
};
|
||||
|
||||
static inline void wait_data_done(struct wait_data *d) {
|
||||
@@ -275,6 +285,20 @@ static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device,
|
||||
if (device_for_action(device, SD_DEVICE_REMOVE))
|
||||
return 0;
|
||||
|
||||
if (w->uevent_seqnum_not_before != UINT64_MAX) {
|
||||
uint64_t seqnum;
|
||||
|
||||
r = sd_device_get_seqnum(device, &seqnum);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (seqnum <= w->uevent_seqnum_not_before) { /* From an older use of this loop device */
|
||||
log_debug("Dropping event because seqnum too old (%" PRIu64 " <= %" PRIu64 ")",
|
||||
seqnum, w->uevent_seqnum_not_before);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = device_is_partition(device, w->parent_device, w->blkidp);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -294,6 +318,8 @@ static int wait_for_partition_device(
|
||||
sd_device *parent,
|
||||
blkid_partition pp,
|
||||
usec_t deadline,
|
||||
uint64_t uevent_seqnum_not_before,
|
||||
usec_t timestamp_not_before,
|
||||
sd_device **ret) {
|
||||
|
||||
_cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
|
||||
@@ -305,7 +331,7 @@ static int wait_for_partition_device(
|
||||
assert(pp);
|
||||
assert(ret);
|
||||
|
||||
r = find_partition(parent, pp, ret);
|
||||
r = find_partition(parent, pp, timestamp_not_before, ret);
|
||||
if (r != -ENXIO)
|
||||
return r;
|
||||
|
||||
@@ -336,6 +362,7 @@ static int wait_for_partition_device(
|
||||
_cleanup_(wait_data_done) struct wait_data w = {
|
||||
.parent_device = parent,
|
||||
.blkidp = pp,
|
||||
.uevent_seqnum_not_before = uevent_seqnum_not_before,
|
||||
};
|
||||
|
||||
r = sd_device_monitor_start(monitor, device_monitor_handler, &w);
|
||||
@@ -343,7 +370,7 @@ static int wait_for_partition_device(
|
||||
return r;
|
||||
|
||||
/* Check again, the partition might have appeared in the meantime */
|
||||
r = find_partition(parent, pp, ret);
|
||||
r = find_partition(parent, pp, timestamp_not_before, ret);
|
||||
if (r != -ENXIO)
|
||||
return r;
|
||||
|
||||
@@ -492,6 +519,8 @@ int dissect_image(
|
||||
int fd,
|
||||
const VeritySettings *verity,
|
||||
const MountOptions *mount_options,
|
||||
uint64_t uevent_seqnum_not_before,
|
||||
usec_t timestamp_not_before,
|
||||
DissectImageFlags flags,
|
||||
DissectedImage **ret) {
|
||||
|
||||
@@ -744,7 +773,7 @@ int dissect_image(
|
||||
if (!pp)
|
||||
return errno_or_else(EIO);
|
||||
|
||||
r = wait_for_partition_device(d, pp, deadline, &q);
|
||||
r = wait_for_partition_device(d, pp, deadline, uevent_seqnum_not_before, timestamp_not_before, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2579,6 +2608,8 @@ int dissect_image_and_warn(
|
||||
const char *name,
|
||||
const VeritySettings *verity,
|
||||
const MountOptions *mount_options,
|
||||
uint64_t uevent_seqnum_not_before,
|
||||
usec_t timestamp_not_before,
|
||||
DissectImageFlags flags,
|
||||
DissectedImage **ret) {
|
||||
|
||||
@@ -2593,7 +2624,7 @@ int dissect_image_and_warn(
|
||||
name = buffer;
|
||||
}
|
||||
|
||||
r = dissect_image(fd, verity, mount_options, flags, ret);
|
||||
r = dissect_image(fd, verity, mount_options, uevent_seqnum_not_before, timestamp_not_before, flags, ret);
|
||||
switch (r) {
|
||||
|
||||
case -EOPNOTSUPP:
|
||||
@@ -2701,7 +2732,7 @@ int mount_image_privately_interactively(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up loopback device: %m");
|
||||
|
||||
r = dissect_image_and_warn(d->fd, image, &verity, NULL, flags, &dissected_image);
|
||||
r = dissect_image_and_warn(d->fd, image, &verity, NULL, d->uevent_seqnum_not_before, d->timestamp_not_before, flags, &dissected_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2792,6 +2823,8 @@ int verity_dissect_and_mount(
|
||||
loop_device->fd,
|
||||
&verity,
|
||||
options,
|
||||
loop_device->uevent_seqnum_not_before,
|
||||
loop_device->timestamp_not_before,
|
||||
dissect_image_flags,
|
||||
&dissected_image);
|
||||
/* No partition table? Might be a single-filesystem image, try again */
|
||||
@@ -2800,7 +2833,9 @@ int verity_dissect_and_mount(
|
||||
loop_device->fd,
|
||||
&verity,
|
||||
options,
|
||||
dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE,
|
||||
loop_device->uevent_seqnum_not_before,
|
||||
loop_device->timestamp_not_before,
|
||||
dissect_image_flags | DISSECT_IMAGE_NO_PARTITION_TABLE,
|
||||
&dissected_image);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to dissect image: %m");
|
||||
|
||||
@@ -159,8 +159,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
|
||||
const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
|
||||
|
||||
int probe_filesystem(const char *node, char **ret_fstype);
|
||||
int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
|
||||
int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, uint64_t uevent_seqnum_not_before, usec_t timestamp_not_before, DissectImageFlags flags, DissectedImage **ret);
|
||||
|
||||
DissectedImage* dissected_image_unref(DissectedImage *m);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
|
||||
|
||||
+69
-7
@@ -53,6 +53,23 @@ static int loop_is_bound(int fd) {
|
||||
return true; /* bound! */
|
||||
}
|
||||
|
||||
static int get_current_uevent_seqnum(uint64_t *ret) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
r = read_full_virtual_file("/sys/kernel/uevent_seqnum", &p, NULL);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read current uevent sequence number: %m");
|
||||
|
||||
truncate_nl(p);
|
||||
|
||||
r = safe_atou64(p, ret);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse current uevent sequence number: %s", p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -114,11 +131,15 @@ static int loop_configure(
|
||||
int fd,
|
||||
int nr,
|
||||
const struct loop_config *c,
|
||||
bool *try_loop_configure) {
|
||||
bool *try_loop_configure,
|
||||
uint64_t *ret_seqnum_not_before,
|
||||
usec_t *ret_timestamp_not_before) {
|
||||
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
_cleanup_free_ char *sysname = NULL;
|
||||
_cleanup_close_ int lock_fd = -1;
|
||||
uint64_t seqnum;
|
||||
usec_t timestamp;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
@@ -167,6 +188,17 @@ static int loop_configure(
|
||||
}
|
||||
|
||||
if (*try_loop_configure) {
|
||||
/* Acquire uevent seqnum immediately before attaching the loopback device. This allows
|
||||
* callers to ignore all uevents with a seqnum before this one, if they need to associate
|
||||
* uevent with this attachment. Doing so isn't race-free though, as uevents that happen in
|
||||
* the window between this reading of the seqnum, and the LOOP_CONFIGURE call might still be
|
||||
* mistaken as originating from our attachment, even though might be caused by an earlier
|
||||
* use. But doing this at least shortens the race window a bit. */
|
||||
r = get_current_uevent_seqnum(&seqnum);
|
||||
if (r < 0)
|
||||
return r;
|
||||
timestamp = now(CLOCK_MONOTONIC);
|
||||
|
||||
if (ioctl(fd, LOOP_CONFIGURE, c) < 0) {
|
||||
/* Do fallback only if LOOP_CONFIGURE is not supported, propagate all other
|
||||
* errors. Note that the kernel is weird: non-existing ioctls currently return EINVAL
|
||||
@@ -224,10 +256,21 @@ static int loop_configure(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ret_seqnum_not_before)
|
||||
*ret_seqnum_not_before = seqnum;
|
||||
if (ret_timestamp_not_before)
|
||||
*ret_timestamp_not_before = timestamp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Let's read the seqnum again, to shorten the window. */
|
||||
r = get_current_uevent_seqnum(&seqnum);
|
||||
if (r < 0)
|
||||
return r;
|
||||
timestamp = now(CLOCK_MONOTONIC);
|
||||
|
||||
/* Since kernel commit 5db470e229e22b7eda6e23b5566e532c96fb5bc3 (kernel v5.0) the LOOP_SET_STATUS64
|
||||
* ioctl can return EAGAIN in case we change the lo_offset field, if someone else is accessing the
|
||||
* block device while we try to reconfigure it. This is a pretty common case, since udev might
|
||||
@@ -252,9 +295,14 @@ static int loop_configure(
|
||||
/* Sleep some random time, but at least 10ms, at most 250ms. Increase the delay the more
|
||||
* failed attempts we see */
|
||||
(void) usleep(UINT64_C(10) * USEC_PER_MSEC +
|
||||
random_u64() % (UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
|
||||
random_u64_range(UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
|
||||
}
|
||||
|
||||
if (ret_seqnum_not_before)
|
||||
*ret_seqnum_not_before = seqnum;
|
||||
if (ret_timestamp_not_before)
|
||||
*ret_timestamp_not_before = timestamp;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -312,6 +360,8 @@ int loop_device_make(
|
||||
bool try_loop_configure = true;
|
||||
struct loop_config config;
|
||||
LoopDevice *d = NULL;
|
||||
uint64_t seqnum = UINT64_MAX;
|
||||
usec_t timestamp = USEC_INFINITY;
|
||||
struct stat st;
|
||||
int nr = -1, r;
|
||||
|
||||
@@ -354,6 +404,8 @@ int loop_device_make(
|
||||
.node = TAKE_PTR(loopdev),
|
||||
.relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */
|
||||
.devno = st.st_rdev,
|
||||
.uevent_seqnum_not_before = UINT64_MAX,
|
||||
.timestamp_not_before = USEC_INFINITY,
|
||||
};
|
||||
|
||||
*ret = d;
|
||||
@@ -401,7 +453,7 @@ int loop_device_make(
|
||||
if (!IN_SET(errno, ENOENT, ENXIO))
|
||||
return -errno;
|
||||
} else {
|
||||
r = loop_configure(loop, nr, &config, &try_loop_configure);
|
||||
r = loop_configure(loop, nr, &config, &try_loop_configure, &seqnum, ×tamp);
|
||||
if (r >= 0) {
|
||||
loop_with_fd = TAKE_FD(loop);
|
||||
break;
|
||||
@@ -422,8 +474,8 @@ int loop_device_make(
|
||||
|
||||
/* Wait some random time, to make collision less likely. Let's pick a random time in the
|
||||
* range 0ms…250ms, linearly scaled by the number of failed attempts. */
|
||||
(void) usleep(random_u64() % (UINT64_C(10) * USEC_PER_MSEC +
|
||||
UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
|
||||
(void) usleep(random_u64_range(UINT64_C(10) * USEC_PER_MSEC +
|
||||
UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
|
||||
}
|
||||
|
||||
if (fstat(loop_with_fd, &st) < 0)
|
||||
@@ -438,13 +490,20 @@ int loop_device_make(
|
||||
.node = TAKE_PTR(loopdev),
|
||||
.nr = nr,
|
||||
.devno = st.st_rdev,
|
||||
.uevent_seqnum_not_before = seqnum,
|
||||
.timestamp_not_before = timestamp,
|
||||
};
|
||||
|
||||
*ret = d;
|
||||
return 0;
|
||||
return d->fd;
|
||||
}
|
||||
|
||||
int loop_device_make_by_path(const char *path, int open_flags, uint32_t loop_flags, LoopDevice **ret) {
|
||||
int loop_device_make_by_path(
|
||||
const char *path,
|
||||
int open_flags,
|
||||
uint32_t loop_flags,
|
||||
LoopDevice **ret) {
|
||||
|
||||
_cleanup_close_ int fd = -1;
|
||||
int r;
|
||||
|
||||
@@ -567,6 +626,9 @@ int loop_device_open(const char *loop_path, int open_flags, LoopDevice **ret) {
|
||||
.nr = nr,
|
||||
.node = TAKE_PTR(p),
|
||||
.relinquished = true, /* It's not ours, don't try to destroy it when this object is freed */
|
||||
.devno = st.st_dev,
|
||||
.uevent_seqnum_not_before = UINT64_MAX,
|
||||
.timestamp_not_before = USEC_INFINITY,
|
||||
};
|
||||
|
||||
*ret = d;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
#include "time-util.h"
|
||||
|
||||
typedef struct LoopDevice LoopDevice;
|
||||
|
||||
@@ -13,6 +14,8 @@ struct LoopDevice {
|
||||
dev_t devno;
|
||||
char *node;
|
||||
bool relinquished;
|
||||
uint64_t uevent_seqnum_not_before; /* uevent sequm right before we attached the loopback device, or UINT64_MAX if we don't know */
|
||||
usec_t timestamp_not_before; /* CLOCK_MONOTONIC timestamp taken immediately before attaching the loopback device, or USEC_INFINITY if we don't know */
|
||||
};
|
||||
|
||||
int loop_device_make(int fd, int open_flags, uint64_t offset, uint64_t size, uint32_t loop_flags, LoopDevice **ret);
|
||||
|
||||
@@ -532,6 +532,8 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
|
||||
img->path,
|
||||
&verity_settings,
|
||||
NULL,
|
||||
d->uevent_seqnum_not_before,
|
||||
d->timestamp_not_before,
|
||||
flags,
|
||||
&m);
|
||||
if (r < 0)
|
||||
|
||||
@@ -79,6 +79,7 @@ int sd_device_get_action(sd_device *device, sd_device_action_t *ret);
|
||||
int sd_device_get_seqnum(sd_device *device, uint64_t *ret);
|
||||
|
||||
int sd_device_get_is_initialized(sd_device *device);
|
||||
int sd_device_get_usec_initialized(sd_device *device, uint64_t *usec);
|
||||
int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec);
|
||||
|
||||
const char *sd_device_get_tag_first(sd_device *device);
|
||||
|
||||
@@ -51,7 +51,7 @@ static void* thread_func(void *ptr) {
|
||||
|
||||
log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);
|
||||
|
||||
r = dissect_image(loop->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY, &dissected);
|
||||
r = dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, DISSECT_IMAGE_READ_ONLY, &dissected);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed dissect loopback device %s: %m", loop->node);
|
||||
assert_se(r >= 0);
|
||||
@@ -188,7 +188,7 @@ int main(int argc, char *argv[]) {
|
||||
sfdisk = NULL;
|
||||
|
||||
assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, LO_FLAGS_PARTSCAN, &loop) >= 0);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
|
||||
|
||||
assert_se(dissected->partitions[PARTITION_ESP].found);
|
||||
assert_se(dissected->partitions[PARTITION_ESP].node);
|
||||
@@ -212,7 +212,7 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", id, true) >= 0);
|
||||
|
||||
dissected = dissected_image_unref(dissected);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
|
||||
assert_se(dissect_image(loop->fd, NULL, NULL, loop->uevent_seqnum_not_before, loop->timestamp_not_before, 0, &dissected) >= 0);
|
||||
|
||||
assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
Skip this test due to issue #17469
|
||||
https://github.com/systemd/systemd/issues/17469
|
||||
Reference in New Issue
Block a user