#include "sd-bus.h"
#include "sd-varlink.h"
+#include "blockdev-util.h"
#include "build.h"
#include "bus-error.h"
#include "bus-locator.h"
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;
}
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)
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;
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;
const char *meta_path,
const char *overlay_path,
const char *work_dir,
- const char *hierarchy) {
+ const char *hierarchy,
+ dev_t backing) {
int r;
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);
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;
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;