diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index fb88f51849..fcbd5a5f79 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -47,18 +47,42 @@ static int loop_configure(int fd, const struct loop_config *c) { if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EINVAL) return -errno; } else { - if (!FLAGS_SET(c->info.lo_flags, LO_FLAGS_PARTSCAN)) + bool good = true; + + if (c->info.lo_sizelimit != 0) { + /* Kernel 5.8 vanilla doesn't properly propagate the size limit into the block + * device. If it's used, let's immediately check if it had the desired effect + * hence. And if not use classic LOOP_SET_STATUS64. */ + uint64_t z; + + if (ioctl(fd, BLKGETSIZE64, &z) < 0) { + r = -errno; + goto fail; + } + + if (z != c->info.lo_sizelimit) { + log_debug("LOOP_CONFIGURE is broken, doesn't honour .lo_sizelimit. Falling back to LOOP_SET_STATUS64."); + good = false; + } + } + + if (FLAGS_SET(c->info.lo_flags, LO_FLAGS_PARTSCAN)) { + /* Kernel 5.8 vanilla doesn't properly propagate the partition scanning flag into the + * block device. Let's hence verify if things work correctly here before + * returning. */ + + r = blockdev_partscan_enabled(fd); + if (r < 0) + goto fail; + if (r == 0) { + log_debug("LOOP_CONFIGURE is broken, doesn't honour LO_FLAGS_PARTSCAN. Falling back to LOOP_SET_STATUS64."); + good = false; + } + } + + if (good) return 0; - /* Kernel 5.8 vanilla doesn't properly propagate the partition scanning flag into the - * block device. Let's hence verify if things work correctly here before returning. */ - - r = blockdev_partscan_enabled(fd); - if (r < 0) - goto fail; - if (r > 0) - return 0; /* All is good. */ - /* Otherwise, undo the attachment and use the old APIs */ (void) ioctl(fd, LOOP_CLR_FD); }