nspawn: extract snapshot creation into new shared helper
This commit extracts the creation of the snapshot for nspawn into a shared helper. Its not a lot of code but its subtle so having a single place seems beneficial. While extracting the snapshot code got tweaked/simplified based on the feedback from Yu (many thanks!). With that we can simplify the snapshot delete and error handling as well. The shared helper is then going to be used by vmspawn when it also gets the --ephemeral option.
This commit is contained in:
@@ -177,6 +177,7 @@ shared_sources = files(
|
||||
'sleep-config.c',
|
||||
'smack-util.c',
|
||||
'smbios11.c',
|
||||
'snapshot-util.c',
|
||||
'socket-label.c',
|
||||
'socket-netlink.c',
|
||||
'specifier.c',
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <sys/file.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "btrfs-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "log.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "snapshot-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
int create_ephemeral_snapshot(
|
||||
const char *directory,
|
||||
RuntimeScope scope,
|
||||
bool read_only,
|
||||
LockFile *tree_global_lock,
|
||||
LockFile *tree_local_lock,
|
||||
char **ret_new_path) {
|
||||
|
||||
_cleanup_free_ char *np = NULL;
|
||||
int r;
|
||||
|
||||
/* If the specified path is a mount point we generate the new snapshot immediately
|
||||
* inside it under a random name. However if the specified is not a mount point we
|
||||
* create the new snapshot in the parent directory, just next to it. */
|
||||
r = path_is_mount_point(directory);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine whether directory %s is mount point: %m", directory);
|
||||
if (r > 0)
|
||||
r = tempfn_random_child(directory, "snapshot.", &np);
|
||||
else
|
||||
r = tempfn_random(directory, "snapshot.", &np);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to generate name for directory snapshot: %m");
|
||||
|
||||
/* We take an exclusive lock on this image, since it's our private, ephemeral copy
|
||||
* only owned by us and no one else. */
|
||||
r = image_path_lock(
|
||||
scope,
|
||||
np,
|
||||
LOCK_EX|LOCK_NB,
|
||||
scope == RUNTIME_SCOPE_SYSTEM ? tree_global_lock : NULL,
|
||||
tree_local_lock);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to lock %s: %m", np);
|
||||
|
||||
{
|
||||
BLOCK_SIGNALS(SIGINT);
|
||||
r = btrfs_subvol_snapshot_at(AT_FDCWD, directory, AT_FDCWD, np,
|
||||
(read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
|
||||
BTRFS_SNAPSHOT_FALLBACK_COPY |
|
||||
BTRFS_SNAPSHOT_FALLBACK_DIRECTORY |
|
||||
BTRFS_SNAPSHOT_RECURSIVE |
|
||||
BTRFS_SNAPSHOT_QUOTA |
|
||||
BTRFS_SNAPSHOT_SIGINT);
|
||||
}
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create snapshot %s from %s: %m", np, directory);
|
||||
|
||||
*ret_new_path = TAKE_PTR(np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "runtime-scope.h"
|
||||
|
||||
/* create_ephemeral_snapshot - create a snapshot of the given directory.
|
||||
*
|
||||
* It will use a btrfs snapshot when available with fallback to traditional dir copy. It will set the global
|
||||
* and local lock files based on the passed runtime scope. On success the new directory path is returned via
|
||||
* `ret_new_path`.
|
||||
*
|
||||
* The caller is responsible for the cleanup of the directory, using `_cleanup_(rm_rf_subvolume_and_freep)`
|
||||
* is recommended.
|
||||
*/
|
||||
int create_ephemeral_snapshot(
|
||||
const char *directory,
|
||||
RuntimeScope scope,
|
||||
bool read_only,
|
||||
LockFile *tree_global_lock,
|
||||
LockFile *tree_local_lock,
|
||||
char **ret_new_path);
|
||||
Reference in New Issue
Block a user