diff options
author | Luca Boccassi <bluca@debian.org> | 2022-08-04 02:02:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-04 02:02:55 +0200 |
commit | 33b7d7b284928bec88015aa2c6ca60e9c9599382 (patch) | |
tree | 34bba2b9d8cd90d5b89d089aa810bfcbf360077e | |
parent | integritysetup: do not use crypt_init_data_device after crypt_init (diff) | |
parent | dissect: Add systemd-dissect --umount (diff) | |
download | systemd-33b7d7b284928bec88015aa2c6ca60e9c9599382.tar.xz systemd-33b7d7b284928bec88015aa2c6ca60e9c9599382.zip |
Merge pull request #24141 from DaanDeMeyer/dissect-umount
dissect: Add systemd-dissect --umount
-rw-r--r-- | man/systemd-dissect.xml | 38 | ||||
-rw-r--r-- | src/dissect/dissect.c | 115 | ||||
-rw-r--r-- | src/shared/blockdev-util.c | 165 | ||||
-rw-r--r-- | src/shared/blockdev-util.h | 7 | ||||
-rw-r--r-- | src/shared/dissect-image.c | 63 | ||||
-rw-r--r-- | src/shared/loop-util.c | 5 | ||||
-rw-r--r-- | src/shared/loop-util.h | 1 | ||||
-rw-r--r-- | src/udev/udevadm-lock.c | 44 | ||||
-rwxr-xr-x | test/units/testsuite-50.sh | 10 |
9 files changed, 339 insertions, 109 deletions
diff --git a/man/systemd-dissect.xml b/man/systemd-dissect.xml index 4cdac2b013..6430501bdf 100644 --- a/man/systemd-dissect.xml +++ b/man/systemd-dissect.xml @@ -29,6 +29,9 @@ <command>systemd-dissect <arg choice="opt" rep="repeat">OPTIONS</arg> <option>--mount</option> <arg choice="plain"><replaceable>IMAGE</replaceable></arg> <arg choice="plain"><replaceable>PATH</replaceable></arg></command> </cmdsynopsis> <cmdsynopsis> + <command>systemd-dissect <arg choice="opt" rep="repeat">OPTIONS</arg> <option>--umount</option> <arg choice="plain"><replaceable>PATH</replaceable></arg></command> + </cmdsynopsis> + <cmdsynopsis> <command>systemd-dissect <arg choice="opt" rep="repeat">OPTIONS</arg> <option>--copy-from</option> <arg choice="plain"><replaceable>IMAGE</replaceable></arg> <arg choice="plain"><replaceable>PATH</replaceable></arg> <arg choice="opt"><replaceable>TARGET</replaceable></arg></command> </cmdsynopsis> <cmdsynopsis> @@ -40,7 +43,7 @@ <title>Description</title> <para><command>systemd-dissect</command> is a tool for introspecting and interacting with file system OS - disk images. It supports four different operations:</para> + disk images. It supports five different operations:</para> <orderedlist> <listitem><para>Show general OS image information, including the image's @@ -51,6 +54,10 @@ mount the included partitions according to their designation onto a directory and possibly sub-directories.</para></listitem> + <listitem><para>Unmount an OS image from a local directory. In this mode it will recursively unmount + the mounted partitions and remove the underlying loop device, including all the partition sub-devices. + </para></listitem> + <listitem><para>Copy files and directories in and out of an OS image.</para></listitem> </orderedlist> @@ -103,10 +110,7 @@ multiple nested mounts are established. This command expects two arguments: a path to an image file and a path to a directory where to mount the image.</para> - <para>To unmount an OS image mounted like this use <citerefentry - project='man-pages'><refentrytitle>umount</refentrytitle><manvolnum>8</manvolnum></citerefentry>'s - <option>-R</option> switch (for recursive operation), so that the OS image and all nested partition - mounts are unmounted.</para> + <para>To unmount an OS image mounted like this use the <option>--umount</option> operation.</para> <para>When the OS image contains LUKS encrypted or Verity integrity protected file systems appropriate volumes are automatically set up and marked for automatic disassembly when the image is @@ -129,6 +133,23 @@ </varlistentry> <varlistentry> + <term><option>--umount</option></term> + <term><option>-u</option></term> + + <listitem><para>Unmount an OS image from the specified directory. This command expects one argument: + a directory where an OS image was mounted.</para> + + <para>All mounted partitions will be recursively unmounted, and the underlying loop device will be + removed, along with all it's partition sub-devices.</para></listitem> + </varlistentry> + + <varlistentry> + <term><option>-U</option></term> + + <listitem><para>This is a shortcut for <option>--umount --rmdir</option>.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>--copy-from</option></term> <term><option>-x</option></term> @@ -225,6 +246,13 @@ </varlistentry> <varlistentry> + <term><option>--rmdir</option></term> + + <listitem><para>If combined with <option>--umount</option> the specified directory where the OS image + is mounted is removed after unmounting the OS image.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>--discard=</option></term> <listitem><para>Takes one of <literal>disabled</literal>, <literal>loop</literal>, diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 4e39f959cf..d9f3fab835 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -8,7 +8,10 @@ #include <sys/ioctl.h> #include <sys/mount.h> +#include "sd-device.h" + #include "architecture.h" +#include "blockdev-util.h" #include "chase-symlinks.h" #include "copy.h" #include "dissect-image.h" @@ -24,6 +27,7 @@ #include "main-func.h" #include "mkdir.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "namespace-util.h" #include "parse-argument.h" #include "parse-util.h" @@ -40,6 +44,7 @@ static enum { ACTION_DISSECT, ACTION_MOUNT, + ACTION_UMOUNT, ACTION_COPY_FROM, ACTION_COPY_TO, } arg_action = ACTION_DISSECT; @@ -58,6 +63,7 @@ static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static PagerFlags arg_pager_flags = 0; static bool arg_legend = true; +static bool arg_rmdir = false; STATIC_DESTRUCTOR_REGISTER(arg_verity_settings, verity_settings_done); @@ -81,6 +87,7 @@ static int help(void) { " --fsck=BOOL Run fsck before mounting\n" " --growfs=BOOL Grow file system to partition size, if marked\n" " --mkdir Make mount directory before mounting, if missing\n" + " --rmdir Remove mount directory after unmounting\n" " --discard=MODE Choose 'discard' mode (disabled, loop, all, crypto)\n" " --root-hash=HASH Specify root hash for verity\n" " --root-hash-sig=SIG Specify pkcs7 signature of root hash for verity\n" @@ -96,6 +103,8 @@ static int help(void) { " --version Show package version\n" " -m --mount Mount the image to the specified directory\n" " -M Shortcut for --mount --mkdir\n" + " -u --umount Unmount the image from the specified directory\n" + " -U Shortcut for --umount --rmdir\n" " -x --copy-from Copy files from image to host\n" " -a --copy-to Copy files from host to image\n" "\nSee the %2$s for details.\n", @@ -122,6 +131,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_ROOT_HASH_SIG, ARG_VERITY_DATA, ARG_MKDIR, + ARG_RMDIR, ARG_JSON, }; @@ -131,6 +141,7 @@ static int parse_argv(int argc, char *argv[]) { { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "mount", no_argument, NULL, 'm' }, + { "umount", no_argument, NULL, 'u' }, { "read-only", no_argument, NULL, 'r' }, { "discard", required_argument, NULL, ARG_DISCARD }, { "fsck", required_argument, NULL, ARG_FSCK }, @@ -139,6 +150,7 @@ static int parse_argv(int argc, char *argv[]) { { "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG }, { "verity-data", required_argument, NULL, ARG_VERITY_DATA }, { "mkdir", no_argument, NULL, ARG_MKDIR }, + { "rmdir", no_argument, NULL, ARG_RMDIR }, { "copy-from", no_argument, NULL, 'x' }, { "copy-to", no_argument, NULL, 'a' }, { "json", required_argument, NULL, ARG_JSON }, @@ -150,7 +162,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hmrMxa", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hmurMUxa", options, NULL)) >= 0) { switch (c) { @@ -182,6 +194,20 @@ static int parse_argv(int argc, char *argv[]) { arg_flags |= DISSECT_IMAGE_MKDIR; break; + case 'u': + arg_action = ACTION_UMOUNT; + break; + + case ARG_RMDIR: + arg_rmdir = true; + break; + + case 'U': + /* Shortcut combination of the above two */ + arg_action = ACTION_UMOUNT; + arg_rmdir = true; + break; + case 'x': arg_action = ACTION_COPY_FROM; arg_flags |= DISSECT_IMAGE_READ_ONLY; @@ -316,6 +342,14 @@ static int parse_argv(int argc, char *argv[]) { arg_flags |= DISSECT_IMAGE_REQUIRE_ROOT; break; + case ACTION_UMOUNT: + if (optind + 1 != argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected a mount point path as only argument."); + + arg_path = argv[optind]; + break; + case ACTION_COPY_FROM: if (argc < optind + 2 || argc > optind + 3) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -823,6 +857,82 @@ static int action_copy(DissectedImage *m, LoopDevice *d) { return 0; } +static int action_umount(const char *path) { + _cleanup_close_ int fd = -1; + _cleanup_free_ char *canonical = NULL; + dev_t devno; + const char *devname; + _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r, k; + + fd = chase_symlinks_and_open(path, NULL, 0, O_DIRECTORY, &canonical); + if (fd == -ENOTDIR) + return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "'%s' is not a directory", path); + if (fd < 0) + return log_error_errno(fd, "Failed to resolve path '%s': %m", path); + + r = fd_is_mount_point(fd, NULL, 0); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "'%s' is not a mount point", canonical); + if (r < 0) + return log_error_errno(r, "Failed to determine whether '%s' is a mount point: %m", canonical); + + r = fd_get_whole_disk(fd, /*backing=*/ true, &devno); + if (r < 0) + return log_error_errno(r, "Failed to find backing block device for '%s': %m", canonical); + + r = sd_device_new_from_devnum(&device, 'b', devno); + if (r < 0) + return log_error_errno(r, "Failed to create sd-device object for block device %u:%u: %m", + major(devno), minor(devno)); + + r = sd_device_get_devname(device, &devname); + if (r < 0) + return log_error_errno(r, "Failed to get devname of block device %u:%u: %m", + major(devno), minor(devno)); + + r = loop_device_open(devname, 0, &d); + if (r < 0) + return log_error_errno(r, "Failed to open loop device '%s': %m", devname); + + r = loop_device_flock(d, LOCK_EX); + if (r < 0) + return log_error_errno(r, "Failed to lock loop device '%s': %m", devname); + + /* We've locked the loop device, now we're ready to unmount. To allow the unmount to succeed, we have + * to close the O_PATH fd we opened earlier. */ + fd = safe_close(fd); + + r = umount_recursive(canonical, 0); + if (r < 0) + return log_error_errno(r, "Failed to unmount '%s': %m", canonical); + + /* We managed to lock and unmount successfully? That means we can try to remove the loop device.*/ + loop_device_unrelinquish(d); + + if (arg_rmdir) { + k = RET_NERRNO(rmdir(canonical)); + if (k < 0) + log_error_errno(k, "Failed to remove mount directory '%s': %m", canonical); + } else + k = 0; + + /* Before loop_device_unrefp() kicks in, let's explicitly remove all the partition subdevices of the + * loop device. We do this to ensure that all traces of the loop device are gone by the time this + * command exits. */ + r = block_device_remove_all_partitions(d->fd); + if (r == -EBUSY) { + log_error_errno(r, "One or more partitions of '%s' are busy, ignoring", devname); + r = 0; + } + if (r < 0) + log_error_errno(r, "Failed to remove one or more partitions of '%s': %m", devname); + + + return k < 0 ? k : r; +} + static int run(int argc, char *argv[]) { _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; @@ -835,6 +945,9 @@ static int run(int argc, char *argv[]) { if (r <= 0) return r; + if (arg_action == ACTION_UMOUNT) + return action_umount(arg_path); + r = verity_settings_load( &arg_verity_settings, arg_image, NULL, NULL); diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index c3b90bb227..0d921cc045 100644 --- a/src/shared/blockdev-util.c +++ b/src/shared/blockdev-util.c @@ -1,13 +1,19 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include <linux/blkpg.h> #include <sys/file.h> +#include <sys/ioctl.h> #include <unistd.h> +#include "sd-device.h" + #include "alloc-util.h" #include "blockdev-util.h" #include "btrfs-util.h" +#include "device-util.h" #include "devnum-util.h" #include "dirent-util.h" +#include "errno-util.h" #include "fd-util.h" #include "fileio.h" #include "missing_magic.h" @@ -377,3 +383,162 @@ int path_is_encrypted(const char *path) { return blockdev_is_encrypted(p, 10 /* safety net: maximum recursion depth */); } + +int fd_get_whole_disk(int fd, bool backing, dev_t *ret) { + dev_t devt; + struct stat st; + int r; + + assert(ret); + + if (fstat(fd, &st) < 0) + return -errno; + + if (S_ISBLK(st.st_mode)) + devt = st.st_rdev; + else if (!backing) + return -ENOTBLK; + else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) + return -ENOTBLK; + else if (major(st.st_dev) != 0) + devt = st.st_dev; + else { + _cleanup_close_ int regfd = -1; + + /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special + * handing, to get the backing device node. */ + + regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (regfd < 0) + return regfd; + + r = btrfs_get_block_device_fd(regfd, &devt); + if (r == -ENOTTY) + return -ENOTBLK; + if (r < 0) + return r; + } + + return block_get_whole_disk(devt, ret); +} + +int path_get_whole_disk(const char *path, bool backing, dev_t *ret) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_CLOEXEC|O_PATH); + if (fd < 0) + return -errno; + + return fd_get_whole_disk(fd, backing, ret); +} + +int block_device_add_partition(int fd, const char *name, int nr, uint64_t start, uint64_t size) { + assert(fd >= 0); + assert(name); + assert(nr > 0); + + struct blkpg_partition bp = { + .pno = nr, + .start = start, + .length = size, + }; + + struct blkpg_ioctl_arg ba = { + .op = BLKPG_ADD_PARTITION, + .data = &bp, + .datalen = sizeof(bp), + }; + + if (strlen(name) >= sizeof(bp.devname)) + return -EINVAL; + + strcpy(bp.devname, name); + + return RET_NERRNO(ioctl(fd, BLKPG, &ba)); +} + +int block_device_remove_partition(int fd, const char *name, int nr) { + assert(fd >= 0); + assert(name); + assert(nr > 0); + + struct blkpg_partition bp = { + .pno = nr, + }; + + struct blkpg_ioctl_arg ba = { + .op = BLKPG_DEL_PARTITION, + .data = &bp, + .datalen = sizeof(bp), + }; + + if (strlen(name) >= sizeof(bp.devname)) + return -EINVAL; + + strcpy(bp.devname, name); + + return RET_NERRNO(ioctl(fd, BLKPG, &ba)); +} + +int block_device_remove_all_partitions(int fd) { + struct stat stat; + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *part; + int r, k = 0; + + if (fstat(fd, &stat) < 0) + return -errno; + + r = sd_device_new_from_devnum(&dev, 'b', stat.st_rdev); + if (r < 0) + return r; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_parent(e, dev); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "block", true); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_property(e, "DEVTYPE", "partition"); + if (r < 0) + return r; + + FOREACH_DEVICE(e, part) { + const char *v, *devname; + int nr; + + r = sd_device_get_devname(part, &devname); + if (r < 0) + return r; + + r = sd_device_get_property_value(part, "PARTN", &v); + if (r < 0) + return r; + + r = safe_atoi(v, &nr); + if (r < 0) + return r; + + r = block_device_remove_partition(fd, devname, nr); + if (r == -ENODEV) { + log_debug("Kernel removed partition %s before us, ignoring", devname); + continue; + } + if (r < 0) { + log_debug_errno(r, "Failed to remove partition %s: %m", devname); + k = k ?: r; + continue; + } + + log_debug("Removed partition %s", devname); + } + + return k; +} diff --git a/src/shared/blockdev-util.h b/src/shared/blockdev-util.h index 05501f2657..8c9401b4a7 100644 --- a/src/shared/blockdev-util.h +++ b/src/shared/blockdev-util.h @@ -27,3 +27,10 @@ int blockdev_partscan_enabled(int fd); int fd_is_encrypted(int fd); int path_is_encrypted(const char *path); + +int fd_get_whole_disk(int fd, bool backing, dev_t *ret); +int path_get_whole_disk(const char *path, bool backing, dev_t *ret); + +int block_device_add_partition(int fd, const char *name, int nr, uint64_t start, uint64_t size); +int block_device_remove_partition(int fd, const char *name, int nr); +int block_device_remove_all_partitions(int fd); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index c7a336d432..87712abfb3 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -4,7 +4,6 @@ #include <valgrind/memcheck.h> #endif -#include <linux/blkpg.h> #include <linux/dm-ioctl.h> #include <linux/loop.h> #include <sys/file.h> @@ -149,29 +148,6 @@ static void check_partition_flags( log_debug("Unexpected partition flag %llu set on %s!", bit, node); } } - -static int ioctl_partition_remove(int fd, const char *name, int nr) { - assert(fd >= 0); - assert(name); - assert(nr > 0); - - struct blkpg_partition bp = { - .pno = nr, - }; - - struct blkpg_ioctl_arg ba = { - .op = BLKPG_DEL_PARTITION, - .data = &bp, - .datalen = sizeof(bp), - }; - - if (strlen(name) >= sizeof(bp.devname)) - return -EINVAL; - - strcpy(bp.devname, name); - - return RET_NERRNO(ioctl(fd, BLKPG, &ba)); -} #endif static void dissected_partition_done(int fd, DissectedPartition *p) { @@ -182,7 +158,7 @@ static void dissected_partition_done(int fd, DissectedPartition *p) { if (p->node && p->partno > 0 && !p->relinquished) { int r; - r = ioctl_partition_remove(fd, p->node, p->partno); + r = block_device_remove_partition(fd, p->node, p->partno); if (r < 0) log_debug_errno(r, "BLKPG_DEL_PARTITION failed, ignoring: %m"); } @@ -202,37 +178,6 @@ static void dissected_partition_done(int fd, DissectedPartition *p) { } #if HAVE_BLKID -static int ioctl_partition_add( - int fd, - const char *name, - int nr, - uint64_t start, - uint64_t size) { - - assert(fd >= 0); - assert(name); - assert(nr > 0); - - struct blkpg_partition bp = { - .pno = nr, - .start = start, - .length = size, - }; - - struct blkpg_ioctl_arg ba = { - .op = BLKPG_ADD_PARTITION, - .data = &bp, - .datalen = sizeof(bp), - }; - - if (strlen(name) >= sizeof(bp.devname)) - return -EINVAL; - - strcpy(bp.devname, name); - - return RET_NERRNO(ioctl(fd, BLKPG, &ba)); -} - static int make_partition_devname( const char *whole_devname, int nr, @@ -548,7 +493,7 @@ int dissect_image( * Kernel returns EBUSY if there's already a partition by that number or an overlapping * partition already existent. */ - r = ioctl_partition_add(fd, node, nr, (uint64_t) start * 512, (uint64_t) size * 512); + r = block_device_add_partition(fd, node, nr, (uint64_t) start * 512, (uint64_t) size * 512); if (r < 0) { if (r != -EBUSY) return log_debug_errno(r, "BLKPG_ADD_PARTITION failed: %m"); @@ -831,7 +776,7 @@ int dissect_image( if (!PARTITION_DESIGNATOR_VERSIONED(designator) || strverscmp_improved(m->partitions[designator].label, label) >= 0) { - r = ioctl_partition_remove(fd, node, nr); + r = block_device_remove_partition(fd, node, nr); if (r < 0) log_debug_errno(r, "BLKPG_DEL_PARTITION failed, ignoring: %m"); continue; @@ -908,7 +853,7 @@ int dissect_image( /* First one wins */ if (m->partitions[PARTITION_XBOOTLDR].found) { - r = ioctl_partition_remove(fd, node, nr); + r = block_device_remove_partition(fd, node, nr); if (r < 0) log_debug_errno(r, "BLKPG_DEL_PARTITION failed, ignoring: %m"); continue; diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index 530688fc97..a5ad914577 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -768,6 +768,11 @@ void loop_device_relinquish(LoopDevice *d) { d->relinquished = true; } +void loop_device_unrelinquish(LoopDevice *d) { + assert(d); + d->relinquished = false; +} + int loop_device_open(const char *loop_path, int open_flags, LoopDevice **ret) { _cleanup_close_ int loop_fd = -1; _cleanup_free_ char *p = NULL; diff --git a/src/shared/loop-util.h b/src/shared/loop-util.h index 964ce3ed08..a33d7e3e59 100644 --- a/src/shared/loop-util.h +++ b/src/shared/loop-util.h @@ -27,6 +27,7 @@ LoopDevice* loop_device_unref(LoopDevice *d); DEFINE_TRIVIAL_CLEANUP_FUNC(LoopDevice*, loop_device_unref); void loop_device_relinquish(LoopDevice *d); +void loop_device_unrelinquish(LoopDevice *d); int loop_device_refresh_size(LoopDevice *d, uint64_t offset, uint64_t size); diff --git a/src/udev/udevadm-lock.c b/src/udev/udevadm-lock.c index 60d6507aaf..a1e04f6516 100644 --- a/src/udev/udevadm-lock.c +++ b/src/udev/udevadm-lock.c @@ -144,9 +144,7 @@ static int find_devno( const char *device, bool backing) { - _cleanup_close_ int fd = -1; - dev_t devt, whole_devt; - struct stat st; + dev_t devt; int r; assert(devnos); @@ -154,51 +152,19 @@ static int find_devno( assert(*devnos || *n_devnos == 0); assert(device); - fd = open(device, O_CLOEXEC|O_PATH); - if (fd < 0) - return log_error_errno(errno, "Failed to open '%s': %m", device); - - if (fstat(fd, &st) < 0) - return log_error_errno(errno, "Failed to stat '%s': %m", device); - - if (S_ISBLK(st.st_mode)) - devt = st.st_rdev; - else if (!backing) - return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Not a block device: %s", device); - else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) - return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Not a block device, regular file or directory: %s", device); - else if (major(st.st_dev) != 0) - devt = st.st_dev; - else { - _cleanup_close_ int regfd = -1; - - /* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special - * handing, to get the backing device node. */ - - regfd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK); - if (regfd < 0) - return log_error_errno(regfd, "Failed to open '%s': %m", device); - - r = btrfs_get_block_device_fd(regfd, &devt); - if (r == -ENOTTY) - return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Path '%s' not backed by block device.", device); - if (r < 0) - return log_error_errno(r, "Failed to acquire btrfs backing device of '%s': %m", device); - } - - r = block_get_whole_disk(devt, &whole_devt); + r = path_get_whole_disk(device, backing, &devt); if (r < 0) return log_error_errno(r, "Failed to find whole block device for '%s': %m", device); - if (typesafe_bsearch(&whole_devt, *devnos, *n_devnos, devt_compare_func)) { - log_debug("Device %u:%u already listed for locking, ignoring.", major(whole_devt), minor(whole_devt)); + if (typesafe_bsearch(&devt, *devnos, *n_devnos, devt_compare_func)) { + log_debug("Device %u:%u already listed for locking, ignoring.", major(devt), minor(devt)); return 0; } if (!GREEDY_REALLOC(*devnos, *n_devnos + 1)) return log_oom(); - (*devnos)[(*n_devnos)++] = whole_devt; + (*devnos)[(*n_devnos)++] = devt; /* Immediately sort again, to ensure the binary search above will work for the next device we add */ typesafe_qsort(*devnos, *n_devnos, devt_compare_func); diff --git a/test/units/testsuite-50.sh b/test/units/testsuite-50.sh index 2f1844ccf7..31cb52064e 100755 --- a/test/units/testsuite-50.sh +++ b/test/units/testsuite-50.sh @@ -58,8 +58,8 @@ if [ "${verity_count}" -lt 1 ]; then echo "Verity device ${image}.raw not found in /dev/mapper/" exit 1 fi -umount "${image_dir}/mount" -umount "${image_dir}/mount2" +systemd-dissect --umount "${image_dir}/mount" +systemd-dissect --umount "${image_dir}/mount2" systemd-run -P -p RootImage="${image}.raw" cat /usr/lib/os-release | grep -q -F "MARKER=1" mv "${image}.verity" "${image}.fooverity" @@ -207,7 +207,7 @@ systemd-dissect --root-hash "${roothash}" --mount "${image}.gpt" "${image_dir}/m grep -q -F -f "$os_release" "${image_dir}/mount/usr/lib/os-release" grep -q -F -f "$os_release" "${image_dir}/mount/etc/os-release" grep -q -F "MARKER=1" "${image_dir}/mount/usr/lib/os-release" -umount "${image_dir}/mount" +systemd-dissect --umount "${image_dir}/mount" # add explicit -p MountAPIVFS=yes once to test the parser systemd-run -P -p RootImage="${image}.gpt" -p RootHash="${roothash}" -p MountAPIVFS=yes cat /usr/lib/os-release | grep -q -F "MARKER=1" @@ -350,8 +350,8 @@ RemainAfterExit=yes EOF systemctl start testservice-50f.service systemctl is-active testservice-50f.service -umount "${image_dir}/app0" -umount "${image_dir}/app1" +systemd-dissect --umount "${image_dir}/app0" +systemd-dissect --umount "${image_dir}/app1" echo OK >/testok |