]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
loop-util: store sd_device object for the loop device
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 5 Sep 2022 19:35:54 +0000 (04:35 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 6 Sep 2022 02:26:00 +0000 (11:26 +0900)
It will be used in later commits.

src/shared/loop-util.c
src/shared/loop-util.h
src/test/test-loop-block.c

index ed237c6f20d7e93ee00bc1438802ec98af39e322..ac873b015492ceaa29688159e21fbe4c1b8c5284 100644 (file)
@@ -132,6 +132,7 @@ static int open_lock_fd(int primary_fd, int operation) {
 }
 
 static int loop_configure(
+                sd_device *dev,
                 int fd,
                 int nr,
                 const struct loop_config *c,
@@ -140,8 +141,6 @@ static int loop_configure(
                 usec_t *ret_timestamp_not_before,
                 int *ret_lock_fd) {
 
-        _cleanup_(sd_device_unrefp) sd_device *d = NULL;
-        _cleanup_free_ char *sysname = NULL;
         _cleanup_close_ int lock_fd = -1;
         struct loop_info64 info_copy;
         uint64_t seqnum;
@@ -153,13 +152,6 @@ static int loop_configure(
         assert(c);
         assert(try_loop_configure);
 
-        if (asprintf(&sysname, "loop%i", nr) < 0)
-                return -ENOMEM;
-
-        r = sd_device_new_from_subsystem_sysname(&d, "block", sysname);
-        if (r < 0)
-                return r;
-
         /* Let's lock the device before we do anything. We take the BSD lock on a second, separately opened
          * fd for the device. udev after all watches for close() events (specifically IN_CLOSE_WRITE) on
          * block devices to reprobe them, hence by having a separate fd we will later close() we can ensure
@@ -176,7 +168,7 @@ static int loop_configure(
          * superficially is detached but still has partition block devices associated for it. Let's then
          * manually remove the partitions via BLKPG, and tell the caller we did that via EUCLEAN, so they try
          * again. */
-        r = device_has_block_children(d);
+        r = device_has_block_children(dev);
         if (r < 0)
                 return r;
         if (r > 0) {
@@ -357,6 +349,7 @@ static int loop_device_make_internal(
                 int lock_op,
                 LoopDevice **ret) {
 
+        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
         _cleanup_close_ int direct_io_fd = -1;
         _cleanup_free_ char *node = NULL;
         bool try_loop_configure = true;
@@ -456,14 +449,19 @@ static int loop_device_make_internal(
                 if (asprintf(&node, "/dev/loop%i", nr) < 0)
                         return -ENOMEM;
 
-                loop = open(node, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
+                dev = sd_device_unref(dev);
+                r = sd_device_new_from_devname(&dev, node);
+                if (r < 0)
+                        return r;
+
+                loop = sd_device_open(dev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
                 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 (!ERRNO_IS_DEVICE_ABSENT(errno))
                                 return -errno;
                 } else {
-                        r = loop_configure(loop, nr, &config, &try_loop_configure, &seqnum, &timestamp, &lock_fd);
+                        r = loop_configure(dev, loop, nr, &config, &try_loop_configure, &seqnum, &timestamp, &lock_fd);
                         if (r >= 0) {
                                 loop_with_fd = TAKE_FD(loop);
                                 break;
@@ -545,6 +543,7 @@ static int loop_device_make_internal(
                 .node = TAKE_PTR(node),
                 .nr = nr,
                 .devno = st.st_rdev,
+                .dev = TAKE_PTR(dev),
                 .diskseq = diskseq,
                 .uevent_seqnum_not_before = seqnum,
                 .timestamp_not_before = timestamp,
@@ -720,6 +719,7 @@ LoopDevice* loop_device_unref(LoopDevice *d) {
                 }
 
         free(d->node);
+        sd_device_unref(d->dev);
         return mfree(d);
 }
 
@@ -744,6 +744,7 @@ int loop_device_open_full(
                 int lock_op,
                 LoopDevice **ret) {
 
+        _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
         _cleanup_close_ int fd = -1, lock_fd = -1;
         _cleanup_free_ char *p = NULL;
         struct loop_info64 info;
@@ -768,6 +769,10 @@ int loop_device_open_full(
         if (!S_ISBLK(st.st_mode))
                 return -ENOTBLK;
 
+        r = sd_device_new_from_stat_rdev(&dev, &st);
+        if (r < 0)
+                return r;
+
         if (fd < 0) {
                 /* If loop_fd is provided through the argument, then we reopen the inode here, instead of
                  * keeping just a dup() clone of it around, since we want to ensure that the O_DIRECT
@@ -797,21 +802,13 @@ int loop_device_open_full(
                         return lock_fd;
         }
 
-        if (loop_path) {
-                /* If loop_path is provided, then honor it. */
-                p = strdup(loop_path);
-                if (!p)
-                        return -ENOMEM;
-        } else if (nr >= 0) {
-                /* This is a loopback block device. Use its index. */
-                if (asprintf(&p, "/dev/loop%i", nr) < 0)
-                        return -ENOMEM;
-        } else {
-                /* This is a non-loopback block device. Let's get the path to the device node. */
-                r = devname_from_stat_rdev(&st, &p);
-                if (r < 0)
-                        return r;
-        }
+        r = sd_device_get_devname(dev, &loop_path);
+        if (r < 0)
+                return r;
+
+        p = strdup(loop_path);
+        if (!p)
+                return -ENOMEM;
 
         d = new(LoopDevice, 1);
         if (!d)
@@ -822,6 +819,7 @@ int loop_device_open_full(
                 .lock_fd = TAKE_FD(lock_fd),
                 .nr = nr,
                 .node = TAKE_PTR(p),
+                .dev = TAKE_PTR(dev),
                 .relinquished = true, /* It's not ours, don't try to destroy it when this object is freed */
                 .devno = st.st_rdev,
                 .diskseq = diskseq,
index 89fcbc00a0ef01c12878a01594eb535213b920c6..43bd25d4454db29959b3283174c7ca773310aa77 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include "sd-device.h"
+
 #include "macro.h"
 #include "time-util.h"
 
@@ -14,6 +16,7 @@ struct LoopDevice {
         int nr;   /* The loopback device index (i.e. 4 for /dev/loop4); if this object encapsulates a non-loopback block device, set to -1 */
         dev_t devno;
         char *node;
+        sd_device *dev;
         bool relinquished;
         uint64_t diskseq; /* Block device sequence number, monothonically incremented by the kernel on create/attach, or 0 if we don't know */
         uint64_t uevent_seqnum_not_before; /* uevent sequm right before we attached the loopback device, or UINT64_MAX if we don't know */
index 143e5a61e0736f701953468ddeaafc6e4580ca25..1809d9f3b8614f9e45ea7282f7b2ff73fbffd428 100644 (file)
@@ -54,6 +54,7 @@ static void* thread_func(void *ptr) {
                 if (r < 0)
                         log_error_errno(r, "Failed to allocate loopback device: %m");
                 assert_se(r >= 0);
+                assert_se(loop->dev);
 
                 log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);