MUTABLE_AUTO,
MUTABLE_IMPORT,
MUTABLE_EPHEMERAL,
+ MUTABLE_EPHEMERAL_IMPORT,
_MUTABLE_MAX,
_MUTABLE_INVALID = -EINVAL,
} MutableMode;
/* Is set to IMAGE_CONFEXT when systemd is called with the confext functionality instead of the default */
static ImageClass arg_image_class = IMAGE_SYSEXT;
+static const char *mutable_extensions_base_dir = "/var/lib/extensions.mutable";
+
STATIC_DESTRUCTOR_REGISTER(arg_hierarchies, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
if (streq(p, "ephemeral"))
return MUTABLE_EPHEMERAL;
+ if (streq(p, "ephemeral-import"))
+ return MUTABLE_EPHEMERAL_IMPORT;
+
r = parse_boolean(p);
if (r < 0)
return r;
char **ret_resolved_mutable_directory) {
_cleanup_free_ char *path = NULL, *resolved_path = NULL, *dir_name = NULL;
- const char *root = arg_root, *base = "/var/lib/extensions.mutable";
+ const char *root = arg_root, *base = mutable_extensions_base_dir;
int r;
assert(hierarchy);
return 0;
}
- if (arg_mutable == MUTABLE_EPHEMERAL) {
+ if (IN_SET(arg_mutable, MUTABLE_EPHEMERAL, MUTABLE_EPHEMERAL_IMPORT)) {
/* We create mutable directory inside the temporary tmpfs workspace, which is a fixed
* location that ignores arg_root. */
root = NULL;
if (!path)
return log_oom();
- if (IN_SET(arg_mutable, MUTABLE_YES, MUTABLE_EPHEMERAL)) {
+ if (IN_SET(arg_mutable, MUTABLE_YES, MUTABLE_EPHEMERAL, MUTABLE_EPHEMERAL_IMPORT)) {
_cleanup_free_ char *path_in_root = NULL;
path_in_root = path_join(root, path);
return 0;
}
+static int resolved_paths_equal(const char *resolved_a, const char *resolved_b) {
+ /* Returns true if paths are of the same entry, false if not, <0 on error. */
+
+ if (path_equal(resolved_a, resolved_b))
+ return 1;
+
+ if (!resolved_a || !resolved_b)
+ return 0;
+
+ return inode_same(resolved_a, resolved_b, 0);
+}
+
+static int maybe_import_mutable_directory(OverlayFSPaths *op) {
+ int r;
+
+ assert(op);
+
+ /* If importing mutable layer and it actually exists and is not a hierarchy itself, add it just below
+ * the meta path */
+
+ if (arg_mutable != MUTABLE_IMPORT || !op->resolved_mutable_directory)
+ return 0;
+
+ r = resolved_paths_equal(op->resolved_hierarchy, op->resolved_mutable_directory);
+ if (r < 0)
+ return log_error_errno(r, "Failed to check equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
+ if (r > 0) {
+ log_debug("Not importing mutable directory for hierarchy %s as a lower dir, because it points to the hierarchy itself", op->hierarchy);
+ return 0;
+ }
+
+ r = strv_extend(&op->lower_dirs, op->resolved_mutable_directory);
+ if (r < 0)
+ return log_oom();
+
+ return 0;
+}
+
+static int maybe_import_ignored_mutable_directory(OverlayFSPaths *op) {
+ _cleanup_free_ char *dir_name = NULL, *path = NULL, *resolved_path = NULL;
+ int r;
+
+ assert(op);
+
+ /* If importing the ignored mutable layer and it actually exists and is not a hierarchy itself, add
+ * it just below the meta path */
+ if (arg_mutable != MUTABLE_EPHEMERAL_IMPORT)
+ return 0;
+
+ dir_name = hierarchy_as_single_path_component(op->hierarchy);
+ if (!dir_name)
+ return log_oom();
+
+ path = path_join(mutable_extensions_base_dir, dir_name);
+ if (!path)
+ return log_oom();
+
+ r = chase(path, arg_root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
+ if (r < 0 && r != -ENOENT)
+ return log_error_errno(r, "Failed to resolve mutable directory '%s': %m", path);
+
+ r = resolved_paths_equal(op->resolved_hierarchy, resolved_path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to check equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
+
+ if (r > 0) {
+ log_debug("Not importing mutable directory for hierarchy %s as a lower dir, because it points to the hierarchy itself", op->hierarchy);
+ return 0;
+ }
+
+ r = strv_consume(&op->lower_dirs, TAKE_PTR(resolved_path));
+ if (r < 0)
+ return log_oom();
+
+ return 0;
+}
+
static int determine_top_lower_dirs(OverlayFSPaths *op, const char *meta_path) {
int r;
if (r < 0)
return log_oom();
- /* If importing mutable layer and it actually exists, add it just below the meta path */
- if (arg_mutable == MUTABLE_IMPORT && op->resolved_mutable_directory) {
- r = strv_extend(&op->lower_dirs, op->resolved_mutable_directory);
- if (r < 0)
- return r;
- }
+ r = maybe_import_mutable_directory(op);
+ if (r < 0)
+ return r;
+
+ r = maybe_import_ignored_mutable_directory(op);
+ if (r < 0)
+ return r;
return 0;
}
}
if (arg_mutable == MUTABLE_IMPORT) {
- log_debug("Mutability for host hierarchy '%s' is disabled, so it will be a lowerdir", op->resolved_hierarchy);
+ log_debug("Mutability for host hierarchy '%s' is disabled, so host hierarchy will be a lowerdir", op->resolved_hierarchy);
+ return 0;
+ }
+
+ if (arg_mutable == MUTABLE_EPHEMERAL_IMPORT) {
+ log_debug("Mutability for host hierarchy '%s' is ephemeral, so host hierarchy will be a lowerdir", op->resolved_hierarchy);
return 0;
}
return 0;
}
- if (path_equal(op->resolved_hierarchy, op->resolved_mutable_directory)) {
- log_debug("Host hierarchy '%s' will serve as upperdir.", op->resolved_hierarchy);
- return 1;
- }
- r = inode_same(op->resolved_hierarchy, op->resolved_mutable_directory, 0);
+ r = resolved_paths_equal(op->resolved_hierarchy, op->resolved_mutable_directory);
if (r < 0)
- return log_error_errno(r, "Failed to check inode equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
+ return log_error_errno(r, "Failed to check equality of hierarchy %s and its mutable directory %s: %m", op->resolved_hierarchy, op->resolved_mutable_directory);
if (r > 0) {
log_debug("Host hierarchy '%s' will serve as upperdir.", op->resolved_hierarchy);
return 1;
if (!r) {
r = strv_extend(&op->lower_dirs, op->resolved_hierarchy);
if (r < 0)
- return r;
+ return log_oom();
}
return 0;
return 0;
/* Do not store work dir path for ephemeral mode, it will be gone once this process is done. */
- if (arg_mutable == MUTABLE_EPHEMERAL)
+ if (IN_SET(arg_mutable, MUTABLE_EPHEMERAL, MUTABLE_EPHEMERAL_IMPORT))
return 0;
work_dir_in_root = path_startswith(work_dir, empty_to_root(arg_root));
" -h --help Show this help\n"
" --version Show package version\n"
"\n%3$sOptions:%4$s\n"
- " --mutable=yes|no|auto|import|ephemeral\n"
+ " --mutable=yes|no|auto|import|ephemeral|ephemeral-import\n"
" Specify a mutability mode of the merged hierarchy\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not show the headers and footers\n"