summaryrefslogtreecommitdiff
path: root/src/nspawn/nspawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nspawn/nspawn.c')
-rw-r--r--src/nspawn/nspawn.c123
1 files changed, 87 insertions, 36 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index a6adbbe879..2770770cd0 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1143,11 +1143,6 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- if (arg_ephemeral && arg_image) {
- log_error("--ephemeral and --image= may not be combined.");
- return -EINVAL;
- }
-
if (arg_ephemeral && !IN_SET(arg_link_journal, LINK_NO, LINK_AUTO)) {
log_error("--ephemeral and --link-journal= may not be combined.");
return -EINVAL;
@@ -2605,7 +2600,7 @@ static int determine_names(void) {
r = image_find(arg_machine, &i);
if (r < 0)
return log_error_errno(r, "Failed to find image for machine '%s': %m", arg_machine);
- else if (r == 0) {
+ if (r == 0) {
log_error("No image for machine '%s': %m", arg_machine);
return -ENOENT;
}
@@ -2615,14 +2610,14 @@ static int determine_names(void) {
else
r = free_and_strdup(&arg_directory, i->path);
if (r < 0)
- return log_error_errno(r, "Invalid image directory: %m");
+ return log_oom();
if (!arg_ephemeral)
arg_read_only = arg_read_only || i->read_only;
} else
arg_directory = get_current_dir_name();
- if (!arg_directory && !arg_machine) {
+ if (!arg_directory && !arg_image) {
log_error("Failed to determine path, please use -D or -i.");
return -EINVAL;
}
@@ -2633,7 +2628,6 @@ static int determine_names(void) {
arg_machine = gethostname_malloc();
else
arg_machine = strdup(basename(arg_image ?: arg_directory));
-
if (!arg_machine)
return log_oom();
@@ -3795,7 +3789,6 @@ static int run(int master,
l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof arg_uid_shift, 0);
if (l < 0)
return log_error_errno(errno, "Failed to read UID shift: %m");
-
if (l != sizeof arg_uid_shift) {
log_error("Short read while reading UID shift.");
return -EIO;
@@ -4029,7 +4022,7 @@ static int run(int master,
terminate_machine(*pid);
/* Normally redundant, but better safe than sorry */
- kill(*pid, SIGKILL);
+ (void) kill(*pid, SIGKILL);
r = wait_for_container(*pid, &container_status);
*pid = 0;
@@ -4077,11 +4070,12 @@ int main(int argc, char *argv[]) {
_cleanup_fdset_free_ FDSet *fds = NULL;
int r, n_fd_passed, loop_nr = -1, ret = EXIT_SUCCESS;
char veth_name[IFNAMSIZ] = "";
- bool secondary = false, remove_subvol = false;
+ bool secondary = false, remove_directory = false, remove_image = false;
pid_t pid = 0;
union in_addr_union exposed = {};
_cleanup_release_lock_file_ LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT;
- bool interactive, veth_created = false;
+ bool interactive, veth_created = false, remove_tmprootdir = false;
+ char tmprootdir[] = "/tmp/nspawn-root-XXXXXX";
log_parse_environment();
log_open();
@@ -4148,7 +4142,7 @@ int main(int argc, char *argv[]) {
else
r = tempfn_random(arg_directory, "machine.", &np);
if (r < 0) {
- log_error_errno(r, "Failed to generate name for snapshot: %m");
+ log_error_errno(r, "Failed to generate name for directory snapshot: %m");
goto finish;
}
@@ -4158,7 +4152,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = btrfs_subvol_snapshot(arg_directory, np, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA);
+ r = btrfs_subvol_snapshot(arg_directory, np,
+ (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
+ BTRFS_SNAPSHOT_FALLBACK_COPY |
+ BTRFS_SNAPSHOT_FALLBACK_DIRECTORY |
+ BTRFS_SNAPSHOT_RECURSIVE |
+ BTRFS_SNAPSHOT_QUOTA);
if (r < 0) {
log_error_errno(r, "Failed to create snapshot %s from %s: %m", np, arg_directory);
goto finish;
@@ -4168,7 +4167,7 @@ int main(int argc, char *argv[]) {
arg_directory = np;
np = NULL;
- remove_subvol = true;
+ remove_directory = true;
} else {
r = image_path_lock(arg_directory, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock);
@@ -4182,7 +4181,13 @@ int main(int argc, char *argv[]) {
}
if (arg_template) {
- r = btrfs_subvol_snapshot(arg_template, arg_directory, (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | BTRFS_SNAPSHOT_FALLBACK_COPY | BTRFS_SNAPSHOT_RECURSIVE | BTRFS_SNAPSHOT_QUOTA);
+ r = btrfs_subvol_snapshot(arg_template, arg_directory,
+ (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
+ BTRFS_SNAPSHOT_FALLBACK_COPY |
+ BTRFS_SNAPSHOT_FALLBACK_DIRECTORY |
+ BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE |
+ BTRFS_SNAPSHOT_RECURSIVE |
+ BTRFS_SNAPSHOT_QUOTA);
if (r == -EEXIST) {
if (!arg_quiet)
log_info("Directory %s already exists, not populating from template %s.", arg_directory, arg_template);
@@ -4214,28 +4219,55 @@ int main(int argc, char *argv[]) {
}
} else {
- char template[] = "/tmp/nspawn-root-XXXXXX";
-
assert(arg_image);
assert(!arg_template);
- r = image_path_lock(arg_image, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock);
- if (r == -EBUSY) {
- r = log_error_errno(r, "Disk image %s is currently busy.", arg_image);
- goto finish;
- }
- if (r < 0) {
- r = log_error_errno(r, "Failed to create image lock: %m");
- goto finish;
+ if (arg_ephemeral) {
+ _cleanup_free_ char *np = NULL;
+
+ r = tempfn_random(arg_image, "machine.", &np);
+ if (r < 0) {
+ log_error_errno(r, "Failed to generate name for image snapshot: %m");
+ goto finish;
+ }
+
+ r = image_path_lock(np, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock);
+ if (r < 0) {
+ r = log_error_errno(r, "Failed to create image lock: %m");
+ goto finish;
+ }
+
+ r = copy_file(arg_image, np, O_EXCL, arg_read_only ? 0400 : 0600, FS_NOCOW_FL);
+ if (r < 0) {
+ r = log_error_errno(r, "Failed to copy image file: %m");
+ goto finish;
+ }
+
+ free(arg_image);
+ arg_image = np;
+ np = NULL;
+
+ remove_image = true;
+ } else {
+ r = image_path_lock(arg_image, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock);
+ if (r == -EBUSY) {
+ r = log_error_errno(r, "Disk image %s is currently busy.", arg_image);
+ goto finish;
+ }
+ if (r < 0) {
+ r = log_error_errno(r, "Failed to create image lock: %m");
+ goto finish;
+ }
}
- if (!mkdtemp(template)) {
- log_error_errno(errno, "Failed to create temporary directory: %m");
- r = -errno;
+ if (!mkdtemp(tmprootdir)) {
+ r = log_error_errno(errno, "Failed to create temporary directory: %m");
goto finish;
}
- arg_directory = strdup(template);
+ remove_tmprootdir = true;
+
+ arg_directory = strdup(tmprootdir);
if (!arg_directory) {
r = log_oom();
goto finish;
@@ -4255,6 +4287,10 @@ int main(int argc, char *argv[]) {
&secondary);
if (r < 0)
goto finish;
+
+ /* Now that we mounted the image, let's try to remove it again, if it is ephemeral */
+ if (remove_image && unlink(arg_image) >= 0)
+ remove_image = false;
}
r = custom_mounts_prepare();
@@ -4321,20 +4357,35 @@ finish:
"STOPPING=1\nSTATUS=Terminating...");
if (pid > 0)
- kill(pid, SIGKILL);
+ (void) kill(pid, SIGKILL);
/* Try to flush whatever is still queued in the pty */
- if (master >= 0)
+ if (master >= 0) {
(void) copy_bytes(master, STDOUT_FILENO, (uint64_t) -1, false);
+ master = safe_close(master);
+ }
+
+ if (pid > 0)
+ (void) wait_for_terminate(pid, NULL);
loop_remove(loop_nr, &image_fd);
- if (remove_subvol && arg_directory) {
+ if (remove_directory && arg_directory) {
int k;
- k = btrfs_subvol_remove(arg_directory, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
+ k = rm_rf(arg_directory, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
if (k < 0)
- log_warning_errno(k, "Cannot remove subvolume '%s', ignoring: %m", arg_directory);
+ log_warning_errno(k, "Cannot remove '%s', ignoring: %m", arg_directory);
+ }
+
+ if (remove_image && arg_image) {
+ if (unlink(arg_image) < 0)
+ log_warning_errno(errno, "Can't remove image file '%s', ignoring: %m", arg_image);
+ }
+
+ if (remove_tmprootdir) {
+ if (rmdir(tmprootdir) < 0)
+ log_debug_errno(errno, "Can't remove temporary root directory '%s', ignoring: %m", tmprootdir);
}
if (arg_machine) {