summaryrefslogtreecommitdiffstats
path: root/src/sysext
diff options
context:
space:
mode:
authorKrzesimir Nowak <knowak@microsoft.com>2024-02-28 09:17:27 +0100
committerKrzesimir Nowak <knowak@microsoft.com>2024-03-25 08:19:43 +0100
commit6be5b442392c50c33dce4d9673be4906fa1c531b (patch)
treed0693e55ac1b6fb4ee5dbde4192fdfb6a5912b50 /src/sysext
parentsysext: Add missing --mutable mode in help output (diff)
downloadsystemd-6be5b442392c50c33dce4d9673be4906fa1c531b.tar.xz
systemd-6be5b442392c50c33dce4d9673be4906fa1c531b.zip
sysext: Implement ephemeral mode
To enable it, use "ephemeral" either for mutable mode environment variable or for value of "--mutable=" flag. Instead of using mutable dir in /var/lib/extensions.mutable/<hierarchy>, we create a directory for overlayfs upperdir and workdir in the same tmpfs mount that sysext worker process creates in /run/systemd/sysext. As the path for the workdir will be gone when the worker quits, there is no need to do any additional cleanup. As such, there is also no need to store a path to workdir in the metadata directory.
Diffstat (limited to 'src/sysext')
-rw-r--r--src/sysext/sysext.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c
index 0e39e1c1b2..51333dc6fd 100644
--- a/src/sysext/sysext.c
+++ b/src/sysext/sysext.c
@@ -56,6 +56,7 @@ typedef enum MutableMode {
MUTABLE_NO,
MUTABLE_AUTO,
MUTABLE_IMPORT,
+ MUTABLE_EPHEMERAL,
_MUTABLE_MAX,
_MUTABLE_INVALID = -EINVAL,
} MutableMode;
@@ -133,6 +134,9 @@ static int parse_mutable_mode(const char *p) {
if (streq(p, "import"))
return MUTABLE_IMPORT;
+ if (streq(p, "ephemeral"))
+ return MUTABLE_EPHEMERAL;
+
r = parse_boolean(p);
if (r < 0)
return r;
@@ -657,17 +661,6 @@ static char *hierarchy_as_single_path_component(const char *hierarchy) {
return TAKE_PTR(dir_name);
}
-static char *determine_mutable_directory_path_for_hierarchy(const char *hierarchy) {
- _cleanup_free_ char *dir_name = NULL;
-
- assert(hierarchy);
- dir_name = hierarchy_as_single_path_component(hierarchy);
- if (!dir_name)
- return NULL;
-
- return path_join("/var/lib/extensions.mutable", dir_name);
-}
-
static int paths_on_same_fs(const char *path1, const char *path2) {
struct stat st1, st2;
@@ -769,8 +762,13 @@ static int resolve_hierarchy(const char *hierarchy, char **ret_resolved_hierarch
return 0;
}
-static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_mutable_directory) {
- _cleanup_free_ char *path = NULL, *resolved_path = NULL;
+static int resolve_mutable_directory(
+ const char *hierarchy,
+ const char *workspace,
+ 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";
int r;
assert(hierarchy);
@@ -782,14 +780,25 @@ static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_
return 0;
}
- path = determine_mutable_directory_path_for_hierarchy(hierarchy);
+ if (arg_mutable == MUTABLE_EPHEMERAL) {
+ /* We create mutable directory inside the temporary tmpfs workspace, which is a fixed
+ * location that ignores arg_root. */
+ root = NULL;
+ base = workspace;
+ }
+
+ dir_name = hierarchy_as_single_path_component(hierarchy);
+ if (!dir_name)
+ return log_oom();
+
+ path = path_join(base, dir_name);
if (!path)
return log_oom();
- if (arg_mutable == MUTABLE_YES) {
+ if (IN_SET(arg_mutable, MUTABLE_YES, MUTABLE_EPHEMERAL)) {
_cleanup_free_ char *path_in_root = NULL;
- path_in_root = path_join(arg_root, path);
+ path_in_root = path_join(root, path);
if (!path_in_root)
return log_oom();
@@ -798,7 +807,7 @@ static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_
return log_error_errno(r, "Failed to create a directory '%s': %m", path_in_root);
}
- r = chase(path, arg_root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
+ r = chase(path, 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);
@@ -806,7 +815,7 @@ static int resolve_mutable_directory(const char *hierarchy, char **ret_resolved_
return 0;
}
-static int overlayfs_paths_new(const char *hierarchy, OverlayFSPaths **ret_op) {
+static int overlayfs_paths_new(const char *hierarchy, const char *workspace_path, OverlayFSPaths **ret_op) {
_cleanup_free_ char *hierarchy_copy = NULL, *resolved_hierarchy = NULL, *resolved_mutable_directory = NULL;
int r;
@@ -820,7 +829,7 @@ static int overlayfs_paths_new(const char *hierarchy, OverlayFSPaths **ret_op) {
r = resolve_hierarchy(hierarchy, &resolved_hierarchy);
if (r < 0)
return r;
- r = resolve_mutable_directory(hierarchy, &resolved_mutable_directory);
+ r = resolve_mutable_directory(hierarchy, workspace_path, &resolved_mutable_directory);
if (r < 0)
return r;
@@ -1137,6 +1146,10 @@ static int write_work_dir_file(ImageClass image_class, const char *meta_path, co
if (!work_dir)
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)
+ return 0;
+
work_dir_in_root = path_startswith(work_dir, empty_to_root(arg_root));
if (!work_dir_in_root)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Workdir '%s' must not be outside root '%s'", work_dir, empty_to_root(arg_root));
@@ -1230,7 +1243,8 @@ static int merge_hierarchy(
char **extensions,
char **paths,
const char *meta_path,
- const char *overlay_path) {
+ const char *overlay_path,
+ const char *workspace_path) {
_cleanup_(overlayfs_paths_freep) OverlayFSPaths *op = NULL;
size_t extensions_used = 0;
@@ -1241,8 +1255,9 @@ static int merge_hierarchy(
assert(paths);
assert(meta_path);
assert(overlay_path);
+ assert(workspace_path);
- r = overlayfs_paths_new(hierarchy, &op);
+ r = overlayfs_paths_new(hierarchy, workspace_path, &op);
if (r < 0)
return r;
@@ -1551,7 +1566,7 @@ static int merge_subprocess(
/* Create overlayfs mounts for all hierarchies */
STRV_FOREACH(h, hierarchies) {
- _cleanup_free_ char *meta_path = NULL, *overlay_path = NULL;
+ _cleanup_free_ char *meta_path = NULL, *overlay_path = NULL, *merge_hierarchy_workspace = NULL;
meta_path = path_join(workspace, "meta", *h); /* The place where to store metadata about this instance */
if (!meta_path)
@@ -1561,6 +1576,11 @@ static int merge_subprocess(
if (!overlay_path)
return log_oom();
+ /* Temporary directory for merge_hierarchy needs, like ephemeral directories. */
+ merge_hierarchy_workspace = path_join(workspace, "mh_workspace", *h);
+ if (!merge_hierarchy_workspace)
+ return log_oom();
+
r = merge_hierarchy(
image_class,
*h,
@@ -1568,7 +1588,8 @@ static int merge_subprocess(
extensions,
paths,
meta_path,
- overlay_path);
+ overlay_path,
+ merge_hierarchy_workspace);
if (r < 0)
return r;
}
@@ -2017,7 +2038,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
" -h --help Show this help\n"
" --version Show package version\n"
"\n%3$sOptions:%4$s\n"
- " --mutable=yes|no|auto|import\n"
+ " --mutable=yes|no|auto|import|ephemeral\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"