]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
loop-util: save backing file of loopback block device
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 5 Sep 2022 20:19:46 +0000 (05:19 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 7 Sep 2022 11:45:24 +0000 (20:45 +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 b5c16b0b0ef1b134374bd4b04fb8aba988a05aa7..7a1b5ad2d394992d7c7b9d3cbcf202a7b8bd90ce 100644 (file)
@@ -26,6 +26,7 @@
 #include "loop-util.h"
 #include "missing_loop.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "random-util.h"
 #include "stat-util.h"
 #include "stdio-util.h"
@@ -294,6 +295,7 @@ fail:
 }
 
 static int loop_device_make_internal(
+                const char *path,
                 int fd,
                 int open_flags,
                 uint64_t offset,
@@ -304,7 +306,7 @@ static int loop_device_make_internal(
 
         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
         _cleanup_close_ int direct_io_fd = -1;
-        _cleanup_free_ char *node = NULL;
+        _cleanup_free_ char *node = NULL, *backing_file = NULL;
         bool try_loop_configure = true;
         struct loop_config config;
         LoopDevice *d;
@@ -332,6 +334,18 @@ static int loop_device_make_internal(
                         return r;
         }
 
+        if (path) {
+                r = path_make_absolute_cwd(path, &backing_file);
+                if (r < 0)
+                        return r;
+
+                path_simplify(backing_file);
+        } else {
+                r = fd_get_path(fd, &backing_file);
+                if (r < 0)
+                        return r;
+        }
+
         f_flags = fcntl(fd, F_GETFL);
         if (f_flags < 0)
                 return -errno;
@@ -497,6 +511,7 @@ static int loop_device_make_internal(
                 .nr = nr,
                 .devno = st.st_rdev,
                 .dev = TAKE_PTR(dev),
+                .backing_file = TAKE_PTR(backing_file),
                 .diskseq = diskseq,
                 .uevent_seqnum_not_before = seqnum,
                 .timestamp_not_before = timestamp,
@@ -535,6 +550,7 @@ int loop_device_make(
         assert(ret);
 
         return loop_device_make_internal(
+                        NULL,
                         fd,
                         open_flags,
                         offset,
@@ -602,7 +618,7 @@ int loop_device_make_by_path(
                   direct ? "enabled" : "disabled",
                   direct != (direct_flags != 0) ? " (O_DIRECT was requested but not supported)" : "");
 
-        return loop_device_make_internal(fd, open_flags, 0, 0, loop_flags, lock_op, ret);
+        return loop_device_make_internal(path, fd, open_flags, 0, 0, loop_flags, lock_op, ret);
 }
 
 LoopDevice* loop_device_unref(LoopDevice *d) {
@@ -673,6 +689,7 @@ LoopDevice* loop_device_unref(LoopDevice *d) {
 
         free(d->node);
         sd_device_unref(d->dev);
+        free(d->backing_file);
         return mfree(d);
 }
 
@@ -699,7 +716,7 @@ int loop_device_open_full(
 
         _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
         _cleanup_close_ int fd = -1, lock_fd = -1;
-        _cleanup_free_ char *p = NULL;
+        _cleanup_free_ char *p = NULL, *backing_file = NULL;
         struct loop_info64 info;
         uint64_t diskseq = 0;
         struct stat st;
@@ -738,11 +755,19 @@ int loop_device_open_full(
         }
 
         if (ioctl(loop_fd, LOOP_GET_STATUS64, &info) >= 0) {
+                const char *s;
+
 #if HAVE_VALGRIND_MEMCHECK_H
                 /* Valgrind currently doesn't know LOOP_GET_STATUS64. Remove this once it does */
                 VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
 #endif
                 nr = info.lo_number;
+
+                if (sd_device_get_sysattr_value(dev, "loop/backing_file", &s) >= 0) {
+                        backing_file = strdup(s);
+                        if (!backing_file)
+                                return -ENOMEM;
+                }
         }
 
         r = fd_get_diskseq(loop_fd, &diskseq);
@@ -773,6 +798,7 @@ int loop_device_open_full(
                 .nr = nr,
                 .node = TAKE_PTR(p),
                 .dev = TAKE_PTR(dev),
+                .backing_file = TAKE_PTR(backing_file),
                 .relinquished = true, /* It's not ours, don't try to destroy it when this object is freed */
                 .devno = st.st_rdev,
                 .diskseq = diskseq,
index 43bd25d4454db29959b3283174c7ca773310aa77..cb0183ba07ae7c5ae7f212ea3cc47450eddbd50a 100644 (file)
@@ -17,6 +17,7 @@ struct LoopDevice {
         dev_t devno;
         char *node;
         sd_device *dev;
+        char *backing_file;
         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 1809d9f3b8614f9e45ea7282f7b2ff73fbffd428..70d4aedb426b3b929a6a911e72300a48585b1c37 100644 (file)
@@ -55,6 +55,7 @@ static void* thread_func(void *ptr) {
                         log_error_errno(r, "Failed to allocate loopback device: %m");
                 assert_se(r >= 0);
                 assert_se(loop->dev);
+                assert_se(loop->backing_file);
 
                 log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);