]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysext: export backing devnum in metadata dir
authorLennart Poettering <lennart@poettering.net>
Wed, 5 Mar 2025 14:22:45 +0000 (15:22 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 6 Mar 2025 09:27:55 +0000 (10:27 +0100)
src/sysext/sysext.c

index dec0becda03bad385b14d457a9c97d3cecbd73f9..420262cd452261b249fc808bc37bf18e33087d58 100644 (file)
@@ -11,6 +11,7 @@
 #include "sd-bus.h"
 #include "sd-varlink.h"
 
+#include "blockdev-util.h"
 #include "build.h"
 #include "bus-error.h"
 #include "bus-locator.h"
@@ -1198,19 +1199,24 @@ static int hierarchy_as_lower_dir(OverlayFSPaths *op) {
         return 0;
 }
 
-static int determine_bottom_lower_dirs(OverlayFSPaths *op) {
+static int determine_bottom_lower_dirs(OverlayFSPaths *op, dev_t *ret_backing_devnum) {
         int r;
 
         assert(op);
+        assert(ret_backing_devnum);
 
         r = hierarchy_as_lower_dir(op);
         if (r < 0)
                 return r;
         if (!r) {
-                r = strv_extend(&op->lower_dirs, op->resolved_hierarchy);
-                if (r < 0)
+                if (strv_extend(&op->lower_dirs, op->resolved_hierarchy) < 0)
                         return log_oom();
-        }
+
+                r = get_block_device(op->resolved_hierarchy, ret_backing_devnum);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to get block device of '%s': %m", op->resolved_hierarchy);
+        } else
+                *ret_backing_devnum = 0;
 
         return 0;
 }
@@ -1218,12 +1224,14 @@ static int determine_bottom_lower_dirs(OverlayFSPaths *op) {
 static int determine_lower_dirs(
                 OverlayFSPaths *op,
                 char **paths,
-                const char *meta_path) {
+                const char *meta_path,
+                dev_t *ret_backing_devnum) {
 
         int r;
 
         assert(op);
         assert(meta_path);
+        assert(ret_backing_devnum);
 
         r = determine_top_lower_dirs(op, meta_path);
         if (r < 0)
@@ -1233,7 +1241,7 @@ static int determine_lower_dirs(
         if (r < 0)
                 return r;
 
-        r = determine_bottom_lower_dirs(op);
+        r = determine_bottom_lower_dirs(op, ret_backing_devnum);
         if (r < 0)
                 return r;
 
@@ -1420,6 +1428,35 @@ static int write_dev_file(ImageClass image_class, const char *meta_path, const c
         return 0;
 }
 
+static int write_backing_file(ImageClass image_class, const char *meta_path, const char *overlay_path, const char *hierarchy, dev_t backing) {
+        int r;
+
+        assert(meta_path);
+        assert(overlay_path);
+        assert(hierarchy);
+
+        if (backing == 0)
+                return 0;
+
+        /* Let's also store away the backing file system dev_t, so that applications can trace back what they are looking at here */
+        _cleanup_free_ char *f = path_join(meta_path, image_class_info[image_class].dot_directory_name, "backing");
+        if (!f)
+                return log_oom();
+
+        /* Modifying the underlying layers while the overlayfs is mounted is technically undefined, but at
+         * least it won't crash or deadlock, as per the kernel docs about overlayfs:
+         * https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#changes-to-underlying-filesystems */
+        _cleanup_free_ char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
+        if (!hierarchy_path)
+                return log_oom();
+
+        r = write_string_file_full(AT_FDCWD, f, FORMAT_DEVNUM(backing), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, /* ts= */ NULL, hierarchy_path);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write '%s': %m", f);
+
+        return 0;
+}
+
 static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir, const char* hierarchy) {
         _cleanup_free_ char *escaped_work_dir_in_root = NULL, *f = NULL;
         char *work_dir_in_root = NULL;
@@ -1465,7 +1502,8 @@ static int store_info_in_meta(
                 const char *meta_path,
                 const char *overlay_path,
                 const char *work_dir,
-                const char *hierarchy) {
+                const char *hierarchy,
+                dev_t backing) {
 
         int r;
 
@@ -1501,6 +1539,10 @@ static int store_info_in_meta(
         if (r < 0)
                 return r;
 
+        r = write_backing_file(image_class, meta_path, overlay_path, hierarchy, backing);
+        if (r < 0)
+                return r;
+
         /* Make sure the top-level dir has an mtime marking the point we established the merge */
         if (utimensat(AT_FDCWD, meta_path, NULL, AT_SYMLINK_NOFOLLOW) < 0)
                 return log_error_errno(r, "Failed fix mtime of '%s': %m", meta_path);
@@ -1575,7 +1617,8 @@ static int merge_hierarchy(
         if (r < 0)
                 return r;
 
-        r = determine_lower_dirs(op, used_paths, meta_path);
+        dev_t backing;
+        r = determine_lower_dirs(op, used_paths, meta_path, &backing);
         if (r < 0)
                 return r;
 
@@ -1591,7 +1634,7 @@ static int merge_hierarchy(
         if (r < 0)
                 return r;
 
-        r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir, op->hierarchy);
+        r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir, op->hierarchy, backing);
         if (r < 0)
                 return r;